A little effort against kernel bloat....
Exclude ATA DMA support if no ATA DMA capable drivers are compiled in.
This commit is contained in:
parent
883278d33e
commit
f87d591722
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ata.c,v 1.77 2006/09/24 03:53:08 jmcneill Exp $ */
|
||||
/* $NetBSD: ata.c,v 1.78 2006/09/30 15:56:18 itohy Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
|
||||
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.77 2006/09/24 03:53:08 jmcneill Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.78 2006/09/30 15:56:18 itohy Exp $");
|
||||
|
||||
#ifndef ATADEBUG
|
||||
#define ATADEBUG
|
||||
|
@ -674,6 +674,7 @@ ata_set_mode(struct ata_drive_datas *drvp, u_int8_t mode, u_int8_t flags)
|
|||
return CMD_OK;
|
||||
}
|
||||
|
||||
#if NATA_DMA
|
||||
void
|
||||
ata_dmaerr(struct ata_drive_datas *drvp, int flags)
|
||||
{
|
||||
|
@ -696,6 +697,7 @@ ata_dmaerr(struct ata_drive_datas *drvp, int flags)
|
|||
drvp->n_xfers = 1; /* restart counting from this error */
|
||||
}
|
||||
}
|
||||
#endif /* NATA_DMA */
|
||||
|
||||
/*
|
||||
* freeze the queue and wait for the controller to be idle. Caller has to
|
||||
|
@ -1016,8 +1018,10 @@ ata_print_modes(struct ata_channel *chp)
|
|||
drvp->drv_softc->dv_xname,
|
||||
atac->atac_dev.dv_xname,
|
||||
chp->ch_channel, drvp->drive, drvp->PIO_mode);
|
||||
#if NATA_DMA
|
||||
if (drvp->drive_flags & DRIVE_DMA)
|
||||
aprint_normal(", DMA mode %d", drvp->DMA_mode);
|
||||
#if NATA_UDMA
|
||||
if (drvp->drive_flags & DRIVE_UDMA) {
|
||||
aprint_normal(", Ultra-DMA mode %d", drvp->UDMA_mode);
|
||||
if (drvp->UDMA_mode == 2)
|
||||
|
@ -1029,17 +1033,25 @@ ata_print_modes(struct ata_channel *chp)
|
|||
else if (drvp->UDMA_mode == 6)
|
||||
aprint_normal(" (Ultra/133)");
|
||||
}
|
||||
if ((drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA))
|
||||
#endif /* NATA_UDMA */
|
||||
#endif /* NATA_DMA */
|
||||
#if NATA_DMA || NATA_PIOBM
|
||||
if (0
|
||||
#if NATA_DMA
|
||||
|| (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA))
|
||||
#endif
|
||||
#if NATA_PIOBM
|
||||
/* PIOBM capable controllers use DMA for PIO commands */
|
||||
|| (atac->atac_cap & ATAC_CAP_PIOBM)
|
||||
#endif
|
||||
)
|
||||
aprint_normal(" (using DMA)");
|
||||
#endif /* NATA_DMA || NATA_PIOBM */
|
||||
aprint_normal("\n");
|
||||
}
|
||||
}
|
||||
|
||||
#if NATA_DMA
|
||||
/*
|
||||
* downgrade the transfer mode of a drive after an error. return 1 if
|
||||
* downgrade was possible, 0 otherwise.
|
||||
|
@ -1064,6 +1076,7 @@ ata_downgrade_mode(struct ata_drive_datas *drvp, int flags)
|
|||
(cf_flags & ATA_CONFIG_UDMA_SET))
|
||||
return 0;
|
||||
|
||||
#if NATA_UDMA
|
||||
/*
|
||||
* If we were using Ultra-DMA mode, downgrade to the next lower mode.
|
||||
*/
|
||||
|
@ -1072,6 +1085,7 @@ ata_downgrade_mode(struct ata_drive_datas *drvp, int flags)
|
|||
printf("%s: transfer error, downgrading to Ultra-DMA mode %d\n",
|
||||
drv_dev->dv_xname, drvp->UDMA_mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If we were using ultra-DMA, don't downgrade to multiword DMA.
|
||||
|
@ -1090,6 +1104,7 @@ ata_downgrade_mode(struct ata_drive_datas *drvp, int flags)
|
|||
ata_reset_channel(chp, flags | AT_RST_NOCMD);
|
||||
return 1;
|
||||
}
|
||||
#endif /* NATA_DMA */
|
||||
|
||||
/*
|
||||
* Probe drive's capabilities, for use by the controller later
|
||||
|
@ -1212,16 +1227,19 @@ ata_probe_caps(struct ata_drive_datas *drvp)
|
|||
for (i = 7; i >= 0; i--) {
|
||||
if ((params.atap_dmamode_supp & (1 << i)) == 0)
|
||||
continue;
|
||||
#if NATA_DMA
|
||||
if ((atac->atac_cap & ATAC_CAP_DMA) &&
|
||||
atac->atac_set_modes != NULL)
|
||||
if (ata_set_mode(drvp, 0x20 | i, AT_WAIT)
|
||||
!= CMD_OK)
|
||||
continue;
|
||||
#endif
|
||||
if (!printed) {
|
||||
aprint_normal("%s DMA mode %d", sep, i);
|
||||
sep = ",";
|
||||
printed = 1;
|
||||
}
|
||||
#if NATA_DMA
|
||||
if (atac->atac_cap & ATAC_CAP_DMA) {
|
||||
if (atac->atac_set_modes != NULL &&
|
||||
atac->atac_dma_cap < i)
|
||||
|
@ -1232,6 +1250,7 @@ ata_probe_caps(struct ata_drive_datas *drvp)
|
|||
drvp->drive_flags |= DRIVE_DMA;
|
||||
splx(s);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
if (params.atap_extensions & WDC_EXT_UDMA_MODES) {
|
||||
|
@ -1240,11 +1259,13 @@ ata_probe_caps(struct ata_drive_datas *drvp)
|
|||
if ((params.atap_udmamode_supp & (1 << i))
|
||||
== 0)
|
||||
continue;
|
||||
#if NATA_UDMA
|
||||
if (atac->atac_set_modes != NULL &&
|
||||
(atac->atac_cap & ATAC_CAP_UDMA))
|
||||
if (ata_set_mode(drvp, 0x40 | i,
|
||||
AT_WAIT) != CMD_OK)
|
||||
continue;
|
||||
#endif
|
||||
if (!printed) {
|
||||
aprint_normal("%s Ultra-DMA mode %d",
|
||||
sep, i);
|
||||
|
@ -1259,6 +1280,7 @@ ata_probe_caps(struct ata_drive_datas *drvp)
|
|||
sep = ",";
|
||||
printed = 1;
|
||||
}
|
||||
#if NATA_UDMA
|
||||
if (atac->atac_cap & ATAC_CAP_UDMA) {
|
||||
if (atac->atac_set_modes != NULL &&
|
||||
atac->atac_udma_cap < i)
|
||||
|
@ -1269,6 +1291,7 @@ ata_probe_caps(struct ata_drive_datas *drvp)
|
|||
drvp->drive_flags |= DRIVE_UDMA;
|
||||
splx(s);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1288,9 +1311,12 @@ ata_probe_caps(struct ata_drive_datas *drvp)
|
|||
|
||||
/* Try to guess ATA version here, if it didn't get reported */
|
||||
if (drvp->ata_vers == 0) {
|
||||
#if NATA_UDMA
|
||||
if (drvp->drive_flags & DRIVE_UDMA)
|
||||
drvp->ata_vers = 4; /* should be at last ATA-4 */
|
||||
else if (drvp->PIO_cap > 2)
|
||||
else
|
||||
#endif
|
||||
if (drvp->PIO_cap > 2)
|
||||
drvp->ata_vers = 2; /* should be at last ATA-2 */
|
||||
}
|
||||
cf_flags = device_cfdata(drv_dev)->cf_flags;
|
||||
|
@ -1301,6 +1327,7 @@ ata_probe_caps(struct ata_drive_datas *drvp)
|
|||
drvp->drive_flags |= DRIVE_MODE;
|
||||
splx(s);
|
||||
}
|
||||
#if NATA_DMA
|
||||
if ((atac->atac_cap & ATAC_CAP_DMA) == 0) {
|
||||
/* don't care about DMA modes */
|
||||
return;
|
||||
|
@ -1317,6 +1344,7 @@ ata_probe_caps(struct ata_drive_datas *drvp)
|
|||
}
|
||||
splx(s);
|
||||
}
|
||||
#if NATA_UDMA
|
||||
if ((atac->atac_cap & ATAC_CAP_UDMA) == 0) {
|
||||
/* don't care about UDMA modes */
|
||||
return;
|
||||
|
@ -1333,6 +1361,8 @@ ata_probe_caps(struct ata_drive_datas *drvp)
|
|||
}
|
||||
splx(s);
|
||||
}
|
||||
#endif /* NATA_UDMA */
|
||||
#endif /* NATA_DMA */
|
||||
}
|
||||
|
||||
/* management of the /dev/atabus* devices */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ata_wdc.c,v 1.84 2006/09/07 12:34:42 itohy Exp $ */
|
||||
/* $NetBSD: ata_wdc.c,v 1.85 2006/09/30 15:56:18 itohy Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001, 2003 Manuel Bouyer.
|
||||
|
@ -66,7 +66,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.84 2006/09/07 12:34:42 itohy Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.85 2006/09/30 15:56:18 itohy Exp $");
|
||||
|
||||
#ifndef ATADEBUG
|
||||
#define ATADEBUG
|
||||
|
@ -161,11 +161,16 @@ wdc_ata_bio(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
|
|||
ata_bio->flags |= ATA_POLL;
|
||||
if (ata_bio->flags & ATA_POLL)
|
||||
xfer->c_flags |= C_POLL;
|
||||
#if NATA_DMA
|
||||
if ((drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&
|
||||
(ata_bio->flags & ATA_SINGLE) == 0)
|
||||
xfer->c_flags |= C_DMA;
|
||||
#endif
|
||||
#if NATA_DMA && NATA_PIOBM
|
||||
else
|
||||
#endif
|
||||
#if NATA_PIOBM
|
||||
else if (atac->atac_cap & ATAC_CAP_PIOBM)
|
||||
if (atac->atac_cap & ATAC_CAP_PIOBM)
|
||||
xfer->c_flags |= C_PIOBM;
|
||||
#endif
|
||||
xfer->c_drive = drvp->drive;
|
||||
|
@ -243,10 +248,14 @@ wdc_ata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer)
|
|||
goto ctrltimeout;
|
||||
if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
|
||||
goto ctrlerror;
|
||||
#if NATA_DMA
|
||||
#if NATA_UDMA
|
||||
if (drvp->drive_flags & DRIVE_UDMA) {
|
||||
wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
|
||||
0x40 | drvp->UDMA_mode, WDSF_SET_MODE);
|
||||
} else if (drvp->drive_flags & DRIVE_DMA) {
|
||||
} else
|
||||
#endif
|
||||
if (drvp->drive_flags & DRIVE_DMA) {
|
||||
wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
|
||||
0x20 | drvp->DMA_mode, WDSF_SET_MODE);
|
||||
} else {
|
||||
|
@ -257,6 +266,7 @@ wdc_ata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer)
|
|||
goto ctrltimeout;
|
||||
if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
|
||||
goto ctrlerror;
|
||||
#endif /* NATA_DMA */
|
||||
geometry:
|
||||
if (ata_bio->flags & ATA_LBA)
|
||||
goto multimode;
|
||||
|
@ -328,20 +338,26 @@ _wdc_ata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer)
|
|||
int wait_flags = (xfer->c_flags & C_POLL) ? AT_POLL : 0;
|
||||
u_int16_t cyl;
|
||||
u_int8_t head, sect, cmd = 0;
|
||||
int nblks, error;
|
||||
int dma_flags = 0;
|
||||
int nblks;
|
||||
#if NATA_DMA || NATA_PIOBM
|
||||
int error, dma_flags = 0;
|
||||
#endif
|
||||
|
||||
ATADEBUG_PRINT(("_wdc_ata_bio_start %s:%d:%d\n",
|
||||
atac->atac_dev.dv_xname, chp->ch_channel, xfer->c_drive),
|
||||
DEBUG_INTR | DEBUG_XFERS);
|
||||
|
||||
#if NATA_DMA || NATA_PIOBM
|
||||
if (xfer->c_flags & (C_DMA | C_PIOBM)) {
|
||||
#if NATA_DMA
|
||||
if (drvp->n_xfers <= NXFER)
|
||||
drvp->n_xfers++;
|
||||
#endif
|
||||
dma_flags = (ata_bio->flags & ATA_READ) ? WDC_DMA_READ : 0;
|
||||
if (ata_bio->flags & ATA_LBA48)
|
||||
dma_flags |= WDC_DMA_LBA48;
|
||||
}
|
||||
#endif
|
||||
again:
|
||||
/*
|
||||
*
|
||||
|
@ -396,6 +412,7 @@ again:
|
|||
cyl = blkno;
|
||||
head |= WDSD_CHS;
|
||||
}
|
||||
#if NATA_DMA
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
ata_bio->nblks = nblks;
|
||||
ata_bio->nbytes = xfer->c_bcount;
|
||||
|
@ -454,6 +471,7 @@ again:
|
|||
goto intr;
|
||||
} /* else not DMA */
|
||||
do_pio:
|
||||
#endif /* NATA_DMA */
|
||||
#if NATA_PIOBM
|
||||
if ((xfer->c_flags & C_PIOBM) && xfer->c_skip == 0) {
|
||||
if (ata_bio->flags & ATA_POLL) {
|
||||
|
@ -563,16 +581,21 @@ again:
|
|||
(char *)xfer->c_databuf + xfer->c_skip, ata_bio->nbytes);
|
||||
}
|
||||
|
||||
intr: /* Wait for IRQ (either real or polled) */
|
||||
#if NATA_DMA
|
||||
intr:
|
||||
#endif
|
||||
/* Wait for IRQ (either real or polled) */
|
||||
if ((ata_bio->flags & ATA_POLL) == 0) {
|
||||
chp->ch_flags |= ATACH_IRQ_WAIT;
|
||||
} else {
|
||||
/* Wait for at last 400ns for status bit to be valid */
|
||||
delay(1);
|
||||
#if NATA_DMA
|
||||
if (chp->ch_flags & ATACH_DMA_WAIT) {
|
||||
wdc_dmawait(chp, xfer, ATA_DELAY);
|
||||
chp->ch_flags &= ~ATACH_DMA_WAIT;
|
||||
}
|
||||
#endif
|
||||
wdc_ata_bio_intr(chp, xfer, 0);
|
||||
if ((ata_bio->flags & ATA_ITSDONE) == 0)
|
||||
goto again;
|
||||
|
@ -644,6 +667,7 @@ wdc_ata_bio_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
|
|||
|
||||
drv_err = wdc_ata_err(drvp, ata_bio);
|
||||
|
||||
#if NATA_DMA
|
||||
/* If we were using DMA, Turn off the DMA channel and check for error */
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
if (ata_bio->flags & ATA_POLL) {
|
||||
|
@ -683,6 +707,7 @@ wdc_ata_bio_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
|
|||
if (ata_bio->r_error & WDCE_CRC || ata_bio->error == ERR_DMA)
|
||||
ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0);
|
||||
}
|
||||
#endif /* NATA_DMA */
|
||||
|
||||
/* if we had an error, end */
|
||||
if (drv_err == WDC_ATA_ERR) {
|
||||
|
@ -715,7 +740,9 @@ wdc_ata_bio_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
|
|||
(char *)xfer->c_databuf + xfer->c_skip, ata_bio->nbytes);
|
||||
}
|
||||
|
||||
#if NATA_DMA || NATA_PIOBM
|
||||
end:
|
||||
#endif
|
||||
ata_bio->blkno += ata_bio->nblks;
|
||||
ata_bio->blkdone += ata_bio->nblks;
|
||||
xfer->c_skip += ata_bio->nbytes;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: atareg.h,v 1.27 2006/09/24 08:32:17 xtraeme Exp $ */
|
||||
/* $NetBSD: atareg.h,v 1.28 2006/09/30 15:56:18 itohy Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001 Manuel Bouyer.
|
||||
|
@ -144,6 +144,8 @@
|
|||
#define WDCC_WRITEDMA_EXT 0x35 /* write 48-bit addressing with DMA */
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <dev/ata/ataconf.h>
|
||||
|
||||
/* Convert a 32-bit command to a 48-bit command. */
|
||||
static __inline int __unused
|
||||
atacmd_to48(int cmd32)
|
||||
|
@ -157,10 +159,12 @@ atacmd_to48(int cmd32)
|
|||
return WDCC_READMULTI_EXT;
|
||||
case WDCC_WRITEMULTI:
|
||||
return WDCC_WRITEMULTI_EXT;
|
||||
#if NATA_DMA
|
||||
case WDCC_READDMA:
|
||||
return WDCC_READDMA_EXT;
|
||||
case WDCC_WRITEDMA:
|
||||
return WDCC_WRITEDMA_EXT;
|
||||
#endif
|
||||
default:
|
||||
panic("atacmd_to48: illegal 32-bit command: %d", cmd32);
|
||||
/* NOTREACHED */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: atavar.h,v 1.72 2006/09/07 12:34:42 itohy Exp $ */
|
||||
/* $NetBSD: atavar.h,v 1.73 2006/09/30 15:56:18 itohy Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001 Manuel Bouyer.
|
||||
|
@ -35,6 +35,8 @@
|
|||
#include <sys/lock.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <dev/ata/ataconf.h>
|
||||
|
||||
/* XXX For scsipi_adapter and scsipi_channel. */
|
||||
#include <dev/scsipi/scsipi_all.h>
|
||||
#include <dev/scsipi/atapiconf.h>
|
||||
|
@ -146,13 +148,21 @@ struct ata_drive_datas {
|
|||
* changed later by the controller's code if needed
|
||||
*/
|
||||
u_int8_t PIO_mode; /* Current setting of drive's PIO mode */
|
||||
#if NATA_DMA
|
||||
u_int8_t DMA_mode; /* Current setting of drive's DMA mode */
|
||||
#if NATA_UDMA
|
||||
u_int8_t UDMA_mode; /* Current setting of drive's UDMA mode */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Supported modes for this drive */
|
||||
u_int8_t PIO_cap; /* supported drive's PIO mode */
|
||||
#if NATA_DMA
|
||||
u_int8_t DMA_cap; /* supported drive's DMA mode */
|
||||
#if NATA_UDMA
|
||||
u_int8_t UDMA_cap; /* supported drive's UDMA mode */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Drive state.
|
||||
|
@ -163,6 +173,7 @@ struct ata_drive_datas {
|
|||
#define RESET 0
|
||||
#define READY 1
|
||||
|
||||
#if NATA_DMA
|
||||
/* numbers of xfers and DMA errs. Used by ata_dmaerr() */
|
||||
u_int8_t n_dmaerrs;
|
||||
u_int32_t n_xfers;
|
||||
|
@ -170,6 +181,7 @@ struct ata_drive_datas {
|
|||
/* Downgrade after NERRS_MAX errors in at most NXFER xfers */
|
||||
#define NERRS_MAX 4
|
||||
#define NXFER 4000
|
||||
#endif
|
||||
|
||||
/* Callbacks into the drive's driver. */
|
||||
void (*drv_done)(void *); /* transfer is done */
|
||||
|
@ -384,8 +396,12 @@ struct atac_softc {
|
|||
#define ATAC_CAP_RAID 0x4000 /* controller "supports" RAID */
|
||||
|
||||
uint8_t atac_pio_cap; /* highest PIO mode supported */
|
||||
#if NATA_DMA
|
||||
uint8_t atac_dma_cap; /* highest DMA mode supported */
|
||||
#if NATA_UDMA
|
||||
uint8_t atac_udma_cap; /* highest UDMA mode supported */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Array of pointers to channel-specific data. */
|
||||
struct ata_channel **atac_channels;
|
||||
|
@ -442,10 +458,14 @@ int ata_addref(struct ata_channel *);
|
|||
void ata_delref(struct ata_channel *);
|
||||
void atastart(struct ata_channel *);
|
||||
void ata_print_modes(struct ata_channel *);
|
||||
#if NATA_DMA
|
||||
int ata_downgrade_mode(struct ata_drive_datas *, int);
|
||||
#endif
|
||||
void ata_probe_caps(struct ata_drive_datas *);
|
||||
|
||||
#if NATA_DMA
|
||||
void ata_dmaerr(struct ata_drive_datas *, int);
|
||||
#endif
|
||||
void ata_queue_idle(struct ata_queue *);
|
||||
#endif /* _KERNEL */
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: wdc.c,v 1.237 2006/08/17 17:11:28 christos Exp $ */
|
||||
/* $NetBSD: wdc.c,v 1.238 2006/09/30 15:56:17 itohy Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001, 2003 Manuel Bouyer. All rights reserved.
|
||||
|
@ -70,7 +70,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.237 2006/08/17 17:11:28 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.238 2006/09/30 15:56:17 itohy Exp $");
|
||||
|
||||
#ifndef ATADEBUG
|
||||
#define ATADEBUG
|
||||
|
@ -280,11 +280,13 @@ wdc_drvprobe(struct ata_channel *chp)
|
|||
chp->ch_drive[i].chnl_softc = chp;
|
||||
chp->ch_drive[i].drive = i;
|
||||
|
||||
#if NATA_DMA
|
||||
/*
|
||||
* Init error counter so that an error withing the first xfers
|
||||
* will trigger a downgrade
|
||||
*/
|
||||
chp->ch_drive[i].n_dmaerrs = NERRS_MAX-1;
|
||||
#endif
|
||||
|
||||
/* If controller can't do 16bit flag the drives as 32bit */
|
||||
if ((atac->atac_cap &
|
||||
|
@ -808,6 +810,7 @@ wdcintr(void *arg)
|
|||
panic("wdcintr: wrong channel");
|
||||
}
|
||||
#endif
|
||||
#if NATA_DMA || NATA_PIOBM
|
||||
if (chp->ch_flags & ATACH_DMA_WAIT) {
|
||||
wdc->dma_status =
|
||||
(*wdc->dma_finish)(wdc->dma_arg, chp->ch_channel,
|
||||
|
@ -818,6 +821,7 @@ wdcintr(void *arg)
|
|||
}
|
||||
chp->ch_flags &= ~ATACH_DMA_WAIT;
|
||||
}
|
||||
#endif
|
||||
chp->ch_flags &= ~ATACH_IRQ_WAIT;
|
||||
ret = xfer->c_intr(chp, xfer, 1);
|
||||
if (ret == 0) /* irq was not for us, still waiting for irq */
|
||||
|
@ -844,7 +848,9 @@ wdc_reset_channel(struct ata_channel *chp, int flags)
|
|||
{
|
||||
TAILQ_HEAD(, ata_xfer) reset_xfer;
|
||||
struct ata_xfer *xfer, *next_xfer;
|
||||
#if NATA_DMA || NATA_PIOBM
|
||||
struct wdc_softc *wdc = CHAN_TO_WDC(chp);
|
||||
#endif
|
||||
|
||||
TAILQ_INIT(&reset_xfer);
|
||||
|
||||
|
@ -904,6 +910,7 @@ wdc_reset_channel(struct ata_channel *chp, int flags)
|
|||
ata_reset_channel(xfer->c_chp, flags);
|
||||
else {
|
||||
callout_stop(&chp->ch_callout);
|
||||
#if NATA_DMA || NATA_PIOBM
|
||||
/*
|
||||
* If we're waiting for DMA, stop the
|
||||
* DMA engine
|
||||
|
@ -916,6 +923,7 @@ wdc_reset_channel(struct ata_channel *chp, int flags)
|
|||
WDC_DMAEND_ABRT_QUIET);
|
||||
chp->ch_flags &= ~ATACH_DMA_WAIT;
|
||||
}
|
||||
#endif
|
||||
chp->ch_queue->active_xfer = NULL;
|
||||
if ((flags & AT_RST_EMERG) == 0)
|
||||
xfer->c_kill_xfer(
|
||||
|
@ -1206,6 +1214,7 @@ wdcwait(struct ata_channel *chp, int mask, int bits, int timeout, int flags)
|
|||
}
|
||||
|
||||
|
||||
#if NATA_DMA
|
||||
/*
|
||||
* Busy-wait for DMA to complete
|
||||
*/
|
||||
|
@ -1228,12 +1237,15 @@ wdc_dmawait(struct ata_channel *chp, struct ata_xfer *xfer, int timeout)
|
|||
chp->ch_channel, xfer->c_drive, WDC_DMAEND_ABRT);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
wdctimeout(void *arg)
|
||||
{
|
||||
struct ata_channel *chp = (struct ata_channel *)arg;
|
||||
#if NATA_DMA || NATA_PIOBM
|
||||
struct wdc_softc *wdc = CHAN_TO_WDC(chp);
|
||||
#endif
|
||||
struct ata_xfer *xfer = chp->ch_queue->active_xfer;
|
||||
int s;
|
||||
|
||||
|
@ -1246,6 +1258,7 @@ wdctimeout(void *arg)
|
|||
(xfer->c_flags & C_ATAPI) ? "atapi" : "ata",
|
||||
xfer->c_bcount,
|
||||
xfer->c_skip);
|
||||
#if NATA_DMA || NATA_PIOBM
|
||||
if (chp->ch_flags & ATACH_DMA_WAIT) {
|
||||
wdc->dma_status =
|
||||
(*wdc->dma_finish)(wdc->dma_arg,
|
||||
|
@ -1253,6 +1266,7 @@ wdctimeout(void *arg)
|
|||
WDC_DMAEND_ABRT);
|
||||
chp->ch_flags &= ~ATACH_DMA_WAIT;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Call the interrupt routine. If we just missed an interrupt,
|
||||
* it will do what's needed. Else, it will take the needed
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: wdcvar.h,v 1.85 2006/09/07 12:46:47 itohy Exp $ */
|
||||
/* $NetBSD: wdcvar.h,v 1.86 2006/09/30 15:56:18 itohy Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
|
||||
|
@ -76,6 +76,7 @@ struct wdc_softc {
|
|||
#define WDC_CAPABILITY_PREATA 0x0200 /* ctrl can be a pre-ata one */
|
||||
#define WDC_CAPABILITY_WIDEREGS 0x0400 /* Ctrl has wide (16bit) registers */
|
||||
|
||||
#if NATA_DMA || NATA_PIOBM
|
||||
/* if WDC_CAPABILITY_DMA set in 'cap' */
|
||||
void *dma_arg;
|
||||
int (*dma_init)(void *, int, int, void *, size_t, int);
|
||||
|
@ -105,6 +106,7 @@ struct wdc_softc {
|
|||
#define WDC_DMAST_NOIRQ 0x01 /* missing IRQ */
|
||||
#define WDC_DMAST_ERR 0x02 /* DMA error */
|
||||
#define WDC_DMAST_UNDER 0x04 /* DMA underrun */
|
||||
#endif /* NATA_DMA || NATA_PIOBM */
|
||||
|
||||
/* Optional callback to select drive. */
|
||||
void (*select)(struct ata_channel *,int);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: atapi_wdc.c,v 1.101 2006/09/07 12:34:42 itohy Exp $ */
|
||||
/* $NetBSD: atapi_wdc.c,v 1.102 2006/09/30 15:56:18 itohy Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001 Manuel Bouyer.
|
||||
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.101 2006/09/07 12:34:42 itohy Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.102 2006/09/30 15:56:18 itohy Exp $");
|
||||
|
||||
#ifndef ATADEBUG
|
||||
#define ATADEBUG
|
||||
|
@ -370,16 +370,22 @@ wdc_atapi_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
|
|||
|
||||
if (sc_xfer->xs_control & XS_CTL_POLL)
|
||||
xfer->c_flags |= C_POLL;
|
||||
#if NATA_DMA
|
||||
if ((atac->atac_channels[channel]->ch_drive[drive].drive_flags &
|
||||
(DRIVE_DMA | DRIVE_UDMA)) && sc_xfer->datalen > 0)
|
||||
xfer->c_flags |= C_DMA;
|
||||
#endif
|
||||
#if NATA_DMA && NATA_PIOBM
|
||||
else
|
||||
#endif
|
||||
#if NATA_PIOBM
|
||||
else if ((atac->atac_cap & ATAC_CAP_PIOBM) &&
|
||||
if ((atac->atac_cap & ATAC_CAP_PIOBM) &&
|
||||
sc_xfer->datalen > 0)
|
||||
xfer->c_flags |= C_PIOBM;
|
||||
#endif
|
||||
xfer->c_drive = drive;
|
||||
xfer->c_flags |= C_ATAPI;
|
||||
#if NATA_DMA
|
||||
if (sc_xfer->cmd->opcode == GPCMD_REPORT_KEY ||
|
||||
sc_xfer->cmd->opcode == GPCMD_SEND_KEY ||
|
||||
sc_xfer->cmd->opcode == GPCMD_READ_DVD_STRUCTURE) {
|
||||
|
@ -399,6 +405,7 @@ wdc_atapi_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
|
|||
*/
|
||||
if (sc_xfer->datalen < 4 || (sc_xfer->datalen & 0x01))
|
||||
xfer->c_flags &= ~C_DMA;
|
||||
#endif /* NATA_DMA */
|
||||
|
||||
xfer->c_cmd = sc_xfer;
|
||||
xfer->c_databuf = sc_xfer->data;
|
||||
|
@ -438,8 +445,10 @@ wdc_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
|
|||
ATADEBUG_PRINT(("wdc_atapi_start %s:%d:%d, scsi flags 0x%x \n",
|
||||
atac->atac_dev.dv_xname, chp->ch_channel, drvp->drive,
|
||||
sc_xfer->xs_control), DEBUG_XFERS);
|
||||
#if NATA_DMA
|
||||
if ((xfer->c_flags & C_DMA) && (drvp->n_xfers <= NXFER))
|
||||
drvp->n_xfers++;
|
||||
#endif
|
||||
/* Do control operations specially. */
|
||||
if (__predict_false(drvp->state < READY)) {
|
||||
/* If it's not a polled command, we need the kernel thread */
|
||||
|
@ -490,10 +499,14 @@ wdc_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
|
|||
} else
|
||||
goto error;
|
||||
}
|
||||
#if NATA_DMA
|
||||
#if NATA_UDMA
|
||||
if (drvp->drive_flags & DRIVE_UDMA) {
|
||||
wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
|
||||
0x40 | drvp->UDMA_mode, WDSF_SET_MODE);
|
||||
} else if (drvp->drive_flags & DRIVE_DMA) {
|
||||
} else
|
||||
#endif
|
||||
if (drvp->drive_flags & DRIVE_DMA) {
|
||||
wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
|
||||
0x20 | drvp->DMA_mode, WDSF_SET_MODE);
|
||||
} else {
|
||||
|
@ -504,9 +517,12 @@ wdc_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
|
|||
goto timeout;
|
||||
if (chp->ch_status & WDCS_ERR) {
|
||||
if (chp->ch_error == WDCE_ABRT) {
|
||||
#if NATA_UDMA
|
||||
if (drvp->drive_flags & DRIVE_UDMA)
|
||||
goto error;
|
||||
else {
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* The drive rejected our DMA setting.
|
||||
* Fall back to mode 1.
|
||||
|
@ -522,6 +538,7 @@ wdc_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
|
|||
} else
|
||||
goto error;
|
||||
}
|
||||
#endif /* NATA_DMA */
|
||||
ready:
|
||||
drvp->state = READY;
|
||||
bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr,
|
||||
|
@ -562,7 +579,11 @@ ready:
|
|||
wdccommand(chp, xfer->c_drive, ATAPI_PKT_CMD,
|
||||
xfer->c_bcount <= 0xffff ? xfer->c_bcount : 0xffff,
|
||||
0, 0, 0,
|
||||
(xfer->c_flags & C_DMA) ? ATAPI_PKT_CMD_FTRE_DMA : 0);
|
||||
#if NATA_DMA
|
||||
(xfer->c_flags & C_DMA) ? ATAPI_PKT_CMD_FTRE_DMA :
|
||||
#endif
|
||||
0
|
||||
);
|
||||
|
||||
#if NATA_PIOBM
|
||||
if (xfer->c_flags & C_PIOBM) {
|
||||
|
@ -611,10 +632,12 @@ ready:
|
|||
chp->ch_flags |= ATACH_IRQ_WAIT;
|
||||
}
|
||||
if (sc_xfer->xs_control & XS_CTL_POLL) {
|
||||
#if NATA_DMA
|
||||
if (chp->ch_flags & ATACH_DMA_WAIT) {
|
||||
wdc_dmawait(chp, xfer, sc_xfer->timeout);
|
||||
chp->ch_flags &= ~ATACH_DMA_WAIT;
|
||||
}
|
||||
#endif
|
||||
while ((sc_xfer->xs_status & XS_STS_DONE) == 0) {
|
||||
/* Wait for at last 400ns for status bit to be valid */
|
||||
DELAY(1);
|
||||
|
@ -653,8 +676,13 @@ wdc_atapi_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
|
|||
struct scsipi_xfer *sc_xfer = xfer->c_cmd;
|
||||
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive];
|
||||
int len, phase, i, retries=0;
|
||||
int ire, error;
|
||||
int ire;
|
||||
#if NATA_DMA
|
||||
int error;
|
||||
#endif
|
||||
#if NATA_DMA || NATA_PIOBM
|
||||
int dma_flags = 0;
|
||||
#endif
|
||||
void *cmd;
|
||||
|
||||
ATADEBUG_PRINT(("wdc_atapi_intr %s:%d:%d\n",
|
||||
|
@ -707,10 +735,12 @@ wdc_atapi_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
|
|||
printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip=%d\n",
|
||||
atac->atac_dev.dv_xname, chp->ch_channel, xfer->c_drive,
|
||||
xfer->c_bcount, xfer->c_skip);
|
||||
#if NATA_DMA
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
ata_dmaerr(drvp,
|
||||
(xfer->c_flags & C_POLL) ? AT_POLL : 0);
|
||||
}
|
||||
#endif
|
||||
sc_xfer->error = XS_TIMEOUT;
|
||||
wdc_atapi_reset(chp, xfer);
|
||||
return 1;
|
||||
|
@ -718,6 +748,7 @@ wdc_atapi_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
|
|||
if (wdc->irqack)
|
||||
wdc->irqack(chp);
|
||||
|
||||
#if NATA_DMA
|
||||
/*
|
||||
* If we missed an IRQ and were using DMA, flag it as a DMA error
|
||||
* and reset device.
|
||||
|
@ -728,14 +759,17 @@ wdc_atapi_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
|
|||
wdc_atapi_reset(chp, xfer);
|
||||
return (1);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* if the request sense command was aborted, report the short sense
|
||||
* previously recorded, else continue normal processing
|
||||
*/
|
||||
|
||||
#if NATA_DMA || NATA_PIOBM
|
||||
if (xfer->c_flags & (C_DMA | C_PIOBM))
|
||||
dma_flags = (sc_xfer->xs_control & XS_CTL_DATA_IN)
|
||||
? WDC_DMA_READ : 0;
|
||||
#endif
|
||||
again:
|
||||
len = bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_cyl_lo], 0) +
|
||||
256 * bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_cyl_hi], 0);
|
||||
|
@ -749,6 +783,7 @@ again:
|
|||
case PHASE_CMDOUT:
|
||||
cmd = sc_xfer->cmd;
|
||||
ATADEBUG_PRINT(("PHASE_CMDOUT\n"), DEBUG_INTR);
|
||||
#if NATA_DMA
|
||||
/* Init the DMA channel if necessary */
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
error = (*wdc->dma_init)(wdc->dma_arg,
|
||||
|
@ -769,17 +804,20 @@ again:
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* send packet command */
|
||||
/* Commands are 12 or 16 bytes long. It's 32-bit aligned */
|
||||
wdc->dataout_pio(chp, drvp->drive_flags, cmd, sc_xfer->cmdlen);
|
||||
|
||||
#if NATA_DMA
|
||||
/* Start the DMA channel if necessary */
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
(*wdc->dma_start)(wdc->dma_arg,
|
||||
chp->ch_channel, xfer->c_drive);
|
||||
chp->ch_flags |= ATACH_DMA_WAIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((sc_xfer->xs_control & XS_CTL_POLL) == 0) {
|
||||
chp->ch_flags |= ATACH_IRQ_WAIT;
|
||||
|
@ -789,6 +827,7 @@ again:
|
|||
case PHASE_DATAOUT:
|
||||
/* write data */
|
||||
ATADEBUG_PRINT(("PHASE_DATAOUT\n"), DEBUG_INTR);
|
||||
#if NATA_DMA
|
||||
if ((sc_xfer->xs_control & XS_CTL_DATA_OUT) == 0 ||
|
||||
(xfer->c_flags & C_DMA) != 0) {
|
||||
printf("wdc_atapi_intr: bad data phase DATAOUT\n");
|
||||
|
@ -800,6 +839,7 @@ again:
|
|||
wdc_atapi_reset(chp, xfer);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
xfer->c_lenoff = len - xfer->c_bcount;
|
||||
if (xfer->c_bcount < len) {
|
||||
printf("wdc_atapi_intr: warning: write only "
|
||||
|
@ -838,6 +878,7 @@ again:
|
|||
case PHASE_DATAIN:
|
||||
/* Read data */
|
||||
ATADEBUG_PRINT(("PHASE_DATAIN\n"), DEBUG_INTR);
|
||||
#if NATA_DMA
|
||||
if ((sc_xfer->xs_control & XS_CTL_DATA_IN) == 0 ||
|
||||
(xfer->c_flags & C_DMA) != 0) {
|
||||
printf("wdc_atapi_intr: bad data phase DATAIN\n");
|
||||
|
@ -849,6 +890,7 @@ again:
|
|||
wdc_atapi_reset(chp, xfer);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
xfer->c_lenoff = len - xfer->c_bcount;
|
||||
if (xfer->c_bcount < len) {
|
||||
printf("wdc_atapi_intr: warning: reading only "
|
||||
|
@ -886,9 +928,11 @@ again:
|
|||
case PHASE_ABORTED:
|
||||
case PHASE_COMPLETED:
|
||||
ATADEBUG_PRINT(("PHASE_COMPLETED\n"), DEBUG_INTR);
|
||||
#if NATA_DMA
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
xfer->c_bcount -= sc_xfer->datalen;
|
||||
}
|
||||
#endif
|
||||
sc_xfer->resid = xfer->c_bcount;
|
||||
wdc_atapi_phase_complete(xfer);
|
||||
return(1);
|
||||
|
@ -907,10 +951,12 @@ again:
|
|||
sc_xfer->error = XS_SHORTSENSE;
|
||||
sc_xfer->sense.atapi_sense = chp->ch_error;
|
||||
} else {
|
||||
#if NATA_DMA
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
ata_dmaerr(drvp,
|
||||
(xfer->c_flags & C_POLL) ? AT_POLL : 0);
|
||||
}
|
||||
#endif
|
||||
sc_xfer->error = XS_RESET;
|
||||
wdc_atapi_reset(chp, xfer);
|
||||
return (1);
|
||||
|
@ -928,7 +974,9 @@ wdc_atapi_phase_complete(struct ata_xfer *xfer)
|
|||
{
|
||||
struct ata_channel *chp = xfer->c_chp;
|
||||
struct atac_softc *atac = chp->ch_atac;
|
||||
#if NATA_DMA || NATA_PIOBM
|
||||
struct wdc_softc *wdc = CHAN_TO_WDC(chp);
|
||||
#endif
|
||||
struct scsipi_xfer *sc_xfer = xfer->c_cmd;
|
||||
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive];
|
||||
|
||||
|
@ -977,14 +1025,19 @@ wdc_atapi_phase_complete(struct ata_xfer *xfer)
|
|||
/* ask scsipi to send a REQUEST_SENSE */
|
||||
sc_xfer->error = XS_BUSY;
|
||||
sc_xfer->status = SCSI_CHECK;
|
||||
} else if (wdc->dma_status &
|
||||
}
|
||||
#if NATA_DMA || NATA_PIOBM
|
||||
else if (wdc->dma_status &
|
||||
(WDC_DMAST_NOIRQ | WDC_DMAST_ERR)) {
|
||||
#if NATA_DMA
|
||||
ata_dmaerr(drvp,
|
||||
(xfer->c_flags & C_POLL) ? AT_POLL : 0);
|
||||
#endif
|
||||
sc_xfer->error = XS_RESET;
|
||||
wdc_atapi_reset(chp, xfer);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (xfer->c_bcount != 0) {
|
||||
ATADEBUG_PRINT(("wdc_atapi_intr: bcount value is "
|
||||
|
|
Loading…
Reference in New Issue