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.
This commit is contained in:
sos 2005-04-08 09:37:47 +00:00
parent bb6185e155
commit c4dba639d5
6 changed files with 241 additions and 188 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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)
{

View File

@ -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);

View File

@ -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);
}

View File

@ -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);