diff options
author | sos <sos@FreeBSD.org> | 2005-04-08 09:37:47 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 2005-04-08 09:37:47 +0000 |
commit | 807c19e46482af6c9718dc815d967bcf150208ed (patch) | |
tree | 4fdd7d0f1c14c46c4d5644201fa9543da4203488 | |
parent | a2b6f806840b15fedd7fb6d52c4487302428cab1 (diff) | |
download | FreeBSD-src-807c19e46482af6c9718dc815d967bcf150208ed.zip FreeBSD-src-807c19e46482af6c9718dc815d967bcf150208ed.tar.gz |
Generalise the SATA PHY handling code so it wont be duplicated for
each SATA chip.
Promise and Silicon Image are the current candidates for this.
-rw-r--r-- | sys/dev/ata/ata-all.c | 4 | ||||
-rw-r--r-- | sys/dev/ata/ata-all.h | 129 | ||||
-rw-r--r-- | sys/dev/ata/ata-chipset.c | 262 | ||||
-rw-r--r-- | sys/dev/ata/ata-lowlevel.c | 19 | ||||
-rw-r--r-- | sys/dev/ata/ata-pci.c | 12 | ||||
-rw-r--r-- | sys/dev/ata/ata-pci.h | 3 |
6 files changed, 241 insertions, 188 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 3240307..5cca7e2 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -122,7 +122,7 @@ ata_attach(device_t dev) mtx_init(&ch->queue_mtx, "ATA queue lock", NULL, MTX_DEF); TAILQ_INIT(&ch->ata_queue); - /* initialise device(s) on this channel */ + /* reset the controller HW, the channel and device(s) */ while (ATA_LOCKING(dev, ATA_LF_LOCK) != ch->unit) tsleep(&error, PRIBIO, "ataatch", 1); ch->hw.reset(ch); @@ -205,7 +205,7 @@ ata_reinit(device_t dev) ch->state = ATA_STALL_QUEUE; mtx_unlock(&ch->state_mtx); - /* reset the channel and devices */ + /* reset the controller HW, the channel and device(s) */ ch->hw.reset(ch); /* reinit the children and delete any that fails */ diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index a356ac8..0e794de 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -103,15 +103,90 @@ #define ATA_A_4BIT 0x08 /* 4 head bits */ #define ATA_A_HOB 0x80 /* High Order Byte enable */ -/* ATAPI misc defines */ -#define ATAPI_MAGIC_LSB 0x14 -#define ATAPI_MAGIC_MSB 0xeb -#define ATAPI_P_READ (ATA_S_DRQ | ATA_I_IN) -#define ATAPI_P_WRITE (ATA_S_DRQ) -#define ATAPI_P_CMDOUT (ATA_S_DRQ | ATA_I_CMD) -#define ATAPI_P_DONEDRQ (ATA_S_DRQ | ATA_I_CMD | ATA_I_IN) -#define ATAPI_P_DONE (ATA_I_CMD | ATA_I_IN) -#define ATAPI_P_ABORT 0 +/* SATA register defines */ +#define ATA_SSTATUS 13 +#define ATA_SS_DET_MASK 0x0000000f +#define ATA_SS_DET_NO_DEVICE 0x00000000 +#define ATA_SS_DET_DEV_PRESENT 0x00000001 +#define ATA_SS_DET_PHY_ONLINE 0x00000003 +#define ATA_SS_DET_PHY_OFFLINE 0x00000004 + +#define ATA_SS_SPD_MASK 0x000000f0 +#define ATA_SS_SPD_NO_SPEED 0x00000000 +#define ATA_SS_SPD_GEN1 0x00000010 +#define ATA_SS_SPD_GEN2 0x00000020 + +#define ATA_SS_IPM_MASK 0x00000f00 +#define ATA_SS_IPM_NO_DEVICE 0x00000000 +#define ATA_SS_IPM_ACTIVE 0x00000100 +#define ATA_SS_IPM_PARTIAL 0x00000200 +#define ATA_SS_IPM_SLUMBER 0x00000600 + +#define ATA_SS_CONWELL_MASK \ + (ATA_SS_DET_MASK|ATA_SS_SPD_MASK|ATA_SS_IPM_MASK) +#define ATA_SS_CONWELL_GEN1 \ + (ATA_SS_DET_PHY_ONLINE|ATA_SS_SPD_GEN1|ATA_SS_IPM_ACTIVE) +#define ATA_SS_CONWELL_GEN2 \ + (ATA_SS_DET_PHY_ONLINE|ATA_SS_SPD_GEN2|ATA_SS_IPM_ACTIVE) + +#define ATA_SERROR 14 +#define ATA_SE_DATA_CORRECTED 0x00000001 +#define ATA_SE_COMM_CORRECTED 0x00000002 +#define ATA_SE_DATA_ERR 0x00000100 +#define ATA_SE_COMM_ERR 0x00000200 +#define ATA_SE_PROT_ERR 0x00000400 +#define ATA_SE_HOST_ERR 0x00000800 +#define ATA_SE_PHY_CHANGED 0x00010000 +#define ATA_SE_PHY_IERROR 0x00020000 +#define ATA_SE_COMM_WAKE 0x00040000 +#define ATA_SE_DECODE_ERR 0x00080000 +#define ATA_SE_PARITY_ERR 0x00100000 +#define ATA_SE_CRC_ERR 0x00200000 +#define ATA_SE_HANDSHAKE_ERR 0x00400000 +#define ATA_SE_LINKSEQ_ERR 0x00800000 +#define ATA_SE_TRANSPORT_ERR 0x01000000 +#define ATA_SE_UNKNOWN_FIS 0x02000000 + +#define ATA_SCONTROL 15 +#define ATA_SC_DET_MASK 0x0000000f +#define ATA_SC_DET_NO_DEVICE 0x00000000 +#define ATA_SC_DET_RESET 0x00000001 +#define ATA_SC_DET_DISABLE 0x00000004 + +#define ATA_SC_SPD_MASK 0x000000f0 +#define ATA_SC_SPD_NO_SPEED 0x00000000 +#define ATA_SC_SPD_SPEED_GEN1 0x00000010 +#define ATA_SC_SPD_SPEED_GEN2 0x00000020 + +#define ATA_SC_IPM_MASK 0x00000f00 +#define ATA_SC_IPM_NONE 0x00000000 +#define ATA_SC_IPM_DIS_PARTIAL 0x00000100 +#define ATA_SC_IPM_DIS_SLUMBER 0x00000200 + +/* DMA register defines */ +#define ATA_DMA_ENTRIES 256 +#define ATA_DMA_EOT 0x80000000 + +#define ATA_BMCMD_PORT 16 +#define ATA_BMCMD_START_STOP 0x01 +#define ATA_BMCMD_WRITE_READ 0x08 + +#define ATA_BMDEVSPEC_0 17 +#define ATA_BMSTAT_PORT 18 +#define ATA_BMSTAT_ACTIVE 0x01 +#define ATA_BMSTAT_ERROR 0x02 +#define ATA_BMSTAT_INTERRUPT 0x04 +#define ATA_BMSTAT_MASK 0x07 +#define ATA_BMSTAT_DMA_MASTER 0x20 +#define ATA_BMSTAT_DMA_SLAVE 0x40 +#define ATA_BMSTAT_DMA_SIMPLEX 0x80 + +#define ATA_BMDEVSPEC_1 19 +#define ATA_BMDTP_PORT 20 + +#define ATA_IDX_ADDR 21 +#define ATA_IDX_DATA 22 +#define ATA_MAX_RES 23 /* misc defines */ #define ATA_PRIMARY 0x1f0 @@ -127,39 +202,19 @@ #define ATA_BMADDR_RID 0x20 #define ATA_PC98_CTLADDR_RID 8 #define ATA_PC98_BANKADDR_RID 9 - #define ATA_IRQ_RID 0 #define ATA_DEV(device) ((device == ATA_MASTER) ? 0 : 1) - -/* busmaster DMA related defines */ -#define ATA_DMA_ENTRIES 256 -#define ATA_DMA_EOT 0x80000000 - -#define ATA_BMCMD_PORT 13 -#define ATA_BMCMD_START_STOP 0x01 -#define ATA_BMCMD_WRITE_READ 0x08 - -#define ATA_BMDEVSPEC_0 14 -#define ATA_BMSTAT_PORT 15 -#define ATA_BMSTAT_ACTIVE 0x01 -#define ATA_BMSTAT_ERROR 0x02 -#define ATA_BMSTAT_INTERRUPT 0x04 -#define ATA_BMSTAT_MASK 0x07 -#define ATA_BMSTAT_DMA_MASTER 0x20 -#define ATA_BMSTAT_DMA_SLAVE 0x40 -#define ATA_BMSTAT_DMA_SIMPLEX 0x80 - -#define ATA_BMDEVSPEC_1 16 -#define ATA_BMDTP_PORT 17 - -#define ATA_IDX_ADDR 18 -#define ATA_IDX_DATA 19 -#define ATA_MAX_RES 20 - +#define ATAPI_MAGIC_LSB 0x14 +#define ATAPI_MAGIC_MSB 0xeb +#define ATAPI_P_READ (ATA_S_DRQ | ATA_I_IN) +#define ATAPI_P_WRITE (ATA_S_DRQ) +#define ATAPI_P_CMDOUT (ATA_S_DRQ | ATA_I_CMD) +#define ATAPI_P_DONEDRQ (ATA_S_DRQ | ATA_I_CMD | ATA_I_IN) +#define ATAPI_P_DONE (ATA_I_CMD | ATA_I_IN) +#define ATAPI_P_ABORT 0 #define ATA_INTR_FLAGS (INTR_MPSAFE|INTR_TYPE_BIO|INTR_ENTROPY) #define ATA_OP_CONTINUES 0 #define ATA_OP_FINISHED 1 - #define ATA_MAX_28BIT_LBA 268435455 /* ATAPI request sense structure */ diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c index 5bcafb1..65efa15 100644 --- a/sys/dev/ata/ata-chipset.c +++ b/sys/dev/ata/ata-chipset.c @@ -112,6 +112,8 @@ static void ata_sii_setmode(struct ata_device *, int); static void ata_cmd_setmode(struct ata_device *, int); static int ata_sis_chipinit(device_t); static void ata_sis_setmode(struct ata_device *, int); +static void ata_print_cable(device_t dev, u_int8_t *who); +static int ata_atapi(struct ata_device *atadev); static int ata_check_80pin(struct ata_device *, int); static struct ata_chip_id *ata_find_chip(device_t, struct ata_chip_id *, int); static int ata_setup_interrupt(device_t); @@ -119,23 +121,6 @@ static int ata_serialize(struct ata_channel *, int); static int ata_mode2idx(int); -static 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 -ata_atapi(struct ata_device *atadev) -{ - struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev)); - - return ((atadev->unit == ATA_MASTER && ch->devices & ATA_ATAPI_MASTER) || - (atadev->unit == ATA_SLAVE && ch->devices & ATA_ATAPI_SLAVE)); -} - - /* generic or unknown ATA chipset support functions */ int ata_generic_ident(device_t dev) @@ -215,8 +200,79 @@ ata_sata_setmode(struct ata_device *atadev, int mode) } } +static int +ata_sata_connect(struct ata_channel *ch) +{ + u_int32_t status; + int timeout; + + /* wait up to 1 second for "connect well" */ + for (timeout = 0; timeout < 100 ; timeout++) { + status = ATA_IDX_INL(ch, ATA_SSTATUS); + if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 || + (status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2) + break; + ata_udelay(10000); + } + if (timeout >= 100) { + if (1 | bootverbose) + device_printf(ch->dev, "SATA connect status=%08x\n", status); + return 0; + } + + /* clear SATA error register */ + ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR)); + + /* find out what type device we got poll for spec'd 31 seconds */ + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM); + DELAY(10); + for (timeout = 0; timeout < 3100; timeout++) { + if (ATA_IDX_INB(ch, ATA_STATUS) & ATA_S_BUSY) + DELAY(10000); + else + break; + } + if (1 | bootverbose) + device_printf(ch->dev, "SATA connect ready time=%dms\n", timeout * 10); + 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 + ch->devices = ATA_ATA_MASTER; + + return 1; +} + static void -ata_sata_connect(void *context, int dummy) +ata_sata_enable_phy(struct ata_channel *ch) +{ + int loop, retry; + + if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == 0 && + ata_sata_connect(ch)) + return; + + for (retry = 0; retry < 10; retry++) { + for (loop = 0; loop < 10; loop++) { + ATA_IDX_OUTL(ch, ATA_SCONTROL, 1); + ata_udelay(100); + if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == 1) + break; + } + ata_udelay(5000); + for (loop = 0; loop < 10; loop++) { + ATA_IDX_OUTL(ch, ATA_SCONTROL, 0); + ata_udelay(100); + if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == 0) + break; + } + if (ata_sata_connect(ch)) + break; + } +} + +static void +ata_sata_phy_event(void *context, int dummy) { struct ata_connect_task *tp = (struct ata_connect_task *)context; device_t *children; @@ -224,9 +280,12 @@ ata_sata_connect(void *context, int dummy) mtx_lock(&Giant); /* newbus suckage it needs Giant */ if (tp->action == ATA_C_ATTACH) { + struct ata_channel *ch = device_get_softc(tp->dev); + + device_printf(tp->dev, "CONNECTED\n"); + ata_sata_connect(ch); bus_generic_probe(tp->dev); bus_generic_attach(tp->dev); - device_printf(tp->dev, "CONNECTED\n"); } if (tp->action == ATA_C_DETACH) { if (!device_get_children(tp->dev, &children, &nchildren)) { @@ -336,7 +395,7 @@ ata_acard_850_setmode(struct ata_device *atadev, int mode) mode = ata_limit_mode(atadev, mode, ata_atapi(atadev) ? ATA_PIO_MAX:ctlr->chip->max_dma); -/* XXX missing WDMA0+1 + PIO modes */ + /* XXX missing WDMA0+1 + PIO modes */ if (mode >= ATA_WDMA2) { error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,mode); if (bootverbose) @@ -374,7 +433,7 @@ ata_acard_86X_setmode(struct ata_device *atadev, int mode) mode = ata_check_80pin(atadev, mode); -/* XXX missing WDMA0+1 + PIO modes */ + /* XXX missing WDMA0+1 + PIO modes */ if (mode >= ATA_WDMA2) { error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,mode); if (bootverbose) @@ -957,6 +1016,7 @@ ata_intel_ident(device_t dev) { ATA_I82801FB, 0, 0, 0x00, ATA_UDMA5, "Intel ICH6" }, { ATA_I82801FB_S1,0, 0, 0x00, ATA_SA150, "Intel ICH6" }, { ATA_I82801FB_R1,0, 0, 0x00, ATA_SA150, "Intel ICH6" }, + { ATA_I82801FBM, 0, 0, 0x00, ATA_SA150, "Intel ICH6" }, { 0, 0, 0, 0, 0, 0}}; char buffer[64]; @@ -1659,11 +1719,17 @@ ata_promise_mio_allocate(device_t dev) ch->r_io[ATA_CONTROL].offset = offset + 0x0238 + (ch->unit << 7); ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2; ata_default_registers(ch); - - ch->flags |= ATA_USE_16BIT; if ((ctlr->chip->cfg2 & (PRSATA | PRSATA2)) || - ((ctlr->chip->cfg2 & (PRCMBO | PRCMBO2)) && ch->unit < 2)) + ((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(ch); if (offset) @@ -1718,7 +1784,7 @@ ata_promise_mio_intr(void *data) device_printf(ch->dev, "DISCONNECT requested\n"); tp->action = ATA_C_DETACH; tp->dev = ch->dev; - TASK_INIT(&tp->task, 0, ata_sata_connect, tp); + TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp); taskqueue_enqueue(taskqueue_thread, &tp->task); } @@ -1730,14 +1796,9 @@ ata_promise_mio_intr(void *data) if (bootverbose) device_printf(ch->dev, "CONNECT requested\n"); - - /* if we dont get "connect well" reset the channel */ - if (!(status & (0x00000100 << unit))) - ctlr->reset(ch); - tp->action = ATA_C_ATTACH; tp->dev = ch->dev; - TASK_INIT(&tp->task, 0, ata_sata_connect, tp); + TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp); taskqueue_enqueue(taskqueue_thread, &tp->task); } @@ -1806,51 +1867,18 @@ ata_promise_mio_dmainit(struct ata_channel *ch) } } -static int -ata_promise_connect(struct ata_channel *ch) -{ - struct ata_pci_controller *ctlr = - device_get_softc(device_get_parent(ch->dev)); - u_int32_t status; - int loop, retry; - - if ((ATA_INL(ctlr->r_res2, 0x408 + (ch->unit << 8)) & 0x07) == 0) { - status = ATA_INL(ctlr->r_res2, 0x400 + (ch->unit << 8)); - if ((status & 0x737) == 0x113 || (status & 0x737) == 0x123) - return 1; - } - for (retry = 0; retry < 10; retry++) { - for (loop = 0; loop < 10; loop++) { - ATA_OUTL(ctlr->r_res2, 0x408 + (ch->unit << 8), 1); - ata_udelay(100); - if ((ATA_INL(ctlr->r_res2, 0x408 + (ch->unit << 8)) & 0x07) == 1) - break; - } - ata_udelay(1000); - for (loop = 0; loop < 10; loop++) { - ATA_OUTL(ctlr->r_res2, 0x408 + (ch->unit << 8), 0); - ata_udelay(100); - if ((ATA_INL(ctlr->r_res2, 0x408 + (ch->unit << 8)) & 0x07) == 0) - break; - } - status = ATA_INL(ctlr->r_res2, 0x400 + (ch->unit << 8)); - if ((status & 0x737) == 0x113 || (status & 0x737) == 0x123) - return 1; - } - return 0; -} - static void ata_promise_mio_reset(struct ata_channel *ch) { struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(ch->dev)); + struct ata_promise_sx4 *hpktp; switch (ctlr->chip->cfg2) { - case PRSX4X: { - struct ata_promise_sx4 *hpktp = device_get_ivars(ctlr->dev); + 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), @@ -1866,14 +1894,10 @@ ata_promise_mio_reset(struct ata_channel *ch) (ATA_INL(ctlr->r_res2, 0xc012c) & ~0x00000f9f)); hpktp->busy = 0; mtx_unlock(&hpktp->mtx); - } break; case PRCMBO: - case PRSATA: { - u_int32_t status = 0; - int timeout; - + case PRSATA: if ((ctlr->chip->cfg2 == PRSATA) || ((ctlr->chip->cfg2 == PRCMBO) && (ch->unit < 2))) { @@ -1891,31 +1915,15 @@ ata_promise_mio_reset(struct ata_channel *ch) if ((ctlr->chip->cfg2 == PRSATA) || ((ctlr->chip->cfg2 == PRCMBO) && (ch->unit < 2))) { - /* enable PHY and try to connect */ - ata_promise_connect(ch); - - /* wait up to 1 sec for "connect well" */ - for (timeout = 0; timeout < 100 ; timeout++) { - status = ATA_INL(ctlr->r_res2, 0x400 + (ch->unit << 8)); - if (((status & 0x717) == 0x113) && - (ATA_IDX_INB(ch, ATA_STATUS) != 0xff)) - break; - ata_udelay(10000); - } - if (timeout >= 100) - device_printf(ch->dev, "connect status=%08x\n", status); + ata_sata_enable_phy(ch); /* reset and enable plug/unplug intr */ ATA_OUTL(ctlr->r_res2, 0x06c, (0x00000011 << ch->unit)); } - } break; case PRCMBO2: - case PRSATA2: { - u_int32_t status = 0; - int timeout; - + case PRSATA2: if ((ctlr->chip->cfg2 == PRSATA2) || ((ctlr->chip->cfg2 == PRCMBO2) && (ch->unit < 2))) { /* set portmultiplier port */ @@ -1940,19 +1948,7 @@ ata_promise_mio_reset(struct ata_channel *ch) (ATA_INL(ctlr->r_res2, 0x414 + (ch->unit << 8)) & ~0x00000003) | 0x00000001); - /* enable PHY and try to connect */ - ata_promise_connect(ch); - - /* wait up to 1 sec for "connect well" */ - for (timeout = 0; timeout < 100 ; timeout++) { - status = ATA_INL(ctlr->r_res2, 0x400 + (ch->unit << 8)); - if (((status & 0x737) == 0x113 || (status & 0x737) == 0x123) && - (ATA_IDX_INB(ch, ATA_STATUS) != 0xff)) - break; - ata_udelay(10000); - } - if (timeout >= 100) - device_printf(ch->dev, "connect status=%08x\n", status); + ata_sata_enable_phy(ch); /* reset and enable plug/unplug intr */ ATA_OUTL(ctlr->r_res2, 0x060, (0x00000011 << ch->unit)); @@ -1960,7 +1956,6 @@ ata_promise_mio_reset(struct ata_channel *ch) /* set portmultiplier port */ ATA_OUTL(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x00); } - } break; } } @@ -2641,10 +2636,14 @@ ata_sii_allocate(device_t dev) ch->r_io[ATA_BMDTP_PORT].offset = 0x04 + (unit01 << 3) + (unit10 << 8); ch->r_io[ATA_BMDEVSPEC_0].res = ctlr->r_res2; ch->r_io[ATA_BMDEVSPEC_0].offset = 0xa1 + (unit01 << 6) + (unit10 << 8); - ch->r_io[ATA_BMDEVSPEC_1].res = ctlr->r_res2; - ch->r_io[ATA_BMDEVSPEC_1].offset = 0x100 + (unit01 << 7) + (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 */ @@ -2667,31 +2666,11 @@ ata_sii_reset(struct ata_channel *ch) struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(ch->dev)); int offset = ((ch->unit & 1) << 7) + ((ch->unit & 2) << 8); - u_int32_t status = 0, error; - int timeout; /* disable PHY state change interrupt */ ATA_OUTL(ctlr->r_res2, 0x148 + offset, ~(1 << 16)); - /* flip reset bit */ - ATA_OUTL(ctlr->r_res2, 0x100 + offset, 0x00000001); - ata_udelay(25000); - ATA_OUTL(ctlr->r_res2, 0x100 + offset, 0x00000000); - - /* enable PHY and try to connect XXX SOS */ - /* wait up to 1 sec for "connect well" */ - for (timeout = 0; timeout < 100 ; timeout++) { - status = ATA_INL(ctlr->r_res2, 0x104 + offset); - if (((status & 0x717) == 0x113) && ATA_IDX_INB(ch, ATA_STATUS) != 0xff) - break; - ata_udelay(10000); - } - if (timeout >= 100) - device_printf(ch->dev, "connect status=%08x\n", status); - - /* clear error register */ - error = ATA_INL(ctlr->r_res2, 0x108 + offset); - ATA_OUTL(ctlr->r_res2, 0x108 + offset, error); + ata_sata_enable_phy(ch); /* enable PHY state change interrupt */ ATA_OUTL(ctlr->r_res2, 0x148 + offset, (1 << 16)); @@ -2711,21 +2690,20 @@ ata_sii_intr(void *data) /* check for PHY related interrupts on SATA capable HW */ if (ctlr->chip->max_dma >= ATA_SA150) { - int offset = ((ch->unit & 1) << 7) + ((ch->unit & 2) << 8); - u_int32_t status = ATA_INL(ctlr->r_res2, 0x104 + offset); - u_int32_t error = ATA_INL(ctlr->r_res2, 0x108 + offset); + u_int32_t status = ATA_IDX_INL(ch, ATA_SSTATUS); + u_int32_t error = ATA_IDX_INL(ch, ATA_SERROR); if (error) { /* clear error bits/interrupt */ - ATA_OUTL(ctlr->r_res2, 0x108 + offset, error); + ATA_IDX_OUTL(ch, ATA_SERROR, error); - /* if we have a connection "surprise" deal with it */ + /* if we have a connection event deal with it */ if (error & (1 << 16)) { struct ata_connect_task *tp = (struct ata_connect_task *) malloc(sizeof(struct ata_connect_task), M_ATA, M_NOWAIT | M_ZERO); - if ((status & 0x717) == 0x113) { + if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1) { device_printf(ch->dev, "CONNECT requested\n"); tp->action = ATA_C_ATTACH; } @@ -2734,7 +2712,7 @@ ata_sii_intr(void *data) tp->action = ATA_C_DETACH; } tp->dev = ch->dev; - TASK_INIT(&tp->task, 0, ata_sata_connect, tp); + TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp); taskqueue_enqueue(taskqueue_thread, &tp->task); } } @@ -3412,6 +3390,22 @@ ata_serialize(struct ata_channel *ch, int flags) return res; } +static 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 +ata_atapi(struct ata_device *atadev) +{ + struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev)); + + return ((atadev->unit == ATA_MASTER && ch->devices & ATA_ATAPI_MASTER) || + (atadev->unit == ATA_SLAVE && ch->devices & ATA_ATAPI_SLAVE)); +} + static int ata_check_80pin(struct ata_device *atadev, int mode) { diff --git a/sys/dev/ata/ata-lowlevel.c b/sys/dev/ata/ata-lowlevel.c index b94558e..ba322ee 100644 --- a/sys/dev/ata/ata-lowlevel.c +++ b/sys/dev/ata/ata-lowlevel.c @@ -79,6 +79,9 @@ ata_getparam(device_t parent, struct ata_device *atadev, u_int8_t command) /* select device */ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | atadev->unit); + /* wait a bit to let slow devices settle */ + DELAY(100); + /* disable interrupt */ ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_4BIT | ATA_A_IDS); @@ -610,15 +613,7 @@ ata_generic_reset(struct ata_channel *ch) u_int8_t err = 0, lsb = 0, msb = 0; int mask = 0, timeout; - /* if DMA functionality present stop it */ - if (ch->dma) { - if (ch->dma->stop) - ch->dma->stop(ch); - if (ch->dma->flags & ATA_DMA_LOADED) - ch->dma->unload(ch); - } - - /* reset host end of channel (if supported) */ + /* reset controller (host) */ ATA_RESET(ch->dev); /* do we have any signs of ATA/ATAPI HW being present ? */ @@ -752,8 +747,8 @@ ata_wait(struct ata_channel *ch, struct ata_device *atadev, u_int8_t mask) DELAY(1); - /* wait 5 seconds for device to get !BUSY */ - while (timeout < 5000000) { + /* wait at max 1 second for device to get !BUSY */ + while (timeout < 1000000) { status = ATA_IDX_INB(ch, ATA_ALTSTAT); /* if drive fails status, reselect the drive and try again */ @@ -777,7 +772,7 @@ ata_wait(struct ata_channel *ch, struct ata_device *atadev, u_int8_t mask) DELAY(10); } } - if (timeout >= 5000000) + if (timeout >= 1000000) return -2; if (!mask) return (status & ATA_S_ERROR); diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c index 5f815d2..42cb152 100644 --- a/sys/dev/ata/ata-pci.c +++ b/sys/dev/ata/ata-pci.c @@ -60,7 +60,6 @@ static MALLOC_DEFINE(M_ATAPCI, "ATA PCI", "ATA driver PCI"); #define IOMASK 0xfffffffc /* prototypes */ -static int ata_pci_allocate(device_t dev); static void ata_pci_dmainit(struct ata_channel *); int @@ -382,7 +381,7 @@ ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, } } -static int +int ata_pci_allocate(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); @@ -569,6 +568,15 @@ ata_pcichannel_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 DMA functionality present stop it */ + if (ch->dma) { + if (ch->dma->stop) + ch->dma->stop(ch); + if (ch->dma->flags & ATA_DMA_LOADED) + ch->dma->unload(ch); + } + + /* reset the controller HW */ if (ctlr->reset) ctlr->reset(ch); } diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h index e914dd5..a440098 100644 --- a/sys/dev/ata/ata-pci.h +++ b/sys/dev/ata/ata-pci.h @@ -139,6 +139,7 @@ struct ata_connect_task { #define ATA_I82801FB 0x266f8086 #define ATA_I82801FB_S1 0x26518086 #define ATA_I82801FB_R1 0x26528086 +#define ATA_I82801FBM 0x26538086 #define ATA_ITE_ID 0x1283 #define ATA_IT8212F 0x82121283 @@ -347,7 +348,7 @@ struct resource * ata_pci_alloc_resource(device_t dev, device_t child, int type, int ata_pci_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r); int ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_intr_t *function, void *argument, void **cookiep); int ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie); -extern driver_t ata_channel_driver; +int ata_pci_allocate(device_t dev); /* global prototypes ata-chipset.c */ int ata_generic_ident(device_t); |