summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ata/ata-all.c4
-rw-r--r--sys/dev/ata/ata-all.h129
-rw-r--r--sys/dev/ata/ata-chipset.c262
-rw-r--r--sys/dev/ata/ata-lowlevel.c19
-rw-r--r--sys/dev/ata/ata-pci.c12
-rw-r--r--sys/dev/ata/ata-pci.h3
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);
OpenPOWER on IntegriCloud