A little effort against kernel bloat....

Exclude ATA DMA support if no ATA DMA capable drivers are compiled in.
This commit is contained in:
itohy 2006-09-30 15:56:17 +00:00
parent 883278d33e
commit f87d591722
7 changed files with 174 additions and 24 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 "