diff options
author | sos <sos@FreeBSD.org> | 2005-05-11 16:10:08 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 2005-05-11 16:10:08 +0000 |
commit | eae1ea62ece9bf50ee32441fbabf913a0c8b6004 (patch) | |
tree | 7a431939e3c9973e4513bb07692a1fbd3bb16e48 /sys/dev/ata | |
parent | 107f3a74d1aae30f5d860bc59a6adf679a57517a (diff) | |
download | FreeBSD-src-eae1ea62ece9bf50ee32441fbabf913a0c8b6004.zip FreeBSD-src-eae1ea62ece9bf50ee32441fbabf913a0c8b6004.tar.gz |
Add support for AHCI compliant ATA devices.
For now just support the Intel ICH6 as that the HW at hand.
Sponsored by: pair.com
Diffstat (limited to 'sys/dev/ata')
-rw-r--r-- | sys/dev/ata/ata-all.h | 98 | ||||
-rw-r--r-- | sys/dev/ata/ata-chipset.c | 379 |
2 files changed, 463 insertions, 14 deletions
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index 32f0e35..47b9604 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -163,16 +163,98 @@ #define ATA_SC_IPM_DIS_PARTIAL 0x00000100 #define ATA_SC_IPM_DIS_SLUMBER 0x00000200 +#define ATA_SACTIVE 16 + +/* SATA AHCI v1.0 register defines */ +#define ATA_AHCI_CAP 0x00 +#define ATA_AHCI_NPMASK 0x1f + +#define ATA_AHCI_GHC 0x04 +#define ATA_AHCI_GHC_AE 0x80000000 +#define ATA_AHCI_GHC_IE 0x00000002 +#define ATA_AHCI_GHC_HR 0x80000001 + +#define ATA_AHCI_IS 0x08 +#define ATA_AHCI_PI 0x0c +#define ATA_AHCI_VS 0x10 + +#define ATA_AHCI_OFFSET 0x80 + +#define ATA_AHCI_P_CLB 0x100 +#define ATA_AHCI_P_CLBU 0x104 +#define ATA_AHCI_P_FB 0x108 +#define ATA_AHCI_P_FBU 0x10c +#define ATA_AHCI_P_IS 0x110 +#define ATA_AHCI_P_IE 0x114 +#define ATA_AHCI_P_IX_DHR 0x00000001 +#define ATA_AHCI_P_IX_PS 0x00000002 +#define ATA_AHCI_P_IX_DS 0x00000004 +#define ATA_AHCI_P_IX_SDB 0x00000008 +#define ATA_AHCI_P_IX_UF 0x00000010 +#define ATA_AHCI_P_IX_DP 0x00000020 +#define ATA_AHCI_P_IX_PC 0x00000040 +#define ATA_AHCI_P_IX_DI 0x00000080 + +#define ATA_AHCI_P_IX_PRC 0x00400000 +#define ATA_AHCI_P_IX_IPM 0x00800000 +#define ATA_AHCI_P_IX_OF 0x01000000 +#define ATA_AHCI_P_IX_INF 0x04000000 +#define ATA_AHCI_P_IX_IF 0x08000000 +#define ATA_AHCI_P_IX_HBD 0x10000000 +#define ATA_AHCI_P_IX_HBF 0x20000000 +#define ATA_AHCI_P_IX_TFE 0x40000000 +#define ATA_AHCI_P_IX_CPD 0x80000000 + +#define ATA_AHCI_P_CMD 0x118 +#define ATA_AHCI_P_CMD_ST 0x00000001 +#define ATA_AHCI_P_CMD_SUD 0x00000002 +#define ATA_AHCI_P_CMD_POD 0x00000004 +#define ATA_AHCI_P_CMD_CLO 0x00000008 +#define ATA_AHCI_P_CMD_FRE 0x00000010 +#define ATA_AHCI_P_CMD_CCS_MASK 0x00001f00 +#define ATA_AHCI_P_CMD_ISS 0x00002000 +#define ATA_AHCI_P_CMD_FR 0x00004000 +#define ATA_AHCI_P_CMD_CR 0x00008000 +#define ATA_AHCI_P_CMD_CPS 0x00010000 +#define ATA_AHCI_P_CMD_PMA 0x00020000 +#define ATA_AHCI_P_CMD_HPCP 0x00040000 +#define ATA_AHCI_P_CMD_ISP 0x00080000 +#define ATA_AHCI_P_CMD_CPD 0x00100000 +#define ATA_AHCI_P_CMD_ATAPI 0x01000000 +#define ATA_AHCI_P_CMD_DLAE 0x02000000 +#define ATA_AHCI_P_CMD_ALPE 0x04000000 +#define ATA_AHCI_P_CMD_ASP 0x08000000 +#define ATA_AHCI_P_CMD_ICC_MASK 0xf0000000 +#define ATA_AHCI_P_CMD_NOOP 0x00000000 +#define ATA_AHCI_P_CMD_ACTIVE 0x10000000 +#define ATA_AHCI_P_CMD_PARTIAL 0x20000000 +#define ATA_AHCI_P_CMD_SLUMPER 0x60000000 + +#define ATA_AHCI_P_TFD 0x120 +#define ATA_AHCI_P_SIG 0x124 +#define ATA_AHCI_P_SSTS 0x128 +#define ATA_AHCI_P_SCTL 0x12c +#define ATA_AHCI_P_SERR 0x130 +#define ATA_AHCI_P_SACT 0x134 +#define ATA_AHCI_P_CI 0x138 + +#define ATA_AHCI_CL_SIZE 32 +#define ATA_AHCI_CL_OFFSET 0 +#define ATA_AHCI_FB_OFFSET 1024 +#define ATA_AHCI_CT_OFFSET 1024+256 +#define ATA_AHCI_CT_SG_OFFSET 128 +#define ATA_AHCI_CT_SIZE 256 + /* DMA register defines */ #define ATA_DMA_ENTRIES 256 #define ATA_DMA_EOT 0x80000000 -#define ATA_BMCMD_PORT 16 +#define ATA_BMCMD_PORT 17 #define ATA_BMCMD_START_STOP 0x01 #define ATA_BMCMD_WRITE_READ 0x08 -#define ATA_BMDEVSPEC_0 17 -#define ATA_BMSTAT_PORT 18 +#define ATA_BMDEVSPEC_0 18 +#define ATA_BMSTAT_PORT 19 #define ATA_BMSTAT_ACTIVE 0x01 #define ATA_BMSTAT_ERROR 0x02 #define ATA_BMSTAT_INTERRUPT 0x04 @@ -181,12 +263,12 @@ #define ATA_BMSTAT_DMA_SLAVE 0x40 #define ATA_BMSTAT_DMA_SIMPLEX 0x80 -#define ATA_BMDEVSPEC_1 19 -#define ATA_BMDTP_PORT 20 +#define ATA_BMDEVSPEC_1 20 +#define ATA_BMDTP_PORT 21 -#define ATA_IDX_ADDR 21 -#define ATA_IDX_DATA 22 -#define ATA_MAX_RES 23 +#define ATA_IDX_ADDR 22 +#define ATA_IDX_DATA 23 +#define ATA_MAX_RES 24 /* misc defines */ #define ATA_PRIMARY 0x1f0 diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c index 85f8c35..5042b0b 100644 --- a/sys/dev/ata/ata-chipset.c +++ b/sys/dev/ata/ata-chipset.c @@ -56,6 +56,11 @@ __FBSDID("$FreeBSD$"); static int ata_generic_chipinit(device_t); static void ata_generic_intr(void *); static void ata_generic_setmode(device_t, int); +static int ata_ahci_allocate(device_t dev); +static int ata_ahci_begin_transaction(struct ata_request *); +static int ata_ahci_end_transaction(struct ata_request *); +static void ata_ahci_intr(void *); +static void ata_ahci_reset(device_t); static int ata_acard_chipinit(device_t); static void ata_acard_intr(void *); static void ata_acard_850_setmode(device_t, int); @@ -243,17 +248,16 @@ ata_sata_connect(struct ata_channel *ch) else break; } - if (1 | bootverbose) + if (bootverbose) device_printf(ch->dev, "SATA connect ready time=%dms\n", timeout * 10); if (timeout < 1000) { if ((ATA_IDX_INB(ch, ATA_CYL_LSB) == ATAPI_MAGIC_LSB) && (ATA_IDX_INB(ch, ATA_CYL_MSB) == ATAPI_MAGIC_MSB)) ch->devices = ATA_ATAPI_MASTER; - else /*if ((ATA_IDX_INB(ch, ATA_COUNT) == 0x01) && - (ATA_IDX_INB(ch, ATA_CYL_LSB) == 0x01)) */ + else ch->devices = ATA_ATA_MASTER; } - if (1 | bootverbose) + if (bootverbose) device_printf(ch->dev, "sata_connect devices=0x%b\n", ch->devices, "\20\3ATAPI_MASTER\1ATA_MASTER"); return 1; @@ -319,6 +323,337 @@ ata_sata_phy_event(void *context, int dummy) /* + * AHCI v1.0 compliant SATA chipset support functions + */ +struct ata_ahci_dma_prd { + u_int64_t dba; + u_int32_t reserved; + u_int32_t dbc; /* 0 based */ +#define ATA_AHCI_PRD_MASK 0x003fffff /* max 4MB */ +#define ATA_AHCI_PRD_IPC (1<<31) +} __packed; + +struct ata_ahci_cmd_tab { + u_int8_t cfis[64]; + u_int8_t acmd[32]; + u_int8_t reserved[32]; + struct ata_ahci_dma_prd prd_tab[16]; +} __packed; + +struct ata_ahci_cmd_list { + u_int16_t cmd_flags; + u_int16_t prd_length; /* PRD entries */ + u_int32_t bytecount; + u_int64_t cmd_table_phys; /* 128byte aligned */ +} __packed; + + +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); + + /* XXX SOS this is a hack to satisfy various legacy cruft */ + ch->r_io[ATA_CYL_LSB].res = ctlr->r_res2; + ch->r_io[ATA_CYL_LSB].offset = ATA_AHCI_P_SIG + 1 + offset; + ch->r_io[ATA_CYL_LSB].res = ctlr->r_res2; + ch->r_io[ATA_CYL_MSB].offset = ATA_AHCI_P_SIG + 3 + offset; + ch->r_io[ATA_STATUS].res = ctlr->r_res2; + ch->r_io[ATA_STATUS].offset = ATA_AHCI_P_TFD + offset; + ch->r_io[ATA_ALTSTAT].res = ctlr->r_res2; + ch->r_io[ATA_ALTSTAT].offset = ATA_AHCI_P_TFD + offset; + + /* 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.begin_transaction = ata_ahci_begin_transaction; + ch->hw.end_transaction = ata_ahci_end_transaction; + ch->hw.command = NULL; /* not used here */ + + /* setup the work areas */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset, + ch->dma->work_bus + ATA_AHCI_CL_OFFSET); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, 0x00000000); + + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset, + ch->dma->work_bus + ATA_AHCI_FB_OFFSET); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, 0x00000000); + + /* 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)); + + /* start operations on this channel */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, + (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_FRE | + ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD | ATA_AHCI_P_CMD_ST)); + return 0; +} + +static int +ata_ahci_setup_fis(u_int8_t *fis, struct ata_request *request) +{ + struct ata_device *atadev = device_get_softc(request->dev); + int idx = 0; + + /* XXX SOS add ATAPI commands support later */ + fis[idx++] = 0x27; /* host to device */ + fis[idx++] = 0x80; /* command FIS (note PM goes here) */ + fis[idx++] = ata_modify_if_48bit(request); + fis[idx++] = request->u.ata.feature; + + fis[idx++] = request->u.ata.lba; + fis[idx++] = request->u.ata.lba >> 8; + fis[idx++] = request->u.ata.lba >> 16; + fis[idx++] = ATA_D_LBA | atadev->unit; + + fis[idx++] = request->u.ata.lba >> 24; + fis[idx++] = request->u.ata.lba >> 32; + fis[idx++] = request->u.ata.lba >> 40; + fis[idx++] = request->u.ata.feature >> 8; + + fis[idx++] = request->u.ata.count; + fis[idx++] = request->u.ata.count >> 8; + fis[idx++] = 0x00; + fis[idx++] = ATA_A_4BIT; + + fis[idx++] = 0x00; + fis[idx++] = 0x00; + fis[idx++] = 0x00; + fis[idx++] = 0x00; + return idx; +} + +/* 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(device_get_parent(request->dev)); + struct ata_ahci_cmd_tab *ctp; + struct ata_ahci_cmd_list *clp; + int fis_size, entries; + int tag = 0; + + /* 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 * tag)); + + /* setup the FIS for this request */ /* XXX SOS ATAPI missing still */ + if (!(fis_size = ata_ahci_setup_fis(&ctp->cfis[0], 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(ch->dev, request->data, request->bytecount, + request->flags & ATA_R_READ, + 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 * tag)); + + clp->prd_length = entries; + clp->cmd_flags = (request->flags & ATA_R_WRITE ? (1<<6) : 0) | + (request->flags & ATA_R_ATAPI ? (1<<5) : 0) | + (fis_size / sizeof(u_int32_t)); + clp->bytecount = 0; + clp->cmd_table_phys = htole64(ch->dma->work_bus + ATA_AHCI_CT_OFFSET + + (ATA_AHCI_CT_SIZE * tag)); + + /* clear eventual ACTIVE bit */ + ATA_IDX_OUTL(ch, ATA_SACTIVE, ATA_IDX_INL(ch, ATA_SACTIVE) & (1 << tag)); + + /* issue the command */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + (ch->unit << 7), (1 << tag)); + + /* 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(device_get_parent(request->dev)); + struct ata_ahci_cmd_list *clp; + u_int32_t tf_data; + int tag = 0; + + /* kill the timeout */ + callout_stop(&request->callout); + + /* get status */ + tf_data = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + (ch->unit << 7)); + request->status = tf_data; + + /* if error status get details */ + if (request->status & ATA_S_ERROR) + request->error = tf_data >> 8; + + /* record how much data we actually moved */ + clp = (struct ata_ahci_cmd_list *) + (ch->dma->work + ATA_AHCI_CL_OFFSET + (ATA_AHCI_CL_SIZE * tag)); + request->donecount = clp->bytecount; + + /* release SG list etc */ + ch->dma->unload(ch->dev); + + return ATA_OP_FINISHED; +} + +static void +ata_ahci_intr(void *data) +{ + struct ata_pci_controller *ctlr = data; + struct ata_channel *ch; + u_int32_t port, status, error, issued; + int unit; + int tag = 0; + + port = ATA_INL(ctlr->r_res2, ATA_AHCI_IS); + + /* implement this as a toggle instead to balance load XXX */ + for (unit = 0; unit < ctlr->channels; unit++) { + if (port & (1 << unit)) { + if ((ch = ctlr->interrupt[unit].argument)) { + struct ata_connect_task *tp; + int offset = (ch->unit << 7); + + error = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SERR + offset); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_SERR + offset, error); + status = ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, status); + issued = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset); + + /* do we have cold connect surprise */ + if (status & ATA_AHCI_P_IX_CPD) { + printf("ata_ahci_intr status=%08x error=%08x issued=%08x\n", + status, error, issued); + } + + /* check for and handle connect events */ + if ((status & ATA_AHCI_P_IX_PC) && + (tp = (struct ata_connect_task *) + malloc(sizeof(struct ata_connect_task), + M_ATA, M_NOWAIT | M_ZERO))) { + + device_printf(ch->dev, "CONNECT requested\n"); + tp->action = ATA_C_ATTACH; + tp->dev = ch->dev; + TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp); + taskqueue_enqueue(taskqueue_thread, &tp->task); + } + + /* check for and handle disconnect events */ + if (((status & (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC)) == + ATA_AHCI_P_IX_PRC) && + (tp = (struct ata_connect_task *) + malloc(sizeof(struct ata_connect_task), + M_ATA, M_NOWAIT | M_ZERO))) { + + device_printf(ch->dev, "DISCONNECT requested\n"); + tp->action = ATA_C_DETACH; + tp->dev = ch->dev; + TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp); + taskqueue_enqueue(taskqueue_thread, &tp->task); + } + + /* any drive action to take care of ? */ + if (!(issued & (1<<tag))) + ctlr->interrupt[unit].function(ch); + } + } + } + ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, port); +} + +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_int32_t cmd; + int offset = (ch->unit << 7); + + /* 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_CR | ATA_AHCI_P_CMD_FR | + ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST)); + + DELAY(500000); /* XXX SOS */ + + /* spin up device */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, ATA_AHCI_P_CMD_SUD); + + ata_sata_phy_enable(ch); + + /* 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 */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, + (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_FRE | + ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD | ATA_AHCI_P_CMD_ST)); +} + +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); + } + } + args->nsegs = nsegs; +} + +static void +ata_ahci_dmainit(device_t dev) +{ + struct ata_channel *ch = device_get_softc(dev); + + ata_dmainit(dev); + if (ch->dma) { + /* note start and stop are not used here */ + ch->dma->setprd = ata_ahci_dmasetprd; + ch->dma->max_iosize = 8192 * DEV_BSIZE; + } +} + + +/* * Acard chipset support functions */ int @@ -1083,10 +1418,42 @@ ata_intel_chipinit(device_t dev) ctlr->setmode = ata_intel_new_setmode; } else { + /* if we have BAR(5) as a memory resource we should use AHCI mode */ + 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 (bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle) || + bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS, + ata_ahci_intr, ctlr, &ctlr->handle)) { + device_printf(dev, "unable to setup interrupt\n"); + return ENXIO; + } + + /* force all ports active "the legacy way" */ + pci_write_config(dev, 0x92, pci_read_config(dev, 0x92, 2) | 0x0f,2); + + /* enable AHCI mode */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE); + + /* get the number of HW channels */ + ctlr->channels = (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & + ATA_AHCI_NPMASK) + 1; + + /* enable AHCI interrupts */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, + ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) | ATA_AHCI_GHC_IE); + + ctlr->reset = ata_ahci_reset; + ctlr->dmainit = ata_ahci_dmainit; + ctlr->allocate = ata_ahci_allocate; + } + else { + ctlr->reset = ata_intel_reset; + } + ctlr->setmode = ata_sata_setmode; pci_write_config(dev, PCIR_COMMAND, pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2); - ctlr->reset = ata_intel_reset; - ctlr->setmode = ata_sata_setmode; } return 0; } |