=== conf/files ================================================================== --- conf/files (revision 183565) +++ conf/files (local) @@ -475,6 +475,8 @@ dev/ata/atapi-cd.c optional atapicd dev/ata/atapi-fd.c optional atapifd dev/ata/atapi-tape.c optional atapist +dev/ata/chipsets/ata-ahci.c optional ata pci +dev/ata/chipsets/ata-intel.c optional ata pci dev/ath/ah_osdep.c optional ath_hal \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/ath_rate/amrr/amrr.c optional ath_rate_amrr \ === dev/ata/ata-chipset.c ================================================================== --- dev/ata/ata-chipset.c (revision 183565) +++ dev/ata/ata-chipset.c (local) @@ -50,159 +50,58 @@ #include #include +#define ATA_CHIPSET_DEBUG 1 +#define ATA_PROBE_OK -10 + +SET_DECLARE(ata_chipset_set, const ata_chipset_info_t); + /* local prototypes */ /* ata-chipset.c */ static int ata_generic_chipinit(device_t dev); static void ata_generic_intr(void *data); static void ata_generic_setmode(device_t dev, int mode); -static void ata_sata_phy_check_events(device_t dev); -static void ata_sata_phy_event(void *context, int dummy); -static int ata_sata_phy_reset(device_t dev); -static int ata_sata_connect(struct ata_channel *ch); -static void ata_sata_setmode(device_t dev, int mode); -static int ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis); -static int ata_ahci_chipinit(device_t dev); -static int ata_ahci_ctlr_reset(device_t dev); -static int ata_ahci_suspend(device_t dev); -static int ata_ahci_allocate(device_t dev); -static int ata_ahci_status(device_t dev); -static int ata_ahci_begin_transaction(struct ata_request *request); -static int ata_ahci_end_transaction(struct ata_request *request); -static int ata_ahci_pm_read(device_t dev, int port, int reg, u_int32_t *result); -static int ata_ahci_pm_write(device_t dev, int port, int reg, u_int32_t result); -static u_int32_t ata_ahci_softreset(device_t dev, int port); -static void ata_ahci_reset(device_t dev); -static void ata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); -static void ata_ahci_dmainit(device_t dev); -static int ata_ahci_setup_fis(struct ata_ahci_cmd_tab *ctp, struct ata_request *request); -static int ata_acard_chipinit(device_t dev); -static int ata_acard_allocate(device_t dev); -static int ata_acard_status(device_t dev); -static void ata_acard_850_setmode(device_t dev, int mode); -static void ata_acard_86X_setmode(device_t dev, int mode); -static int ata_ali_chipinit(device_t dev); -static int ata_ali_allocate(device_t dev); -static int ata_ali_sata_allocate(device_t dev); -static void ata_ali_reset(device_t dev); -static void ata_ali_setmode(device_t dev, int mode); -static int ata_amd_chipinit(device_t dev); -static int ata_ati_chipinit(device_t dev); -static void ata_ati_setmode(device_t dev, int mode); -static int ata_cyrix_chipinit(device_t dev); -static void ata_cyrix_setmode(device_t dev, int mode); -static int ata_cypress_chipinit(device_t dev); -static void ata_cypress_setmode(device_t dev, int mode); -static int ata_highpoint_chipinit(device_t dev); -static int ata_highpoint_allocate(device_t dev); -static void ata_highpoint_setmode(device_t dev, int mode); -static int ata_highpoint_check_80pin(device_t dev, int mode); -static int ata_intel_chipinit(device_t dev); -static int ata_intel_allocate(device_t dev); -static void ata_intel_reset(device_t dev); -static void ata_intel_old_setmode(device_t dev, int mode); -static void ata_intel_new_setmode(device_t dev, int mode); -static void ata_intel_sata_setmode(device_t dev, int mode); -static int ata_intel_31244_allocate(device_t dev); -static int ata_intel_31244_status(device_t dev); -static void ata_intel_31244_tf_write(struct ata_request *request); -static void ata_intel_31244_reset(device_t dev); -static int ata_ite_chipinit(device_t dev); -static void ata_ite_8213_setmode(device_t dev, int mode); -static void ata_ite_821x_setmode(device_t dev, int mode); -static int ata_jmicron_chipinit(device_t dev); -static int ata_jmicron_allocate(device_t dev); -static void ata_jmicron_reset(device_t dev); -static void ata_jmicron_dmainit(device_t dev); -static void ata_jmicron_setmode(device_t dev, int mode); -static int ata_marvell_pata_chipinit(device_t dev); -static int ata_marvell_pata_allocate(device_t dev); -static void ata_marvell_pata_setmode(device_t dev, int mode); -static int ata_marvell_edma_chipinit(device_t dev); -static int ata_marvell_edma_allocate(device_t dev); -static int ata_marvell_edma_status(device_t dev); -static int ata_marvell_edma_begin_transaction(struct ata_request *request); -static int ata_marvell_edma_end_transaction(struct ata_request *request); -static void ata_marvell_edma_reset(device_t dev); -static void ata_marvell_edma_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); -static void ata_marvell_edma_dmainit(device_t dev); -static int ata_national_chipinit(device_t dev); -static void ata_national_setmode(device_t dev, int mode); -static int ata_netcell_chipinit(device_t dev); -static int ata_netcell_allocate(device_t dev); -static int ata_nvidia_chipinit(device_t dev); -static int ata_nvidia_allocate(device_t dev); -static int ata_nvidia_status(device_t dev); -static void ata_nvidia_reset(device_t dev); -static int ata_promise_chipinit(device_t dev); -static int ata_promise_allocate(device_t dev); -static int ata_promise_status(device_t dev); -static int ata_promise_dmastart(struct ata_request *request); -static int ata_promise_dmastop(struct ata_request *request); -static void ata_promise_dmareset(device_t dev); -static void ata_promise_dmainit(device_t dev); -static void ata_promise_setmode(device_t dev, int mode); -static int ata_promise_tx2_allocate(device_t dev); -static int ata_promise_tx2_status(device_t dev); -static int ata_promise_mio_allocate(device_t dev); -static void ata_promise_mio_intr(void *data); -static int ata_promise_mio_status(device_t dev); -static int ata_promise_mio_command(struct ata_request *request); -static void ata_promise_mio_reset(device_t dev); -static int ata_promise_mio_pm_read(device_t dev, int port, int reg, u_int32_t *result); -static int ata_promise_mio_pm_write(device_t dev, int port, int reg, u_int32_t result); -static u_int32_t ata_promise_mio_softreset(device_t dev, int port); -static void ata_promise_mio_dmainit(device_t dev); -static void ata_promise_mio_setprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); -static void ata_promise_mio_setmode(device_t dev, int mode); -static void ata_promise_sx4_intr(void *data); -static int ata_promise_sx4_command(struct ata_request *request); -static int ata_promise_apkt(u_int8_t *bytep, struct ata_request *request); -static void ata_promise_queue_hpkt(struct ata_pci_controller *ctlr, u_int32_t hpkt); -static void ata_promise_next_hpkt(struct ata_pci_controller *ctlr); -static int ata_serverworks_chipinit(device_t dev); -static int ata_serverworks_allocate(device_t dev); -static void ata_serverworks_tf_read(struct ata_request *request); -static void ata_serverworks_tf_write(struct ata_request *request); -static void ata_serverworks_setmode(device_t dev, int mode); -static int ata_sii_chipinit(device_t dev); -static int ata_cmd_allocate(device_t dev); -static int ata_cmd_status(device_t dev); -static void ata_cmd_setmode(device_t dev, int mode); -static int ata_sii_allocate(device_t dev); -static int ata_sii_status(device_t dev); -static void ata_sii_reset(device_t dev); -static void ata_sii_setmode(device_t dev, int mode); -static int ata_siiprb_allocate(device_t dev); -static int ata_siiprb_status(device_t dev); -static int ata_siiprb_begin_transaction(struct ata_request *request); -static int ata_siiprb_end_transaction(struct ata_request *request); -static int ata_siiprb_pm_read(device_t dev, int port, int reg, u_int32_t *result); -static int ata_siiprb_pm_write(device_t dev, int port, int reg, u_int32_t result); -static u_int32_t ata_siiprb_softreset(device_t dev, int port); -static void ata_siiprb_reset(device_t dev); -static void ata_siiprb_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); -static void ata_siiprb_dmainit(device_t dev); -static int ata_sis_chipinit(device_t dev); -static int ata_sis_allocate(device_t dev); -static void ata_sis_reset(device_t dev); -static void ata_sis_setmode(device_t dev, int mode); -static int ata_via_chipinit(device_t dev); -static int ata_via_allocate(device_t dev); -static void ata_via_reset(device_t dev); -static void ata_via_setmode(device_t dev, int mode); -static void ata_via_southbridge_fixup(device_t dev); -static void ata_via_family_setmode(device_t dev, int mode); -static void ata_set_desc(device_t dev); -static struct ata_chip_id *ata_match_chip(device_t dev, struct ata_chip_id *index); -static struct ata_chip_id *ata_find_chip(device_t dev, struct ata_chip_id *index, int slot); -static int ata_setup_interrupt(device_t dev); -static int ata_serialize(device_t dev, int flags); -static void ata_print_cable(device_t dev, u_int8_t *who); -static int ata_atapi(device_t dev); + static int ata_check_80pin(device_t dev, int mode); -static int ata_mode2idx(int mode); +int +ata_chipset_ident(device_t dev) +{ + const ata_chipset_info_t **list; + const ata_chipset_info_t *p; + /* if this is an AHCI chipset grab it */ + if (pci_get_subclass(dev) == PCIS_STORAGE_SATA) { + if (!ata_ahci_ident(dev)) + return ATA_PROBE_OK; + } + + SET_FOREACH(list, ata_chipset_set) { + p = *list; +#ifdef ATA_CHIPSET_DEBUG + printf("ATA chipset '%s': ", p->name); +#endif + if (!p->ident_func(dev)) { +#ifdef ATA_CHIPSET_DEBUG + printf("yes\n"); +#endif + return ATA_PROBE_OK; + } + else { +#ifdef ATA_CHIPSET_DEBUG + printf("no\n"); +#endif + } + } + + /* unknown chipset, try generic DMA if it seems possible */ + if (pci_get_subclass(dev) == PCIS_STORAGE_IDE) { + if (!ata_generic_ident(dev)) + return ATA_PROBE_OK; + } + + return ENXIO; +} + /* * generic ATA support functions */ @@ -257,7 +156,7 @@ /* * SATA support functions */ -static void +void ata_sata_phy_check_events(device_t dev) { struct ata_channel *ch = device_get_softc(dev); @@ -295,7 +194,7 @@ } } -static void +void ata_sata_phy_event(void *context, int dummy) { struct ata_connect_task *tp = (struct ata_connect_task *)context; @@ -327,7 +226,7 @@ free(tp, M_ATA); } -static int +int ata_sata_phy_reset(device_t dev) { struct ata_channel *ch = device_get_softc(dev); @@ -357,7 +256,7 @@ return 0; } -static int +int ata_sata_connect(struct ata_channel *ch) { u_int32_t status; @@ -385,7 +284,7 @@ return 1; } -static void +void ata_sata_setmode(device_t dev, int mode) { struct ata_device *atadev = device_get_softc(dev); @@ -419,7 +318,7 @@ } } -static void +void ata_pm_identify(device_t dev) { struct ata_channel *ch = device_get_softc(dev); @@ -517,7 +416,7 @@ } } -static int +int ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis) { struct ata_device *atadev = device_get_softc(request->dev); @@ -560,5820 +459,8 @@ return 0; } - -/* - * AHCI v1.x compliant SATA chipset support functions - */ -int -ata_ahci_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - char buffer[64]; - - /* is this PCI device flagged as an AHCI compliant chip ? */ - if (pci_read_config(dev, PCIR_PROGIF, 1) != PCIP_STORAGE_SATA_AHCI_1_0) - return ENXIO; - - if (bootverbose) - sprintf(buffer, "%s (ID=%08x) AHCI controller", - ata_pcivendor2str(dev), pci_get_devid(dev)); - else - sprintf(buffer, "%s AHCI controller", ata_pcivendor2str(dev)); - device_set_desc_copy(dev, buffer); - ctlr->chipinit = ata_ahci_chipinit; - return 0; -} - -static int -ata_ahci_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - u_int32_t version; - - /* if we have a memory BAR(5) we are likely on an AHCI part */ - ctlr->r_type2 = SYS_RES_MEMORY; - ctlr->r_rid2 = PCIR_BAR(5); - if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, - &ctlr->r_rid2, RF_ACTIVE))) - return ENXIO; - - /* setup interrupt delivery if not done allready by a vendor driver */ - if (!ctlr->r_irq) { - if (ata_setup_interrupt(dev)) - return ENXIO; - } - else - device_printf(dev, "AHCI called from vendor specific driver\n"); - - /* reset controller */ - ata_ahci_ctlr_reset(dev); - - /* get the number of HW channels */ - ctlr->channels = - MAX(flsl(ATA_INL(ctlr->r_res2, ATA_AHCI_PI)), - (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) + 1); - - ctlr->reset = ata_ahci_reset; - ctlr->dmainit = ata_ahci_dmainit; - ctlr->allocate = ata_ahci_allocate; - ctlr->setmode = ata_sata_setmode; - ctlr->suspend = ata_ahci_suspend; - ctlr->resume = ata_ahci_ctlr_reset; - - /* enable PCI interrupt */ - pci_write_config(dev, PCIR_COMMAND, - pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2); - - /* announce we support the HW */ - version = ATA_INL(ctlr->r_res2, ATA_AHCI_VS); - device_printf(dev, - "AHCI Version %x%x.%x%x controller with %d ports PM %s\n", - (version >> 24) & 0xff, (version >> 16) & 0xff, - (version >> 8) & 0xff, version & 0xff, - (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) + 1, - (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) ? - "supported" : "not supported"); - return 0; -} - -static int -ata_ahci_ctlr_reset(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - /* enable AHCI mode */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE); - - /* reset AHCI controller */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_HR); - DELAY(1000000); - if (ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) & ATA_AHCI_GHC_HR) { - bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2); - device_printf(dev, "AHCI controller reset failure\n"); - return ENXIO; - } - - /* reenable AHCI mode */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE); - - /* clear interrupts */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, ATA_INL(ctlr->r_res2, ATA_AHCI_IS)); - - /* enable AHCI interrupts */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, - ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) | ATA_AHCI_GHC_IE); - - return 0; -} - -static int -ata_ahci_suspend(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - /* disable interupts so the state change(s) doesn't trigger */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, - ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) & (~ATA_AHCI_GHC_IE)); - return 0; -} - - -static int -ata_ahci_allocate(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int offset = ch->unit << 7; - - /* set the SATA resources */ - ch->r_io[ATA_SSTATUS].res = ctlr->r_res2; - ch->r_io[ATA_SSTATUS].offset = ATA_AHCI_P_SSTS + offset; - ch->r_io[ATA_SERROR].res = ctlr->r_res2; - ch->r_io[ATA_SERROR].offset = ATA_AHCI_P_SERR + offset; - ch->r_io[ATA_SCONTROL].res = ctlr->r_res2; - ch->r_io[ATA_SCONTROL].offset = ATA_AHCI_P_SCTL + offset; - ch->r_io[ATA_SACTIVE].res = ctlr->r_res2; - ch->r_io[ATA_SACTIVE].offset = ATA_AHCI_P_SACT + offset; - - ch->hw.status = ata_ahci_status; - ch->hw.begin_transaction = ata_ahci_begin_transaction; - ch->hw.end_transaction = ata_ahci_end_transaction; - ch->hw.command = NULL; /* not used here */ - ch->hw.softreset = ata_ahci_softreset; - ch->hw.pm_read = ata_ahci_pm_read; - ch->hw.pm_write = ata_ahci_pm_write; - - return 0; -} - -static int -ata_ahci_status(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - u_int32_t action = ATA_INL(ctlr->r_res2, ATA_AHCI_IS); - int offset = ch->unit << 7; - -#define ATA_AHCI_STATBITS \ - (ATA_AHCI_P_IX_IF|ATA_AHCI_P_IX_HBD|ATA_AHCI_P_IX_HBF|ATA_AHCI_P_IX_TFE) - - if (action & (1 << ch->unit)) { - u_int32_t istatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset); - u_int32_t cstatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset); - - /* clear interrupt(s) */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, istatus); - ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, action & (1 << ch->unit)); - - /* do we have any PHY events ? */ - if (istatus & (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC)) - ata_sata_phy_check_events(dev); - - /* do we have a potentially hanging engine to take care of? */ - /* XXX SOS what todo on NCQ */ - if ((istatus & ATA_AHCI_STATBITS) && (cstatus & 1)) { - - u_int32_t cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); - int timeout = 0; - - /* kill off all activity on this channel */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, - cmd & ~(ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST)); - - /* XXX SOS this is not entirely wrong */ - do { - DELAY(1000); - if (timeout++ > 1000) { - device_printf(dev, "stopping AHCI engine failed\n"); - break; - } - } while (ATA_INL(ctlr->r_res2, - ATA_AHCI_P_CMD + offset) & ATA_AHCI_P_CMD_CR); - - /* start operations on this channel */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, - cmd | (ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST)); - - return 1; - } - else - /* XXX SOS what todo on NCQ */ - return (!(cstatus & 1)); - } - return 0; -} - -/* must be called with ATA channel locked and state_mtx held */ -static int -ata_ahci_begin_transaction(struct ata_request *request) -{ - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); - struct ata_channel *ch = device_get_softc(request->parent); - struct ata_device *atadev = device_get_softc(request->dev); - struct ata_ahci_cmd_tab *ctp; - struct ata_ahci_cmd_list *clp; - int offset = ch->unit << 7; - int port = atadev->unit & 0x0f; - int entries = 0; - int fis_size; - - /* get a piece of the workspace for this request */ - ctp = (struct ata_ahci_cmd_tab *) - (ch->dma.work + ATA_AHCI_CT_OFFSET + (ATA_AHCI_CT_SIZE*request->tag)); - - /* setup the FIS for this request */ - if (!(fis_size = ata_ahci_setup_fis(ctp, request))) { - device_printf(request->dev, "setting up SATA FIS failed\n"); - request->result = EIO; - return ATA_OP_FINISHED; - } - - /* if request moves data setup and load SG list */ - if (request->flags & (ATA_R_READ | ATA_R_WRITE)) { - if (ch->dma.load(request, ctp->prd_tab, &entries)) { - device_printf(request->dev, "setting up DMA failed\n"); - request->result = EIO; - return ATA_OP_FINISHED; - } - } - - /* setup the command list entry */ - clp = (struct ata_ahci_cmd_list *) - (ch->dma.work + ATA_AHCI_CL_OFFSET + (ATA_AHCI_CL_SIZE*request->tag)); - - clp->prd_length = entries; - clp->cmd_flags = (request->flags & ATA_R_WRITE ? ATA_AHCI_CMD_WRITE : 0) | - (request->flags & ATA_R_ATAPI ? - (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) | - (fis_size / sizeof(u_int32_t)) | - (port << 12); - clp->bytecount = 0; - clp->cmd_table_phys = htole64(ch->dma.work_bus + ATA_AHCI_CT_OFFSET + - (ATA_AHCI_CT_SIZE * request->tag)); - - /* clear eventual ACTIVE bit */ - ATA_IDX_OUTL(ch, ATA_SACTIVE, - ATA_IDX_INL(ch, ATA_SACTIVE) & (1 << request->tag)); - - /* set command type bit */ - if (request->flags & ATA_R_ATAPI) - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, - ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) | - ATA_AHCI_P_CMD_ATAPI); - else - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, - ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) & - ~ATA_AHCI_P_CMD_ATAPI); - - /* set PM port to address */ - //ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, (port << 8) | 0x00000001); - - /* issue command to controller */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, (1 << request->tag)); - - if (!(request->flags & ATA_R_ATAPI)) { - /* device reset doesn't interrupt */ - if (request->u.ata.command == ATA_DEVICE_RESET) { - u_int32_t tf_data; - int timeout = 1000000; - - do { - DELAY(10); - tf_data = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + (ch->unit<<7)); - } while ((tf_data & ATA_S_BUSY) && timeout--); - if (bootverbose) - device_printf(ch->dev, "device_reset timeout=%dus\n", - (1000000-timeout)*10); - request->status = tf_data; - if (request->status & ATA_S_ERROR) - request->error = tf_data >> 8; - return ATA_OP_FINISHED; - } - } - - /* start the timeout */ - callout_reset(&request->callout, request->timeout * hz, - (timeout_t*)ata_timeout, request); - return ATA_OP_CONTINUES; -} - -/* must be called with ATA channel locked and state_mtx held */ -static int -ata_ahci_end_transaction(struct ata_request *request) -{ - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); - struct ata_channel *ch = device_get_softc(request->parent); - struct ata_ahci_cmd_list *clp; - u_int32_t tf_data; - int offset = ch->unit << 7; - - /* kill the timeout */ - callout_stop(&request->callout); - - /* get status */ - tf_data = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset); - request->status = tf_data; - - /* if error status get details */ - if (request->status & ATA_S_ERROR) - request->error = tf_data >> 8; - - /* on control commands read back registers to the request struct */ - if (request->flags & ATA_R_CONTROL) { - struct ata_device *atadev = device_get_softc(request->dev); - u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40; - - request->u.ata.count = fis[12] | ((u_int16_t)fis[13] << 8); - request->u.ata.lba = fis[4] | ((u_int64_t)fis[5] << 8) | - ((u_int64_t)fis[6] << 16); - if (atadev->flags & ATA_D_48BIT_ACTIVE) - request->u.ata.lba |= ((u_int64_t)fis[8] << 24) | - ((u_int64_t)fis[9] << 32) | - ((u_int64_t)fis[10] << 40); - else - request->u.ata.lba |= ((u_int64_t)(fis[7] & 0x0f) << 24); - } - - /* record how much data we actually moved */ - clp = (struct ata_ahci_cmd_list *) - (ch->dma.work + ATA_AHCI_CL_OFFSET + (ATA_AHCI_CL_SIZE*request->tag)); - request->donecount = clp->bytecount; - - /* release SG list etc */ - ch->dma.unload(request); - - return ATA_OP_FINISHED; -} - -static int -ata_ahci_issue_cmd(device_t dev, u_int16_t flags, int timeout) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - struct ata_ahci_cmd_list *clp = - (struct ata_ahci_cmd_list *)(ch->dma.work + ATA_AHCI_CL_OFFSET); - struct ata_ahci_cmd_tab *ctp = - (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); - u_int32_t status = 0; - int offset = ch->unit << 7; - int port = (ctp->cfis[1] & 0x0f); - int count; - - clp->prd_length = 0; - clp->cmd_flags = (20 / sizeof(u_int32_t)) | flags | (port << 12); - clp->bytecount = 0; - clp->cmd_table_phys = htole64(ch->dma.work_bus + ATA_AHCI_CT_OFFSET); - - /* set PM port */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, (port << 8) | 0x00000001); - - /* issue command to controller */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, 1); - - /* poll for command finished */ - for (count = 0; count < timeout; count++) { - DELAY(1000); - if (!((status = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset)) & 1)) - break; - } - - /* clear interrupts */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, - ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset)); - - if (bootverbose) - device_printf(dev, "ahci_issue_cmd time=%dms cnt=%dms status=%08x\n", - timeout, count, status); - if (timeout && (count >= timeout)) - return EIO; - - return 0; -} - -static int -ata_ahci_pm_read(device_t dev, int port, int reg, u_int32_t *result) -{ - struct ata_channel *ch = device_get_softc(dev); - struct ata_ahci_cmd_tab *ctp = - (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); - u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40; - - bzero(ctp->cfis, 64); - ctp->cfis[0] = 0x27; /* host to device */ - ctp->cfis[1] = 0x8f; /* command FIS to PM port */ - ctp->cfis[2] = ATA_READ_PM; - ctp->cfis[3] = reg; - ctp->cfis[7] = port | ATA_D_LBA; - ctp->cfis[15] = ATA_A_4BIT; - - if (ata_ahci_issue_cmd(dev, 0, 10)) { - device_printf(dev, "error reading PM port\n"); - return EIO; - } - - *result = fis[12] | (fis[4] << 8) | (fis[5] << 16) | (fis[6] << 24); - return 0; -} - -static int -ata_ahci_pm_write(device_t dev, int port, int reg, u_int32_t value) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - struct ata_ahci_cmd_tab *ctp = - (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); - int offset = ch->unit << 7; - - bzero(ctp->cfis, 64); - ctp->cfis[0] = 0x27; /* host to device */ - ctp->cfis[1] = 0x8f; /* command FIS to PM port */ - ctp->cfis[2] = ATA_WRITE_PM; - ctp->cfis[3] = reg; - ctp->cfis[7] = port | ATA_D_LBA; - ctp->cfis[12] = value & 0xff; - ctp->cfis[4] = (value >> 8) & 0xff;; - ctp->cfis[5] = (value >> 16) & 0xff;; - ctp->cfis[6] = (value >> 24) & 0xff;; - ctp->cfis[15] = ATA_A_4BIT; - - if (ata_ahci_issue_cmd(dev, 0, 100)) { - device_printf(dev, "error writing PM port\n"); - return ATA_E_ABORT; - } - - return (ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset) >> 8) & 0xff; -} - -static void -ata_ahci_restart(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - u_int32_t cmd; - int offset = ch->unit << 7; - int timeout; - - /* kill off all activity on this channel */ - cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, - cmd & ~(ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST)); - - /* XXX SOS this is not entirely wrong */ - timeout = 0; - do { - DELAY(1000); - if (timeout++ > 1000) { - device_printf(dev, "stopping AHCI engine failed\n"); - break; - } - } - while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) & ATA_AHCI_P_CMD_CR); - - /* issue Command List Override if supported */ - if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_CLO) { - cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); - cmd |= ATA_AHCI_P_CMD_CLO; - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, cmd); - timeout = 0; - do { - DELAY(1000); - if (timeout++ > 1000) { - device_printf(dev, "executing CLO failed\n"); - break; - } - } - while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD+offset)&ATA_AHCI_P_CMD_CLO); - } - - /* clear SATA error register */ - ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR)); - - /* clear any interrupts pending on this channel */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, - ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset)); - - /* start operations on this channel */ - cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, - cmd | (ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST) | - (ch->devices & ATA_PORTMULTIPLIER ? ATA_AHCI_P_CMD_PMA : 0)); -} - -static u_int32_t -ata_ahci_softreset(device_t dev, int port) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int offset = ch->unit << 7; - int timeout = 0; -#ifdef AHCI_PM - struct ata_ahci_cmd_tab *ctp = - (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); - - /* kick controller into sane state if needed */ - ata_ahci_restart(dev); - - /* pull reset active */ - bzero(ctp->cfis, 64); - ctp->cfis[0] = 0x27; - ctp->cfis[1] = port & 0x0f; - //ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM; - ctp->cfis[15] = (ATA_A_4BIT | ATA_A_RESET); - - if (ata_ahci_issue_cmd(dev, ATA_AHCI_CMD_RESET | ATA_AHCI_CMD_CLR_BUSY,100)) - device_printf(dev, "setting SRST failed ??\n"); - //return -1; - - ata_udelay(5000); - - /* pull reset inactive -> device softreset */ - bzero(ctp->cfis, 64); - ctp->cfis[0] = 0x27; - ctp->cfis[1] = port & 0x0f; - //ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM; - ctp->cfis[15] = ATA_A_4BIT; - if (ata_ahci_issue_cmd(dev, 0, 0)) - return -1; - - ata_udelay(150000); - -#endif - do { - DELAY(1000); - if (timeout++ > 1000) { - device_printf(dev, "still BUSY after softreset\n"); - break; - } - } while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset) & ATA_S_BUSY); - if (bootverbose) - device_printf(dev, "BUSY wait time=%dms\n", timeout); - - return ATA_INL(ctlr->r_res2, ATA_AHCI_P_SIG + offset); -} - -static void -ata_ahci_reset(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - u_int64_t work; - u_int32_t cmd, signature; - int offset = ch->unit << 7; - - if (!(ATA_INL(ctlr->r_res2, ATA_AHCI_PI) & (1 << ch->unit))) { - device_printf(dev, "port not implemented\n"); - return; - } - - /* setup work areas */ - work = ch->dma.work_bus + ATA_AHCI_CL_OFFSET; - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset, work & 0xffffffff); - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, work >> 32); - - work = ch->dma.work_bus + ATA_AHCI_FB_OFFSET; - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset, work & 0xffffffff); - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, work >> 32); - - /* enable wanted port interrupts */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, - (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF | - ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF | - ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC | ATA_AHCI_P_IX_DP | - ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | ATA_AHCI_P_IX_DS | - ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR)); - - /* activate the channel and power/spin up device */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, - (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD)); - - ata_ahci_restart(dev); - - /* enable FIS based switching */ - //ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, 0x00000003); - - if (!ata_sata_phy_reset(dev)) { - if (bootverbose) - device_printf(dev, "phy reset found no device\n"); - ch->devices = 0; - - /* kill off all activity on this channel */ - cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, - cmd & ~(ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST)); - return; - } - - /* only probe for PortMultiplier if HW has support */ - if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) - signature = ata_ahci_softreset(dev, ATA_PM); - else { - signature = ata_ahci_softreset(dev, 0); - } - if (bootverbose) - device_printf(dev, "SIGNATURE: %08x\n", signature); - - switch (signature) { - case 0x00000101: - ch->devices = ATA_ATA_MASTER; - break; - case 0x96690101: - ch->devices = ATA_PORTMULTIPLIER; - ata_pm_identify(dev); - break; - case 0xeb140101: - ch->devices = ATA_ATAPI_MASTER; - break; - default: /* SOS XXX */ - if (bootverbose) - device_printf(dev, "No signature, asuming disk device\n"); - ch->devices = ATA_ATA_MASTER; - } - if (bootverbose) - device_printf(dev, "ahci_reset devices=%08x\n", ch->devices); -} - -static void -ata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) -{ - struct ata_dmasetprd_args *args = xsc; - struct ata_ahci_dma_prd *prd = args->dmatab; - int i; - - if (!(args->error = error)) { - for (i = 0; i < nsegs; i++) { - prd[i].dba = htole64(segs[i].ds_addr); - prd[i].dbc = htole32((segs[i].ds_len - 1) & ATA_AHCI_PRD_MASK); - } - } - - KASSERT(nsegs <= ATA_AHCI_DMA_ENTRIES, ("too many DMA segment entries\n")); - args->nsegs = nsegs; -} - -static void -ata_ahci_dmainit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - - ata_dmainit(dev); - /* note start and stop are not used here */ - ch->dma.setprd = ata_ahci_dmasetprd; - ch->dma.max_iosize = 8192 * DEV_BSIZE; - if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_64BIT) - ch->dma.max_address = BUS_SPACE_MAXADDR; -} - -static int -ata_ahci_setup_fis(struct ata_ahci_cmd_tab *ctp, struct ata_request *request) -{ - bzero(ctp->cfis, 64); - if (request->flags & ATA_R_ATAPI) { - bzero(ctp->acmd, 32); - bcopy(request->u.atapi.ccb, ctp->acmd, 16); - } - return ata_request2fis_h2d(request, &ctp->cfis[0]); -} - - -/* - * Acard chipset support functions - */ -int -ata_acard_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - static struct ata_chip_id ids[] = - {{ ATA_ATP850R, 0, ATPOLD, 0x00, ATA_UDMA2, "ATP850" }, - { ATA_ATP860A, 0, 0, 0x00, ATA_UDMA4, "ATP860A" }, - { ATA_ATP860R, 0, 0, 0x00, ATA_UDMA4, "ATP860R" }, - { ATA_ATP865A, 0, 0, 0x00, ATA_UDMA6, "ATP865A" }, - { ATA_ATP865R, 0, 0, 0x00, ATA_UDMA6, "ATP865R" }, - { 0, 0, 0, 0, 0, 0}}; - - if (!(ctlr->chip = ata_match_chip(dev, ids))) - return ENXIO; - - ata_set_desc(dev); - ctlr->chipinit = ata_acard_chipinit; - return 0; -} - -static int -ata_acard_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - ctlr->allocate = ata_acard_allocate; - if (ctlr->chip->cfg1 == ATPOLD) { - ctlr->setmode = ata_acard_850_setmode; - ctlr->locking = ata_serialize; - } - else - ctlr->setmode = ata_acard_86X_setmode; - return 0; -} - -static int -ata_acard_allocate(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - - /* setup the usual register normal pci style */ - if (ata_pci_allocate(dev)) - return ENXIO; - - ch->hw.status = ata_acard_status; - return 0; -} - -static int -ata_acard_status(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - - if (ctlr->chip->cfg1 == ATPOLD && - ATA_LOCKING(dev, ATA_LF_WHICH) != ch->unit) - return 0; - if (ch->dma.flags & ATA_DMA_ACTIVE) { - int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; - - if ((bmstat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) != - ATA_BMSTAT_INTERRUPT) - return 0; - ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR); - DELAY(1); - ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, - ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); - DELAY(1); - } - if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY) { - DELAY(100); - if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY) - return 0; - } - return 1; -} - -static void -ata_acard_850_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int error; - - mode = ata_limit_mode(dev, mode, - ata_atapi(dev) ? ATA_PIO_MAX : ctlr->chip->max_dma); - - /* XXX SOS missing WDMA0+1 + PIO modes */ - if (mode >= ATA_WDMA2) { - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { - u_int8_t reg54 = pci_read_config(gparent, 0x54, 1); - - reg54 &= ~(0x03 << (devno << 1)); - if (mode >= ATA_UDMA0) - reg54 |= (((mode & ATA_MODE_MASK) + 1) << (devno << 1)); - pci_write_config(gparent, 0x54, reg54, 1); - pci_write_config(gparent, 0x4a, 0xa6, 1); - pci_write_config(gparent, 0x40 + (devno << 1), 0x0301, 2); - atadev->mode = mode; - return; - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ -} - -static void -ata_acard_86X_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int error; - - - mode = ata_limit_mode(dev, mode, - ata_atapi(dev) ? ATA_PIO_MAX : ctlr->chip->max_dma); - - mode = ata_check_80pin(dev, mode); - - /* XXX SOS missing WDMA0+1 + PIO modes */ - if (mode >= ATA_WDMA2) { - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { - u_int16_t reg44 = pci_read_config(gparent, 0x44, 2); - - reg44 &= ~(0x000f << (devno << 2)); - if (mode >= ATA_UDMA0) - reg44 |= (((mode & ATA_MODE_MASK) + 1) << (devno << 2)); - pci_write_config(gparent, 0x44, reg44, 2); - pci_write_config(gparent, 0x4a, 0xa6, 1); - pci_write_config(gparent, 0x40 + devno, 0x31, 1); - atadev->mode = mode; - return; - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ -} - - -/* - * Acer Labs Inc (ALI) chipset support functions - */ -int -ata_ali_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - static struct ata_chip_id ids[] = - {{ ATA_ALI_5289, 0x00, 2, ALISATA, ATA_SA150, "M5289" }, - { ATA_ALI_5288, 0x00, 4, ALISATA, ATA_SA300, "M5288" }, - { ATA_ALI_5287, 0x00, 4, ALISATA, ATA_SA150, "M5287" }, - { ATA_ALI_5281, 0x00, 2, ALISATA, ATA_SA150, "M5281" }, - { ATA_ALI_5229, 0xc5, 0, ALINEW, ATA_UDMA6, "M5229" }, - { ATA_ALI_5229, 0xc4, 0, ALINEW, ATA_UDMA5, "M5229" }, - { ATA_ALI_5229, 0xc2, 0, ALINEW, ATA_UDMA4, "M5229" }, - { ATA_ALI_5229, 0x20, 0, ALIOLD, ATA_UDMA2, "M5229" }, - { ATA_ALI_5229, 0x00, 0, ALIOLD, ATA_WDMA2, "M5229" }, - { 0, 0, 0, 0, 0, 0}}; - - if (!(ctlr->chip = ata_match_chip(dev, ids))) - return ENXIO; - - ata_set_desc(dev); - ctlr->chipinit = ata_ali_chipinit; - return 0; -} - -static int -ata_ali_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - switch (ctlr->chip->cfg2) { - case ALISATA: - ctlr->channels = ctlr->chip->cfg1; - ctlr->allocate = ata_ali_sata_allocate; - ctlr->setmode = ata_sata_setmode; - - /* AHCI mode is correctly supported only on the ALi 5288. */ - if ((ctlr->chip->chipid == ATA_ALI_5288) && - (ata_ahci_chipinit(dev) != ENXIO)) - return 0; - - /* enable PCI interrupt */ - pci_write_config(dev, PCIR_COMMAND, - pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2); - break; - - case ALINEW: - /* use device interrupt as byte count end */ - pci_write_config(dev, 0x4a, pci_read_config(dev, 0x4a, 1) | 0x20, 1); - - /* enable cable detection and UDMA support on newer chips */ - pci_write_config(dev, 0x4b, pci_read_config(dev, 0x4b, 1) | 0x09, 1); - - /* enable ATAPI UDMA mode */ - pci_write_config(dev, 0x53, pci_read_config(dev, 0x53, 1) | 0x01, 1); - - /* only chips with revision > 0xc4 can do 48bit DMA */ - if (ctlr->chip->chiprev <= 0xc4) - device_printf(dev, - "using PIO transfers above 137GB as workaround for " - "48bit DMA access bug, expect reduced performance\n"); - ctlr->allocate = ata_ali_allocate; - ctlr->reset = ata_ali_reset; - ctlr->setmode = ata_ali_setmode; - break; - - case ALIOLD: - /* deactivate the ATAPI FIFO and enable ATAPI UDMA */ - pci_write_config(dev, 0x53, pci_read_config(dev, 0x53, 1) | 0x03, 1); - ctlr->setmode = ata_ali_setmode; - break; - } - return 0; -} - -static int -ata_ali_allocate(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - - /* setup the usual register normal pci style */ - if (ata_pci_allocate(dev)) - return ENXIO; - - /* older chips can't do 48bit DMA transfers */ - if (ctlr->chip->chiprev <= 0xc4) - ch->flags |= ATA_NO_48BIT_DMA; - - return 0; -} - -static int -ata_ali_sata_allocate(device_t dev) -{ - device_t parent = device_get_parent(dev); - struct ata_pci_controller *ctlr = device_get_softc(parent); - struct ata_channel *ch = device_get_softc(dev); - struct resource *io = NULL, *ctlio = NULL; - int unit01 = (ch->unit & 1), unit10 = (ch->unit & 2); - int i, rid; - - rid = PCIR_BAR(0) + (unit01 ? 8 : 0); - io = bus_alloc_resource_any(parent, SYS_RES_IOPORT, &rid, RF_ACTIVE); - if (!io) - return ENXIO; - - rid = PCIR_BAR(1) + (unit01 ? 8 : 0); - ctlio = bus_alloc_resource_any(parent, SYS_RES_IOPORT, &rid, RF_ACTIVE); - if (!ctlio) { - bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io); - return ENXIO; - } - - for (i = ATA_DATA; i <= ATA_COMMAND; i ++) { - ch->r_io[i].res = io; - ch->r_io[i].offset = i + (unit10 ? 8 : 0); - } - ch->r_io[ATA_CONTROL].res = ctlio; - ch->r_io[ATA_CONTROL].offset = 2 + (unit10 ? 4 : 0); - ch->r_io[ATA_IDX_ADDR].res = io; - ata_default_registers(dev); - if (ctlr->r_res1) { - for (i = ATA_BMCMD_PORT; i <= ATA_BMDTP_PORT; i++) { - ch->r_io[i].res = ctlr->r_res1; - ch->r_io[i].offset = (i - ATA_BMCMD_PORT)+(ch->unit * ATA_BMIOSIZE); - } - } - ch->flags |= ATA_NO_SLAVE; - - /* XXX SOS PHY handling awkward in ALI chip not supported yet */ - ata_pci_hw(dev); - return 0; -} - -static void -ata_ali_reset(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - device_t *children; - int nchildren, i; - - ata_generic_reset(dev); - - /* - * workaround for datacorruption bug found on at least SUN Blade-100 - * find the ISA function on the southbridge and disable then enable - * the ATA channel tristate buffer - */ - if (ctlr->chip->chiprev == 0xc3 || ctlr->chip->chiprev == 0xc2) { - if (!device_get_children(GRANDPARENT(dev), &children, &nchildren)) { - for (i = 0; i < nchildren; i++) { - if (pci_get_devid(children[i]) == ATA_ALI_1533) { - pci_write_config(children[i], 0x58, - pci_read_config(children[i], 0x58, 1) & - ~(0x04 << ch->unit), 1); - pci_write_config(children[i], 0x58, - pci_read_config(children[i], 0x58, 1) | - (0x04 << ch->unit), 1); - break; - } - } - free(children, M_TEMP); - } - } -} - -static void -ata_ali_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int error; - - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - if (ctlr->chip->cfg2 & ALINEW) { - if (mode > ATA_UDMA2 && - pci_read_config(gparent, 0x4a, 1) & (1 << ch->unit)) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - } - else - mode = ata_check_80pin(dev, mode); - - if (ctlr->chip->cfg2 & ALIOLD) { - /* doesn't support ATAPI DMA on write */ - ch->flags |= ATA_ATAPI_DMA_RO; - if (ch->devices & ATA_ATAPI_MASTER && ch->devices & ATA_ATAPI_SLAVE) { - /* doesn't support ATAPI DMA on two ATAPI devices */ - device_printf(dev, "two atapi devices on this channel, no DMA\n"); - mode = ata_limit_mode(dev, mode, ATA_PIO_MAX); - } - } - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { - if (mode >= ATA_UDMA0) { - u_int8_t udma[] = {0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x0f, 0x0d}; - u_int32_t word54 = pci_read_config(gparent, 0x54, 4); - - word54 &= ~(0x000f000f << (devno << 2)); - word54 |= (((udma[mode&ATA_MODE_MASK]<<16)|0x05)<<(devno<<2)); - pci_write_config(gparent, 0x54, word54, 4); - pci_write_config(gparent, 0x58 + (ch->unit << 2), - 0x00310001, 4); - } - else { - u_int32_t piotimings[] = - { 0x006d0003, 0x00580002, 0x00440001, 0x00330001, - 0x00310001, 0x00440001, 0x00330001, 0x00310001}; - - pci_write_config(gparent, 0x54, pci_read_config(gparent, 0x54, 4) & - ~(0x0008000f << (devno << 2)), 4); - pci_write_config(gparent, 0x58 + (ch->unit << 2), - piotimings[ata_mode2idx(mode)], 4); - } - atadev->mode = mode; - } -} - - -/* - * American Micro Devices (AMD) chipset support functions - */ -int -ata_amd_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - static struct ata_chip_id ids[] = - {{ ATA_AMD756, 0x00, AMDNVIDIA, 0x00, ATA_UDMA4, "756" }, - { ATA_AMD766, 0x00, AMDNVIDIA, AMDCABLE|AMDBUG, ATA_UDMA5, "766" }, - { ATA_AMD768, 0x00, AMDNVIDIA, AMDCABLE, ATA_UDMA5, "768" }, - { ATA_AMD8111, 0x00, AMDNVIDIA, AMDCABLE, ATA_UDMA6, "8111" }, - { ATA_AMD5536, 0x00, AMDNVIDIA, 0x00, ATA_UDMA5, "CS5536" }, - { 0, 0, 0, 0, 0, 0}}; - - if (!(ctlr->chip = ata_match_chip(dev, ids))) - return ENXIO; - - ata_set_desc(dev); - ctlr->chipinit = ata_amd_chipinit; - return 0; -} - -static int -ata_amd_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - /* disable/set prefetch, postwrite */ - if (ctlr->chip->cfg2 & AMDBUG) - pci_write_config(dev, 0x41, pci_read_config(dev, 0x41, 1) & 0x0f, 1); - else - pci_write_config(dev, 0x41, pci_read_config(dev, 0x41, 1) | 0xf0, 1); - - ctlr->setmode = ata_via_family_setmode; - return 0; -} - - -/* - * Adaptec chipset support functions - */ -int -ata_adaptec_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - static struct ata_chip_id ids[] = - {{ ATA_ADAPTEC_1420, 0, 4, MV60XX, ATA_SA300, "1420SA" }, - { 0, 0, 0, 0, 0, 0}}; - - if (!(ctlr->chip = ata_match_chip(dev, ids))) - return ENXIO; - - ata_set_desc(dev); - ctlr->chipinit = ata_marvell_edma_chipinit; - - return 0; -} - - -/* - * ATI chipset support functions - */ -int -ata_ati_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - static struct ata_chip_id ids[] = - {{ ATA_ATI_IXP200, 0x00, 0, ATIPATA, ATA_UDMA5, "IXP200" }, - { ATA_ATI_IXP300, 0x00, 0, ATIPATA, ATA_UDMA6, "IXP300" }, - { ATA_ATI_IXP300_S1, 0x00, 0, ATISATA, ATA_SA150, "IXP300" }, - { ATA_ATI_IXP400, 0x00, 0, ATIPATA, ATA_UDMA6, "IXP400" }, - { ATA_ATI_IXP400_S1, 0x00, 0, ATISATA, ATA_SA150, "IXP400" }, - { ATA_ATI_IXP400_S2, 0x00, 0, ATISATA, ATA_SA150, "IXP400" }, - { ATA_ATI_IXP600, 0x00, 0, ATIPATA, ATA_UDMA6, "IXP600" }, - { ATA_ATI_IXP600_S1, 0x00, 0, ATIAHCI, ATA_SA300, "IXP600" }, - { ATA_ATI_IXP700, 0x00, 0, ATIPATA, ATA_UDMA6, "IXP700" }, - { ATA_ATI_IXP700_S1, 0x00, 0, ATIAHCI, ATA_SA300, "IXP700" }, - { 0, 0, 0, 0, 0, 0}}; - - if (!(ctlr->chip = ata_match_chip(dev, ids))) - return ENXIO; - - ata_set_desc(dev); - - switch (ctlr->chip->cfg2) { - case ATIPATA: - ctlr->chipinit = ata_ati_chipinit; - break; - case ATISATA: - /* the ATI SATA controller is actually a SiI 3112 controller */ - ctlr->chip->cfg1 = SIIMEMIO; - ctlr->chipinit = ata_sii_chipinit; - break; - case ATIAHCI: - ctlr->chipinit = ata_ahci_chipinit; - break; - } - return 0; -} - -static int -ata_ati_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - /* IXP600 & IXP700 only have 1 PATA channel */ - if ((ctlr->chip->chipid == ATA_ATI_IXP600) || - (ctlr->chip->chipid == ATA_ATI_IXP700)) - ctlr->channels = 1; - - ctlr->setmode = ata_ati_setmode; - return 0; -} - -static void -ata_ati_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int offset = (devno ^ 0x01) << 3; - int error; - u_int8_t piotimings[] = { 0x5d, 0x47, 0x34, 0x22, 0x20, 0x34, 0x22, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; - u_int8_t dmatimings[] = { 0x77, 0x21, 0x20 }; - - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - mode = ata_check_80pin(dev, mode); - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { - if (mode >= ATA_UDMA0) { - pci_write_config(gparent, 0x56, - (pci_read_config(gparent, 0x56, 2) & - ~(0xf << (devno << 2))) | - ((mode & ATA_MODE_MASK) << (devno << 2)), 2); - pci_write_config(gparent, 0x54, - pci_read_config(gparent, 0x54, 1) | - (0x01 << devno), 1); - pci_write_config(gparent, 0x44, - (pci_read_config(gparent, 0x44, 4) & - ~(0xff << offset)) | - (dmatimings[2] << offset), 4); - } - else if (mode >= ATA_WDMA0) { - pci_write_config(gparent, 0x54, - pci_read_config(gparent, 0x54, 1) & - ~(0x01 << devno), 1); - pci_write_config(gparent, 0x44, - (pci_read_config(gparent, 0x44, 4) & - ~(0xff << offset)) | - (dmatimings[mode & ATA_MODE_MASK] << offset), 4); - } - else - pci_write_config(gparent, 0x54, - pci_read_config(gparent, 0x54, 1) & - ~(0x01 << devno), 1); - - pci_write_config(gparent, 0x4a, - (pci_read_config(gparent, 0x4a, 2) & - ~(0xf << (devno << 2))) | - (((mode - ATA_PIO0) & ATA_MODE_MASK) << (devno<<2)),2); - pci_write_config(gparent, 0x40, - (pci_read_config(gparent, 0x40, 4) & - ~(0xff << offset)) | - (piotimings[ata_mode2idx(mode)] << offset), 4); - atadev->mode = mode; - } -} - - -/* - * Cyrix chipset support functions - */ -int -ata_cyrix_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (pci_get_devid(dev) == ATA_CYRIX_5530) { - device_set_desc(dev, "Cyrix 5530 ATA33 controller"); - ctlr->chipinit = ata_cyrix_chipinit; - return 0; - } - return ENXIO; -} - -static int -ata_cyrix_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - if (ctlr->r_res1) - ctlr->setmode = ata_cyrix_setmode; - else - ctlr->setmode = ata_generic_setmode; - return 0; -} - -static void -ata_cyrix_setmode(device_t dev, int mode) -{ - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - u_int32_t piotiming[] = - { 0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010 }; - u_int32_t dmatiming[] = { 0x00077771, 0x00012121, 0x00002020 }; - u_int32_t udmatiming[] = { 0x00921250, 0x00911140, 0x00911030 }; - int error; - - ch->dma.alignment = 16; - ch->dma.max_iosize = 126 * DEV_BSIZE; - - mode = ata_limit_mode(dev, mode, ATA_UDMA2); - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on Cyrix chip\n", - (error) ? "FAILURE " : "", ata_mode2str(mode)); - if (!error) { - if (mode >= ATA_UDMA0) { - ATA_OUTL(ch->r_io[ATA_BMCMD_PORT].res, - 0x24 + (devno << 3), udmatiming[mode & ATA_MODE_MASK]); - } - else if (mode >= ATA_WDMA0) { - ATA_OUTL(ch->r_io[ATA_BMCMD_PORT].res, - 0x24 + (devno << 3), dmatiming[mode & ATA_MODE_MASK]); - } - else { - ATA_OUTL(ch->r_io[ATA_BMCMD_PORT].res, - 0x20 + (devno << 3), piotiming[mode & ATA_MODE_MASK]); - } - atadev->mode = mode; - } -} - - -/* - * Cypress chipset support functions - */ -int -ata_cypress_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - /* - * the Cypress chip is a mess, it contains two ATA functions, but - * both channels are visible on the first one. - * simply ignore the second function for now, as the right - * solution (ignoring the second channel on the first function) - * doesn't work with the crappy ATA interrupt setup on the alpha. - */ - if (pci_get_devid(dev) == ATA_CYPRESS_82C693 && - pci_get_function(dev) == 1 && - pci_get_subclass(dev) == PCIS_STORAGE_IDE) { - device_set_desc(dev, "Cypress 82C693 ATA controller"); - ctlr->chipinit = ata_cypress_chipinit; - return 0; - } - return ENXIO; -} - -static int -ata_cypress_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - ctlr->setmode = ata_cypress_setmode; - return 0; -} - -static void -ata_cypress_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int error; - - mode = ata_limit_mode(dev, mode, ATA_WDMA2); - - /* XXX SOS missing WDMA0+1 + PIO modes */ - if (mode == ATA_WDMA2) { - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - if (bootverbose) - device_printf(dev, "%ssetting WDMA2 on Cypress chip\n", - error ? "FAILURE " : ""); - if (!error) { - pci_write_config(gparent, ch->unit ? 0x4e : 0x4c, 0x2020, 2); - atadev->mode = mode; - return; - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ -} - - -/* - * HighPoint chipset support functions - */ -int -ata_highpoint_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - struct ata_chip_id *idx; - static struct ata_chip_id ids[] = - {{ ATA_HPT374, 0x07, HPT374, 0x00, ATA_UDMA6, "HPT374" }, - { ATA_HPT372, 0x02, HPT372, 0x00, ATA_UDMA6, "HPT372N" }, - { ATA_HPT372, 0x01, HPT372, 0x00, ATA_UDMA6, "HPT372" }, - { ATA_HPT371, 0x01, HPT372, 0x00, ATA_UDMA6, "HPT371" }, - { ATA_HPT366, 0x05, HPT372, 0x00, ATA_UDMA6, "HPT372" }, - { ATA_HPT366, 0x03, HPT370, 0x00, ATA_UDMA5, "HPT370" }, - { ATA_HPT366, 0x02, HPT366, 0x00, ATA_UDMA4, "HPT368" }, - { ATA_HPT366, 0x00, HPT366, HPTOLD, ATA_UDMA4, "HPT366" }, - { ATA_HPT302, 0x01, HPT372, 0x00, ATA_UDMA6, "HPT302" }, - { 0, 0, 0, 0, 0, 0}}; - char buffer[64]; - - if (!(idx = ata_match_chip(dev, ids))) - return ENXIO; - - strcpy(buffer, "HighPoint "); - strcat(buffer, idx->text); - if (idx->cfg1 == HPT374) { - if (pci_get_function(dev) == 0) - strcat(buffer, " (channel 0+1)"); - if (pci_get_function(dev) == 1) - strcat(buffer, " (channel 2+3)"); - } - sprintf(buffer, "%s %s controller", buffer, ata_mode2str(idx->max_dma)); - device_set_desc_copy(dev, buffer); - ctlr->chip = idx; - ctlr->chipinit = ata_highpoint_chipinit; - return 0; -} - -static int -ata_highpoint_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - if (ctlr->chip->cfg2 == HPTOLD) { - /* disable interrupt prediction */ - pci_write_config(dev, 0x51, (pci_read_config(dev, 0x51, 1) & ~0x80), 1); - } - else { - /* disable interrupt prediction */ - pci_write_config(dev, 0x51, (pci_read_config(dev, 0x51, 1) & ~0x03), 1); - pci_write_config(dev, 0x55, (pci_read_config(dev, 0x55, 1) & ~0x03), 1); - - /* enable interrupts */ - pci_write_config(dev, 0x5a, (pci_read_config(dev, 0x5a, 1) & ~0x10), 1); - - /* set clocks etc */ - if (ctlr->chip->cfg1 < HPT372) - pci_write_config(dev, 0x5b, 0x22, 1); - else - pci_write_config(dev, 0x5b, - (pci_read_config(dev, 0x5b, 1) & 0x01) | 0x20, 1); - } - ctlr->allocate = ata_highpoint_allocate; - ctlr->setmode = ata_highpoint_setmode; - return 0; -} - -static int -ata_highpoint_allocate(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - - /* setup the usual register normal pci style */ - if (ata_pci_allocate(dev)) - return ENXIO; - - ch->flags |= ATA_ALWAYS_DMASTAT; - return 0; -} - -static void -ata_highpoint_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int error; - u_int32_t timings33[][4] = { - /* HPT366 HPT370 HPT372 HPT374 mode */ - { 0x40d0a7aa, 0x06914e57, 0x0d029d5e, 0x0ac1f48a }, /* PIO 0 */ - { 0x40d0a7a3, 0x06914e43, 0x0d029d26, 0x0ac1f465 }, /* PIO 1 */ - { 0x40d0a753, 0x06514e33, 0x0c829ca6, 0x0a81f454 }, /* PIO 2 */ - { 0x40c8a742, 0x06514e22, 0x0c829c84, 0x0a81f443 }, /* PIO 3 */ - { 0x40c8a731, 0x06514e21, 0x0c829c62, 0x0a81f442 }, /* PIO 4 */ - { 0x20c8a797, 0x26514e97, 0x2c82922e, 0x228082ea }, /* MWDMA 0 */ - { 0x20c8a732, 0x26514e33, 0x2c829266, 0x22808254 }, /* MWDMA 1 */ - { 0x20c8a731, 0x26514e21, 0x2c829262, 0x22808242 }, /* MWDMA 2 */ - { 0x10c8a731, 0x16514e31, 0x1c829c62, 0x121882ea }, /* UDMA 0 */ - { 0x10cba731, 0x164d4e31, 0x1c9a9c62, 0x12148254 }, /* UDMA 1 */ - { 0x10caa731, 0x16494e31, 0x1c929c62, 0x120c8242 }, /* UDMA 2 */ - { 0x10cfa731, 0x166d4e31, 0x1c8e9c62, 0x128c8242 }, /* UDMA 3 */ - { 0x10c9a731, 0x16454e31, 0x1c8a9c62, 0x12ac8242 }, /* UDMA 4 */ - { 0, 0x16454e31, 0x1c8a9c62, 0x12848242 }, /* UDMA 5 */ - { 0, 0, 0x1c869c62, 0x12808242 } /* UDMA 6 */ - }; - - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - if (ctlr->chip->cfg1 == HPT366 && ata_atapi(dev)) - mode = ata_limit_mode(dev, mode, ATA_PIO_MAX); - - mode = ata_highpoint_check_80pin(dev, mode); - - /* - * most if not all HPT chips cant really handle that the device is - * running at ATA_UDMA6/ATA133 speed, so we cheat at set the device to - * a max of ATA_UDMA5/ATA100 to guard against suboptimal performance - */ - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, - ata_limit_mode(dev, mode, ATA_UDMA5)); - if (bootverbose) - device_printf(dev, "%ssetting %s on HighPoint chip\n", - (error) ? "FAILURE " : "", ata_mode2str(mode)); - if (!error) - pci_write_config(gparent, 0x40 + (devno << 2), - timings33[ata_mode2idx(mode)][ctlr->chip->cfg1], 4); - atadev->mode = mode; -} - -static int -ata_highpoint_check_80pin(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - u_int8_t reg, val, res; - - if (ctlr->chip->cfg1 == HPT374 && pci_get_function(gparent) == 1) { - reg = ch->unit ? 0x57 : 0x53; - val = pci_read_config(gparent, reg, 1); - pci_write_config(gparent, reg, val | 0x80, 1); - } - else { - reg = 0x5b; - val = pci_read_config(gparent, reg, 1); - pci_write_config(gparent, reg, val & 0xfe, 1); - } - res = pci_read_config(gparent, 0x5a, 1) & (ch->unit ? 0x1:0x2); - pci_write_config(gparent, reg, val, 1); - - if (mode > ATA_UDMA2 && res) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - return mode; -} - - -/* - * Intel chipset support functions - */ -int -ata_intel_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - static struct ata_chip_id ids[] = - {{ ATA_I82371FB, 0, 0, 2, ATA_WDMA2, "PIIX" }, - { ATA_I82371SB, 0, 0, 2, ATA_WDMA2, "PIIX3" }, - { ATA_I82371AB, 0, 0, 2, ATA_UDMA2, "PIIX4" }, - { ATA_I82443MX, 0, 0, 2, ATA_UDMA2, "PIIX4" }, - { ATA_I82451NX, 0, 0, 2, ATA_UDMA2, "PIIX4" }, - { ATA_I82801AB, 0, 0, 2, ATA_UDMA2, "ICH0" }, - { ATA_I82801AA, 0, 0, 2, ATA_UDMA4, "ICH" }, - { ATA_I82372FB, 0, 0, 2, ATA_UDMA4, "ICH" }, - { ATA_I82801BA, 0, 0, 2, ATA_UDMA5, "ICH2" }, - { ATA_I82801BA_1, 0, 0, 2, ATA_UDMA5, "ICH2" }, - { ATA_I82801CA, 0, 0, 2, ATA_UDMA5, "ICH3" }, - { ATA_I82801CA_1, 0, 0, 2, ATA_UDMA5, "ICH3" }, - { ATA_I82801DB, 0, 0, 2, ATA_UDMA5, "ICH4" }, - { ATA_I82801DB_1, 0, 0, 2, ATA_UDMA5, "ICH4" }, - { ATA_I82801EB, 0, 0, 2, ATA_UDMA5, "ICH5" }, - { ATA_I82801EB_S1, 0, 0, 2, ATA_SA150, "ICH5" }, - { ATA_I82801EB_R1, 0, 0, 2, ATA_SA150, "ICH5" }, - { ATA_I6300ESB, 0, 0, 2, ATA_UDMA5, "6300ESB" }, - { ATA_I6300ESB_S1, 0, 0, 2, ATA_SA150, "6300ESB" }, - { ATA_I6300ESB_R1, 0, 0, 2, ATA_SA150, "6300ESB" }, - { ATA_I82801FB, 0, 0, 2, ATA_UDMA5, "ICH6" }, - { ATA_I82801FB_S1, 0, AHCI, 0, ATA_SA150, "ICH6" }, - { ATA_I82801FB_R1, 0, AHCI, 0, ATA_SA150, "ICH6" }, - { ATA_I82801FBM, 0, AHCI, 0, ATA_SA150, "ICH6M" }, - { ATA_I82801GB, 0, 0, 1, ATA_UDMA5, "ICH7" }, - { ATA_I82801GB_S1, 0, AHCI, 0, ATA_SA300, "ICH7" }, - { ATA_I82801GB_R1, 0, AHCI, 0, ATA_SA300, "ICH7" }, - { ATA_I82801GB_AH, 0, AHCI, 0, ATA_SA300, "ICH7" }, - { ATA_I82801GBM_S1, 0, AHCI, 0, ATA_SA300, "ICH7M" }, - { ATA_I82801GBM_R1, 0, AHCI, 0, ATA_SA300, "ICH7M" }, - { ATA_I82801GBM_AH, 0, AHCI, 0, ATA_SA300, "ICH7M" }, - { ATA_I63XXESB2, 0, 0, 1, ATA_UDMA5, "63XXESB2" }, - { ATA_I63XXESB2_S1, 0, AHCI, 0, ATA_SA300, "63XXESB2" }, - { ATA_I63XXESB2_S2, 0, AHCI, 0, ATA_SA300, "63XXESB2" }, - { ATA_I63XXESB2_R1, 0, AHCI, 0, ATA_SA300, "63XXESB2" }, - { ATA_I63XXESB2_R2, 0, AHCI, 0, ATA_SA300, "63XXESB2" }, - { ATA_I82801HB_S1, 0, AHCI, 0, ATA_SA300, "ICH8" }, - { ATA_I82801HB_S2, 0, AHCI, 0, ATA_SA300, "ICH8" }, - { ATA_I82801HB_R1, 0, AHCI, 0, ATA_SA300, "ICH8" }, - { ATA_I82801HB_AH4, 0, AHCI, 0, ATA_SA300, "ICH8" }, - { ATA_I82801HB_AH6, 0, AHCI, 0, ATA_SA300, "ICH8" }, - { ATA_I82801HBM, 0, 0, 1, ATA_UDMA5, "ICH8M" }, - { ATA_I82801HBM_S1, 0, AHCI, 0, ATA_SA300, "ICH8M" }, - { ATA_I82801HBM_S2, 0, AHCI, 0, ATA_SA300, "ICH8M" }, - { ATA_I82801HBM_S3, 0, AHCI, 0, ATA_SA300, "ICH8M" }, - { ATA_I82801IB_S1, 0, AHCI, 0, ATA_SA300, "ICH9" }, - { ATA_I82801IB_S2, 0, AHCI, 0, ATA_SA300, "ICH9" }, - { ATA_I82801IB_AH2, 0, AHCI, 0, ATA_SA300, "ICH9" }, - { ATA_I82801IB_AH4, 0, AHCI, 0, ATA_SA300, "ICH9" }, - { ATA_I82801IB_AH6, 0, AHCI, 0, ATA_SA300, "ICH9" }, - { ATA_I82801IB_R1, 0, AHCI, 0, ATA_SA300, "ICH9" }, - { ATA_I82801JIB_S1, 0, AHCI, 0, ATA_SA300, "ICH10" }, - { ATA_I82801JIB_AH, 0, AHCI, 0, ATA_SA300, "ICH10" }, - { ATA_I82801JIB_R1, 0, AHCI, 0, ATA_SA300, "ICH10" }, - { ATA_I82801JIB_S2, 0, AHCI, 0, ATA_SA300, "ICH10" }, - { ATA_I82801JD_S1, 0, AHCI, 0, ATA_SA300, "ICH10" }, - { ATA_I82801JD_AH, 0, AHCI, 0, ATA_SA300, "ICH10" }, - { ATA_I82801JD_R1, 0, AHCI, 0, ATA_SA300, "ICH10" }, - { ATA_I82801JD_S2, 0, AHCI, 0, ATA_SA300, "ICH10" }, - { ATA_I31244, 0, 0, 2, ATA_SA150, "31244" }, - { 0, 0, 0, 0, 0, 0}}; - - if (!(ctlr->chip = ata_match_chip(dev, ids))) - return ENXIO; - - ata_set_desc(dev); - ctlr->chipinit = ata_intel_chipinit; - return 0; -} - -static int -ata_intel_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - /* good old PIIX needs special treatment (not implemented) */ - if (ctlr->chip->chipid == ATA_I82371FB) { - ctlr->setmode = ata_intel_old_setmode; - } - - /* the intel 31244 needs special care if in DPA mode */ - else if (ctlr->chip->chipid == ATA_I31244) { - if (pci_get_subclass(dev) != PCIS_STORAGE_IDE) { - ctlr->r_type2 = SYS_RES_MEMORY; - ctlr->r_rid2 = PCIR_BAR(0); - if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, - &ctlr->r_rid2, - RF_ACTIVE))) - return ENXIO; - ctlr->channels = 4; - ctlr->allocate = ata_intel_31244_allocate; - ctlr->reset = ata_intel_31244_reset; - } - ctlr->setmode = ata_sata_setmode; - } - - /* non SATA intel chips goes here */ - else if (ctlr->chip->max_dma < ATA_SA150) { - ctlr->channels = ctlr->chip->cfg2; - ctlr->allocate = ata_intel_allocate; - ctlr->setmode = ata_intel_new_setmode; - } - - /* SATA parts can be either compat or AHCI */ - else { - /* force all ports active "the legacy way" */ - pci_write_config(dev, 0x92, pci_read_config(dev, 0x92, 2) | 0x0f, 2); - - ctlr->allocate = ata_intel_allocate; - ctlr->reset = ata_intel_reset; - - /* - * if we have AHCI capability and AHCI or RAID mode enabled - * in BIOS we try for AHCI mode - */ - if ((ctlr->chip->cfg1 == AHCI) && - (pci_read_config(dev, 0x90, 1) & 0xc0) && - (ata_ahci_chipinit(dev) != ENXIO)) - return 0; - - /* if BAR(5) is IO it should point to SATA interface registers */ - ctlr->r_type2 = SYS_RES_IOPORT; - ctlr->r_rid2 = PCIR_BAR(5); - if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, - &ctlr->r_rid2, RF_ACTIVE))) - ctlr->setmode = ata_intel_sata_setmode; - else - ctlr->setmode = ata_sata_setmode; - - /* enable PCI interrupt */ - pci_write_config(dev, PCIR_COMMAND, - pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2); - } - return 0; -} - -static int -ata_intel_allocate(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - - /* setup the usual register normal pci style */ - if (ata_pci_allocate(dev)) - return ENXIO; - - /* if r_res2 is valid it points to SATA interface registers */ - if (ctlr->r_res2) { - ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2; - ch->r_io[ATA_IDX_ADDR].offset = 0x00; - ch->r_io[ATA_IDX_DATA].res = ctlr->r_res2; - ch->r_io[ATA_IDX_DATA].offset = 0x04; - } - - ch->flags |= ATA_ALWAYS_DMASTAT; - return 0; -} - -static void -ata_intel_reset(device_t dev) -{ - device_t parent = device_get_parent(dev); - struct ata_pci_controller *ctlr = device_get_softc(parent); - struct ata_channel *ch = device_get_softc(dev); - int mask, timeout; - - /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */ - if (ctlr->chip->cfg1) { - mask = (0x0005 << ch->unit); - } - else { - /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */ - if (pci_read_config(parent, 0x90, 1) & 0x04) - mask = 0x0003; - else { - mask = (0x0001 << ch->unit); - /* XXX SOS should be in intel_allocate if we grow it */ - ch->flags |= ATA_NO_SLAVE; - } - } - pci_write_config(parent, 0x92, pci_read_config(parent, 0x92, 2) & ~mask, 2); - DELAY(10); - pci_write_config(parent, 0x92, pci_read_config(parent, 0x92, 2) | mask, 2); - - /* wait up to 1 sec for "connect well" */ - for (timeout = 0; timeout < 100 ; timeout++) { - if (((pci_read_config(parent, 0x92, 2) & (mask << 4)) == (mask << 4)) && - (ATA_IDX_INB(ch, ATA_STATUS) != 0xff)) - break; - ata_udelay(10000); - } - ata_generic_reset(dev); -} - -static void -ata_intel_old_setmode(device_t dev, int mode) -{ - /* NOT YET */ -} - -static void -ata_intel_new_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - u_int32_t reg40 = pci_read_config(gparent, 0x40, 4); - u_int8_t reg44 = pci_read_config(gparent, 0x44, 1); - u_int8_t reg48 = pci_read_config(gparent, 0x48, 1); - u_int16_t reg4a = pci_read_config(gparent, 0x4a, 2); - u_int16_t reg54 = pci_read_config(gparent, 0x54, 2); - u_int32_t mask40 = 0, new40 = 0; - u_int8_t mask44 = 0, new44 = 0; - int error; - u_int8_t timings[] = { 0x00, 0x00, 0x10, 0x21, 0x23, 0x10, 0x21, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23 }; - - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - if ( mode > ATA_UDMA2 && !(reg54 & (0x10 << devno))) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { - if (mode >= ATA_UDMA0) { - u_int8_t utimings[] = { 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10 }; - - pci_write_config(gparent, 0x48, reg48 | (0x0001 << devno), 2); - pci_write_config(gparent, 0x4a, - (reg4a & ~(0x3 << (devno << 2))) | - (utimings[mode & ATA_MODE_MASK] << (devno<<2)), 2); - } - else { - pci_write_config(gparent, 0x48, reg48 & ~(0x0001 << devno), 2); - pci_write_config(gparent, 0x4a, (reg4a & ~(0x3 << (devno << 2))),2); - } - reg54 |= 0x0400; - if (mode >= ATA_UDMA2) - reg54 |= (0x1 << devno); - else - reg54 &= ~(0x1 << devno); - if (mode >= ATA_UDMA5) - reg54 |= (0x1000 << devno); - else - reg54 &= ~(0x1000 << devno); - - pci_write_config(gparent, 0x54, reg54, 2); - - reg40 &= ~0x00ff00ff; - reg40 |= 0x40774077; - - if (atadev->unit == ATA_MASTER) { - mask40 = 0x3300; - new40 = timings[ata_mode2idx(mode)] << 8; - } - else { - mask44 = 0x0f; - new44 = ((timings[ata_mode2idx(mode)] & 0x30) >> 2) | - (timings[ata_mode2idx(mode)] & 0x03); - } - if (ch->unit) { - mask40 <<= 16; - new40 <<= 16; - mask44 <<= 4; - new44 <<= 4; - } - pci_write_config(gparent, 0x40, (reg40 & ~mask40) | new40, 4); - pci_write_config(gparent, 0x44, (reg44 & ~mask44) | new44, 1); - - atadev->mode = mode; - } -} - -static void -ata_intel_sata_setmode(device_t dev, int mode) -{ - struct ata_device *atadev = device_get_softc(dev); - - if (atadev->param.satacapabilities != 0x0000 && - atadev->param.satacapabilities != 0xffff) { - - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - int devno = (ch->unit << 1) + atadev->unit; - - /* on some drives we need to set the transfer mode */ - ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, - ata_limit_mode(dev, mode, ATA_UDMA6)); - - /* set ATA_SSTATUS register offset */ - ATA_IDX_OUTL(ch, ATA_IDX_ADDR, devno * 0x100); - - /* query SATA STATUS for the speed */ - if ((ATA_IDX_INL(ch, ATA_IDX_DATA) & ATA_SS_CONWELL_MASK) == - ATA_SS_CONWELL_GEN2) - atadev->mode = ATA_SA300; - else - atadev->mode = ATA_SA150; - } - else { - mode = ata_limit_mode(dev, mode, ATA_UDMA5); - if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) - atadev->mode = mode; - } -} - -static int -ata_intel_31244_allocate(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int i; - int ch_offset; - - ch_offset = 0x200 + ch->unit * 0x200; - - for (i = ATA_DATA; i < ATA_MAX_RES; i++) - ch->r_io[i].res = ctlr->r_res2; - - /* setup ATA registers */ - ch->r_io[ATA_DATA].offset = ch_offset + 0x00; - ch->r_io[ATA_FEATURE].offset = ch_offset + 0x06; - ch->r_io[ATA_COUNT].offset = ch_offset + 0x08; - ch->r_io[ATA_SECTOR].offset = ch_offset + 0x0c; - ch->r_io[ATA_CYL_LSB].offset = ch_offset + 0x10; - ch->r_io[ATA_CYL_MSB].offset = ch_offset + 0x14; - ch->r_io[ATA_DRIVE].offset = ch_offset + 0x18; - ch->r_io[ATA_COMMAND].offset = ch_offset + 0x1d; - ch->r_io[ATA_ERROR].offset = ch_offset + 0x04; - ch->r_io[ATA_STATUS].offset = ch_offset + 0x1c; - ch->r_io[ATA_ALTSTAT].offset = ch_offset + 0x28; - ch->r_io[ATA_CONTROL].offset = ch_offset + 0x29; - - /* setup DMA registers */ - ch->r_io[ATA_SSTATUS].offset = ch_offset + 0x100; - ch->r_io[ATA_SERROR].offset = ch_offset + 0x104; - ch->r_io[ATA_SCONTROL].offset = ch_offset + 0x108; - - /* setup SATA registers */ - ch->r_io[ATA_BMCMD_PORT].offset = ch_offset + 0x70; - ch->r_io[ATA_BMSTAT_PORT].offset = ch_offset + 0x72; - ch->r_io[ATA_BMDTP_PORT].offset = ch_offset + 0x74; - - ch->flags |= ATA_NO_SLAVE; - ata_pci_hw(dev); - ch->hw.status = ata_intel_31244_status; - ch->hw.tf_write = ata_intel_31244_tf_write; - - /* enable PHY state change interrupt */ - ATA_OUTL(ctlr->r_res2, 0x4, - ATA_INL(ctlr->r_res2, 0x04) | (0x01 << (ch->unit << 3))); - return 0; -} - -static int -ata_intel_31244_status(device_t dev) -{ - /* do we have any PHY events ? */ - ata_sata_phy_check_events(dev); - - /* any drive action to take care of ? */ - return ata_pci_status(dev); -} - -static void -ata_intel_31244_tf_write(struct ata_request *request) -{ - struct ata_channel *ch = device_get_softc(device_get_parent(request->dev)); - struct ata_device *atadev = device_get_softc(request->dev); - - if (atadev->flags & ATA_D_48BIT_ACTIVE) { - ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature); - ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count); - ATA_IDX_OUTW(ch, ATA_SECTOR, ((request->u.ata.lba >> 16) & 0xff00) | - (request->u.ata.lba & 0x00ff)); - ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((request->u.ata.lba >> 24) & 0xff00) | - ((request->u.ata.lba >> 8) & 0x00ff)); - ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((request->u.ata.lba >> 32) & 0xff00) | - ((request->u.ata.lba >> 16) & 0x00ff)); - ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(atadev->unit)); - } - else { - ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature); - ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count); - if (atadev->flags & ATA_D_USE_CHS) { - int heads, sectors; - - if (atadev->param.atavalid & ATA_FLAG_54_58) { - heads = atadev->param.current_heads; - sectors = atadev->param.current_sectors; - } - else { - heads = atadev->param.heads; - sectors = atadev->param.sectors; - } - ATA_IDX_OUTB(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1); - ATA_IDX_OUTB(ch, ATA_CYL_LSB, - (request->u.ata.lba / (sectors * heads))); - ATA_IDX_OUTB(ch, ATA_CYL_MSB, - (request->u.ata.lba / (sectors * heads)) >> 8); - ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit) | - (((request->u.ata.lba% (sectors * heads)) / - sectors) & 0xf)); - } - else { - ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba); - ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8); - ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16); - ATA_IDX_OUTB(ch, ATA_DRIVE, - ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit) | - ((request->u.ata.lba >> 24) & 0x0f)); - } - } -} - -static void -ata_intel_31244_reset(device_t dev) -{ - if (ata_sata_phy_reset(dev)) - ata_generic_reset(dev); -} - - -/* - * Integrated Technology Express Inc. (ITE) chipset support functions - */ -int -ata_ite_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - static struct ata_chip_id ids[] = - {{ ATA_IT8213F, 0x00, 0x00, 0x00, ATA_UDMA6, "IT8213F" }, - { ATA_IT8212F, 0x00, 0x00, 0x00, ATA_UDMA6, "IT8212F" }, - { ATA_IT8211F, 0x00, 0x00, 0x00, ATA_UDMA6, "IT8211F" }, - { 0, 0, 0, 0, 0, 0}}; - - if (!(ctlr->chip = ata_match_chip(dev, ids))) - return ENXIO; - - ata_set_desc(dev); - ctlr->chipinit = ata_ite_chipinit; - return 0; -} - -static int -ata_ite_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - if (ctlr->chip->chipid == ATA_IT8213F) { - /* the ITE 8213F only has one channel */ - ctlr->channels = 1; - - ctlr->setmode = ata_ite_8213_setmode; - } - else { - /* set PCI mode and 66Mhz reference clock */ - pci_write_config(dev, 0x50, pci_read_config(dev, 0x50, 1) & ~0x83, 1); - - /* set default active & recover timings */ - pci_write_config(dev, 0x54, 0x31, 1); - pci_write_config(dev, 0x56, 0x31, 1); - - ctlr->setmode = ata_ite_821x_setmode; - } - - return 0; -} - -static void -ata_ite_821x_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int error; - - /* correct the mode for what the HW supports */ - mode = ata_limit_mode(dev, mode, ATA_UDMA6); - - /* check the CBLID bits for 80 conductor cable detection */ - if (mode > ATA_UDMA2 && (pci_read_config(gparent, 0x40, 2) & - (ch->unit ? (1<<3) : (1<<2)))) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - - /* set the wanted mode on the device */ - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%s setting %s on ITE8212F chip\n", - (error) ? "failed" : "success", ata_mode2str(mode)); - - /* if the device accepted the mode change, setup the HW accordingly */ - if (!error) { - if (mode >= ATA_UDMA0) { - u_int8_t udmatiming[] = - { 0x44, 0x42, 0x31, 0x21, 0x11, 0xa2, 0x91 }; - - /* enable UDMA mode */ - pci_write_config(gparent, 0x50, - pci_read_config(gparent, 0x50, 1) & - ~(1 << (devno + 3)), 1); - - /* set UDMA timing */ - pci_write_config(gparent, - 0x56 + (ch->unit << 2) + atadev->unit, - udmatiming[mode & ATA_MODE_MASK], 1); - } - else { - u_int8_t chtiming[] = - { 0xaa, 0xa3, 0xa1, 0x33, 0x31, 0x88, 0x32, 0x31 }; - - /* disable UDMA mode */ - pci_write_config(gparent, 0x50, - pci_read_config(gparent, 0x50, 1) | - (1 << (devno + 3)), 1); - - /* set active and recover timing (shared between master & slave) */ - if (pci_read_config(gparent, 0x54 + (ch->unit << 2), 1) < - chtiming[ata_mode2idx(mode)]) - pci_write_config(gparent, 0x54 + (ch->unit << 2), - chtiming[ata_mode2idx(mode)], 1); - } - atadev->mode = mode; - } -} - -static void -ata_ite_8213_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_device *atadev = device_get_softc(dev); - u_int16_t reg40 = pci_read_config(gparent, 0x40, 2); - u_int8_t reg44 = pci_read_config(gparent, 0x44, 1); - u_int8_t reg48 = pci_read_config(gparent, 0x48, 1); - u_int16_t reg4a = pci_read_config(gparent, 0x4a, 2); - u_int16_t reg54 = pci_read_config(gparent, 0x54, 2); - u_int16_t mask40 = 0, new40 = 0; - u_int8_t mask44 = 0, new44 = 0; - int devno = atadev->unit; - int error; - u_int8_t timings[] = { 0x00, 0x00, 0x10, 0x21, 0x23, 0x10, 0x21, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23 }; - - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - if (mode > ATA_UDMA2 && !(reg54 & (0x10 << devno))) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { - if (mode >= ATA_UDMA0) { - u_int8_t utimings[] = { 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10 }; - - pci_write_config(gparent, 0x48, reg48 | (0x0001 << devno), 2); - pci_write_config(gparent, 0x4a, - (reg4a & ~(0x3 << (devno << 2))) | - (utimings[mode & ATA_MODE_MASK] << (devno<<2)), 2); - } - else { - pci_write_config(gparent, 0x48, reg48 & ~(0x0001 << devno), 2); - pci_write_config(gparent, 0x4a, (reg4a & ~(0x3 << (devno << 2))),2); - } - if (mode >= ATA_UDMA2) - reg54 |= (0x1 << devno); - else - reg54 &= ~(0x1 << devno); - if (mode >= ATA_UDMA5) - reg54 |= (0x1000 << devno); - else - reg54 &= ~(0x1000 << devno); - pci_write_config(gparent, 0x54, reg54, 2); - - reg40 &= 0xff00; - reg40 |= 0x4033; - if (atadev->unit == ATA_MASTER) { - reg40 |= (ata_atapi(dev) ? 0x04 : 0x00); - mask40 = 0x3300; - new40 = timings[ata_mode2idx(mode)] << 8; - } - else { - reg40 |= (ata_atapi(dev) ? 0x40 : 0x00); - mask44 = 0x0f; - new44 = ((timings[ata_mode2idx(mode)] & 0x30) >> 2) | - (timings[ata_mode2idx(mode)] & 0x03); - } - pci_write_config(gparent, 0x40, (reg40 & ~mask40) | new40, 4); - pci_write_config(gparent, 0x44, (reg44 & ~mask44) | new44, 1); - - atadev->mode = mode; - } -} - - -/* - * JMicron chipset support functions - */ -int -ata_jmicron_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - struct ata_chip_id *idx; - static struct ata_chip_id ids[] = - {{ ATA_JMB360, 0, 1, 0, ATA_SA300, "JMB360" }, - { ATA_JMB361, 0, 1, 1, ATA_SA300, "JMB361" }, - { ATA_JMB363, 0, 2, 1, ATA_SA300, "JMB363" }, - { ATA_JMB365, 0, 1, 2, ATA_SA300, "JMB365" }, - { ATA_JMB366, 0, 2, 2, ATA_SA300, "JMB366" }, - { ATA_JMB368, 0, 0, 1, ATA_UDMA6, "JMB368" }, - { 0, 0, 0, 0, 0, 0}}; - char buffer[64]; - - if (!(idx = ata_match_chip(dev, ids))) - return ENXIO; - - if ((pci_read_config(dev, 0xdf, 1) & 0x40) && - (pci_get_function(dev) == (pci_read_config(dev, 0x40, 1) & 0x02 >> 1))) - sprintf(buffer, "JMicron %s %s controller", - idx->text, ata_mode2str(ATA_UDMA6)); - else - sprintf(buffer, "JMicron %s %s controller", - idx->text, ata_mode2str(idx->max_dma)); - device_set_desc_copy(dev, buffer); - ctlr->chip = idx; - ctlr->chipinit = ata_jmicron_chipinit; - return 0; -} - -static int -ata_jmicron_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - int error; - - if (ata_setup_interrupt(dev)) - return ENXIO; - - /* do we have multiple PCI functions ? */ - if (pci_read_config(dev, 0xdf, 1) & 0x40) { - /* are we on the AHCI part ? */ - if (ata_ahci_chipinit(dev) != ENXIO) - return 0; - - /* otherwise we are on the PATA part */ - ctlr->allocate = ata_pci_allocate; - ctlr->reset = ata_generic_reset; - ctlr->dmainit = ata_pci_dmainit; - ctlr->setmode = ata_jmicron_setmode; - ctlr->channels = ctlr->chip->cfg2; - } - else { - /* set controller configuration to a combined setup we support */ - pci_write_config(dev, 0x40, 0x80c0a131, 4); - pci_write_config(dev, 0x80, 0x01200000, 4); - - if (ctlr->chip->cfg1 && (error = ata_ahci_chipinit(dev))) - return error; - - ctlr->allocate = ata_jmicron_allocate; - ctlr->reset = ata_jmicron_reset; - ctlr->dmainit = ata_jmicron_dmainit; - ctlr->setmode = ata_jmicron_setmode; - - /* set the number of HW channels */ - ctlr->channels = ctlr->chip->cfg1 + ctlr->chip->cfg2; - } - return 0; -} - -static int -ata_jmicron_allocate(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int error; - - if (ch->unit >= ctlr->chip->cfg1) { - ch->unit -= ctlr->chip->cfg1; - error = ata_pci_allocate(dev); - ch->unit += ctlr->chip->cfg1; - } - else - error = ata_ahci_allocate(dev); - return error; -} - -static void -ata_jmicron_reset(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - - if (ch->unit >= ctlr->chip->cfg1) - ata_generic_reset(dev); - else - ata_ahci_reset(dev); -} - -static void -ata_jmicron_dmainit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - - if (ch->unit >= ctlr->chip->cfg1) - ata_pci_dmainit(dev); - else - ata_ahci_dmainit(dev); -} - -static void -ata_jmicron_setmode(device_t dev, int mode) -{ - struct ata_pci_controller *ctlr = device_get_softc(GRANDPARENT(dev)); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - - if (pci_read_config(dev, 0xdf, 1) & 0x40 || ch->unit >= ctlr->chip->cfg1) { - struct ata_device *atadev = device_get_softc(dev); - - /* check for 80pin cable present */ - if (pci_read_config(dev, 0x40, 1) & 0x08) - mode = ata_limit_mode(dev, mode, ATA_UDMA2); - else - mode = ata_limit_mode(dev, mode, ATA_UDMA6); - - if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) - atadev->mode = mode; - } - else - ata_sata_setmode(dev, mode); -} - - -/* - * Marvell chipset support functions - */ -#define ATA_MV_HOST_BASE(ch) \ - ((ch->unit & 3) * 0x0100) + (ch->unit > 3 ? 0x30000 : 0x20000) -#define ATA_MV_EDMA_BASE(ch) \ - ((ch->unit & 3) * 0x2000) + (ch->unit > 3 ? 0x30000 : 0x20000) - -struct ata_marvell_response { - u_int16_t tag; - u_int8_t edma_status; - u_int8_t dev_status; - u_int32_t timestamp; -}; - -struct ata_marvell_dma_prdentry { - u_int32_t addrlo; - u_int32_t count; - u_int32_t addrhi; - u_int32_t reserved; -}; - -int -ata_marvell_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - static struct ata_chip_id ids[] = - {{ ATA_M88SX5040, 0, 4, MV50XX, ATA_SA150, "88SX5040" }, - { ATA_M88SX5041, 0, 4, MV50XX, ATA_SA150, "88SX5041" }, - { ATA_M88SX5080, 0, 8, MV50XX, ATA_SA150, "88SX5080" }, - { ATA_M88SX5081, 0, 8, MV50XX, ATA_SA150, "88SX5081" }, - { ATA_M88SX6041, 0, 4, MV60XX, ATA_SA300, "88SX6041" }, - { ATA_M88SX6081, 0, 8, MV60XX, ATA_SA300, "88SX6081" }, - { ATA_M88SX6101, 0, 1, MV61XX, ATA_UDMA6, "88SX6101" }, - { ATA_M88SX6145, 0, 2, MV61XX, ATA_UDMA6, "88SX6145" }, - { 0, 0, 0, 0, 0, 0}}; - - if (!(ctlr->chip = ata_match_chip(dev, ids))) - return ENXIO; - - ata_set_desc(dev); - - switch (ctlr->chip->cfg2) { - case MV50XX: - case MV60XX: - ctlr->chipinit = ata_marvell_edma_chipinit; - break; - case MV61XX: - ctlr->chipinit = ata_marvell_pata_chipinit; - break; - } - return 0; -} - -static int -ata_marvell_pata_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - ctlr->allocate = ata_marvell_pata_allocate; - ctlr->setmode = ata_marvell_pata_setmode; - ctlr->channels = ctlr->chip->cfg1; - return 0; -} - -static int -ata_marvell_pata_allocate(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - - /* setup the usual register normal pci style */ - if (ata_pci_allocate(dev)) - return ENXIO; - - /* dont use 32 bit PIO transfers */ - ch->flags |= ATA_USE_16BIT; - - return 0; -} - -static void -ata_marvell_pata_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_device *atadev = device_get_softc(dev); - - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - mode = ata_check_80pin(dev, mode); - if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) - atadev->mode = mode; -} - -static int -ata_marvell_edma_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - ctlr->r_type1 = SYS_RES_MEMORY; - ctlr->r_rid1 = PCIR_BAR(0); - if (!(ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1, - &ctlr->r_rid1, RF_ACTIVE))) - return ENXIO; - - /* mask all host controller interrupts */ - ATA_OUTL(ctlr->r_res1, 0x01d64, 0x00000000); - - /* mask all PCI interrupts */ - ATA_OUTL(ctlr->r_res1, 0x01d5c, 0x00000000); - - ctlr->allocate = ata_marvell_edma_allocate; - ctlr->reset = ata_marvell_edma_reset; - ctlr->dmainit = ata_marvell_edma_dmainit; - ctlr->setmode = ata_sata_setmode; - ctlr->channels = ctlr->chip->cfg1; - - /* clear host controller interrupts */ - ATA_OUTL(ctlr->r_res1, 0x20014, 0x00000000); - if (ctlr->chip->cfg1 > 4) - ATA_OUTL(ctlr->r_res1, 0x30014, 0x00000000); - - /* clear PCI interrupts */ - ATA_OUTL(ctlr->r_res1, 0x01d58, 0x00000000); - - /* unmask PCI interrupts we want */ - ATA_OUTL(ctlr->r_res1, 0x01d5c, 0x007fffff); - - /* unmask host controller interrupts we want */ - ATA_OUTL(ctlr->r_res1, 0x01d64, 0x000000ff/*HC0*/ | 0x0001fe00/*HC1*/ | - /*(1<<19) | (1<<20) | (1<<21) |*/(1<<22) | (1<<24) | (0x7f << 25)); - - /* enable PCI interrupt */ - pci_write_config(dev, PCIR_COMMAND, - pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2); - return 0; -} - -static int -ata_marvell_edma_allocate(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - u_int64_t work = ch->dma.work_bus; - int i; - - /* clear work area */ - bzero(ch->dma.work, 1024+256); - - /* set legacy ATA resources */ - for (i = ATA_DATA; i <= ATA_COMMAND; i++) { - ch->r_io[i].res = ctlr->r_res1; - ch->r_io[i].offset = 0x02100 + (i << 2) + ATA_MV_EDMA_BASE(ch); - } - ch->r_io[ATA_CONTROL].res = ctlr->r_res1; - ch->r_io[ATA_CONTROL].offset = 0x02120 + ATA_MV_EDMA_BASE(ch); - ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res1; - ata_default_registers(dev); - - /* set SATA resources */ - switch (ctlr->chip->cfg2) { - case MV50XX: - ch->r_io[ATA_SSTATUS].res = ctlr->r_res1; - ch->r_io[ATA_SSTATUS].offset = 0x00100 + ATA_MV_HOST_BASE(ch); - ch->r_io[ATA_SERROR].res = ctlr->r_res1; - ch->r_io[ATA_SERROR].offset = 0x00104 + ATA_MV_HOST_BASE(ch); - ch->r_io[ATA_SCONTROL].res = ctlr->r_res1; - ch->r_io[ATA_SCONTROL].offset = 0x00108 + ATA_MV_HOST_BASE(ch); - break; - case MV60XX: - ch->r_io[ATA_SSTATUS].res = ctlr->r_res1; - ch->r_io[ATA_SSTATUS].offset = 0x02300 + ATA_MV_EDMA_BASE(ch); - ch->r_io[ATA_SERROR].res = ctlr->r_res1; - ch->r_io[ATA_SERROR].offset = 0x02304 + ATA_MV_EDMA_BASE(ch); - ch->r_io[ATA_SCONTROL].res = ctlr->r_res1; - ch->r_io[ATA_SCONTROL].offset = 0x02308 + ATA_MV_EDMA_BASE(ch); - ch->r_io[ATA_SACTIVE].res = ctlr->r_res1; - ch->r_io[ATA_SACTIVE].offset = 0x02350 + ATA_MV_EDMA_BASE(ch); - break; - } - - ch->flags |= ATA_NO_SLAVE; - ch->flags |= ATA_USE_16BIT; /* XXX SOS needed ? */ - ata_generic_hw(dev); - ch->hw.begin_transaction = ata_marvell_edma_begin_transaction; - ch->hw.end_transaction = ata_marvell_edma_end_transaction; - ch->hw.status = ata_marvell_edma_status; - - /* disable the EDMA machinery */ - ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000002); - DELAY(100000); /* SOS should poll for disabled */ - - /* set configuration to non-queued 128b read transfers stop on error */ - ATA_OUTL(ctlr->r_res1, 0x02000 + ATA_MV_EDMA_BASE(ch), (1<<11) | (1<<13)); - - /* request queue base high */ - ATA_OUTL(ctlr->r_res1, 0x02010 + ATA_MV_EDMA_BASE(ch), work >> 32); - - /* request queue in ptr */ - ATA_OUTL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch), work & 0xffffffff); - - /* request queue out ptr */ - ATA_OUTL(ctlr->r_res1, 0x02018 + ATA_MV_EDMA_BASE(ch), 0x0); - - /* response queue base high */ - work += 1024; - ATA_OUTL(ctlr->r_res1, 0x0201c + ATA_MV_EDMA_BASE(ch), work >> 32); - - /* response queue in ptr */ - ATA_OUTL(ctlr->r_res1, 0x02020 + ATA_MV_EDMA_BASE(ch), 0x0); - - /* response queue out ptr */ - ATA_OUTL(ctlr->r_res1, 0x02024 + ATA_MV_EDMA_BASE(ch), work & 0xffffffff); - - /* clear SATA error register */ - ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR)); - - /* clear any outstanding error interrupts */ - ATA_OUTL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch), 0x0); - - /* unmask all error interrupts */ - ATA_OUTL(ctlr->r_res1, 0x0200c + ATA_MV_EDMA_BASE(ch), ~0x0); - - /* enable EDMA machinery */ - ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000001); - return 0; -} - -static int -ata_marvell_edma_status(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - u_int32_t cause = ATA_INL(ctlr->r_res1, 0x01d60); - int shift = (ch->unit << 1) + (ch->unit > 3); - - if (cause & (1 << shift)) { - - /* clear interrupt(s) */ - ATA_OUTL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch), 0x0); - - /* do we have any PHY events ? */ - ata_sata_phy_check_events(dev); - } - - /* do we have any device action ? */ - return (cause & (2 << shift)); -} - -/* must be called with ATA channel locked and state_mtx held */ -static int -ata_marvell_edma_begin_transaction(struct ata_request *request) -{ - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); - struct ata_channel *ch = device_get_softc(request->parent); - u_int32_t req_in; - u_int8_t *bytep; - u_int16_t *wordp; - u_int32_t *quadp; - int i; - int error, slot; - - /* only DMA R/W goes through the EMDA machine */ - if (request->u.ata.command != ATA_READ_DMA && - request->u.ata.command != ATA_WRITE_DMA) { - - /* disable the EDMA machinery */ - if (ATA_INL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001) - ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000002); - return ata_begin_transaction(request); - } - - /* check for 48 bit access and convert if needed */ - ata_modify_if_48bit(request); - - /* check sanity, setup SG list and DMA engine */ - if ((error = ch->dma.load(request, NULL, NULL))) { - device_printf(request->dev, "setting up DMA failed\n"); - request->result = error; - return ATA_OP_FINISHED; - } - - /* get next free request queue slot */ - req_in = ATA_INL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch)); - slot = (((req_in & ~0xfffffc00) >> 5) + 0) & 0x1f; - bytep = (u_int8_t *)(ch->dma.work); - bytep += (slot << 5); - wordp = (u_int16_t *)bytep; - quadp = (u_int32_t *)bytep; - - /* fill in this request */ - quadp[0] = (long)request->dma->sg_bus & 0xffffffff; - quadp[1] = (u_int64_t)request->dma->sg_bus >> 32; - wordp[4] = (request->flags & ATA_R_READ ? 0x01 : 0x00) | (request->tag<<1); - - i = 10; - bytep[i++] = (request->u.ata.count >> 8) & 0xff; - bytep[i++] = 0x10 | ATA_COUNT; - bytep[i++] = request->u.ata.count & 0xff; - bytep[i++] = 0x10 | ATA_COUNT; - - bytep[i++] = (request->u.ata.lba >> 24) & 0xff; - bytep[i++] = 0x10 | ATA_SECTOR; - bytep[i++] = request->u.ata.lba & 0xff; - bytep[i++] = 0x10 | ATA_SECTOR; - - bytep[i++] = (request->u.ata.lba >> 32) & 0xff; - bytep[i++] = 0x10 | ATA_CYL_LSB; - bytep[i++] = (request->u.ata.lba >> 8) & 0xff; - bytep[i++] = 0x10 | ATA_CYL_LSB; - - bytep[i++] = (request->u.ata.lba >> 40) & 0xff; - bytep[i++] = 0x10 | ATA_CYL_MSB; - bytep[i++] = (request->u.ata.lba >> 16) & 0xff; - bytep[i++] = 0x10 | ATA_CYL_MSB; - - bytep[i++] = ATA_D_LBA | ATA_D_IBM | ((request->u.ata.lba >> 24) & 0xf); - bytep[i++] = 0x10 | ATA_DRIVE; - - bytep[i++] = request->u.ata.command; - bytep[i++] = 0x90 | ATA_COMMAND; - - /* enable EDMA machinery if needed */ - if (!(ATA_INL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001)) { - ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000001); - while (!(ATA_INL(ctlr->r_res1, - 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001)) - DELAY(10); - } - - /* tell EDMA it has a new request */ - slot = (((req_in & ~0xfffffc00) >> 5) + 1) & 0x1f; - req_in &= 0xfffffc00; - req_in += (slot << 5); - ATA_OUTL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch), req_in); - - return ATA_OP_CONTINUES; -} - -/* must be called with ATA channel locked and state_mtx held */ -static int -ata_marvell_edma_end_transaction(struct ata_request *request) -{ - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); - struct ata_channel *ch = device_get_softc(request->parent); - int offset = (ch->unit > 3 ? 0x30014 : 0x20014); - u_int32_t icr = ATA_INL(ctlr->r_res1, offset); - int res; - - /* EDMA interrupt */ - if ((icr & (0x0001 << (ch->unit & 3)))) { - struct ata_marvell_response *response; - u_int32_t rsp_in, rsp_out; - int slot; - - /* stop timeout */ - callout_stop(&request->callout); - - /* get response ptr's */ - rsp_in = ATA_INL(ctlr->r_res1, 0x02020 + ATA_MV_EDMA_BASE(ch)); - rsp_out = ATA_INL(ctlr->r_res1, 0x02024 + ATA_MV_EDMA_BASE(ch)); - slot = (((rsp_in & ~0xffffff00) >> 3)) & 0x1f; - rsp_out &= 0xffffff00; - rsp_out += (slot << 3); - response = (struct ata_marvell_response *) - (ch->dma.work + 1024 + (slot << 3)); - - /* record status for this request */ - request->status = response->dev_status; - request->error = 0; - - /* ack response */ - ATA_OUTL(ctlr->r_res1, 0x02024 + ATA_MV_EDMA_BASE(ch), rsp_out); - - /* update progress */ - if (!(request->status & ATA_S_ERROR) && - !(request->flags & ATA_R_TIMEOUT)) - request->donecount = request->bytecount; - - /* unload SG list */ - ch->dma.unload(request); - - res = ATA_OP_FINISHED; - } - - /* legacy ATA interrupt */ - else { - res = ata_end_transaction(request); - } - - /* ack interrupt */ - ATA_OUTL(ctlr->r_res1, offset, ~(icr & (0x0101 << (ch->unit & 3)))); - return res; -} - -static void -ata_marvell_edma_reset(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - - /* disable the EDMA machinery */ - ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000002); - while ((ATA_INL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001)) - DELAY(10); - - /* clear SATA error register */ - ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR)); - - /* clear any outstanding error interrupts */ - ATA_OUTL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch), 0x0); - - /* unmask all error interrupts */ - ATA_OUTL(ctlr->r_res1, 0x0200c + ATA_MV_EDMA_BASE(ch), ~0x0); - - /* enable channel and test for devices */ - if (ata_sata_phy_reset(dev)) - ata_generic_reset(dev); - - /* enable EDMA machinery */ - ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000001); -} - -static void -ata_marvell_edma_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, - int error) -{ - struct ata_dmasetprd_args *args = xsc; - struct ata_marvell_dma_prdentry *prd = args->dmatab; - int i; - - if ((args->error = error)) - return; - - for (i = 0; i < nsegs; i++) { - prd[i].addrlo = htole32(segs[i].ds_addr); - prd[i].count = htole32(segs[i].ds_len); - prd[i].addrhi = htole32((u_int64_t)segs[i].ds_addr >> 32); - } - prd[i - 1].count |= htole32(ATA_DMA_EOT); - KASSERT(nsegs <= ATA_DMA_ENTRIES, ("too many DMA segment entries\n")); - args->nsegs = nsegs; -} - -static void -ata_marvell_edma_dmainit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - - ata_dmainit(dev); - /* note start and stop are not used here */ - ch->dma.setprd = ata_marvell_edma_dmasetprd; - - /* if 64bit support present adjust max address used */ - if (ATA_INL(ctlr->r_res1, 0x00d00) & 0x00000004) - ch->dma.max_address = BUS_SPACE_MAXADDR; - - /* chip does not reliably do 64K DMA transfers */ - ch->dma.max_iosize = 126 * DEV_BSIZE; -} - - -/* - * National chipset support functions - */ -int -ata_national_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - /* this chip is a clone of the Cyrix chip, bugs and all */ - if (pci_get_devid(dev) == ATA_SC1100) { - device_set_desc(dev, "National Geode SC1100 ATA33 controller"); - ctlr->chipinit = ata_national_chipinit; - return 0; - } - return ENXIO; -} - -static int -ata_national_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - ctlr->setmode = ata_national_setmode; - return 0; -} - -static void -ata_national_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - u_int32_t piotiming[] = - { 0x9172d132, 0x21717121, 0x00803020, 0x20102010, 0x00100010, - 0x00803020, 0x20102010, 0x00100010, - 0x00100010, 0x00100010, 0x00100010 }; - u_int32_t dmatiming[] = { 0x80077771, 0x80012121, 0x80002020 }; - u_int32_t udmatiming[] = { 0x80921250, 0x80911140, 0x80911030 }; - int error; - - ch->dma.alignment = 16; - ch->dma.max_iosize = 126 * DEV_BSIZE; - - mode = ata_limit_mode(dev, mode, ATA_UDMA2); - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%s setting %s on National chip\n", - (error) ? "failed" : "success", ata_mode2str(mode)); - if (!error) { - if (mode >= ATA_UDMA0) { - pci_write_config(gparent, 0x44 + (devno << 3), - udmatiming[mode & ATA_MODE_MASK], 4); - } - else if (mode >= ATA_WDMA0) { - pci_write_config(gparent, 0x44 + (devno << 3), - dmatiming[mode & ATA_MODE_MASK], 4); - } - else { - pci_write_config(gparent, 0x44 + (devno << 3), - pci_read_config(gparent, 0x44 + (devno << 3), 4) | - 0x80000000, 4); - } - pci_write_config(gparent, 0x40 + (devno << 3), - piotiming[ata_mode2idx(mode)], 4); - atadev->mode = mode; - } -} - - -/* - * NetCell chipset support functions - */ -int -ata_netcell_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (pci_get_devid(dev) == ATA_NETCELL_SR) { - device_set_desc(dev, "Netcell SyncRAID SR3000/5000 RAID Controller"); - ctlr->chipinit = ata_netcell_chipinit; - return 0; - } - return ENXIO; -} - -static int -ata_netcell_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_generic_chipinit(dev)) - return ENXIO; - - ctlr->allocate = ata_netcell_allocate; - return 0; -} - -static int -ata_netcell_allocate(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - - /* setup the usual register normal pci style */ - if (ata_pci_allocate(dev)) - return ENXIO; - - /* the NetCell only supports 16 bit PIO transfers */ - ch->flags |= ATA_USE_16BIT; - - return 0; -} - - -/* - * nVidia chipset support functions - */ -int -ata_nvidia_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - static struct ata_chip_id ids[] = - {{ ATA_NFORCE1, 0, AMDNVIDIA, NVIDIA, ATA_UDMA5, "nForce" }, - { ATA_NFORCE2, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nForce2" }, - { ATA_NFORCE2_PRO, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nForce2 Pro" }, - { ATA_NFORCE2_PRO_S1, 0, 0, 0, ATA_SA150, "nForce2 Pro" }, - { ATA_NFORCE3, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nForce3" }, - { ATA_NFORCE3_PRO, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nForce3 Pro" }, - { ATA_NFORCE3_PRO_S1, 0, 0, 0, ATA_SA150, "nForce3 Pro" }, - { ATA_NFORCE3_PRO_S2, 0, 0, 0, ATA_SA150, "nForce3 Pro" }, - { ATA_NFORCE_MCP04, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nForce MCP" }, - { ATA_NFORCE_MCP04_S1, 0, 0, NV4, ATA_SA150, "nForce MCP" }, - { ATA_NFORCE_MCP04_S2, 0, 0, NV4, ATA_SA150, "nForce MCP" }, - { ATA_NFORCE_CK804, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nForce CK804" }, - { ATA_NFORCE_CK804_S1, 0, 0, NV4, ATA_SA300, "nForce CK804" }, - { ATA_NFORCE_CK804_S2, 0, 0, NV4, ATA_SA300, "nForce CK804" }, - { ATA_NFORCE_MCP51, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nForce MCP51" }, - { ATA_NFORCE_MCP51_S1, 0, 0, NV4|NVQ, ATA_SA300, "nForce MCP51" }, - { ATA_NFORCE_MCP51_S2, 0, 0, NV4|NVQ, ATA_SA300, "nForce MCP51" }, - { ATA_NFORCE_MCP55, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nForce MCP55" }, - { ATA_NFORCE_MCP55_S1, 0, 0, NV4|NVQ, ATA_SA300, "nForce MCP55" }, - { ATA_NFORCE_MCP55_S2, 0, 0, NV4|NVQ, ATA_SA300, "nForce MCP55" }, - { ATA_NFORCE_MCP61, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nForce MCP61" }, - { ATA_NFORCE_MCP61_S1, 0, 0, NV4|NVQ, ATA_SA300, "nForce MCP61" }, - { ATA_NFORCE_MCP61_S2, 0, 0, NV4|NVQ, ATA_SA300, "nForce MCP61" }, - { ATA_NFORCE_MCP61_S3, 0, 0, NV4|NVQ, ATA_SA300, "nForce MCP61" }, - { ATA_NFORCE_MCP65, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nForce MCP65" }, - { ATA_NFORCE_MCP67, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nForce MCP67" }, - { ATA_NFORCE_MCP73, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nForce MCP73" }, - { ATA_NFORCE_MCP77, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nForce MCP77" }, - { 0, 0, 0, 0, 0, 0}} ; - - if (!(ctlr->chip = ata_match_chip(dev, ids))) - return ENXIO; - - ata_set_desc(dev); - ctlr->chipinit = ata_nvidia_chipinit; - return 0; -} - -static int -ata_nvidia_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - if (ctlr->chip->max_dma >= ATA_SA150) { - if (pci_read_config(dev, PCIR_BAR(5), 1) & 1) - ctlr->r_type2 = SYS_RES_IOPORT; - else - ctlr->r_type2 = SYS_RES_MEMORY; - ctlr->r_rid2 = PCIR_BAR(5); - if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, - &ctlr->r_rid2, RF_ACTIVE))) { - int offset = ctlr->chip->cfg2 & NV4 ? 0x0440 : 0x0010; - - ctlr->allocate = ata_nvidia_allocate; - ctlr->reset = ata_nvidia_reset; - - /* enable control access */ - pci_write_config(dev, 0x50, pci_read_config(dev, 0x50, 1) | 0x04,1); - - if (ctlr->chip->cfg2 & NVQ) { - /* clear interrupt status */ - ATA_OUTL(ctlr->r_res2, offset, 0x00ff00ff); - - /* enable device and PHY state change interrupts */ - ATA_OUTL(ctlr->r_res2, offset + 4, 0x000d000d); - - /* disable NCQ support */ - ATA_OUTL(ctlr->r_res2, 0x0400, - ATA_INL(ctlr->r_res2, 0x0400) & 0xfffffff9); - } - else { - /* clear interrupt status */ - ATA_OUTB(ctlr->r_res2, offset, 0xff); - - /* enable device and PHY state change interrupts */ - ATA_OUTB(ctlr->r_res2, offset + 1, 0xdd); - } - - /* enable PCI interrupt */ - pci_write_config(dev, PCIR_COMMAND, - pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400,2); - - } - ctlr->setmode = ata_sata_setmode; - } - else { - /* disable prefetch, postwrite */ - pci_write_config(dev, 0x51, pci_read_config(dev, 0x51, 1) & 0x0f, 1); - ctlr->setmode = ata_via_family_setmode; - } - return 0; -} - -static int -ata_nvidia_allocate(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - - /* setup the usual register normal pci style */ - if (ata_pci_allocate(dev)) - return ENXIO; - - ch->r_io[ATA_SSTATUS].res = ctlr->r_res2; - ch->r_io[ATA_SSTATUS].offset = (ch->unit << 6); - ch->r_io[ATA_SERROR].res = ctlr->r_res2; - ch->r_io[ATA_SERROR].offset = 0x04 + (ch->unit << 6); - ch->r_io[ATA_SCONTROL].res = ctlr->r_res2; - ch->r_io[ATA_SCONTROL].offset = 0x08 + (ch->unit << 6); - - ch->hw.status = ata_nvidia_status; - ch->flags |= ATA_NO_SLAVE; - - return 0; -} - -static int -ata_nvidia_status(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int offset = ctlr->chip->cfg2 & NV4 ? 0x0440 : 0x0010; - int shift = ch->unit << (ctlr->chip->cfg2 & NVQ ? 4 : 2); - u_int32_t istatus; - - /* get interrupt status */ - if (ctlr->chip->cfg2 & NVQ) - istatus = ATA_INL(ctlr->r_res2, offset); - else - istatus = ATA_INB(ctlr->r_res2, offset); - - /* do we have any PHY events ? */ - if (istatus & (0x0c << shift)) - ata_sata_phy_check_events(dev); - - /* clear interrupt(s) */ - if (ctlr->chip->cfg2 & NVQ) - ATA_OUTL(ctlr->r_res2, offset, (0x0f << shift) | 0x00f000f0); - else - ATA_OUTB(ctlr->r_res2, offset, (0x0f << shift)); - - /* do we have any device action ? */ - return (istatus & (0x01 << shift)); -} - -static void -ata_nvidia_reset(device_t dev) -{ - if (ata_sata_phy_reset(dev)) - ata_generic_reset(dev); -} - - -/* - * Promise chipset support functions - */ -#define ATA_PDC_APKT_OFFSET 0x00000010 -#define ATA_PDC_HPKT_OFFSET 0x00000040 -#define ATA_PDC_ASG_OFFSET 0x00000080 -#define ATA_PDC_LSG_OFFSET 0x000000c0 -#define ATA_PDC_HSG_OFFSET 0x00000100 -#define ATA_PDC_CHN_OFFSET 0x00000400 -#define ATA_PDC_BUF_BASE 0x00400000 -#define ATA_PDC_BUF_OFFSET 0x00100000 -#define ATA_PDC_MAX_HPKT 8 -#define ATA_PDC_WRITE_REG 0x00 -#define ATA_PDC_WRITE_CTL 0x0e -#define ATA_PDC_WRITE_END 0x08 -#define ATA_PDC_WAIT_NBUSY 0x10 -#define ATA_PDC_WAIT_READY 0x18 -#define ATA_PDC_1B 0x20 -#define ATA_PDC_2B 0x40 - -struct host_packet { -u_int32_t addr; - TAILQ_ENTRY(host_packet) chain; -}; - -struct ata_promise_sx4 { - struct mtx mtx; - TAILQ_HEAD(, host_packet) queue; - int busy; -}; - -int -ata_promise_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - struct ata_chip_id *idx; - static struct ata_chip_id ids[] = - {{ ATA_PDC20246, 0, PROLD, 0x00, ATA_UDMA2, "PDC20246" }, - { ATA_PDC20262, 0, PRNEW, 0x00, ATA_UDMA4, "PDC20262" }, - { ATA_PDC20263, 0, PRNEW, 0x00, ATA_UDMA4, "PDC20263" }, - { ATA_PDC20265, 0, PRNEW, 0x00, ATA_UDMA5, "PDC20265" }, - { ATA_PDC20267, 0, PRNEW, 0x00, ATA_UDMA5, "PDC20267" }, - { ATA_PDC20268, 0, PRTX, PRTX4, ATA_UDMA5, "PDC20268" }, - { ATA_PDC20269, 0, PRTX, 0x00, ATA_UDMA6, "PDC20269" }, - { ATA_PDC20270, 0, PRTX, PRTX4, ATA_UDMA5, "PDC20270" }, - { ATA_PDC20271, 0, PRTX, 0x00, ATA_UDMA6, "PDC20271" }, - { ATA_PDC20275, 0, PRTX, 0x00, ATA_UDMA6, "PDC20275" }, - { ATA_PDC20276, 0, PRTX, PRSX6K, ATA_UDMA6, "PDC20276" }, - { ATA_PDC20277, 0, PRTX, 0x00, ATA_UDMA6, "PDC20277" }, - { ATA_PDC20318, 0, PRMIO, PRSATA, ATA_SA150, "PDC20318" }, - { ATA_PDC20319, 0, PRMIO, PRSATA, ATA_SA150, "PDC20319" }, - { ATA_PDC20371, 0, PRMIO, PRCMBO, ATA_SA150, "PDC20371" }, - { ATA_PDC20375, 0, PRMIO, PRCMBO, ATA_SA150, "PDC20375" }, - { ATA_PDC20376, 0, PRMIO, PRCMBO, ATA_SA150, "PDC20376" }, - { ATA_PDC20377, 0, PRMIO, PRCMBO, ATA_SA150, "PDC20377" }, - { ATA_PDC20378, 0, PRMIO, PRCMBO, ATA_SA150, "PDC20378" }, - { ATA_PDC20379, 0, PRMIO, PRCMBO, ATA_SA150, "PDC20379" }, - { ATA_PDC20571, 0, PRMIO, PRCMBO2, ATA_SA150, "PDC20571" }, - { ATA_PDC20575, 0, PRMIO, PRCMBO2, ATA_SA150, "PDC20575" }, - { ATA_PDC20579, 0, PRMIO, PRCMBO2, ATA_SA150, "PDC20579" }, - { ATA_PDC20771, 0, PRMIO, PRCMBO2, ATA_SA300, "PDC20771" }, - { ATA_PDC40775, 0, PRMIO, PRCMBO2, ATA_SA300, "PDC40775" }, - { ATA_PDC20617, 0, PRMIO, PRPATA, ATA_UDMA6, "PDC20617" }, - { ATA_PDC20618, 0, PRMIO, PRPATA, ATA_UDMA6, "PDC20618" }, - { ATA_PDC20619, 0, PRMIO, PRPATA, ATA_UDMA6, "PDC20619" }, - { ATA_PDC20620, 0, PRMIO, PRPATA, ATA_UDMA6, "PDC20620" }, - { ATA_PDC20621, 0, PRMIO, PRSX4X, ATA_UDMA5, "PDC20621" }, - { ATA_PDC20622, 0, PRMIO, PRSX4X, ATA_SA150, "PDC20622" }, - { ATA_PDC40518, 0, PRMIO, PRSATA2, ATA_SA150, "PDC40518" }, - { ATA_PDC40519, 0, PRMIO, PRSATA2, ATA_SA150, "PDC40519" }, - { ATA_PDC40718, 0, PRMIO, PRSATA2, ATA_SA300, "PDC40718" }, - { ATA_PDC40719, 0, PRMIO, PRSATA2, ATA_SA300, "PDC40719" }, - { ATA_PDC40779, 0, PRMIO, PRSATA2, ATA_SA300, "PDC40779" }, - { 0, 0, 0, 0, 0, 0}}; - char buffer[64]; - uintptr_t devid = 0; - - if (!(idx = ata_match_chip(dev, ids))) - return ENXIO; - - /* if we are on a SuperTrak SX6000 dont attach */ - if ((idx->cfg2 & PRSX6K) && pci_get_class(GRANDPARENT(dev))==PCIC_BRIDGE && - !BUS_READ_IVAR(device_get_parent(GRANDPARENT(dev)), - GRANDPARENT(dev), PCI_IVAR_DEVID, &devid) && - devid == ATA_I960RM) - return ENXIO; - - strcpy(buffer, "Promise "); - strcat(buffer, idx->text); - - /* if we are on a FastTrak TX4, adjust the interrupt resource */ - if ((idx->cfg2 & PRTX4) && pci_get_class(GRANDPARENT(dev))==PCIC_BRIDGE && - !BUS_READ_IVAR(device_get_parent(GRANDPARENT(dev)), - GRANDPARENT(dev), PCI_IVAR_DEVID, &devid) && - ((devid == ATA_DEC_21150) || (devid == ATA_DEC_21150_1))) { - static long start = 0, end = 0; - - if (pci_get_slot(dev) == 1) { - bus_get_resource(dev, SYS_RES_IRQ, 0, &start, &end); - strcat(buffer, " (channel 0+1)"); - } - else if (pci_get_slot(dev) == 2 && start && end) { - bus_set_resource(dev, SYS_RES_IRQ, 0, start, end); - strcat(buffer, " (channel 2+3)"); - } - else { - start = end = 0; - } - } - sprintf(buffer, "%s %s controller", buffer, ata_mode2str(idx->max_dma)); - device_set_desc_copy(dev, buffer); - ctlr->chip = idx; - ctlr->chipinit = ata_promise_chipinit; - return 0; -} - -static int -ata_promise_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - int fake_reg, stat_reg; - - if (ata_setup_interrupt(dev)) - return ENXIO; - - switch (ctlr->chip->cfg1) { - case PRNEW: - /* setup clocks */ - ATA_OUTB(ctlr->r_res1, 0x11, ATA_INB(ctlr->r_res1, 0x11) | 0x0a); - - ctlr->dmainit = ata_promise_dmainit; - /* FALLTHROUGH */ - - case PROLD: - /* enable burst mode */ - ATA_OUTB(ctlr->r_res1, 0x1f, ATA_INB(ctlr->r_res1, 0x1f) | 0x01); - ctlr->allocate = ata_promise_allocate; - ctlr->setmode = ata_promise_setmode; - return 0; - - case PRTX: - ctlr->allocate = ata_promise_tx2_allocate; - ctlr->setmode = ata_promise_setmode; - return 0; - - case PRMIO: - ctlr->r_type1 = SYS_RES_MEMORY; - ctlr->r_rid1 = PCIR_BAR(4); - if (!(ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1, - &ctlr->r_rid1, RF_ACTIVE))) - goto failnfree; - - ctlr->r_type2 = SYS_RES_MEMORY; - ctlr->r_rid2 = PCIR_BAR(3); - if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, - &ctlr->r_rid2, RF_ACTIVE))) - goto failnfree; - - if (ctlr->chip->cfg2 == PRSX4X) { - struct ata_promise_sx4 *hpkt; - u_int32_t dimm = ATA_INL(ctlr->r_res2, 0x000c0080); - - if (bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle) || - bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS, NULL, - ata_promise_sx4_intr, ctlr, &ctlr->handle)) { - device_printf(dev, "unable to setup interrupt\n"); - goto failnfree; - } - - /* print info about cache memory */ - device_printf(dev, "DIMM size %dMB @ 0x%08x%s\n", - (((dimm >> 16) & 0xff)-((dimm >> 24) & 0xff)+1) << 4, - ((dimm >> 24) & 0xff), - ATA_INL(ctlr->r_res2, 0x000c0088) & (1<<16) ? - " ECC enabled" : "" ); - - /* adjust cache memory parameters */ - ATA_OUTL(ctlr->r_res2, 0x000c000c, - (ATA_INL(ctlr->r_res2, 0x000c000c) & 0xffff0000)); - - /* setup host packet controls */ - hpkt = malloc(sizeof(struct ata_promise_sx4), - M_TEMP, M_NOWAIT | M_ZERO); - mtx_init(&hpkt->mtx, "ATA promise HPKT lock", NULL, MTX_DEF); - TAILQ_INIT(&hpkt->queue); - hpkt->busy = 0; - device_set_ivars(dev, hpkt); - ctlr->allocate = ata_promise_mio_allocate; - ctlr->reset = ata_promise_mio_reset; - ctlr->dmainit = ata_promise_mio_dmainit; - ctlr->setmode = ata_promise_setmode; - ctlr->channels = 4; - return 0; - } - - /* mio type controllers need an interrupt intercept */ - if (bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle) || - bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS, NULL, - ata_promise_mio_intr, ctlr, &ctlr->handle)) { - device_printf(dev, "unable to setup interrupt\n"); - goto failnfree; - } - - switch (ctlr->chip->cfg2) { - case PRPATA: - ctlr->channels = ((ATA_INL(ctlr->r_res2, 0x48) & 0x01) > 0) + - ((ATA_INL(ctlr->r_res2, 0x48) & 0x02) > 0) + 2; - goto sata150; - case PRCMBO: - ctlr->channels = 3; - goto sata150; - case PRSATA: - ctlr->channels = 4; -sata150: - fake_reg = 0x60; - stat_reg = 0x6c; - break; - - case PRCMBO2: - ctlr->channels = 3; - goto sataii; - case PRSATA2: - default: - ctlr->channels = 4; -sataii: - fake_reg = 0x54; - stat_reg = 0x60; - break; - } - - /* prime fake interrupt register */ - ATA_OUTL(ctlr->r_res2, fake_reg, 0xffffffff); - - /* clear SATA status and unmask interrupts */ - ATA_OUTL(ctlr->r_res2, stat_reg, 0x000000ff); - - /* enable "long burst length" on gen2 chips */ - if ((ctlr->chip->cfg2 == PRSATA2) || (ctlr->chip->cfg2 == PRCMBO2)) - ATA_OUTL(ctlr->r_res2, 0x44, ATA_INL(ctlr->r_res2, 0x44) | 0x2000); - - ctlr->allocate = ata_promise_mio_allocate; - ctlr->reset = ata_promise_mio_reset; - ctlr->dmainit = ata_promise_mio_dmainit; - ctlr->setmode = ata_promise_mio_setmode; - - return 0; - } - -failnfree: - if (ctlr->r_res2) - bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2); - if (ctlr->r_res1) - bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1, ctlr->r_res1); - return ENXIO; -} - -static int -ata_promise_allocate(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - - if (ata_pci_allocate(dev)) - return ENXIO; - - ch->hw.status = ata_promise_status; - return 0; -} - -static int -ata_promise_status(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - - if (ATA_INL(ctlr->r_res1, 0x1c) & (ch->unit ? 0x00004000 : 0x00000400)) { - return ata_pci_status(dev); - } - return 0; -} - -static int -ata_promise_dmastart(struct ata_request *request) -{ - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); - struct ata_channel *ch = device_get_softc(request->parent); - struct ata_device *atadev = device_get_softc(request->dev); - - if (atadev->flags & ATA_D_48BIT_ACTIVE) { - ATA_OUTB(ctlr->r_res1, 0x11, - ATA_INB(ctlr->r_res1, 0x11) | (ch->unit ? 0x08 : 0x02)); - ATA_OUTL(ctlr->r_res1, ch->unit ? 0x24 : 0x20, - ((request->flags & ATA_R_READ) ? 0x05000000 : 0x06000000) | - (request->bytecount >> 1)); - } - ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) | - (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR))); - ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, request->dma->sg_bus); - ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, - ((request->flags & ATA_R_READ) ? ATA_BMCMD_WRITE_READ : 0) | - ATA_BMCMD_START_STOP); - ch->dma.flags |= ATA_DMA_ACTIVE; - return 0; -} - -static int -ata_promise_dmastop(struct ata_request *request) -{ - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); - struct ata_channel *ch = device_get_softc(request->parent); - struct ata_device *atadev = device_get_softc(request->dev); - int error; - - if (atadev->flags & ATA_D_48BIT_ACTIVE) { - ATA_OUTB(ctlr->r_res1, 0x11, - ATA_INB(ctlr->r_res1, 0x11) & ~(ch->unit ? 0x08 : 0x02)); - ATA_OUTL(ctlr->r_res1, ch->unit ? 0x24 : 0x20, 0); - } - error = ATA_IDX_INB(ch, ATA_BMSTAT_PORT); - ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, - ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); - ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR); - ch->dma.flags &= ~ATA_DMA_ACTIVE; - return error; -} - -static void -ata_promise_dmareset(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - - ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, - ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); - ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR); - ch->flags &= ~ATA_DMA_ACTIVE; -} - -static void -ata_promise_dmainit(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - - ata_dmainit(dev); - ch->dma.start = ata_promise_dmastart; - ch->dma.stop = ata_promise_dmastop; - ch->dma.reset = ata_promise_dmareset; -} - -static void -ata_promise_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int error; - u_int32_t timings[][2] = { - /* PROLD PRNEW mode */ - { 0x004ff329, 0x004fff2f }, /* PIO 0 */ - { 0x004fec25, 0x004ff82a }, /* PIO 1 */ - { 0x004fe823, 0x004ff026 }, /* PIO 2 */ - { 0x004fe622, 0x004fec24 }, /* PIO 3 */ - { 0x004fe421, 0x004fe822 }, /* PIO 4 */ - { 0x004567f3, 0x004acef6 }, /* MWDMA 0 */ - { 0x004467f3, 0x0048cef6 }, /* MWDMA 1 */ - { 0x004367f3, 0x0046cef6 }, /* MWDMA 2 */ - { 0x004367f3, 0x0046cef6 }, /* UDMA 0 */ - { 0x004247f3, 0x00448ef6 }, /* UDMA 1 */ - { 0x004127f3, 0x00436ef6 }, /* UDMA 2 */ - { 0, 0x00424ef6 }, /* UDMA 3 */ - { 0, 0x004127f3 }, /* UDMA 4 */ - { 0, 0x004127f3 } /* UDMA 5 */ - }; - - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - switch (ctlr->chip->cfg1) { - case PROLD: - case PRNEW: - if (mode > ATA_UDMA2 && (pci_read_config(gparent, 0x50, 2) & - (ch->unit ? 1 << 11 : 1 << 10))) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - if (ata_atapi(dev) && mode > ATA_PIO_MAX) - mode = ata_limit_mode(dev, mode, ATA_PIO_MAX); - break; - - case PRTX: - ATA_IDX_OUTB(ch, ATA_BMDEVSPEC_0, 0x0b); - if (mode > ATA_UDMA2 && - ATA_IDX_INB(ch, ATA_BMDEVSPEC_1) & 0x04) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - break; - - case PRMIO: - if (mode > ATA_UDMA2 && - (ATA_INL(ctlr->r_res2, - (ctlr->chip->cfg2 & PRSX4X ? 0x000c0260 : 0x0260) + - (ch->unit << 7)) & 0x01000000)) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - break; - } - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { - if (ctlr->chip->cfg1 < PRTX) - pci_write_config(gparent, 0x60 + (devno << 2), - timings[ata_mode2idx(mode)][ctlr->chip->cfg1], 4); - atadev->mode = mode; - } - return; -} - -static int -ata_promise_tx2_allocate(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - - if (ata_pci_allocate(dev)) - return ENXIO; - - ch->hw.status = ata_promise_tx2_status; - return 0; -} - -static int -ata_promise_tx2_status(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - - ATA_IDX_OUTB(ch, ATA_BMDEVSPEC_0, 0x0b); - if (ATA_IDX_INB(ch, ATA_BMDEVSPEC_1) & 0x20) { - return ata_pci_status(dev); - } - return 0; -} - -static int -ata_promise_mio_allocate(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int offset = (ctlr->chip->cfg2 & PRSX4X) ? 0x000c0000 : 0; - int i; - - for (i = ATA_DATA; i <= ATA_COMMAND; i++) { - ch->r_io[i].res = ctlr->r_res2; - ch->r_io[i].offset = offset + 0x0200 + (i << 2) + (ch->unit << 7); - } - ch->r_io[ATA_CONTROL].res = ctlr->r_res2; - ch->r_io[ATA_CONTROL].offset = offset + 0x0238 + (ch->unit << 7); - ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2; - ata_default_registers(dev); - if ((ctlr->chip->cfg2 & (PRSATA | PRSATA2)) || - ((ctlr->chip->cfg2 & (PRCMBO | PRCMBO2)) && ch->unit < 2)) { - ch->r_io[ATA_SSTATUS].res = ctlr->r_res2; - ch->r_io[ATA_SSTATUS].offset = 0x400 + (ch->unit << 8); - ch->r_io[ATA_SERROR].res = ctlr->r_res2; - ch->r_io[ATA_SERROR].offset = 0x404 + (ch->unit << 8); - ch->r_io[ATA_SCONTROL].res = ctlr->r_res2; - ch->r_io[ATA_SCONTROL].offset = 0x408 + (ch->unit << 8); - ch->flags |= ATA_NO_SLAVE; - } - ch->flags |= ATA_USE_16BIT; - - ata_generic_hw(dev); - if (ctlr->chip->cfg2 & PRSX4X) { - ch->hw.command = ata_promise_sx4_command; - } - else { - ch->hw.command = ata_promise_mio_command; - ch->hw.status = ata_promise_mio_status; - ch->hw.softreset = ata_promise_mio_softreset; - ch->hw.pm_read = ata_promise_mio_pm_read; - ch->hw.pm_write = ata_promise_mio_pm_write; - } - return 0; -} - -static void -ata_promise_mio_intr(void *data) -{ - struct ata_pci_controller *ctlr = data; - struct ata_channel *ch; - u_int32_t vector; - int unit, fake_reg; - - switch (ctlr->chip->cfg2) { - case PRPATA: - case PRCMBO: - case PRSATA: - fake_reg = 0x60; - break; - case PRCMBO2: - case PRSATA2: - default: - fake_reg = 0x54; - break; - } - - /* - * since reading interrupt status register on early "mio" chips - * clears the status bits we cannot read it for each channel later on - * in the generic interrupt routine. - * store the bits in an unused register in the chip so we can read - * it from there safely to get around this "feature". - */ - vector = ATA_INL(ctlr->r_res2, 0x040); - ATA_OUTL(ctlr->r_res2, 0x040, vector); - ATA_OUTL(ctlr->r_res2, fake_reg, vector); - - for (unit = 0; unit < ctlr->channels; unit++) { - if ((ch = ctlr->interrupt[unit].argument)) - ctlr->interrupt[unit].function(ch); - } - - ATA_OUTL(ctlr->r_res2, fake_reg, 0xffffffff); -} - -static int -ata_promise_mio_status(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - struct ata_connect_task *tp; - u_int32_t fake_reg, stat_reg, vector, status; - - switch (ctlr->chip->cfg2) { - case PRPATA: - case PRCMBO: - case PRSATA: - fake_reg = 0x60; - stat_reg = 0x6c; - break; - case PRCMBO2: - case PRSATA2: - default: - fake_reg = 0x54; - stat_reg = 0x60; - break; - } - - /* read and acknowledge interrupt */ - vector = ATA_INL(ctlr->r_res2, fake_reg); - - /* read and clear interface status */ - status = ATA_INL(ctlr->r_res2, stat_reg); - ATA_OUTL(ctlr->r_res2, stat_reg, status & (0x00000011 << ch->unit)); - - /* check for and handle disconnect events */ - if ((status & (0x00000001 << ch->unit)) && - (tp = (struct ata_connect_task *) - malloc(sizeof(struct ata_connect_task), - M_ATA, M_NOWAIT | M_ZERO))) { - - if (bootverbose) - device_printf(dev, "DISCONNECT requested\n"); - tp->action = ATA_C_DETACH; - tp->dev = dev; - TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp); - taskqueue_enqueue(taskqueue_thread, &tp->task); - } - - /* check for and handle connect events */ - if ((status & (0x00000010 << ch->unit)) && - (tp = (struct ata_connect_task *) - malloc(sizeof(struct ata_connect_task), - M_ATA, M_NOWAIT | M_ZERO))) { - - if (bootverbose) - device_printf(dev, "CONNECT requested\n"); - tp->action = ATA_C_ATTACH; - tp->dev = dev; - TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp); - taskqueue_enqueue(taskqueue_thread, &tp->task); - } - - /* do we have any device action ? */ - return (vector & (1 << (ch->unit + 1))); -} - -static int -ata_promise_mio_command(struct ata_request *request) -{ - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); - struct ata_channel *ch = device_get_softc(request->parent); - struct ata_device *atadev = device_get_softc(request->dev); - - u_int32_t *wordp = (u_int32_t *)ch->dma.work; - - ATA_OUTL(ctlr->r_res2, (ch->unit + 1) << 2, 0x00000001); - - /* set portmultiplier port */ - ATA_OUTB(ctlr->r_res2, 0x4e8 + (ch->unit << 8), atadev->unit & 0x0f); - - /* XXX SOS add ATAPI commands support later */ - switch (request->u.ata.command) { - default: - return ata_generic_command(request); - - case ATA_READ_DMA: - case ATA_READ_DMA48: - wordp[0] = htole32(0x04 | ((ch->unit + 1) << 16) | (0x00 << 24)); - break; - - case ATA_WRITE_DMA: - case ATA_WRITE_DMA48: - wordp[0] = htole32(0x00 | ((ch->unit + 1) << 16) | (0x00 << 24)); - break; - } - wordp[1] = htole32(request->dma->sg_bus); - wordp[2] = 0; - ata_promise_apkt((u_int8_t*)wordp, request); - - ATA_OUTL(ctlr->r_res2, 0x0240 + (ch->unit << 7), ch->dma.work_bus); - return 0; -} - -static void -ata_promise_mio_reset(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - struct ata_promise_sx4 *hpktp; - - switch (ctlr->chip->cfg2) { - case PRSX4X: - - /* softreset channel ATA module */ - hpktp = device_get_ivars(ctlr->dev); - ATA_OUTL(ctlr->r_res2, 0xc0260 + (ch->unit << 7), ch->unit + 1); - ata_udelay(1000); - ATA_OUTL(ctlr->r_res2, 0xc0260 + (ch->unit << 7), - (ATA_INL(ctlr->r_res2, 0xc0260 + (ch->unit << 7)) & - ~0x00003f9f) | (ch->unit + 1)); - - /* softreset HOST module */ /* XXX SOS what about other outstandings */ - mtx_lock(&hpktp->mtx); - ATA_OUTL(ctlr->r_res2, 0xc012c, - (ATA_INL(ctlr->r_res2, 0xc012c) & ~0x00000f9f) | (1 << 11)); - DELAY(10); - ATA_OUTL(ctlr->r_res2, 0xc012c, - (ATA_INL(ctlr->r_res2, 0xc012c) & ~0x00000f9f)); - hpktp->busy = 0; - mtx_unlock(&hpktp->mtx); - ata_generic_reset(dev); - break; - - case PRPATA: - case PRCMBO: - case PRSATA: - if ((ctlr->chip->cfg2 == PRSATA) || - ((ctlr->chip->cfg2 == PRCMBO) && (ch->unit < 2))) { - - /* mask plug/unplug intr */ - ATA_OUTL(ctlr->r_res2, 0x06c, (0x00110000 << ch->unit)); - } - - /* softreset channels ATA module */ - ATA_OUTL(ctlr->r_res2, 0x0260 + (ch->unit << 7), (1 << 11)); - ata_udelay(10000); - ATA_OUTL(ctlr->r_res2, 0x0260 + (ch->unit << 7), - (ATA_INL(ctlr->r_res2, 0x0260 + (ch->unit << 7)) & - ~0x00003f9f) | (ch->unit + 1)); - - if ((ctlr->chip->cfg2 == PRSATA) || - ((ctlr->chip->cfg2 == PRCMBO) && (ch->unit < 2))) { - - if (ata_sata_phy_reset(dev)) - ata_generic_reset(dev); - - /* reset and enable plug/unplug intr */ - ATA_OUTL(ctlr->r_res2, 0x06c, (0x00000011 << ch->unit)); - } - else - ata_generic_reset(dev); - break; - - case PRCMBO2: - case PRSATA2: - if ((ctlr->chip->cfg2 == PRSATA2) || - ((ctlr->chip->cfg2 == PRCMBO2) && (ch->unit < 2))) { - /* set portmultiplier port */ - //ATA_OUTL(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x0f); - - /* mask plug/unplug intr */ - ATA_OUTL(ctlr->r_res2, 0x060, (0x00110000 << ch->unit)); - } - - /* softreset channels ATA module */ - ATA_OUTL(ctlr->r_res2, 0x0260 + (ch->unit << 7), (1 << 11)); - ata_udelay(10000); - ATA_OUTL(ctlr->r_res2, 0x0260 + (ch->unit << 7), - (ATA_INL(ctlr->r_res2, 0x0260 + (ch->unit << 7)) & - ~0x00003f9f) | (ch->unit + 1)); - - if ((ctlr->chip->cfg2 == PRSATA2) || - ((ctlr->chip->cfg2 == PRCMBO2) && (ch->unit < 2))) { - - /* set PHY mode to "improved" */ - ATA_OUTL(ctlr->r_res2, 0x414 + (ch->unit << 8), - (ATA_INL(ctlr->r_res2, 0x414 + (ch->unit << 8)) & - ~0x00000003) | 0x00000001); - - if (ata_sata_phy_reset(dev)) { - u_int32_t signature = ch->hw.softreset(dev, ATA_PM); - - if (1 | bootverbose) - device_printf(dev, "SIGNATURE: %08x\n", signature); - - switch (signature) { - case 0x00000101: - ch->devices = ATA_ATA_MASTER; - break; - case 0x96690101: - ch->devices = ATA_PORTMULTIPLIER; - ata_pm_identify(dev); - break; - case 0xeb140101: - ch->devices = ATA_ATAPI_MASTER; - break; - default: /* SOS XXX */ - if (bootverbose) - device_printf(dev, - "No signature, asuming disk device\n"); - ch->devices = ATA_ATA_MASTER; - } - if (bootverbose) - device_printf(dev, "promise_mio_reset devices=%08x\n", - ch->devices); - - } - - /* reset and enable plug/unplug intr */ - ATA_OUTL(ctlr->r_res2, 0x060, (0x00000011 << ch->unit)); - - ///* set portmultiplier port */ - ATA_OUTL(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x00); - } - else - ata_generic_reset(dev); - break; - - } -} - -static int -ata_promise_mio_pm_read(device_t dev, int port, int reg, u_int32_t *result) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int timeout = 0; - - /* set portmultiplier port */ - ATA_OUTB(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x0f); - - ATA_IDX_OUTB(ch, ATA_FEATURE, reg); - ATA_IDX_OUTB(ch, ATA_DRIVE, port); - - ATA_IDX_OUTB(ch, ATA_COMMAND, ATA_READ_PM); - - while (timeout < 1000000) { - u_int8_t status = ATA_IDX_INB(ch, ATA_STATUS); - if (!(status & ATA_S_BUSY)) - break; - timeout += 1000; - DELAY(1000); - } - if (timeout >= 1000000) - return ATA_E_ABORT; - - *result = ATA_IDX_INB(ch, ATA_COUNT) | - (ATA_IDX_INB(ch, ATA_SECTOR) << 8) | - (ATA_IDX_INB(ch, ATA_CYL_LSB) << 16) | - (ATA_IDX_INB(ch, ATA_CYL_MSB) << 24); - return 0; -} - -static int -ata_promise_mio_pm_write(device_t dev, int port, int reg, u_int32_t value) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int timeout = 0; - - /* set portmultiplier port */ - ATA_OUTB(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x0f); - - ATA_IDX_OUTB(ch, ATA_FEATURE, reg); - ATA_IDX_OUTB(ch, ATA_DRIVE, port); - ATA_IDX_OUTB(ch, ATA_COUNT, value & 0xff); - ATA_IDX_OUTB(ch, ATA_SECTOR, (value >> 8) & 0xff); - ATA_IDX_OUTB(ch, ATA_CYL_LSB, (value >> 16) & 0xff); - ATA_IDX_OUTB(ch, ATA_CYL_MSB, (value >> 24) & 0xff); - - ATA_IDX_OUTB(ch, ATA_COMMAND, ATA_WRITE_PM); - - while (timeout < 1000000) { - u_int8_t status = ATA_IDX_INB(ch, ATA_STATUS); - if (!(status & ATA_S_BUSY)) - break; - timeout += 1000; - DELAY(1000); - } - if (timeout >= 1000000) - return ATA_E_ABORT; - - return ATA_IDX_INB(ch, ATA_ERROR); -} - -/* must be called with ATA channel locked and state_mtx held */ -static u_int32_t -ata_promise_mio_softreset(device_t dev, int port) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int timeout; - - /* set portmultiplier port */ - ATA_OUTB(ctlr->r_res2, 0x4e8 + (ch->unit << 8), port & 0x0f); - - /* softreset device on this channel */ - ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_DEV(ATA_MASTER)); - DELAY(10); - ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_IDS | ATA_A_RESET); - ata_udelay(10000); - ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_IDS); - ata_udelay(150000); - ATA_IDX_INB(ch, ATA_ERROR); - - /* wait for BUSY to go inactive */ - for (timeout = 0; timeout < 100; timeout++) { - u_int8_t err, stat; - - err = ATA_IDX_INB(ch, ATA_ERROR); - stat = ATA_IDX_INB(ch, ATA_STATUS); - - //if (stat == err && timeout > (stat & ATA_S_BUSY ? 100 : 10)) - //break; - - if (!(stat & ATA_S_BUSY)) { - //if ((err & 0x7f) == ATA_E_ILI) { - return ATA_IDX_INB(ch, ATA_COUNT) | - (ATA_IDX_INB(ch, ATA_SECTOR) << 8) | - (ATA_IDX_INB(ch, ATA_CYL_LSB) << 16) | - (ATA_IDX_INB(ch, ATA_CYL_MSB) << 24); - //} - //else if (stat & 0x0f) { - //stat |= ATA_S_BUSY; - //} - } - - if (!(stat & ATA_S_BUSY) || (stat == 0xff && timeout > 10)) - break; - ata_udelay(100000); - } - return -1; -} - -static void -ata_promise_mio_dmainit(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - - ata_dmainit(dev); - /* note start and stop are not used here */ - ch->dma.setprd = ata_promise_mio_setprd; -} - - -#define MAXLASTSGSIZE (32 * sizeof(u_int32_t)) -static void -ata_promise_mio_setprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) -{ - struct ata_dmasetprd_args *args = xsc; - struct ata_dma_prdentry *prd = args->dmatab; - int i; - - if ((args->error = error)) - return; - - for (i = 0; i < nsegs; i++) { - prd[i].addr = htole32(segs[i].ds_addr); - prd[i].count = htole32(segs[i].ds_len); - } - if (segs[i - 1].ds_len > MAXLASTSGSIZE) { - //printf("split last SG element of %u\n", segs[i - 1].ds_len); - prd[i - 1].count = htole32(segs[i - 1].ds_len - MAXLASTSGSIZE); - prd[i].count = htole32(MAXLASTSGSIZE); - prd[i].addr = htole32(segs[i - 1].ds_addr + - (segs[i - 1].ds_len - MAXLASTSGSIZE)); - nsegs++; - i++; - } - prd[i - 1].count |= htole32(ATA_DMA_EOT); - KASSERT(nsegs <= ATA_DMA_ENTRIES, ("too many DMA segment entries\n")); - args->nsegs = nsegs; -} - -static void -ata_promise_mio_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - - if ( (ctlr->chip->cfg2 == PRSATA) || - ((ctlr->chip->cfg2 == PRCMBO) && (ch->unit < 2)) || - (ctlr->chip->cfg2 == PRSATA2) || - ((ctlr->chip->cfg2 == PRCMBO2) && (ch->unit < 2))) - ata_sata_setmode(dev, mode); - else - ata_promise_setmode(dev, mode); -} - -static void -ata_promise_sx4_intr(void *data) -{ - struct ata_pci_controller *ctlr = data; - struct ata_channel *ch; - u_int32_t vector = ATA_INL(ctlr->r_res2, 0x000c0480); - int unit; - - for (unit = 0; unit < ctlr->channels; unit++) { - if (vector & (1 << (unit + 1))) - if ((ch = ctlr->interrupt[unit].argument)) - ctlr->interrupt[unit].function(ch); - if (vector & (1 << (unit + 5))) - if ((ch = ctlr->interrupt[unit].argument)) - ata_promise_queue_hpkt(ctlr, - htole32((ch->unit * ATA_PDC_CHN_OFFSET) + - ATA_PDC_HPKT_OFFSET)); - if (vector & (1 << (unit + 9))) { - ata_promise_next_hpkt(ctlr); - if ((ch = ctlr->interrupt[unit].argument)) - ctlr->interrupt[unit].function(ch); - } - if (vector & (1 << (unit + 13))) { - ata_promise_next_hpkt(ctlr); - if ((ch = ctlr->interrupt[unit].argument)) - ATA_OUTL(ctlr->r_res2, 0x000c0240 + (ch->unit << 7), - htole32((ch->unit * ATA_PDC_CHN_OFFSET) + - ATA_PDC_APKT_OFFSET)); - } - } -} - -static int -ata_promise_sx4_command(struct ata_request *request) -{ - device_t gparent = GRANDPARENT(request->dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(request->parent); - struct ata_dma_prdentry *prd = request->dma->sg; - caddr_t window = rman_get_virtual(ctlr->r_res1); - u_int32_t *wordp; - int i, idx, length = 0; - - /* XXX SOS add ATAPI commands support later */ - switch (request->u.ata.command) { - - default: - return -1; - - case ATA_ATA_IDENTIFY: - case ATA_READ: - case ATA_READ48: - case ATA_READ_MUL: - case ATA_READ_MUL48: - case ATA_WRITE: - case ATA_WRITE48: - case ATA_WRITE_MUL: - case ATA_WRITE_MUL48: - ATA_OUTL(ctlr->r_res2, 0x000c0400 + ((ch->unit + 1) << 2), 0x00000001); - return ata_generic_command(request); - - case ATA_SETFEATURES: - case ATA_FLUSHCACHE: - case ATA_FLUSHCACHE48: - case ATA_SLEEP: - case ATA_SET_MULTI: - wordp = (u_int32_t *) - (window + (ch->unit * ATA_PDC_CHN_OFFSET) + ATA_PDC_APKT_OFFSET); - wordp[0] = htole32(0x08 | ((ch->unit + 1)<<16) | (0x00 << 24)); - wordp[1] = 0; - wordp[2] = 0; - ata_promise_apkt((u_int8_t *)wordp, request); - ATA_OUTL(ctlr->r_res2, 0x000c0484, 0x00000001); - ATA_OUTL(ctlr->r_res2, 0x000c0400 + ((ch->unit + 1) << 2), 0x00000001); - ATA_OUTL(ctlr->r_res2, 0x000c0240 + (ch->unit << 7), - htole32((ch->unit * ATA_PDC_CHN_OFFSET)+ATA_PDC_APKT_OFFSET)); - return 0; - - case ATA_READ_DMA: - case ATA_READ_DMA48: - case ATA_WRITE_DMA: - case ATA_WRITE_DMA48: - wordp = (u_int32_t *) - (window + (ch->unit * ATA_PDC_CHN_OFFSET) + ATA_PDC_HSG_OFFSET); - i = idx = 0; - do { - wordp[idx++] = prd[i].addr; - wordp[idx++] = prd[i].count; - length += (prd[i].count & ~ATA_DMA_EOT); - } while (!(prd[i++].count & ATA_DMA_EOT)); - - wordp = (u_int32_t *) - (window + (ch->unit * ATA_PDC_CHN_OFFSET) + ATA_PDC_LSG_OFFSET); - wordp[0] = htole32((ch->unit * ATA_PDC_BUF_OFFSET) + ATA_PDC_BUF_BASE); - wordp[1] = htole32(request->bytecount | ATA_DMA_EOT); - - wordp = (u_int32_t *) - (window + (ch->unit * ATA_PDC_CHN_OFFSET) + ATA_PDC_ASG_OFFSET); - wordp[0] = htole32((ch->unit * ATA_PDC_BUF_OFFSET) + ATA_PDC_BUF_BASE); - wordp[1] = htole32(request->bytecount | ATA_DMA_EOT); - - wordp = (u_int32_t *) - (window + (ch->unit * ATA_PDC_CHN_OFFSET) + ATA_PDC_HPKT_OFFSET); - if (request->flags & ATA_R_READ) - wordp[0] = htole32(0x14 | ((ch->unit+9)<<16) | ((ch->unit+5)<<24)); - if (request->flags & ATA_R_WRITE) - wordp[0] = htole32(0x00 | ((ch->unit+13)<<16) | (0x00<<24)); - wordp[1] = htole32((ch->unit * ATA_PDC_CHN_OFFSET)+ATA_PDC_HSG_OFFSET); - wordp[2] = htole32((ch->unit * ATA_PDC_CHN_OFFSET)+ATA_PDC_LSG_OFFSET); - wordp[3] = 0; - - wordp = (u_int32_t *) - (window + (ch->unit * ATA_PDC_CHN_OFFSET) + ATA_PDC_APKT_OFFSET); - if (request->flags & ATA_R_READ) - wordp[0] = htole32(0x04 | ((ch->unit+5)<<16) | (0x00<<24)); - if (request->flags & ATA_R_WRITE) - wordp[0] = htole32(0x10 | ((ch->unit+1)<<16) | ((ch->unit+13)<<24)); - wordp[1] = htole32((ch->unit * ATA_PDC_CHN_OFFSET)+ATA_PDC_ASG_OFFSET); - wordp[2] = 0; - ata_promise_apkt((u_int8_t *)wordp, request); - ATA_OUTL(ctlr->r_res2, 0x000c0484, 0x00000001); - - if (request->flags & ATA_R_READ) { - ATA_OUTL(ctlr->r_res2, 0x000c0400 + ((ch->unit+5)<<2), 0x00000001); - ATA_OUTL(ctlr->r_res2, 0x000c0400 + ((ch->unit+9)<<2), 0x00000001); - ATA_OUTL(ctlr->r_res2, 0x000c0240 + (ch->unit << 7), - htole32((ch->unit * ATA_PDC_CHN_OFFSET) + ATA_PDC_APKT_OFFSET)); - } - if (request->flags & ATA_R_WRITE) { - ATA_OUTL(ctlr->r_res2, 0x000c0400 + ((ch->unit+1)<<2), 0x00000001); - ATA_OUTL(ctlr->r_res2, 0x000c0400 + ((ch->unit+13)<<2), 0x00000001); - ata_promise_queue_hpkt(ctlr, - htole32((ch->unit * ATA_PDC_CHN_OFFSET) + ATA_PDC_HPKT_OFFSET)); - } - return 0; - } -} - -static int -ata_promise_apkt(u_int8_t *bytep, struct ata_request *request) -{ - struct ata_device *atadev = device_get_softc(request->dev); - int i = 12; - - bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_PDC_WAIT_NBUSY|ATA_DRIVE; - bytep[i++] = ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit); - bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_CTL; - bytep[i++] = ATA_A_4BIT; - - if (atadev->flags & ATA_D_48BIT_ACTIVE) { - bytep[i++] = ATA_PDC_2B | ATA_PDC_WRITE_REG | ATA_FEATURE; - bytep[i++] = request->u.ata.feature >> 8; - bytep[i++] = request->u.ata.feature; - bytep[i++] = ATA_PDC_2B | ATA_PDC_WRITE_REG | ATA_COUNT; - bytep[i++] = request->u.ata.count >> 8; - bytep[i++] = request->u.ata.count; - bytep[i++] = ATA_PDC_2B | ATA_PDC_WRITE_REG | ATA_SECTOR; - bytep[i++] = request->u.ata.lba >> 24; - bytep[i++] = request->u.ata.lba; - bytep[i++] = ATA_PDC_2B | ATA_PDC_WRITE_REG | ATA_CYL_LSB; - bytep[i++] = request->u.ata.lba >> 32; - bytep[i++] = request->u.ata.lba >> 8; - bytep[i++] = ATA_PDC_2B | ATA_PDC_WRITE_REG | ATA_CYL_MSB; - bytep[i++] = request->u.ata.lba >> 40; - bytep[i++] = request->u.ata.lba >> 16; - bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_DRIVE; - bytep[i++] = ATA_D_LBA | ATA_DEV(atadev->unit); - } - else { - bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_FEATURE; - bytep[i++] = request->u.ata.feature; - bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_COUNT; - bytep[i++] = request->u.ata.count; - bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_SECTOR; - bytep[i++] = request->u.ata.lba; - bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_CYL_LSB; - bytep[i++] = request->u.ata.lba >> 8; - bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_CYL_MSB; - bytep[i++] = request->u.ata.lba >> 16; - bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_DRIVE; - bytep[i++] = (atadev->flags & ATA_D_USE_CHS ? 0 : ATA_D_LBA) | - ATA_D_IBM | ATA_DEV(atadev->unit) | - ((request->u.ata.lba >> 24)&0xf); - } - bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_END | ATA_COMMAND; - bytep[i++] = request->u.ata.command; - return i; -} - -static void -ata_promise_queue_hpkt(struct ata_pci_controller *ctlr, u_int32_t hpkt) -{ - struct ata_promise_sx4 *hpktp = device_get_ivars(ctlr->dev); - - mtx_lock(&hpktp->mtx); - if (hpktp->busy) { - struct host_packet *hp = - malloc(sizeof(struct host_packet), M_TEMP, M_NOWAIT | M_ZERO); - hp->addr = hpkt; - TAILQ_INSERT_TAIL(&hpktp->queue, hp, chain); - } - else { - hpktp->busy = 1; - ATA_OUTL(ctlr->r_res2, 0x000c0100, hpkt); - } - mtx_unlock(&hpktp->mtx); -} - -static void -ata_promise_next_hpkt(struct ata_pci_controller *ctlr) -{ - struct ata_promise_sx4 *hpktp = device_get_ivars(ctlr->dev); - struct host_packet *hp; - - mtx_lock(&hpktp->mtx); - if ((hp = TAILQ_FIRST(&hpktp->queue))) { - TAILQ_REMOVE(&hpktp->queue, hp, chain); - ATA_OUTL(ctlr->r_res2, 0x000c0100, hp->addr); - free(hp, M_TEMP); - } - else - hpktp->busy = 0; - mtx_unlock(&hpktp->mtx); -} - - -/* - * ServerWorks chipset support functions - */ -int -ata_serverworks_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - static struct ata_chip_id ids[] = - {{ ATA_ROSB4, 0x00, SWKS33, 0, ATA_UDMA2, "ROSB4" }, - { ATA_CSB5, 0x92, SWKS100, 0, ATA_UDMA5, "CSB5" }, - { ATA_CSB5, 0x00, SWKS66, 0, ATA_UDMA4, "CSB5" }, - { ATA_CSB6, 0x00, SWKS100, 0, ATA_UDMA5, "CSB6" }, - { ATA_CSB6_1, 0x00, SWKS66, 0, ATA_UDMA4, "CSB6" }, - { ATA_HT1000, 0x00, SWKS100, 0, ATA_UDMA5, "HT1000" }, - { ATA_HT1000_S1, 0x00, SWKS100, 4, ATA_SA150, "HT1000" }, - { ATA_HT1000_S2, 0x00, SWKSMIO, 4, ATA_SA150, "HT1000" }, - { ATA_K2, 0x00, SWKSMIO, 4, ATA_SA150, "K2" }, - { ATA_FRODO4, 0x00, SWKSMIO, 4, ATA_SA150, "Frodo4" }, - { ATA_FRODO8, 0x00, SWKSMIO, 8, ATA_SA150, "Frodo8" }, - { 0, 0, 0, 0, 0, 0}}; - - if (!(ctlr->chip = ata_match_chip(dev, ids))) - return ENXIO; - - ata_set_desc(dev); - ctlr->chipinit = ata_serverworks_chipinit; - return 0; -} - -static int -ata_serverworks_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - if (ctlr->chip->cfg1 == SWKSMIO) { - ctlr->r_type2 = SYS_RES_MEMORY; - ctlr->r_rid2 = PCIR_BAR(5); - if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, - &ctlr->r_rid2, RF_ACTIVE))) - return ENXIO; - - ctlr->channels = ctlr->chip->cfg2; - ctlr->allocate = ata_serverworks_allocate; - ctlr->setmode = ata_sata_setmode; - return 0; - } - else if (ctlr->chip->cfg1 == SWKS33) { - device_t *children; - int nchildren, i; - - /* locate the ISA part in the southbridge and enable UDMA33 */ - if (!device_get_children(device_get_parent(dev), &children,&nchildren)){ - for (i = 0; i < nchildren; i++) { - if (pci_get_devid(children[i]) == ATA_ROSB4_ISA) { - pci_write_config(children[i], 0x64, - (pci_read_config(children[i], 0x64, 4) & - ~0x00002000) | 0x00004000, 4); - break; - } - } - free(children, M_TEMP); - } - } - else { - pci_write_config(dev, 0x5a, - (pci_read_config(dev, 0x5a, 1) & ~0x40) | - (ctlr->chip->cfg1 == SWKS100) ? 0x03 : 0x02, 1); - } - ctlr->setmode = ata_serverworks_setmode; - return 0; -} - -static int -ata_serverworks_allocate(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int ch_offset; - int i; - - ch_offset = ch->unit * 0x100; - - for (i = ATA_DATA; i < ATA_MAX_RES; i++) - ch->r_io[i].res = ctlr->r_res2; - - /* setup ATA registers */ - ch->r_io[ATA_DATA].offset = ch_offset + 0x00; - ch->r_io[ATA_FEATURE].offset = ch_offset + 0x04; - ch->r_io[ATA_COUNT].offset = ch_offset + 0x08; - ch->r_io[ATA_SECTOR].offset = ch_offset + 0x0c; - ch->r_io[ATA_CYL_LSB].offset = ch_offset + 0x10; - ch->r_io[ATA_CYL_MSB].offset = ch_offset + 0x14; - ch->r_io[ATA_DRIVE].offset = ch_offset + 0x18; - ch->r_io[ATA_COMMAND].offset = ch_offset + 0x1c; - ch->r_io[ATA_CONTROL].offset = ch_offset + 0x20; - ata_default_registers(dev); - - /* setup DMA registers */ - ch->r_io[ATA_BMCMD_PORT].offset = ch_offset + 0x30; - ch->r_io[ATA_BMSTAT_PORT].offset = ch_offset + 0x32; - ch->r_io[ATA_BMDTP_PORT].offset = ch_offset + 0x34; - - /* setup SATA registers */ - ch->r_io[ATA_SSTATUS].offset = ch_offset + 0x40; - ch->r_io[ATA_SERROR].offset = ch_offset + 0x44; - ch->r_io[ATA_SCONTROL].offset = ch_offset + 0x48; - - ch->flags |= ATA_NO_SLAVE; - ata_pci_hw(dev); - ch->hw.tf_read = ata_serverworks_tf_read; - ch->hw.tf_write = ata_serverworks_tf_write; - - /* chip does not reliably do 64K DMA transfers */ - ch->dma.max_iosize = 126 * DEV_BSIZE; - - return 0; -} - -static void -ata_serverworks_tf_read(struct ata_request *request) -{ - struct ata_channel *ch = device_get_softc(request->parent); - struct ata_device *atadev = device_get_softc(request->dev); - - if (atadev->flags & ATA_D_48BIT_ACTIVE) { - u_int16_t temp; - - request->u.ata.count = ATA_IDX_INW(ch, ATA_COUNT); - temp = ATA_IDX_INW(ch, ATA_SECTOR); - request->u.ata.lba = (u_int64_t)(temp & 0x00ff) | - ((u_int64_t)(temp & 0xff00) << 24); - temp = ATA_IDX_INW(ch, ATA_CYL_LSB); - request->u.ata.lba |= ((u_int64_t)(temp & 0x00ff) << 8) | - ((u_int64_t)(temp & 0xff00) << 32); - temp = ATA_IDX_INW(ch, ATA_CYL_MSB); - request->u.ata.lba |= ((u_int64_t)(temp & 0x00ff) << 16) | - ((u_int64_t)(temp & 0xff00) << 40); - } - else { - request->u.ata.count = ATA_IDX_INW(ch, ATA_COUNT) & 0x00ff; - request->u.ata.lba = (ATA_IDX_INW(ch, ATA_SECTOR) & 0x00ff) | - ((ATA_IDX_INW(ch, ATA_CYL_LSB) & 0x00ff) << 8) | - ((ATA_IDX_INW(ch, ATA_CYL_MSB) & 0x00ff) << 16) | - ((ATA_IDX_INW(ch, ATA_DRIVE) & 0xf) << 24); - } -} - -static void -ata_serverworks_tf_write(struct ata_request *request) -{ - struct ata_channel *ch = device_get_softc(request->parent); - struct ata_device *atadev = device_get_softc(request->dev); - - if (atadev->flags & ATA_D_48BIT_ACTIVE) { - ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature); - ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count); - ATA_IDX_OUTW(ch, ATA_SECTOR, ((request->u.ata.lba >> 16) & 0xff00) | - (request->u.ata.lba & 0x00ff)); - ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((request->u.ata.lba >> 24) & 0xff00) | - ((request->u.ata.lba >> 8) & 0x00ff)); - ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((request->u.ata.lba >> 32) & 0xff00) | - ((request->u.ata.lba >> 16) & 0x00ff)); - ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(atadev->unit)); - } - else { - ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature); - ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count); - if (atadev->flags & ATA_D_USE_CHS) { - int heads, sectors; - - if (atadev->param.atavalid & ATA_FLAG_54_58) { - heads = atadev->param.current_heads; - sectors = atadev->param.current_sectors; - } - else { - heads = atadev->param.heads; - sectors = atadev->param.sectors; - } - ATA_IDX_OUTW(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1); - ATA_IDX_OUTW(ch, ATA_CYL_LSB, - (request->u.ata.lba / (sectors * heads))); - ATA_IDX_OUTW(ch, ATA_CYL_MSB, - (request->u.ata.lba / (sectors * heads)) >> 8); - ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit) | - (((request->u.ata.lba% (sectors * heads)) / - sectors) & 0xf)); - } - else { - ATA_IDX_OUTW(ch, ATA_SECTOR, request->u.ata.lba); - ATA_IDX_OUTW(ch, ATA_CYL_LSB, request->u.ata.lba >> 8); - ATA_IDX_OUTW(ch, ATA_CYL_MSB, request->u.ata.lba >> 16); - ATA_IDX_OUTW(ch, ATA_DRIVE, - ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit) | - ((request->u.ata.lba >> 24) & 0x0f)); - } - } -} - -static void -ata_serverworks_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int offset = (devno ^ 0x01) << 3; - int error; - u_int8_t piotimings[] = { 0x5d, 0x47, 0x34, 0x22, 0x20, 0x34, 0x22, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; - u_int8_t dmatimings[] = { 0x77, 0x21, 0x20 }; - - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - mode = ata_check_80pin(dev, mode); - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { - if (mode >= ATA_UDMA0) { - pci_write_config(gparent, 0x56, - (pci_read_config(gparent, 0x56, 2) & - ~(0xf << (devno << 2))) | - ((mode & ATA_MODE_MASK) << (devno << 2)), 2); - pci_write_config(gparent, 0x54, - pci_read_config(gparent, 0x54, 1) | - (0x01 << devno), 1); - pci_write_config(gparent, 0x44, - (pci_read_config(gparent, 0x44, 4) & - ~(0xff << offset)) | - (dmatimings[2] << offset), 4); - } - else if (mode >= ATA_WDMA0) { - pci_write_config(gparent, 0x54, - pci_read_config(gparent, 0x54, 1) & - ~(0x01 << devno), 1); - pci_write_config(gparent, 0x44, - (pci_read_config(gparent, 0x44, 4) & - ~(0xff << offset)) | - (dmatimings[mode & ATA_MODE_MASK] << offset), 4); - } - else - pci_write_config(gparent, 0x54, - pci_read_config(gparent, 0x54, 1) & - ~(0x01 << devno), 1); - - pci_write_config(gparent, 0x40, - (pci_read_config(gparent, 0x40, 4) & - ~(0xff << offset)) | - (piotimings[ata_mode2idx(mode)] << offset), 4); - atadev->mode = mode; - } -} - - -/* - * Silicon Image Inc. (SiI) (former CMD) chipset support functions - */ -int -ata_sii_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - static struct ata_chip_id ids[] = - {{ ATA_SII3114, 0x00, SIIMEMIO, SII4CH, ATA_SA150, "3114" }, - { ATA_SII3512, 0x02, SIIMEMIO, 0, ATA_SA150, "3512" }, - { ATA_SII3112, 0x02, SIIMEMIO, 0, ATA_SA150, "3112" }, - { ATA_SII3112_1, 0x02, SIIMEMIO, 0, ATA_SA150, "3112" }, - { ATA_SII3512, 0x00, SIIMEMIO, SIIBUG, ATA_SA150, "3512" }, - { ATA_SII3112, 0x00, SIIMEMIO, SIIBUG, ATA_SA150, "3112" }, - { ATA_SII3112_1, 0x00, SIIMEMIO, SIIBUG, ATA_SA150, "3112" }, - { ATA_SII3124, 0x00, SIIPRBIO, SII4CH, ATA_SA300, "3124" }, - { ATA_SII3132, 0x00, SIIPRBIO, 0, ATA_SA300, "3132" }, - { ATA_SII3132_1, 0x00, SIIPRBIO, 0, ATA_SA300, "3132" }, - { ATA_SII0680, 0x00, SIIMEMIO, SIISETCLK, ATA_UDMA6, "680" }, - { ATA_CMD649, 0x00, 0, SIIINTR, ATA_UDMA5, "(CMD) 649" }, - { ATA_CMD648, 0x00, 0, SIIINTR, ATA_UDMA4, "(CMD) 648" }, - { ATA_CMD646, 0x07, 0, 0, ATA_UDMA2, "(CMD) 646U2" }, - { ATA_CMD646, 0x00, 0, 0, ATA_WDMA2, "(CMD) 646" }, - { 0, 0, 0, 0, 0, 0}}; - - if (!(ctlr->chip = ata_match_chip(dev, ids))) - return ENXIO; - - ata_set_desc(dev); - ctlr->chipinit = ata_sii_chipinit; - return 0; -} - -static int -ata_sii_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - switch (ctlr->chip->cfg1) { - case SIIPRBIO: - ctlr->r_type1 = SYS_RES_MEMORY; - ctlr->r_rid1 = PCIR_BAR(0); - if (!(ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1, - &ctlr->r_rid1, RF_ACTIVE))) - return ENXIO; - - ctlr->r_rid2 = PCIR_BAR(2); - ctlr->r_type2 = SYS_RES_MEMORY; - if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, - &ctlr->r_rid2, RF_ACTIVE))){ - bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1,ctlr->r_res1); - return ENXIO; - } - ctlr->allocate = ata_siiprb_allocate; - ctlr->reset = ata_siiprb_reset; - ctlr->dmainit = ata_siiprb_dmainit; - ctlr->setmode = ata_sata_setmode; - ctlr->channels = (ctlr->chip->cfg2 == SII4CH) ? 4 : 2; - - /* reset controller */ - ATA_OUTL(ctlr->r_res1, 0x0040, 0x80000000); - DELAY(10000); - ATA_OUTL(ctlr->r_res1, 0x0040, 0x0000000f); - - /* enable PCI interrupt */ - pci_write_config(dev, PCIR_COMMAND, - pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2); - break; - - case SIIMEMIO: - ctlr->r_type2 = SYS_RES_MEMORY; - ctlr->r_rid2 = PCIR_BAR(5); - if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, - &ctlr->r_rid2, RF_ACTIVE))){ - if (ctlr->chip->chipid != ATA_SII0680 || - (pci_read_config(dev, 0x8a, 1) & 1)) - return ENXIO; - } - - if (ctlr->chip->cfg2 & SIISETCLK) { - if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10) - pci_write_config(dev, 0x8a, - (pci_read_config(dev, 0x8a, 1) & 0xcf)|0x10,1); - if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10) - device_printf(dev, "%s could not set ATA133 clock\n", - ctlr->chip->text); - } - - /* if we have 4 channels enable the second set */ - if (ctlr->chip->cfg2 & SII4CH) { - ATA_OUTL(ctlr->r_res2, 0x0200, 0x00000002); - ctlr->channels = 4; - } - - /* dont block interrupts from any channel */ - pci_write_config(dev, 0x48, - (pci_read_config(dev, 0x48, 4) & ~0x03c00000), 4); - - /* enable PCI interrupt as BIOS might not */ - pci_write_config(dev, 0x8a, (pci_read_config(dev, 0x8a, 1) & 0x3f), 1); - - if (ctlr->r_res2) - ctlr->allocate = ata_sii_allocate; - - if (ctlr->chip->max_dma >= ATA_SA150) { - ctlr->reset = ata_sii_reset; - ctlr->setmode = ata_sata_setmode; - } - else - ctlr->setmode = ata_sii_setmode; - break; - - default: - if ((pci_read_config(dev, 0x51, 1) & 0x08) != 0x08) { - device_printf(dev, "HW has secondary channel disabled\n"); - ctlr->channels = 1; - } - - /* enable interrupt as BIOS might not */ - pci_write_config(dev, 0x71, 0x01, 1); - - ctlr->allocate = ata_cmd_allocate; - ctlr->setmode = ata_cmd_setmode; - break; - } - return 0; -} - -static int -ata_cmd_allocate(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - - /* setup the usual register normal pci style */ - if (ata_pci_allocate(dev)) - return ENXIO; - - if (ctlr->chip->cfg2 & SIIINTR) - ch->hw.status = ata_cmd_status; - - return 0; -} - -static int -ata_cmd_status(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - u_int8_t reg71; - - if (((reg71 = pci_read_config(device_get_parent(dev), 0x71, 1)) & - (ch->unit ? 0x08 : 0x04))) { - pci_write_config(device_get_parent(dev), 0x71, - reg71 & ~(ch->unit ? 0x04 : 0x08), 1); - return ata_pci_status(dev); - } - return 0; -} - -static void -ata_cmd_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int error; - - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - mode = ata_check_80pin(dev, mode); - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { - int treg = 0x54 + ((devno < 3) ? (devno << 1) : 7); - int ureg = ch->unit ? 0x7b : 0x73; - - if (mode >= ATA_UDMA0) { - int udmatimings[][2] = { { 0x31, 0xc2 }, { 0x21, 0x82 }, - { 0x11, 0x42 }, { 0x25, 0x8a }, - { 0x15, 0x4a }, { 0x05, 0x0a } }; - - u_int8_t umode = pci_read_config(gparent, ureg, 1); - - umode &= ~(atadev->unit == ATA_MASTER ? 0x35 : 0xca); - umode |= udmatimings[mode & ATA_MODE_MASK][atadev->unit]; - pci_write_config(gparent, ureg, umode, 1); - } - else if (mode >= ATA_WDMA0) { - int dmatimings[] = { 0x87, 0x32, 0x3f }; - - pci_write_config(gparent, treg, dmatimings[mode & ATA_MODE_MASK],1); - pci_write_config(gparent, ureg, - pci_read_config(gparent, ureg, 1) & - ~(atadev->unit == ATA_MASTER ? 0x35 : 0xca), 1); - } - else { - int piotimings[] = { 0xa9, 0x57, 0x44, 0x32, 0x3f }; - pci_write_config(gparent, treg, - piotimings[(mode & ATA_MODE_MASK) - ATA_PIO0], 1); - pci_write_config(gparent, ureg, - pci_read_config(gparent, ureg, 1) & - ~(atadev->unit == ATA_MASTER ? 0x35 : 0xca), 1); - } - atadev->mode = mode; - } -} - -static int -ata_sii_allocate(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int unit01 = (ch->unit & 1), unit10 = (ch->unit & 2); - int i; - - for (i = ATA_DATA; i <= ATA_COMMAND; i++) { - ch->r_io[i].res = ctlr->r_res2; - ch->r_io[i].offset = 0x80 + i + (unit01 << 6) + (unit10 << 8); - } - ch->r_io[ATA_CONTROL].res = ctlr->r_res2; - ch->r_io[ATA_CONTROL].offset = 0x8a + (unit01 << 6) + (unit10 << 8); - ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2; - ata_default_registers(dev); - - ch->r_io[ATA_BMCMD_PORT].res = ctlr->r_res2; - ch->r_io[ATA_BMCMD_PORT].offset = 0x00 + (unit01 << 3) + (unit10 << 8); - ch->r_io[ATA_BMSTAT_PORT].res = ctlr->r_res2; - ch->r_io[ATA_BMSTAT_PORT].offset = 0x02 + (unit01 << 3) + (unit10 << 8); - ch->r_io[ATA_BMDTP_PORT].res = ctlr->r_res2; - ch->r_io[ATA_BMDTP_PORT].offset = 0x04 + (unit01 << 3) + (unit10 << 8); - - if (ctlr->chip->max_dma >= ATA_SA150) { - ch->r_io[ATA_SSTATUS].res = ctlr->r_res2; - ch->r_io[ATA_SSTATUS].offset = 0x104 + (unit01 << 7) + (unit10 << 8); - ch->r_io[ATA_SERROR].res = ctlr->r_res2; - ch->r_io[ATA_SERROR].offset = 0x108 + (unit01 << 7) + (unit10 << 8); - ch->r_io[ATA_SCONTROL].res = ctlr->r_res2; - ch->r_io[ATA_SCONTROL].offset = 0x100 + (unit01 << 7) + (unit10 << 8); - ch->flags |= ATA_NO_SLAVE; - - /* enable PHY state change interrupt */ - ATA_OUTL(ctlr->r_res2, 0x148 + (unit01 << 7) + (unit10 << 8),(1 << 16)); - } - - if (ctlr->chip->cfg2 & SIIBUG) { - /* work around errata in early chips */ - ch->dma.boundary = 8192; - ch->dma.segsize = 15 * DEV_BSIZE; - } - - ata_pci_hw(dev); - ch->hw.status = ata_sii_status; - return 0; -} - -static int -ata_sii_status(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int offset0 = ((ch->unit & 1) << 3) + ((ch->unit & 2) << 8); - int offset1 = ((ch->unit & 1) << 6) + ((ch->unit & 2) << 8); - - /* do we have any PHY events ? */ - if (ctlr->chip->max_dma >= ATA_SA150 && - (ATA_INL(ctlr->r_res2, 0x10 + offset0) & 0x00000010)) - ata_sata_phy_check_events(dev); - - if (ATA_INL(ctlr->r_res2, 0xa0 + offset1) & 0x00000800) - return ata_pci_status(dev); - else - return 0; -} - -static void -ata_sii_reset(device_t dev) -{ - if (ata_sata_phy_reset(dev)) - ata_generic_reset(dev); -} - -static void -ata_sii_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int rego = (ch->unit << 4) + (atadev->unit << 1); - int mreg = ch->unit ? 0x84 : 0x80; - int mask = 0x03 << (atadev->unit << 2); - int mval = pci_read_config(gparent, mreg, 1) & ~mask; - int error; - - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - if (ctlr->chip->cfg2 & SIISETCLK) { - if (mode > ATA_UDMA2 && (pci_read_config(gparent, 0x79, 1) & - (ch->unit ? 0x02 : 0x01))) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - } - else - mode = ata_check_80pin(dev, mode); - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (error) - return; - - if (mode >= ATA_UDMA0) { - u_int8_t udmatimings[] = { 0xf, 0xb, 0x7, 0x5, 0x3, 0x2, 0x1 }; - u_int8_t ureg = 0xac + rego; - - pci_write_config(gparent, mreg, - mval | (0x03 << (atadev->unit << 2)), 1); - pci_write_config(gparent, ureg, - (pci_read_config(gparent, ureg, 1) & ~0x3f) | - udmatimings[mode & ATA_MODE_MASK], 1); - - } - else if (mode >= ATA_WDMA0) { - u_int8_t dreg = 0xa8 + rego; - u_int16_t dmatimings[] = { 0x2208, 0x10c2, 0x10c1 }; - - pci_write_config(gparent, mreg, - mval | (0x02 << (atadev->unit << 2)), 1); - pci_write_config(gparent, dreg, dmatimings[mode & ATA_MODE_MASK], 2); - - } - else { - u_int8_t preg = 0xa4 + rego; - u_int16_t piotimings[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 }; - - pci_write_config(gparent, mreg, - mval | (0x01 << (atadev->unit << 2)), 1); - pci_write_config(gparent, preg, piotimings[mode & ATA_MODE_MASK], 2); - } - atadev->mode = mode; -} - - -struct ata_siiprb_dma_prdentry { - u_int64_t addr; - u_int32_t count; - u_int32_t control; -} __packed; - -#define ATA_SIIPRB_DMA_ENTRIES 125 -struct ata_siiprb_ata_command { - struct ata_siiprb_dma_prdentry prd[ATA_SIIPRB_DMA_ENTRIES]; -} __packed; - -struct ata_siiprb_atapi_command { - u_int8_t ccb[16]; - struct ata_siiprb_dma_prdentry prd[ATA_SIIPRB_DMA_ENTRIES]; -} __packed; - -struct ata_siiprb_command { - u_int16_t control; - u_int16_t protocol_override; - u_int32_t transfer_count; - u_int8_t fis[24]; - union { - struct ata_siiprb_ata_command ata; - struct ata_siiprb_atapi_command atapi; - } u; -} __packed; - -static int -ata_siiprb_allocate(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int offset = ch->unit * 0x2000; - - /* set the SATA resources */ - ch->r_io[ATA_SSTATUS].res = ctlr->r_res2; - ch->r_io[ATA_SSTATUS].offset = 0x1f04 + offset; - ch->r_io[ATA_SERROR].res = ctlr->r_res2; - ch->r_io[ATA_SERROR].offset = 0x1f08 + offset; - ch->r_io[ATA_SCONTROL].res = ctlr->r_res2; - ch->r_io[ATA_SCONTROL].offset = 0x1f00 + offset; - ch->r_io[ATA_SACTIVE].res = ctlr->r_res2; - ch->r_io[ATA_SACTIVE].offset = 0x1f0c + offset; - - ch->hw.status = ata_siiprb_status; - ch->hw.begin_transaction = ata_siiprb_begin_transaction; - ch->hw.end_transaction = ata_siiprb_end_transaction; - ch->hw.command = NULL; /* not used here */ - ch->hw.softreset = ata_siiprb_softreset; - ch->hw.pm_read = ata_siiprb_pm_read; - ch->hw.pm_write = ata_siiprb_pm_write; - - return 0; -} - -static int -ata_siiprb_status(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - u_int32_t action = ATA_INL(ctlr->r_res1, 0x0044); - int offset = ch->unit * 0x2000; - - if (action & (1 << ch->unit)) { - u_int32_t istatus = ATA_INL(ctlr->r_res2, 0x1008 + offset); - - /* do we have any PHY events ? */ - ata_sata_phy_check_events(dev); - - /* clear interrupt(s) */ - ATA_OUTL(ctlr->r_res2, 0x1008 + offset, istatus); - - /* do we have any device action ? */ - return (istatus & 0x00000003); - } - return 0; -} - -static int -ata_siiprb_begin_transaction(struct ata_request *request) -{ - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); - struct ata_channel *ch = device_get_softc(request->parent); - struct ata_siiprb_command *prb; - struct ata_siiprb_dma_prdentry *prd; - int offset = ch->unit * 0x2000; - u_int64_t prb_bus; - - /* SOS XXX */ - if (request->u.ata.command == ATA_DEVICE_RESET) { - request->result = 0; - return ATA_OP_FINISHED; - } - - /* get a piece of the workspace for this request */ - prb = (struct ata_siiprb_command *) - (ch->dma.work + (sizeof(struct ata_siiprb_command) * request->tag)); - - /* set basic prd options ata/atapi etc etc */ - bzero(prb, sizeof(struct ata_siiprb_command)); - - /* setup the FIS for this request */ - if (!ata_request2fis_h2d(request, &prb->fis[0])) { - device_printf(request->dev, "setting up SATA FIS failed\n"); - request->result = EIO; - return ATA_OP_FINISHED; - } - - /* setup transfer type */ - if (request->flags & ATA_R_ATAPI) { - struct ata_device *atadev = device_get_softc(request->dev); - - bcopy(request->u.atapi.ccb, prb->u.atapi.ccb, 16); - if ((atadev->param.config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) - ATA_OUTL(ctlr->r_res2, 0x1004 + offset, 0x00000020); - else - ATA_OUTL(ctlr->r_res2, 0x1000 + offset, 0x00000020); - if (request->flags & ATA_R_READ) - prb->control = htole16(0x0010); - if (request->flags & ATA_R_WRITE) - prb->control = htole16(0x0020); - prd = &prb->u.atapi.prd[0]; - } - else - prd = &prb->u.ata.prd[0]; - - /* if request moves data setup and load SG list */ - if (request->flags & (ATA_R_READ | ATA_R_WRITE)) { - if (ch->dma.load(request, prd, NULL)) { - device_printf(request->dev, "setting up DMA failed\n"); - request->result = EIO; - return ATA_OP_FINISHED; - } - } - - /* activate the prb */ - prb_bus = ch->dma.work_bus + - (sizeof(struct ata_siiprb_command) * request->tag); - ATA_OUTL(ctlr->r_res2, - 0x1c00 + offset + (request->tag * sizeof(u_int64_t)), prb_bus); - ATA_OUTL(ctlr->r_res2, - 0x1c04 + offset + (request->tag * sizeof(u_int64_t)), prb_bus>>32); - - /* start the timeout */ - callout_reset(&request->callout, request->timeout * hz, - (timeout_t*)ata_timeout, request); - return ATA_OP_CONTINUES; -} - -static int -ata_siiprb_end_transaction(struct ata_request *request) -{ - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); - struct ata_channel *ch = device_get_softc(request->parent); - struct ata_siiprb_command *prb; - int offset = ch->unit * 0x2000; - int error, timeout; - - /* kill the timeout */ - callout_stop(&request->callout); - - prb = (struct ata_siiprb_command *) - ((u_int8_t *)rman_get_virtual(ctlr->r_res2)+(request->tag << 7)+offset); - - /* any controller errors flagged ? */ - if ((error = ATA_INL(ctlr->r_res2, 0x1024 + offset))) { - if (bootverbose) - printf("ata_siiprb_end_transaction %s error=%08x\n", - ata_cmd2str(request), error); - - /* if device error status get details */ - if (error == 1 || error == 2) { - request->status = prb->fis[2]; - if (request->status & ATA_S_ERROR) - request->error = prb->fis[3]; - } - - /* SOS XXX handle other controller errors here */ - - /* initialize port */ - ATA_OUTL(ctlr->r_res2, 0x1000 + offset, 0x00000004); - - /* poll for port ready */ - for (timeout = 0; timeout < 1000; timeout++) { - DELAY(1000); - if (ATA_INL(ctlr->r_res2, 0x1008 + offset) & 0x00040000) - break; - } - if (bootverbose) { - if (timeout >= 1000) - device_printf(ch->dev, "port initialize timeout\n"); - else - device_printf(ch->dev, "port initialize time=%dms\n", timeout); - } - } - - /* on control commands read back registers to the request struct */ - if (request->flags & ATA_R_CONTROL) { - struct ata_device *atadev = device_get_softc(request->dev); - - request->u.ata.count = prb->fis[12] | ((u_int16_t)prb->fis[13] << 8); - request->u.ata.lba = prb->fis[4] | ((u_int64_t)prb->fis[5] << 8) | - ((u_int64_t)prb->fis[6] << 16); - if (atadev->flags & ATA_D_48BIT_ACTIVE) - request->u.ata.lba |= ((u_int64_t)prb->fis[8] << 24) | - ((u_int64_t)prb->fis[9] << 32) | - ((u_int64_t)prb->fis[10] << 40); - else - request->u.ata.lba |= ((u_int64_t)(prb->fis[7] & 0x0f) << 24); - } - - /* update progress */ - if (!(request->status & ATA_S_ERROR) && !(request->flags & ATA_R_TIMEOUT)) { - if (request->flags & ATA_R_READ) - request->donecount = prb->transfer_count; - else - request->donecount = request->bytecount; - } - - /* release SG list etc */ - ch->dma.unload(request); - - return ATA_OP_FINISHED; -} - -static int -ata_siiprb_issue_cmd(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - u_int64_t prb_bus = ch->dma.work_bus; - u_int32_t status; - int offset = ch->unit * 0x2000; - int timeout; - - /* issue command to chip */ - ATA_OUTL(ctlr->r_res2, 0x1c00 + offset, prb_bus); - ATA_OUTL(ctlr->r_res2, 0x1c04 + offset, prb_bus >> 32); - - /* poll for command finished */ - for (timeout = 0; timeout < 10000; timeout++) { - DELAY(1000); - if ((status = ATA_INL(ctlr->r_res2, 0x1008 + offset)) & 0x00010000) - break; - } - ATA_OUTL(ctlr->r_res2, 0x1008 + offset, 0x00010000); - - if (timeout >= 1000) - return EIO; - - if (bootverbose) - device_printf(dev, "siiprb_issue_cmd time=%dms status=%08x\n", - timeout, status); - return 0; -} - -static int -ata_siiprb_pm_read(device_t dev, int port, int reg, u_int32_t *result) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - struct ata_siiprb_command *prb = (struct ata_siiprb_command *)ch->dma.work; - int offset = ch->unit * 0x2000; - - bzero(prb, sizeof(struct ata_siiprb_command)); - prb->fis[0] = 0x27; /* host to device */ - prb->fis[1] = 0x8f; /* command FIS to PM port */ - prb->fis[2] = ATA_READ_PM; - prb->fis[3] = reg; - prb->fis[7] = port; - if (ata_siiprb_issue_cmd(dev)) { - device_printf(dev, "error reading PM port\n"); - return EIO; - } - prb = (struct ata_siiprb_command *) - ((u_int8_t *)rman_get_virtual(ctlr->r_res2) + offset); - *result = prb->fis[12]|(prb->fis[4]<<8)|(prb->fis[5]<<16)|(prb->fis[6]<<24); - return 0; -} - -static int -ata_siiprb_pm_write(device_t dev, int port, int reg, u_int32_t value) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - struct ata_siiprb_command *prb = (struct ata_siiprb_command *)ch->dma.work; - int offset = ch->unit * 0x2000; - - bzero(prb, sizeof(struct ata_siiprb_command)); - prb->fis[0] = 0x27; /* host to device */ - prb->fis[1] = 0x8f; /* command FIS to PM port */ - prb->fis[2] = ATA_WRITE_PM; - prb->fis[3] = reg; - prb->fis[7] = port; - prb->fis[12] = value & 0xff; - prb->fis[4] = (value >> 8) & 0xff;; - prb->fis[5] = (value >> 16) & 0xff;; - prb->fis[6] = (value >> 24) & 0xff;; - if (ata_siiprb_issue_cmd(dev)) { - device_printf(dev, "error writing PM port\n"); - return ATA_E_ABORT; - } - prb = (struct ata_siiprb_command *) - ((u_int8_t *)rman_get_virtual(ctlr->r_res2) + offset); - return prb->fis[3]; -} - -static u_int32_t -ata_siiprb_softreset(device_t dev, int port) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - struct ata_siiprb_command *prb = (struct ata_siiprb_command *)ch->dma.work; - int offset = ch->unit * 0x2000; - - /* setup the workspace for a soft reset command */ - bzero(prb, sizeof(struct ata_siiprb_command)); - prb->control = htole16(0x0080); - prb->fis[1] = port & 0x0f; - - /* issue soft reset */ - if (ata_siiprb_issue_cmd(dev)) - return -1; - - ata_udelay(150000); - - /* return possible signature */ - prb = (struct ata_siiprb_command *) - ((u_int8_t *)rman_get_virtual(ctlr->r_res2) + offset); - return prb->fis[12]|(prb->fis[4]<<8)|(prb->fis[5]<<16)|(prb->fis[6]<<24); -} - -static void -ata_siiprb_reset(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int offset = ch->unit * 0x2000; - u_int32_t status, signature; - int timeout; - - /* reset channel HW */ - ATA_OUTL(ctlr->r_res2, 0x1000 + offset, 0x00000001); - DELAY(1000); - ATA_OUTL(ctlr->r_res2, 0x1004 + offset, 0x00000001); - DELAY(10000); - - /* poll for channel ready */ - for (timeout = 0; timeout < 1000; timeout++) { - if ((status = ATA_INL(ctlr->r_res2, 0x1008 + offset)) & 0x00040000) - break; - DELAY(1000); - } - - if (bootverbose) { - if (timeout >= 1000) - device_printf(dev, "channel HW reset timeout\n"); - else - device_printf(dev, "channel HW reset time=%dms\n", timeout); - } - - /* reset phy */ - if (!ata_sata_phy_reset(dev)) { - if (bootverbose) - device_printf(dev, "phy reset found no device\n"); - ch->devices = 0; - goto finish; - } - - /* issue soft reset */ - signature = ata_siiprb_softreset(dev, ATA_PM); - if (bootverbose) - device_printf(dev, "SIGNATURE=%08x\n", signature); - - /* figure out whats there */ - switch (signature) { - case 0x00000101: - ch->devices = ATA_ATA_MASTER; - break; - case 0x96690101: - ch->devices = ATA_PORTMULTIPLIER; - ATA_OUTL(ctlr->r_res2, 0x1000 + offset, 0x2000); /* enable PM support */ - ata_pm_identify(dev); - break; - case 0xeb140101: - ch->devices = ATA_ATAPI_MASTER; - break; - default: - ch->devices = 0; - } - if (bootverbose) - device_printf(dev, "siiprb_reset devices=%08x\n", ch->devices); - -finish: - /* clear interrupt(s) */ - ATA_OUTL(ctlr->r_res2, 0x1008 + offset, 0x000008ff); - - /* require explicit interrupt ack */ - ATA_OUTL(ctlr->r_res2, 0x1000 + offset, 0x00000008); - - /* 64bit mode */ - ATA_OUTL(ctlr->r_res2, 0x1004 + offset, 0x00000400); - - /* enable interrupts wanted */ - ATA_OUTL(ctlr->r_res2, 0x1010 + offset, 0x000000ff); -} - -static void -ata_siiprb_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) -{ - struct ata_dmasetprd_args *args = xsc; - struct ata_siiprb_dma_prdentry *prd = args->dmatab; - int i; - - if ((args->error = error)) - return; - - for (i = 0; i < nsegs; i++) { - prd[i].addr = htole64(segs[i].ds_addr); - prd[i].count = htole32(segs[i].ds_len); - } - prd[i - 1].control = htole32(ATA_DMA_EOT); - KASSERT(nsegs <= ATA_SIIPRB_DMA_ENTRIES,("too many DMA segment entries\n")); - args->nsegs = nsegs; -} - -static void -ata_siiprb_dmainit(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - - ata_dmainit(dev); - /* note start and stop are not used here */ - ch->dma.setprd = ata_siiprb_dmasetprd; - ch->dma.max_address = BUS_SPACE_MAXADDR; -} - - -/* - * Silicon Integrated Systems Corp. (SiS) chipset support functions - */ -int -ata_sis_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - struct ata_chip_id *idx; - static struct ata_chip_id ids[] = - {{ ATA_SIS182, 0x00, SISSATA, 0, ATA_SA150, "182" }, /* south */ - { ATA_SIS181, 0x00, SISSATA, 0, ATA_SA150, "181" }, /* south */ - { ATA_SIS180, 0x00, SISSATA, 0, ATA_SA150, "180" }, /* south */ - { ATA_SIS965, 0x00, SIS133NEW, 0, ATA_UDMA6, "965" }, /* south */ - { ATA_SIS964, 0x00, SIS133NEW, 0, ATA_UDMA6, "964" }, /* south */ - { ATA_SIS963, 0x00, SIS133NEW, 0, ATA_UDMA6, "963" }, /* south */ - { ATA_SIS962, 0x00, SIS133NEW, 0, ATA_UDMA6, "962" }, /* south */ - - { ATA_SIS745, 0x00, SIS100NEW, 0, ATA_UDMA5, "745" }, /* 1chip */ - { ATA_SIS735, 0x00, SIS100NEW, 0, ATA_UDMA5, "735" }, /* 1chip */ - { ATA_SIS733, 0x00, SIS100NEW, 0, ATA_UDMA5, "733" }, /* 1chip */ - { ATA_SIS730, 0x00, SIS100OLD, 0, ATA_UDMA5, "730" }, /* 1chip */ - - { ATA_SIS635, 0x00, SIS100NEW, 0, ATA_UDMA5, "635" }, /* 1chip */ - { ATA_SIS633, 0x00, SIS100NEW, 0, ATA_UDMA5, "633" }, /* unknown */ - { ATA_SIS630, 0x30, SIS100OLD, 0, ATA_UDMA5, "630S"}, /* 1chip */ - { ATA_SIS630, 0x00, SIS66, 0, ATA_UDMA4, "630" }, /* 1chip */ - { ATA_SIS620, 0x00, SIS66, 0, ATA_UDMA4, "620" }, /* 1chip */ - - { ATA_SIS550, 0x00, SIS66, 0, ATA_UDMA5, "550" }, - { ATA_SIS540, 0x00, SIS66, 0, ATA_UDMA4, "540" }, - { ATA_SIS530, 0x00, SIS66, 0, ATA_UDMA4, "530" }, - - { ATA_SIS5513, 0xc2, SIS33, 1, ATA_UDMA2, "5513" }, - { ATA_SIS5513, 0x00, SIS33, 1, ATA_WDMA2, "5513" }, - { 0, 0, 0, 0, 0, 0 }}; - char buffer[64]; - int found = 0; - - if (!(idx = ata_find_chip(dev, ids, -pci_get_slot(dev)))) - return ENXIO; - - if (idx->cfg2 && !found) { - u_int8_t reg57 = pci_read_config(dev, 0x57, 1); - - pci_write_config(dev, 0x57, (reg57 & 0x7f), 1); - if (pci_read_config(dev, PCIR_DEVVENDOR, 4) == ATA_SIS5518) { - found = 1; - idx->cfg1 = SIS133NEW; - idx->max_dma = ATA_UDMA6; - sprintf(buffer, "SiS 962/963 %s controller", - ata_mode2str(idx->max_dma)); - } - pci_write_config(dev, 0x57, reg57, 1); - } - if (idx->cfg2 && !found) { - u_int8_t reg4a = pci_read_config(dev, 0x4a, 1); - - pci_write_config(dev, 0x4a, (reg4a | 0x10), 1); - if (pci_read_config(dev, PCIR_DEVVENDOR, 4) == ATA_SIS5517) { - struct ata_chip_id id[] = - {{ ATA_SISSOUTH, 0x10, 0, 0, 0, "" }, { 0, 0, 0, 0, 0, 0 }}; - - found = 1; - if (ata_find_chip(dev, id, pci_get_slot(dev))) { - idx->cfg1 = SIS133OLD; - idx->max_dma = ATA_UDMA6; - } - else { - idx->cfg1 = SIS100NEW; - idx->max_dma = ATA_UDMA5; - } - sprintf(buffer, "SiS 961 %s controller",ata_mode2str(idx->max_dma)); - } - pci_write_config(dev, 0x4a, reg4a, 1); - } - if (!found) - sprintf(buffer,"SiS %s %s controller", - idx->text, ata_mode2str(idx->max_dma)); - - device_set_desc_copy(dev, buffer); - ctlr->chip = idx; - ctlr->chipinit = ata_sis_chipinit; - return 0; -} - -static int -ata_sis_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - switch (ctlr->chip->cfg1) { - case SIS33: - break; - case SIS66: - case SIS100OLD: - pci_write_config(dev, 0x52, pci_read_config(dev, 0x52, 1) & ~0x04, 1); - break; - case SIS100NEW: - case SIS133OLD: - pci_write_config(dev, 0x49, pci_read_config(dev, 0x49, 1) & ~0x01, 1); - break; - case SIS133NEW: - pci_write_config(dev, 0x50, pci_read_config(dev, 0x50, 2) | 0x0008, 2); - pci_write_config(dev, 0x52, pci_read_config(dev, 0x52, 2) | 0x0008, 2); - break; - case SISSATA: - ctlr->r_type2 = SYS_RES_IOPORT; - ctlr->r_rid2 = PCIR_BAR(5); - if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, - &ctlr->r_rid2, RF_ACTIVE))) { - ctlr->allocate = ata_sis_allocate; - ctlr->reset = ata_sis_reset; - - /* enable PCI interrupt */ - pci_write_config(dev, PCIR_COMMAND, - pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400,2); - } - ctlr->setmode = ata_sata_setmode; - return 0; - default: - return ENXIO; - } - ctlr->setmode = ata_sis_setmode; - return 0; -} - -static int -ata_sis_allocate(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int offset = ch->unit << ((ctlr->chip->chipid == ATA_SIS182) ? 5 : 6); - - /* setup the usual register normal pci style */ - if (ata_pci_allocate(dev)) - return ENXIO; - - ch->r_io[ATA_SSTATUS].res = ctlr->r_res2; - ch->r_io[ATA_SSTATUS].offset = 0x00 + offset; - ch->r_io[ATA_SERROR].res = ctlr->r_res2; - ch->r_io[ATA_SERROR].offset = 0x04 + offset; - ch->r_io[ATA_SCONTROL].res = ctlr->r_res2; - ch->r_io[ATA_SCONTROL].offset = 0x08 + offset; - ch->flags |= ATA_NO_SLAVE; - - /* XXX SOS PHY hotplug handling missing in SiS chip ?? */ - /* XXX SOS unknown how to enable PHY state change interrupt */ - return 0; -} - -static void -ata_sis_reset(device_t dev) -{ - if (ata_sata_phy_reset(dev)) - ata_generic_reset(dev); -} - -static void -ata_sis_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int error; - - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - if (ctlr->chip->cfg1 == SIS133NEW) { - if (mode > ATA_UDMA2 && - pci_read_config(gparent, ch->unit ? 0x52 : 0x50,2) & 0x8000) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - } - else { - if (mode > ATA_UDMA2 && - pci_read_config(gparent, 0x48, 1)&(ch->unit ? 0x20 : 0x10)) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - } - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { - switch (ctlr->chip->cfg1) { - case SIS133NEW: { - u_int32_t timings[] = - { 0x28269008, 0x0c266008, 0x04263008, 0x0c0a3008, 0x05093008, - 0x22196008, 0x0c0a3008, 0x05093008, 0x050939fc, 0x050936ac, - 0x0509347c, 0x0509325c, 0x0509323c, 0x0509322c, 0x0509321c}; - u_int32_t reg; - - reg = (pci_read_config(gparent, 0x57, 1)&0x40?0x70:0x40)+(devno<<2); - pci_write_config(gparent, reg, timings[ata_mode2idx(mode)], 4); - break; - } - case SIS133OLD: { - u_int16_t timings[] = - { 0x00cb, 0x0067, 0x0044, 0x0033, 0x0031, 0x0044, 0x0033, 0x0031, - 0x8f31, 0x8a31, 0x8731, 0x8531, 0x8331, 0x8231, 0x8131 }; - - u_int16_t reg = 0x40 + (devno << 1); - - pci_write_config(gparent, reg, timings[ata_mode2idx(mode)], 2); - break; - } - case SIS100NEW: { - u_int16_t timings[] = - { 0x00cb, 0x0067, 0x0044, 0x0033, 0x0031, 0x0044, 0x0033, - 0x0031, 0x8b31, 0x8731, 0x8531, 0x8431, 0x8231, 0x8131 }; - u_int16_t reg = 0x40 + (devno << 1); - - pci_write_config(gparent, reg, timings[ata_mode2idx(mode)], 2); - break; - } - case SIS100OLD: - case SIS66: - case SIS33: { - u_int16_t timings[] = - { 0x0c0b, 0x0607, 0x0404, 0x0303, 0x0301, 0x0404, 0x0303, - 0x0301, 0xf301, 0xd301, 0xb301, 0xa301, 0x9301, 0x8301 }; - u_int16_t reg = 0x40 + (devno << 1); - - pci_write_config(gparent, reg, timings[ata_mode2idx(mode)], 2); - break; - } - } - atadev->mode = mode; - } -} - - -/* VIA Technologies Inc. chipset support functions */ -int -ata_via_ident(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - static struct ata_chip_id ids[] = - {{ ATA_VIA82C586, 0x02, VIA33, 0x00, ATA_UDMA2, "82C586B" }, - { ATA_VIA82C586, 0x00, VIA33, 0x00, ATA_WDMA2, "82C586" }, - { ATA_VIA82C596, 0x12, VIA66, VIACLK, ATA_UDMA4, "82C596B" }, - { ATA_VIA82C596, 0x00, VIA33, 0x00, ATA_UDMA2, "82C596" }, - { ATA_VIA82C686, 0x40, VIA100, VIABUG, ATA_UDMA5, "82C686B"}, - { ATA_VIA82C686, 0x10, VIA66, VIACLK, ATA_UDMA4, "82C686A" }, - { ATA_VIA82C686, 0x00, VIA33, 0x00, ATA_UDMA2, "82C686" }, - { ATA_VIA8231, 0x00, VIA100, VIABUG, ATA_UDMA5, "8231" }, - { ATA_VIA8233, 0x00, VIA100, 0x00, ATA_UDMA5, "8233" }, - { ATA_VIA8233C, 0x00, VIA100, 0x00, ATA_UDMA5, "8233C" }, - { ATA_VIA8233A, 0x00, VIA133, 0x00, ATA_UDMA6, "8233A" }, - { ATA_VIA8235, 0x00, VIA133, 0x00, ATA_UDMA6, "8235" }, - { ATA_VIA8237, 0x00, VIA133, 0x00, ATA_UDMA6, "8237" }, - { ATA_VIA8237A, 0x00, VIA133, 0x00, ATA_UDMA6, "8237A" }, - { ATA_VIA8237S, 0x00, VIA133, 0x00, ATA_UDMA6, "8237S" }, - { ATA_VIA8251, 0x00, VIA133, 0x00, ATA_UDMA6, "8251" }, - { 0, 0, 0, 0, 0, 0 }}; - static struct ata_chip_id new_ids[] = - {{ ATA_VIA6410, 0x00, 0, 0x00, ATA_UDMA6, "6410" }, - { ATA_VIA6420, 0x00, 7, 0x00, ATA_SA150, "6420" }, - { ATA_VIA6421, 0x00, 6, VIABAR, ATA_SA150, "6421" }, - { ATA_VIA8237A, 0x00, 7, 0x00, ATA_SA150, "8237A" }, - { ATA_VIA8237S, 0x00, 7, 0x00, ATA_SA150, "8237S" }, - { ATA_VIA8251, 0x00, 0, VIAAHCI, ATA_SA300, "8251" }, - { 0, 0, 0, 0, 0, 0 }}; - - if (pci_get_devid(dev) == ATA_VIA82C571) { - if (!(ctlr->chip = ata_find_chip(dev, ids, -99))) - return ENXIO; - } - else { - if (!(ctlr->chip = ata_match_chip(dev, new_ids))) - return ENXIO; - } - - ata_set_desc(dev); - ctlr->chipinit = ata_via_chipinit; - return 0; -} - -static int -ata_via_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev)) - return ENXIO; - - if (ctlr->chip->max_dma >= ATA_SA150) { - /* do we have AHCI capability ? */ - if ((ctlr->chip->cfg2 == VIAAHCI) && ata_ahci_chipinit(dev) != ENXIO) - return 0; - - ctlr->r_type2 = SYS_RES_IOPORT; - ctlr->r_rid2 = PCIR_BAR(5); - if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, - &ctlr->r_rid2, RF_ACTIVE))) { - ctlr->allocate = ata_via_allocate; - ctlr->reset = ata_via_reset; - - /* enable PCI interrupt */ - pci_write_config(dev, PCIR_COMMAND, - pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400,2); - } - - if (ctlr->chip->cfg2 & VIABAR) { - ctlr->channels = 3; - ctlr->setmode = ata_via_setmode; - } - else - ctlr->setmode = ata_sata_setmode; - return 0; - } - - /* prepare for ATA-66 on the 82C686a and 82C596b */ - if (ctlr->chip->cfg2 & VIACLK) - pci_write_config(dev, 0x50, 0x030b030b, 4); - - /* the southbridge might need the data corruption fix */ - if (ctlr->chip->cfg2 & VIABUG) - ata_via_southbridge_fixup(dev); - - /* set fifo configuration half'n'half */ - pci_write_config(dev, 0x43, - (pci_read_config(dev, 0x43, 1) & 0x90) | 0x2a, 1); - - /* set status register read retry */ - pci_write_config(dev, 0x44, pci_read_config(dev, 0x44, 1) | 0x08, 1); - - /* set DMA read & end-of-sector fifo flush */ - pci_write_config(dev, 0x46, - (pci_read_config(dev, 0x46, 1) & 0x0c) | 0xf0, 1); - - /* set sector size */ - pci_write_config(dev, 0x60, DEV_BSIZE, 2); - pci_write_config(dev, 0x68, DEV_BSIZE, 2); - - ctlr->setmode = ata_via_family_setmode; - return 0; -} - -static int -ata_via_allocate(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - - /* newer SATA chips has resources in one BAR for each channel */ - if (ctlr->chip->cfg2 & VIABAR) { - struct resource *r_io; - int i, rid; - - rid = PCIR_BAR(ch->unit); - if (!(r_io = bus_alloc_resource_any(device_get_parent(dev), - SYS_RES_IOPORT, - &rid, RF_ACTIVE))) - return ENXIO; - - for (i = ATA_DATA; i <= ATA_COMMAND; i ++) { - ch->r_io[i].res = r_io; - ch->r_io[i].offset = i; - } - ch->r_io[ATA_CONTROL].res = r_io; - ch->r_io[ATA_CONTROL].offset = 2 + ATA_IOSIZE; - ch->r_io[ATA_IDX_ADDR].res = r_io; - ata_default_registers(dev); - for (i = ATA_BMCMD_PORT; i <= ATA_BMDTP_PORT; i++) { - ch->r_io[i].res = ctlr->r_res1; - ch->r_io[i].offset = (i - ATA_BMCMD_PORT)+(ch->unit * ATA_BMIOSIZE); - } - ata_pci_hw(dev); - if (ch->unit >= 2) - return 0; - } - else { - /* setup the usual register normal pci style */ - if (ata_pci_allocate(dev)) - return ENXIO; - } - - ch->r_io[ATA_SSTATUS].res = ctlr->r_res2; - ch->r_io[ATA_SSTATUS].offset = (ch->unit << ctlr->chip->cfg1); - ch->r_io[ATA_SERROR].res = ctlr->r_res2; - ch->r_io[ATA_SERROR].offset = 0x04 + (ch->unit << ctlr->chip->cfg1); - ch->r_io[ATA_SCONTROL].res = ctlr->r_res2; - ch->r_io[ATA_SCONTROL].offset = 0x08 + (ch->unit << ctlr->chip->cfg1); - ch->flags |= ATA_NO_SLAVE; - - /* XXX SOS PHY hotplug handling missing in VIA chip ?? */ - /* XXX SOS unknown how to enable PHY state change interrupt */ - return 0; -} - -static void -ata_via_reset(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - - if ((ctlr->chip->cfg2 & VIABAR) && (ch->unit > 1)) - ata_generic_reset(dev); - else - if (ata_sata_phy_reset(dev)) - ata_generic_reset(dev); -} - -static void -ata_via_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int error; - - if ((ctlr->chip->cfg2 & VIABAR) && (ch->unit > 1)) { - u_int8_t pio_timings[] = { 0xa8, 0x65, 0x65, 0x32, 0x20, - 0x65, 0x32, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; - u_int8_t dma_timings[] = { 0xee, 0xe8, 0xe6, 0xe4, 0xe2, 0xe1, 0xe0 }; - - mode = ata_check_80pin(dev, ata_limit_mode(dev, mode, ATA_UDMA6)); - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", ata_mode2str(mode), - ctlr->chip->text); - if (!error) { - pci_write_config(gparent, 0xab, pio_timings[ata_mode2idx(mode)], 1); - if (mode >= ATA_UDMA0) - pci_write_config(gparent, 0xb3, - dma_timings[mode & ATA_MODE_MASK], 1); - atadev->mode = mode; - } - } - else - ata_sata_setmode(dev, mode); -} - -static void -ata_via_southbridge_fixup(device_t dev) -{ - device_t *children; - int nchildren, i; - - if (device_get_children(device_get_parent(dev), &children, &nchildren)) - return; - - for (i = 0; i < nchildren; i++) { - if (pci_get_devid(children[i]) == ATA_VIA8363 || - pci_get_devid(children[i]) == ATA_VIA8371 || - pci_get_devid(children[i]) == ATA_VIA8662 || - pci_get_devid(children[i]) == ATA_VIA8361) { - u_int8_t reg76 = pci_read_config(children[i], 0x76, 1); - - if ((reg76 & 0xf0) != 0xd0) { - device_printf(dev, - "Correcting VIA config for southbridge data corruption bug\n"); - pci_write_config(children[i], 0x75, 0x80, 1); - pci_write_config(children[i], 0x76, (reg76 & 0x0f) | 0xd0, 1); - } - break; - } - } - free(children, M_TEMP); -} - - -/* common code for VIA, AMD & nVidia */ -static void -ata_via_family_setmode(device_t dev, int mode) -{ - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - u_int8_t timings[] = { 0xa8, 0x65, 0x42, 0x22, 0x20, 0x42, 0x22, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; - int modes[][7] = { - { 0xc2, 0xc1, 0xc0, 0x00, 0x00, 0x00, 0x00 }, /* VIA ATA33 */ - { 0xee, 0xec, 0xea, 0xe9, 0xe8, 0x00, 0x00 }, /* VIA ATA66 */ - { 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0, 0x00 }, /* VIA ATA100 */ - { 0xf7, 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0 }, /* VIA ATA133 */ - { 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 0xc7 }}; /* AMD/nVIDIA */ - int devno = (ch->unit << 1) + atadev->unit; - int reg = 0x53 - devno; - int error; - - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - if (ctlr->chip->cfg2 & AMDCABLE) { - if (mode > ATA_UDMA2 && - !(pci_read_config(gparent, 0x42, 1) & (1 << devno))) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - } - else - mode = ata_check_80pin(dev, mode); - - if (ctlr->chip->cfg2 & NVIDIA) - reg += 0x10; - - if (ctlr->chip->cfg1 != VIA133) - pci_write_config(gparent, reg - 0x08, timings[ata_mode2idx(mode)], 1); - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", ata_mode2str(mode), - ctlr->chip->text); - if (!error) { - if (mode >= ATA_UDMA0) - pci_write_config(gparent, reg, - modes[ctlr->chip->cfg1][mode & ATA_MODE_MASK], 1); - else - pci_write_config(gparent, reg, 0x8b, 1); - atadev->mode = mode; - } -} - - /* misc functions */ -static void +void ata_set_desc(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(dev); @@ -6385,7 +472,7 @@ device_set_desc_copy(dev, buffer); } -static struct ata_chip_id * +struct ata_chip_id * ata_match_chip(device_t dev, struct ata_chip_id *index) { while (index->chipid != 0) { @@ -6397,7 +484,7 @@ return NULL; } -static struct ata_chip_id * +struct ata_chip_id * ata_find_chip(device_t dev, struct ata_chip_id *index, int slot) { device_t *children; @@ -6422,7 +509,7 @@ return NULL; } -static int +int ata_setup_interrupt(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(dev); @@ -6444,72 +531,15 @@ return 0; } -struct ata_serialize { - struct mtx locked_mtx; - int locked_ch; - int restart_ch; -}; -static int -ata_serialize(device_t dev, int flags) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - struct ata_serialize *serial; - static int inited = 0; - int res; - - if (!inited) { - serial = malloc(sizeof(struct ata_serialize), - M_TEMP, M_NOWAIT | M_ZERO); - mtx_init(&serial->locked_mtx, "ATA serialize lock", NULL, MTX_DEF); - serial->locked_ch = -1; - serial->restart_ch = -1; - device_set_ivars(ctlr->dev, serial); - inited = 1; - } - else - serial = device_get_ivars(ctlr->dev); - - mtx_lock(&serial->locked_mtx); - switch (flags) { - case ATA_LF_LOCK: - if (serial->locked_ch == -1) - serial->locked_ch = ch->unit; - if (serial->locked_ch != ch->unit) - serial->restart_ch = ch->unit; - break; - - case ATA_LF_UNLOCK: - if (serial->locked_ch == ch->unit) { - serial->locked_ch = -1; - if (serial->restart_ch != -1) { - if ((ch = ctlr->interrupt[serial->restart_ch].argument)) { - serial->restart_ch = -1; - mtx_unlock(&serial->locked_mtx); - ata_start(dev); - return -1; - } - } - } - break; - - case ATA_LF_WHICH: - break; - } - res = serial->locked_ch; - mtx_unlock(&serial->locked_mtx); - return res; -} - -static void +void ata_print_cable(device_t dev, u_int8_t *who) { device_printf(dev, "DMA limited to UDMA33, %s found non-ATA66 cable\n", who); } -static int +int ata_atapi(device_t dev) { struct ata_channel *ch = device_get_softc(device_get_parent(dev)); @@ -6537,7 +567,7 @@ return mode; } -static int +int ata_mode2idx(int mode) { if ((mode & ATA_DMA_MASK) == ATA_UDMA0) @@ -6546,3 +576,15 @@ return (mode & ATA_MODE_MASK) + 5; return (mode & ATA_MODE_MASK) - ATA_PIO0; } + +/* + * Dummy chipset entry. It's required to satisfy linker + * if tehre are no other chipsets + */ +static int ata_dummy_ident(device_t dev) +{ + + return ENXIO; +} + +ATA_CHIPSET(dummy, ata_dummy_ident); === dev/ata/ata-pci.c ================================================================== --- dev/ata/ata-pci.c (revision 183565) +++ dev/ata/ata-pci.c (local) @@ -54,7 +54,6 @@ /* misc defines */ #define IOMASK 0xfffffffc -#define ATA_PROBE_OK -10 int ata_legacy(device_t dev) @@ -76,118 +75,7 @@ if (pci_get_class(dev) != PCIC_STORAGE) return ENXIO; - /* if this is an AHCI chipset grab it */ - if (pci_get_subclass(dev) == PCIS_STORAGE_SATA) { - if (!ata_ahci_ident(dev)) - return ATA_PROBE_OK; - } - - /* run through the vendor specific drivers */ - switch (pci_get_vendor(dev)) { - case ATA_ACARD_ID: - if (!ata_acard_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_ACER_LABS_ID: - if (!ata_ali_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_AMD_ID: - if (!ata_amd_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_ADAPTEC_ID: - if (!ata_adaptec_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_ATI_ID: - if (!ata_ati_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_CYRIX_ID: - if (!ata_cyrix_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_CYPRESS_ID: - if (!ata_cypress_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_HIGHPOINT_ID: - if (!ata_highpoint_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_INTEL_ID: - if (!ata_intel_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_ITE_ID: - if (!ata_ite_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_JMICRON_ID: - if (!ata_jmicron_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_MARVELL_ID: - if (!ata_marvell_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_NATIONAL_ID: - if (!ata_national_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_NETCELL_ID: - if (!ata_netcell_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_NVIDIA_ID: - if (!ata_nvidia_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_PROMISE_ID: - if (!ata_promise_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_SERVERWORKS_ID: - if (!ata_serverworks_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_SILICON_IMAGE_ID: - if (!ata_sii_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_SIS_ID: - if (!ata_sis_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_VIA_ID: - if (!ata_via_ident(dev)) - return ATA_PROBE_OK; - break; - case ATA_CENATEK_ID: - if (pci_get_devid(dev) == ATA_CENATEK_ROCKET) { - ata_generic_ident(dev); - device_set_desc(dev, "Cenatek Rocket Drive controller"); - return ATA_PROBE_OK; - } - break; - case ATA_MICRON_ID: - if (pci_get_devid(dev) == ATA_MICRON_RZ1000 || - pci_get_devid(dev) == ATA_MICRON_RZ1001) { - ata_generic_ident(dev); - device_set_desc(dev, - "RZ 100? ATA controller !WARNING! data loss/corruption risk"); - return ATA_PROBE_OK; - } - break; - } - - /* unknown chipset, try generic DMA if it seems possible */ - if (pci_get_subclass(dev) == PCIS_STORAGE_IDE) { - if (!ata_generic_ident(dev)) - return ATA_PROBE_OK; - } - return ENXIO; + return ata_chipset_ident(dev); } int === dev/ata/ata-pci.h ================================================================== --- dev/ata/ata-pci.h (revision 183565) +++ dev/ata/ata-pci.h (local) @@ -487,27 +487,43 @@ /* global prototypes ata-chipset.c */ int ata_generic_ident(device_t); +int ata_ahci_chipinit(device_t); int ata_ahci_ident(device_t); -int ata_acard_ident(device_t); -int ata_ali_ident(device_t); -int ata_amd_ident(device_t); -int ata_adaptec_ident(device_t); -int ata_ati_ident(device_t); -int ata_cyrix_ident(device_t); -int ata_cypress_ident(device_t); -int ata_highpoint_ident(device_t); -int ata_intel_ident(device_t); -int ata_ite_ident(device_t); -int ata_jmicron_ident(device_t); -int ata_marvell_ident(device_t); -int ata_national_ident(device_t); -int ata_nvidia_ident(device_t); -int ata_netcell_ident(device_t); -int ata_promise_ident(device_t); -int ata_serverworks_ident(device_t); -int ata_sii_ident(device_t); -int ata_sis_ident(device_t); -int ata_via_ident(device_t); + +int ata_chipset_ident(device_t dev); +int ata_atapi(device_t dev); +void ata_pm_identify(device_t dev); +void ata_sata_phy_check_events(device_t dev); +void ata_sata_phy_event(void *context, int dummy); +int ata_sata_phy_reset(device_t dev); +int ata_sata_connect(struct ata_channel *ch); +void ata_sata_setmode(device_t dev, int mode); +void ata_set_desc(device_t dev); +struct ata_chip_id *ata_match_chip(device_t dev, struct ata_chip_id *index); +struct ata_chip_id *ata_find_chip(device_t dev, struct ata_chip_id *index, int slot); +int ata_mode2idx(int mode); +int ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis); +int ata_setup_interrupt(device_t dev); +void ata_print_cable(device_t dev, u_int8_t *who); + +/* chipset handling structs/macroses */ +typedef int ata_chipset_identfunc_t(device_t); +typedef struct ata_chipset_info { + SLIST_ENTRY(ata_chipset_info) link; + char *name; + ata_chipset_identfunc_t *ident_func; + +} ata_chipset_info_t; + +#define ATA_CHIPSET(name, ident_func) \ + \ + static struct ata_chipset_info ata_chipset_##name##_info = { \ + { NULL }, #name, ident_func \ + }; \ + DATA_SET(ata_chipset_set, ata_chipset_##name##_info); + +void ata_chipset_register(const void *); + int ata_legacy(device_t); /* global prototypes ata-dma.c */ === dev/ata/chipsets (new directory) ================================================================== === dev/ata/chipsets/ata-ahci.c ================================================================== --- dev/ata/chipsets/ata-ahci.c (revision 183565) +++ dev/ata/chipsets/ata-ahci.c (local) @@ -0,0 +1,736 @@ +/*- + * Copyright (c) 2008, Oleksandr Tymoshenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static int ata_ahci_ctlr_reset(device_t dev); +static int ata_ahci_suspend(device_t dev); +static int ata_ahci_allocate(device_t dev); +static int ata_ahci_status(device_t dev); +static int ata_ahci_begin_transaction(struct ata_request *request); +static int ata_ahci_end_transaction(struct ata_request *request); +static int ata_ahci_pm_read(device_t dev, int port, int reg, u_int32_t *result); +static int ata_ahci_pm_write(device_t dev, int port, int reg, u_int32_t result); +static u_int32_t ata_ahci_softreset(device_t dev, int port); +static void ata_ahci_reset(device_t dev); +static void ata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); +static void ata_ahci_dmainit(device_t dev); +static int ata_ahci_setup_fis(struct ata_ahci_cmd_tab *ctp, struct ata_request *request); + +/* + * AHCI v1.x compliant SATA chipset support functions + */ +int +ata_ahci_ident(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + char buffer[64]; + + /* is this PCI device flagged as an AHCI compliant chip ? */ + if (pci_read_config(dev, PCIR_PROGIF, 1) != PCIP_STORAGE_SATA_AHCI_1_0) + return ENXIO; + + if (bootverbose) + sprintf(buffer, "%s (ID=%08x) AHCI controller", + ata_pcivendor2str(dev), pci_get_devid(dev)); + else + sprintf(buffer, "%s AHCI controller", ata_pcivendor2str(dev)); + device_set_desc_copy(dev, buffer); + ctlr->chipinit = ata_ahci_chipinit; + return 0; +} + +int +ata_ahci_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + u_int32_t version; + + /* if we have a memory BAR(5) we are likely on an AHCI part */ + ctlr->r_type2 = SYS_RES_MEMORY; + ctlr->r_rid2 = PCIR_BAR(5); + if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, + &ctlr->r_rid2, RF_ACTIVE))) + return ENXIO; + + /* setup interrupt delivery if not done allready by a vendor driver */ + if (!ctlr->r_irq) { + if (ata_setup_interrupt(dev)) + return ENXIO; + } + else + device_printf(dev, "AHCI called from vendor specific driver\n"); + + /* reset controller */ + ata_ahci_ctlr_reset(dev); + + /* get the number of HW channels */ + ctlr->channels = + MAX(flsl(ATA_INL(ctlr->r_res2, ATA_AHCI_PI)), + (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) + 1); + + ctlr->reset = ata_ahci_reset; + ctlr->dmainit = ata_ahci_dmainit; + ctlr->allocate = ata_ahci_allocate; + ctlr->setmode = ata_sata_setmode; + ctlr->suspend = ata_ahci_suspend; + ctlr->resume = ata_ahci_ctlr_reset; + + /* enable PCI interrupt */ + pci_write_config(dev, PCIR_COMMAND, + pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2); + + /* announce we support the HW */ + version = ATA_INL(ctlr->r_res2, ATA_AHCI_VS); + device_printf(dev, + "AHCI Version %x%x.%x%x controller with %d ports PM %s\n", + (version >> 24) & 0xff, (version >> 16) & 0xff, + (version >> 8) & 0xff, version & 0xff, + (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) + 1, + (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) ? + "supported" : "not supported"); + return 0; +} + +static int +ata_ahci_ctlr_reset(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + /* enable AHCI mode */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE); + + /* reset AHCI controller */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_HR); + DELAY(1000000); + if (ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) & ATA_AHCI_GHC_HR) { + bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2); + device_printf(dev, "AHCI controller reset failure\n"); + return ENXIO; + } + + /* reenable AHCI mode */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE); + + /* clear interrupts */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, ATA_INL(ctlr->r_res2, ATA_AHCI_IS)); + + /* enable AHCI interrupts */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, + ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) | ATA_AHCI_GHC_IE); + + return 0; +} + +static int +ata_ahci_suspend(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + /* disable interupts so the state change(s) doesn't trigger */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, + ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) & (~ATA_AHCI_GHC_IE)); + return 0; +} + + +static int +ata_ahci_allocate(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + int offset = ch->unit << 7; + + /* set the SATA resources */ + ch->r_io[ATA_SSTATUS].res = ctlr->r_res2; + ch->r_io[ATA_SSTATUS].offset = ATA_AHCI_P_SSTS + offset; + ch->r_io[ATA_SERROR].res = ctlr->r_res2; + ch->r_io[ATA_SERROR].offset = ATA_AHCI_P_SERR + offset; + ch->r_io[ATA_SCONTROL].res = ctlr->r_res2; + ch->r_io[ATA_SCONTROL].offset = ATA_AHCI_P_SCTL + offset; + ch->r_io[ATA_SACTIVE].res = ctlr->r_res2; + ch->r_io[ATA_SACTIVE].offset = ATA_AHCI_P_SACT + offset; + + ch->hw.status = ata_ahci_status; + ch->hw.begin_transaction = ata_ahci_begin_transaction; + ch->hw.end_transaction = ata_ahci_end_transaction; + ch->hw.command = NULL; /* not used here */ + ch->hw.softreset = ata_ahci_softreset; + ch->hw.pm_read = ata_ahci_pm_read; + ch->hw.pm_write = ata_ahci_pm_write; + + return 0; +} + +static int +ata_ahci_status(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + u_int32_t action = ATA_INL(ctlr->r_res2, ATA_AHCI_IS); + int offset = ch->unit << 7; + +#define ATA_AHCI_STATBITS \ + (ATA_AHCI_P_IX_IF|ATA_AHCI_P_IX_HBD|ATA_AHCI_P_IX_HBF|ATA_AHCI_P_IX_TFE) + + if (action & (1 << ch->unit)) { + u_int32_t istatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset); + u_int32_t cstatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset); + + /* clear interrupt(s) */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, istatus); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, action & (1 << ch->unit)); + + /* do we have any PHY events ? */ + if (istatus & (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC)) + ata_sata_phy_check_events(dev); + + /* do we have a potentially hanging engine to take care of? */ + /* XXX SOS what todo on NCQ */ + if ((istatus & ATA_AHCI_STATBITS) && (cstatus & 1)) { + + u_int32_t cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); + int timeout = 0; + + /* kill off all activity on this channel */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, + cmd & ~(ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST)); + + /* XXX SOS this is not entirely wrong */ + do { + DELAY(1000); + if (timeout++ > 1000) { + device_printf(dev, "stopping AHCI engine failed\n"); + break; + } + } while (ATA_INL(ctlr->r_res2, + ATA_AHCI_P_CMD + offset) & ATA_AHCI_P_CMD_CR); + + /* start operations on this channel */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, + cmd | (ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST)); + + return 1; + } + else + /* XXX SOS what todo on NCQ */ + return (!(cstatus & 1)); + } + return 0; +} + +/* must be called with ATA channel locked and state_mtx held */ +static int +ata_ahci_begin_transaction(struct ata_request *request) +{ + struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); + struct ata_channel *ch = device_get_softc(request->parent); + struct ata_device *atadev = device_get_softc(request->dev); + struct ata_ahci_cmd_tab *ctp; + struct ata_ahci_cmd_list *clp; + int offset = ch->unit << 7; + int port = atadev->unit & 0x0f; + int entries = 0; + int fis_size; + + /* get a piece of the workspace for this request */ + ctp = (struct ata_ahci_cmd_tab *) + (ch->dma.work + ATA_AHCI_CT_OFFSET + (ATA_AHCI_CT_SIZE*request->tag)); + + /* setup the FIS for this request */ + if (!(fis_size = ata_ahci_setup_fis(ctp, request))) { + device_printf(request->dev, "setting up SATA FIS failed\n"); + request->result = EIO; + return ATA_OP_FINISHED; + } + + /* if request moves data setup and load SG list */ + if (request->flags & (ATA_R_READ | ATA_R_WRITE)) { + if (ch->dma.load(request, ctp->prd_tab, &entries)) { + device_printf(request->dev, "setting up DMA failed\n"); + request->result = EIO; + return ATA_OP_FINISHED; + } + } + + /* setup the command list entry */ + clp = (struct ata_ahci_cmd_list *) + (ch->dma.work + ATA_AHCI_CL_OFFSET + (ATA_AHCI_CL_SIZE*request->tag)); + + clp->prd_length = entries; + clp->cmd_flags = (request->flags & ATA_R_WRITE ? ATA_AHCI_CMD_WRITE : 0) | + (request->flags & ATA_R_ATAPI ? + (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) | + (fis_size / sizeof(u_int32_t)) | + (port << 12); + clp->bytecount = 0; + clp->cmd_table_phys = htole64(ch->dma.work_bus + ATA_AHCI_CT_OFFSET + + (ATA_AHCI_CT_SIZE * request->tag)); + + /* clear eventual ACTIVE bit */ + ATA_IDX_OUTL(ch, ATA_SACTIVE, + ATA_IDX_INL(ch, ATA_SACTIVE) & (1 << request->tag)); + + /* set command type bit */ + if (request->flags & ATA_R_ATAPI) + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, + ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) | + ATA_AHCI_P_CMD_ATAPI); + else + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, + ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) & + ~ATA_AHCI_P_CMD_ATAPI); + + /* set PM port to address */ + //ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, (port << 8) | 0x00000001); + + /* issue command to controller */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, (1 << request->tag)); + + if (!(request->flags & ATA_R_ATAPI)) { + /* device reset doesn't interrupt */ + if (request->u.ata.command == ATA_DEVICE_RESET) { + u_int32_t tf_data; + int timeout = 1000000; + + do { + DELAY(10); + tf_data = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + (ch->unit<<7)); + } while ((tf_data & ATA_S_BUSY) && timeout--); + if (bootverbose) + device_printf(ch->dev, "device_reset timeout=%dus\n", + (1000000-timeout)*10); + request->status = tf_data; + if (request->status & ATA_S_ERROR) + request->error = tf_data >> 8; + return ATA_OP_FINISHED; + } + } + + /* start the timeout */ + callout_reset(&request->callout, request->timeout * hz, + (timeout_t*)ata_timeout, request); + return ATA_OP_CONTINUES; +} + +/* must be called with ATA channel locked and state_mtx held */ +static int +ata_ahci_end_transaction(struct ata_request *request) +{ + struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); + struct ata_channel *ch = device_get_softc(request->parent); + struct ata_ahci_cmd_list *clp; + u_int32_t tf_data; + int offset = ch->unit << 7; + + /* kill the timeout */ + callout_stop(&request->callout); + + /* get status */ + tf_data = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset); + request->status = tf_data; + + /* if error status get details */ + if (request->status & ATA_S_ERROR) + request->error = tf_data >> 8; + + /* on control commands read back registers to the request struct */ + if (request->flags & ATA_R_CONTROL) { + struct ata_device *atadev = device_get_softc(request->dev); + u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40; + + request->u.ata.count = fis[12] | ((u_int16_t)fis[13] << 8); + request->u.ata.lba = fis[4] | ((u_int64_t)fis[5] << 8) | + ((u_int64_t)fis[6] << 16); + if (atadev->flags & ATA_D_48BIT_ACTIVE) + request->u.ata.lba |= ((u_int64_t)fis[8] << 24) | + ((u_int64_t)fis[9] << 32) | + ((u_int64_t)fis[10] << 40); + else + request->u.ata.lba |= ((u_int64_t)(fis[7] & 0x0f) << 24); + } + + /* record how much data we actually moved */ + clp = (struct ata_ahci_cmd_list *) + (ch->dma.work + ATA_AHCI_CL_OFFSET + (ATA_AHCI_CL_SIZE*request->tag)); + request->donecount = clp->bytecount; + + /* release SG list etc */ + ch->dma.unload(request); + + return ATA_OP_FINISHED; +} + +static int +ata_ahci_issue_cmd(device_t dev, u_int16_t flags, int timeout) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + struct ata_ahci_cmd_list *clp = + (struct ata_ahci_cmd_list *)(ch->dma.work + ATA_AHCI_CL_OFFSET); + struct ata_ahci_cmd_tab *ctp = + (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); + u_int32_t status = 0; + int offset = ch->unit << 7; + int port = (ctp->cfis[1] & 0x0f); + int count; + + clp->prd_length = 0; + clp->cmd_flags = (20 / sizeof(u_int32_t)) | flags | (port << 12); + clp->bytecount = 0; + clp->cmd_table_phys = htole64(ch->dma.work_bus + ATA_AHCI_CT_OFFSET); + + /* set PM port */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, (port << 8) | 0x00000001); + + /* issue command to controller */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, 1); + + /* poll for command finished */ + for (count = 0; count < timeout; count++) { + DELAY(1000); + if (!((status = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset)) & 1)) + break; + } + + /* clear interrupts */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, + ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset)); + + if (bootverbose) + device_printf(dev, "ahci_issue_cmd time=%dms cnt=%dms status=%08x\n", + timeout, count, status); + if (timeout && (count >= timeout)) + return EIO; + + return 0; +} + +static int +ata_ahci_pm_read(device_t dev, int port, int reg, u_int32_t *result) +{ + struct ata_channel *ch = device_get_softc(dev); + struct ata_ahci_cmd_tab *ctp = + (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); + u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40; + + bzero(ctp->cfis, 64); + ctp->cfis[0] = 0x27; /* host to device */ + ctp->cfis[1] = 0x8f; /* command FIS to PM port */ + ctp->cfis[2] = ATA_READ_PM; + ctp->cfis[3] = reg; + ctp->cfis[7] = port | ATA_D_LBA; + ctp->cfis[15] = ATA_A_4BIT; + + if (ata_ahci_issue_cmd(dev, 0, 10)) { + device_printf(dev, "error reading PM port\n"); + return EIO; + } + + *result = fis[12] | (fis[4] << 8) | (fis[5] << 16) | (fis[6] << 24); + return 0; +} + +static int +ata_ahci_pm_write(device_t dev, int port, int reg, u_int32_t value) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + struct ata_ahci_cmd_tab *ctp = + (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); + int offset = ch->unit << 7; + + bzero(ctp->cfis, 64); + ctp->cfis[0] = 0x27; /* host to device */ + ctp->cfis[1] = 0x8f; /* command FIS to PM port */ + ctp->cfis[2] = ATA_WRITE_PM; + ctp->cfis[3] = reg; + ctp->cfis[7] = port | ATA_D_LBA; + ctp->cfis[12] = value & 0xff; + ctp->cfis[4] = (value >> 8) & 0xff;; + ctp->cfis[5] = (value >> 16) & 0xff;; + ctp->cfis[6] = (value >> 24) & 0xff;; + ctp->cfis[15] = ATA_A_4BIT; + + if (ata_ahci_issue_cmd(dev, 0, 100)) { + device_printf(dev, "error writing PM port\n"); + return ATA_E_ABORT; + } + + return (ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset) >> 8) & 0xff; +} + +static void +ata_ahci_restart(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + u_int32_t cmd; + int offset = ch->unit << 7; + int timeout; + + /* kill off all activity on this channel */ + cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, + cmd & ~(ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST)); + + /* XXX SOS this is not entirely wrong */ + timeout = 0; + do { + DELAY(1000); + if (timeout++ > 1000) { + device_printf(dev, "stopping AHCI engine failed\n"); + break; + } + } + while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) & ATA_AHCI_P_CMD_CR); + + /* issue Command List Override if supported */ + if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_CLO) { + cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); + cmd |= ATA_AHCI_P_CMD_CLO; + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, cmd); + timeout = 0; + do { + DELAY(1000); + if (timeout++ > 1000) { + device_printf(dev, "executing CLO failed\n"); + break; + } + } + while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD+offset)&ATA_AHCI_P_CMD_CLO); + } + + /* clear SATA error register */ + ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR)); + + /* clear any interrupts pending on this channel */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, + ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset)); + + /* start operations on this channel */ + cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, + cmd | (ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST) | + (ch->devices & ATA_PORTMULTIPLIER ? ATA_AHCI_P_CMD_PMA : 0)); +} + +static u_int32_t +ata_ahci_softreset(device_t dev, int port) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + int offset = ch->unit << 7; + int timeout = 0; +#ifdef AHCI_PM + struct ata_ahci_cmd_tab *ctp = + (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); + + /* kick controller into sane state if needed */ + ata_ahci_restart(dev); + + /* pull reset active */ + bzero(ctp->cfis, 64); + ctp->cfis[0] = 0x27; + ctp->cfis[1] = port & 0x0f; + //ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM; + ctp->cfis[15] = (ATA_A_4BIT | ATA_A_RESET); + + if (ata_ahci_issue_cmd(dev, ATA_AHCI_CMD_RESET | ATA_AHCI_CMD_CLR_BUSY,100)) + device_printf(dev, "setting SRST failed ??\n"); + //return -1; + + ata_udelay(5000); + + /* pull reset inactive -> device softreset */ + bzero(ctp->cfis, 64); + ctp->cfis[0] = 0x27; + ctp->cfis[1] = port & 0x0f; + //ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM; + ctp->cfis[15] = ATA_A_4BIT; + if (ata_ahci_issue_cmd(dev, 0, 0)) + return -1; + + ata_udelay(150000); + +#endif + do { + DELAY(1000); + if (timeout++ > 1000) { + device_printf(dev, "still BUSY after softreset\n"); + break; + } + } while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset) & ATA_S_BUSY); + if (bootverbose) + device_printf(dev, "BUSY wait time=%dms\n", timeout); + + return ATA_INL(ctlr->r_res2, ATA_AHCI_P_SIG + offset); +} + +static void +ata_ahci_reset(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + u_int64_t work; + u_int32_t cmd, signature; + int offset = ch->unit << 7; + + if (!(ATA_INL(ctlr->r_res2, ATA_AHCI_PI) & (1 << ch->unit))) { + device_printf(dev, "port not implemented\n"); + return; + } + + /* setup work areas */ + work = ch->dma.work_bus + ATA_AHCI_CL_OFFSET; + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset, work & 0xffffffff); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, work >> 32); + + work = ch->dma.work_bus + ATA_AHCI_FB_OFFSET; + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset, work & 0xffffffff); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, work >> 32); + + /* enable wanted port interrupts */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, + (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF | + ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF | + ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC | ATA_AHCI_P_IX_DP | + ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | ATA_AHCI_P_IX_DS | + ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR)); + + /* activate the channel and power/spin up device */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, + (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD)); + + ata_ahci_restart(dev); + + /* enable FIS based switching */ + //ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, 0x00000003); + + if (!ata_sata_phy_reset(dev)) { + if (bootverbose) + device_printf(dev, "phy reset found no device\n"); + ch->devices = 0; + + /* kill off all activity on this channel */ + cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, + cmd & ~(ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST)); + return; + } + + /* only probe for PortMultiplier if HW has support */ + if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) + signature = ata_ahci_softreset(dev, ATA_PM); + else { + signature = ata_ahci_softreset(dev, 0); + } + if (bootverbose) + device_printf(dev, "SIGNATURE: %08x\n", signature); + + switch (signature) { + case 0x00000101: + ch->devices = ATA_ATA_MASTER; + break; + case 0x96690101: + ch->devices = ATA_PORTMULTIPLIER; + ata_pm_identify(dev); + break; + case 0xeb140101: + ch->devices = ATA_ATAPI_MASTER; + break; + default: /* SOS XXX */ + if (bootverbose) + device_printf(dev, "No signature, asuming disk device\n"); + ch->devices = ATA_ATA_MASTER; + } + if (bootverbose) + device_printf(dev, "ahci_reset devices=%08x\n", ch->devices); +} + +static void +ata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) +{ + struct ata_dmasetprd_args *args = xsc; + struct ata_ahci_dma_prd *prd = args->dmatab; + int i; + + if (!(args->error = error)) { + for (i = 0; i < nsegs; i++) { + prd[i].dba = htole64(segs[i].ds_addr); + prd[i].dbc = htole32((segs[i].ds_len - 1) & ATA_AHCI_PRD_MASK); + } + } + + KASSERT(nsegs <= ATA_AHCI_DMA_ENTRIES, ("too many DMA segment entries\n")); + args->nsegs = nsegs; +} + +static void +ata_ahci_dmainit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + + ata_dmainit(dev); + /* note start and stop are not used here */ + ch->dma.setprd = ata_ahci_dmasetprd; + ch->dma.max_iosize = 8192 * DEV_BSIZE; + if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_64BIT) + ch->dma.max_address = BUS_SPACE_MAXADDR; +} + +static int +ata_ahci_setup_fis(struct ata_ahci_cmd_tab *ctp, struct ata_request *request) +{ + bzero(ctp->cfis, 64); + if (request->flags & ATA_R_ATAPI) { + bzero(ctp->acmd, 32); + bcopy(request->u.atapi.ccb, ctp->acmd, 16); + } + return ata_request2fis_h2d(request, &ctp->cfis[0]); +} === dev/ata/chipsets/ata-intel.c ================================================================== --- dev/ata/chipsets/ata-intel.c (revision 183565) +++ dev/ata/chipsets/ata-intel.c (local) @@ -0,0 +1,508 @@ +/*- + * Copyright (c) 2008, Oleksandr Tymoshenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * Intel chipset support functions + */ + +static int ata_intel_ident(device_t dev); +static int ata_intel_chipinit(device_t dev); +static int ata_intel_allocate(device_t dev); +static void ata_intel_reset(device_t dev); +static void ata_intel_old_setmode(device_t dev, int mode); +static void ata_intel_new_setmode(device_t dev, int mode); +static void ata_intel_sata_setmode(device_t dev, int mode); +static int ata_intel_31244_allocate(device_t dev); +static int ata_intel_31244_status(device_t dev); +static void ata_intel_31244_tf_write(struct ata_request *request); +static void ata_intel_31244_reset(device_t dev); + +static int +ata_intel_ident(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + static struct ata_chip_id ids[] = + {{ ATA_I82371FB, 0, 0, 2, ATA_WDMA2, "PIIX" }, + { ATA_I82371SB, 0, 0, 2, ATA_WDMA2, "PIIX3" }, + { ATA_I82371AB, 0, 0, 2, ATA_UDMA2, "PIIX4" }, + { ATA_I82443MX, 0, 0, 2, ATA_UDMA2, "PIIX4" }, + { ATA_I82451NX, 0, 0, 2, ATA_UDMA2, "PIIX4" }, + { ATA_I82801AB, 0, 0, 2, ATA_UDMA2, "ICH0" }, + { ATA_I82801AA, 0, 0, 2, ATA_UDMA4, "ICH" }, + { ATA_I82372FB, 0, 0, 2, ATA_UDMA4, "ICH" }, + { ATA_I82801BA, 0, 0, 2, ATA_UDMA5, "ICH2" }, + { ATA_I82801BA_1, 0, 0, 2, ATA_UDMA5, "ICH2" }, + { ATA_I82801CA, 0, 0, 2, ATA_UDMA5, "ICH3" }, + { ATA_I82801CA_1, 0, 0, 2, ATA_UDMA5, "ICH3" }, + { ATA_I82801DB, 0, 0, 2, ATA_UDMA5, "ICH4" }, + { ATA_I82801DB_1, 0, 0, 2, ATA_UDMA5, "ICH4" }, + { ATA_I82801EB, 0, 0, 2, ATA_UDMA5, "ICH5" }, + { ATA_I82801EB_S1, 0, 0, 2, ATA_SA150, "ICH5" }, + { ATA_I82801EB_R1, 0, 0, 2, ATA_SA150, "ICH5" }, + { ATA_I6300ESB, 0, 0, 2, ATA_UDMA5, "6300ESB" }, + { ATA_I6300ESB_S1, 0, 0, 2, ATA_SA150, "6300ESB" }, + { ATA_I6300ESB_R1, 0, 0, 2, ATA_SA150, "6300ESB" }, + { ATA_I82801FB, 0, 0, 2, ATA_UDMA5, "ICH6" }, + { ATA_I82801FB_S1, 0, AHCI, 0, ATA_SA150, "ICH6" }, + { ATA_I82801FB_R1, 0, AHCI, 0, ATA_SA150, "ICH6" }, + { ATA_I82801FBM, 0, AHCI, 0, ATA_SA150, "ICH6M" }, + { ATA_I82801GB, 0, 0, 1, ATA_UDMA5, "ICH7" }, + { ATA_I82801GB_S1, 0, AHCI, 0, ATA_SA300, "ICH7" }, + { ATA_I82801GB_R1, 0, AHCI, 0, ATA_SA300, "ICH7" }, + { ATA_I82801GB_AH, 0, AHCI, 0, ATA_SA300, "ICH7" }, + { ATA_I82801GBM_S1, 0, AHCI, 0, ATA_SA300, "ICH7M" }, + { ATA_I82801GBM_R1, 0, AHCI, 0, ATA_SA300, "ICH7M" }, + { ATA_I82801GBM_AH, 0, AHCI, 0, ATA_SA300, "ICH7M" }, + { ATA_I63XXESB2, 0, 0, 1, ATA_UDMA5, "63XXESB2" }, + { ATA_I63XXESB2_S1, 0, AHCI, 0, ATA_SA300, "63XXESB2" }, + { ATA_I63XXESB2_S2, 0, AHCI, 0, ATA_SA300, "63XXESB2" }, + { ATA_I63XXESB2_R1, 0, AHCI, 0, ATA_SA300, "63XXESB2" }, + { ATA_I63XXESB2_R2, 0, AHCI, 0, ATA_SA300, "63XXESB2" }, + { ATA_I82801HB_S1, 0, AHCI, 0, ATA_SA300, "ICH8" }, + { ATA_I82801HB_S2, 0, AHCI, 0, ATA_SA300, "ICH8" }, + { ATA_I82801HB_R1, 0, AHCI, 0, ATA_SA300, "ICH8" }, + { ATA_I82801HB_AH4, 0, AHCI, 0, ATA_SA300, "ICH8" }, + { ATA_I82801HB_AH6, 0, AHCI, 0, ATA_SA300, "ICH8" }, + { ATA_I82801HBM, 0, 0, 1, ATA_UDMA5, "ICH8M" }, + { ATA_I82801HBM_S1, 0, AHCI, 0, ATA_SA300, "ICH8M" }, + { ATA_I82801HBM_S2, 0, AHCI, 0, ATA_SA300, "ICH8M" }, + { ATA_I82801HBM_S3, 0, AHCI, 0, ATA_SA300, "ICH8M" }, + { ATA_I82801IB_S1, 0, AHCI, 0, ATA_SA300, "ICH9" }, + { ATA_I82801IB_S2, 0, AHCI, 0, ATA_SA300, "ICH9" }, + { ATA_I82801IB_AH2, 0, AHCI, 0, ATA_SA300, "ICH9" }, + { ATA_I82801IB_AH4, 0, AHCI, 0, ATA_SA300, "ICH9" }, + { ATA_I82801IB_AH6, 0, AHCI, 0, ATA_SA300, "ICH9" }, + { ATA_I82801IB_R1, 0, AHCI, 0, ATA_SA300, "ICH9" }, + { ATA_I82801JIB_S1, 0, AHCI, 0, ATA_SA300, "ICH10" }, + { ATA_I82801JIB_AH, 0, AHCI, 0, ATA_SA300, "ICH10" }, + { ATA_I82801JIB_R1, 0, AHCI, 0, ATA_SA300, "ICH10" }, + { ATA_I82801JIB_S2, 0, AHCI, 0, ATA_SA300, "ICH10" }, + { ATA_I82801JD_S1, 0, AHCI, 0, ATA_SA300, "ICH10" }, + { ATA_I82801JD_AH, 0, AHCI, 0, ATA_SA300, "ICH10" }, + { ATA_I82801JD_R1, 0, AHCI, 0, ATA_SA300, "ICH10" }, + { ATA_I82801JD_S2, 0, AHCI, 0, ATA_SA300, "ICH10" }, + { ATA_I31244, 0, 0, 2, ATA_SA150, "31244" }, + { 0, 0, 0, 0, 0, 0}}; + + if (pci_get_vendor(dev) != ATA_INTEL_ID) + return; + + if (!(ctlr->chip = ata_match_chip(dev, ids))) + return ENXIO; + + ata_set_desc(dev); + ctlr->chipinit = ata_intel_chipinit; + return 0; +} + +static int +ata_intel_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + if (ata_setup_interrupt(dev)) + return ENXIO; + + /* good old PIIX needs special treatment (not implemented) */ + if (ctlr->chip->chipid == ATA_I82371FB) { + ctlr->setmode = ata_intel_old_setmode; + } + + /* the intel 31244 needs special care if in DPA mode */ + else if (ctlr->chip->chipid == ATA_I31244) { + if (pci_get_subclass(dev) != PCIS_STORAGE_IDE) { + ctlr->r_type2 = SYS_RES_MEMORY; + ctlr->r_rid2 = PCIR_BAR(0); + if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, + &ctlr->r_rid2, + RF_ACTIVE))) + return ENXIO; + ctlr->channels = 4; + ctlr->allocate = ata_intel_31244_allocate; + ctlr->reset = ata_intel_31244_reset; + } + ctlr->setmode = ata_sata_setmode; + } + + /* non SATA intel chips goes here */ + else if (ctlr->chip->max_dma < ATA_SA150) { + ctlr->channels = ctlr->chip->cfg2; + ctlr->allocate = ata_intel_allocate; + ctlr->setmode = ata_intel_new_setmode; + } + + /* SATA parts can be either compat or AHCI */ + else { + /* force all ports active "the legacy way" */ + pci_write_config(dev, 0x92, pci_read_config(dev, 0x92, 2) | 0x0f, 2); + + ctlr->allocate = ata_intel_allocate; + ctlr->reset = ata_intel_reset; + + /* + * if we have AHCI capability and AHCI or RAID mode enabled + * in BIOS we try for AHCI mode + */ + if ((ctlr->chip->cfg1 == AHCI) && + (pci_read_config(dev, 0x90, 1) & 0xc0) && + (ata_ahci_chipinit(dev) != ENXIO)) + return 0; + + /* if BAR(5) is IO it should point to SATA interface registers */ + ctlr->r_type2 = SYS_RES_IOPORT; + ctlr->r_rid2 = PCIR_BAR(5); + if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, + &ctlr->r_rid2, RF_ACTIVE))) + ctlr->setmode = ata_intel_sata_setmode; + else + ctlr->setmode = ata_sata_setmode; + + /* enable PCI interrupt */ + pci_write_config(dev, PCIR_COMMAND, + pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2); + } + return 0; +} + +static int +ata_intel_allocate(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + + /* setup the usual register normal pci style */ + if (ata_pci_allocate(dev)) + return ENXIO; + + /* if r_res2 is valid it points to SATA interface registers */ + if (ctlr->r_res2) { + ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2; + ch->r_io[ATA_IDX_ADDR].offset = 0x00; + ch->r_io[ATA_IDX_DATA].res = ctlr->r_res2; + ch->r_io[ATA_IDX_DATA].offset = 0x04; + } + + ch->flags |= ATA_ALWAYS_DMASTAT; + return 0; +} + +static void +ata_intel_reset(device_t dev) +{ + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int mask, timeout; + + /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */ + if (ctlr->chip->cfg1) { + mask = (0x0005 << ch->unit); + } + else { + /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */ + if (pci_read_config(parent, 0x90, 1) & 0x04) + mask = 0x0003; + else { + mask = (0x0001 << ch->unit); + /* XXX SOS should be in intel_allocate if we grow it */ + ch->flags |= ATA_NO_SLAVE; + } + } + pci_write_config(parent, 0x92, pci_read_config(parent, 0x92, 2) & ~mask, 2); + DELAY(10); + pci_write_config(parent, 0x92, pci_read_config(parent, 0x92, 2) | mask, 2); + + /* wait up to 1 sec for "connect well" */ + for (timeout = 0; timeout < 100 ; timeout++) { + if (((pci_read_config(parent, 0x92, 2) & (mask << 4)) == (mask << 4)) && + (ATA_IDX_INB(ch, ATA_STATUS) != 0xff)) + break; + ata_udelay(10000); + } + ata_generic_reset(dev); +} + +static void +ata_intel_old_setmode(device_t dev, int mode) +{ + /* NOT YET */ +} + +static void +ata_intel_new_setmode(device_t dev, int mode) +{ + device_t gparent = GRANDPARENT(dev); + struct ata_pci_controller *ctlr = device_get_softc(gparent); + struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + struct ata_device *atadev = device_get_softc(dev); + int devno = (ch->unit << 1) + atadev->unit; + u_int32_t reg40 = pci_read_config(gparent, 0x40, 4); + u_int8_t reg44 = pci_read_config(gparent, 0x44, 1); + u_int8_t reg48 = pci_read_config(gparent, 0x48, 1); + u_int16_t reg4a = pci_read_config(gparent, 0x4a, 2); + u_int16_t reg54 = pci_read_config(gparent, 0x54, 2); + u_int32_t mask40 = 0, new40 = 0; + u_int8_t mask44 = 0, new44 = 0; + int error; + u_int8_t timings[] = { 0x00, 0x00, 0x10, 0x21, 0x23, 0x10, 0x21, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23 }; + + mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); + + if ( mode > ATA_UDMA2 && !(reg54 & (0x10 << devno))) { + ata_print_cable(dev, "controller"); + mode = ATA_UDMA2; + } + + error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); + + if (bootverbose) + device_printf(dev, "%ssetting %s on %s chip\n", + (error) ? "FAILURE " : "", + ata_mode2str(mode), ctlr->chip->text); + if (!error) { + if (mode >= ATA_UDMA0) { + u_int8_t utimings[] = { 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10 }; + + pci_write_config(gparent, 0x48, reg48 | (0x0001 << devno), 2); + pci_write_config(gparent, 0x4a, + (reg4a & ~(0x3 << (devno << 2))) | + (utimings[mode & ATA_MODE_MASK] << (devno<<2)), 2); + } + else { + pci_write_config(gparent, 0x48, reg48 & ~(0x0001 << devno), 2); + pci_write_config(gparent, 0x4a, (reg4a & ~(0x3 << (devno << 2))),2); + } + reg54 |= 0x0400; + if (mode >= ATA_UDMA2) + reg54 |= (0x1 << devno); + else + reg54 &= ~(0x1 << devno); + if (mode >= ATA_UDMA5) + reg54 |= (0x1000 << devno); + else + reg54 &= ~(0x1000 << devno); + + pci_write_config(gparent, 0x54, reg54, 2); + + reg40 &= ~0x00ff00ff; + reg40 |= 0x40774077; + + if (atadev->unit == ATA_MASTER) { + mask40 = 0x3300; + new40 = timings[ata_mode2idx(mode)] << 8; + } + else { + mask44 = 0x0f; + new44 = ((timings[ata_mode2idx(mode)] & 0x30) >> 2) | + (timings[ata_mode2idx(mode)] & 0x03); + } + if (ch->unit) { + mask40 <<= 16; + new40 <<= 16; + mask44 <<= 4; + new44 <<= 4; + } + pci_write_config(gparent, 0x40, (reg40 & ~mask40) | new40, 4); + pci_write_config(gparent, 0x44, (reg44 & ~mask44) | new44, 1); + + atadev->mode = mode; + } +} + +static void +ata_intel_sata_setmode(device_t dev, int mode) +{ + struct ata_device *atadev = device_get_softc(dev); + + if (atadev->param.satacapabilities != 0x0000 && + atadev->param.satacapabilities != 0xffff) { + + struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + int devno = (ch->unit << 1) + atadev->unit; + + /* on some drives we need to set the transfer mode */ + ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, + ata_limit_mode(dev, mode, ATA_UDMA6)); + + /* set ATA_SSTATUS register offset */ + ATA_IDX_OUTL(ch, ATA_IDX_ADDR, devno * 0x100); + + /* query SATA STATUS for the speed */ + if ((ATA_IDX_INL(ch, ATA_IDX_DATA) & ATA_SS_CONWELL_MASK) == + ATA_SS_CONWELL_GEN2) + atadev->mode = ATA_SA300; + else + atadev->mode = ATA_SA150; + } + else { + mode = ata_limit_mode(dev, mode, ATA_UDMA5); + if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) + atadev->mode = mode; + } +} + +static int +ata_intel_31244_allocate(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + int i; + int ch_offset; + + ch_offset = 0x200 + ch->unit * 0x200; + + for (i = ATA_DATA; i < ATA_MAX_RES; i++) + ch->r_io[i].res = ctlr->r_res2; + + /* setup ATA registers */ + ch->r_io[ATA_DATA].offset = ch_offset + 0x00; + ch->r_io[ATA_FEATURE].offset = ch_offset + 0x06; + ch->r_io[ATA_COUNT].offset = ch_offset + 0x08; + ch->r_io[ATA_SECTOR].offset = ch_offset + 0x0c; + ch->r_io[ATA_CYL_LSB].offset = ch_offset + 0x10; + ch->r_io[ATA_CYL_MSB].offset = ch_offset + 0x14; + ch->r_io[ATA_DRIVE].offset = ch_offset + 0x18; + ch->r_io[ATA_COMMAND].offset = ch_offset + 0x1d; + ch->r_io[ATA_ERROR].offset = ch_offset + 0x04; + ch->r_io[ATA_STATUS].offset = ch_offset + 0x1c; + ch->r_io[ATA_ALTSTAT].offset = ch_offset + 0x28; + ch->r_io[ATA_CONTROL].offset = ch_offset + 0x29; + + /* setup DMA registers */ + ch->r_io[ATA_SSTATUS].offset = ch_offset + 0x100; + ch->r_io[ATA_SERROR].offset = ch_offset + 0x104; + ch->r_io[ATA_SCONTROL].offset = ch_offset + 0x108; + + /* setup SATA registers */ + ch->r_io[ATA_BMCMD_PORT].offset = ch_offset + 0x70; + ch->r_io[ATA_BMSTAT_PORT].offset = ch_offset + 0x72; + ch->r_io[ATA_BMDTP_PORT].offset = ch_offset + 0x74; + + ch->flags |= ATA_NO_SLAVE; + ata_pci_hw(dev); + ch->hw.status = ata_intel_31244_status; + ch->hw.tf_write = ata_intel_31244_tf_write; + + /* enable PHY state change interrupt */ + ATA_OUTL(ctlr->r_res2, 0x4, + ATA_INL(ctlr->r_res2, 0x04) | (0x01 << (ch->unit << 3))); + return 0; +} + +static int +ata_intel_31244_status(device_t dev) +{ + /* do we have any PHY events ? */ + ata_sata_phy_check_events(dev); + + /* any drive action to take care of ? */ + return ata_pci_status(dev); +} + +static void +ata_intel_31244_tf_write(struct ata_request *request) +{ + struct ata_channel *ch = device_get_softc(device_get_parent(request->dev)); + struct ata_device *atadev = device_get_softc(request->dev); + + if (atadev->flags & ATA_D_48BIT_ACTIVE) { + ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature); + ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count); + ATA_IDX_OUTW(ch, ATA_SECTOR, ((request->u.ata.lba >> 16) & 0xff00) | + (request->u.ata.lba & 0x00ff)); + ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((request->u.ata.lba >> 24) & 0xff00) | + ((request->u.ata.lba >> 8) & 0x00ff)); + ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((request->u.ata.lba >> 32) & 0xff00) | + ((request->u.ata.lba >> 16) & 0x00ff)); + ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(atadev->unit)); + } + else { + ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature); + ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count); + if (atadev->flags & ATA_D_USE_CHS) { + int heads, sectors; + + if (atadev->param.atavalid & ATA_FLAG_54_58) { + heads = atadev->param.current_heads; + sectors = atadev->param.current_sectors; + } + else { + heads = atadev->param.heads; + sectors = atadev->param.sectors; + } + ATA_IDX_OUTB(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1); + ATA_IDX_OUTB(ch, ATA_CYL_LSB, + (request->u.ata.lba / (sectors * heads))); + ATA_IDX_OUTB(ch, ATA_CYL_MSB, + (request->u.ata.lba / (sectors * heads)) >> 8); + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit) | + (((request->u.ata.lba% (sectors * heads)) / + sectors) & 0xf)); + } + else { + ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba); + ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8); + ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16); + ATA_IDX_OUTB(ch, ATA_DRIVE, + ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit) | + ((request->u.ata.lba >> 24) & 0x0f)); + } + } +} + +static void +ata_intel_31244_reset(device_t dev) +{ + if (ata_sata_phy_reset(dev)) + ata_generic_reset(dev); +} + + +ATA_CHIPSET(intel, ata_intel_ident);