From f87d591722d3fccbcdb0983dc896074230fcc60a Mon Sep 17 00:00:00 2001 From: itohy Date: Sat, 30 Sep 2006 15:56:17 +0000 Subject: [PATCH] A little effort against kernel bloat.... Exclude ATA DMA support if no ATA DMA capable drivers are compiled in. --- sys/dev/ata/ata.c | 38 ++++++++++++++++++--- sys/dev/ata/ata_wdc.c | 41 ++++++++++++++++++---- sys/dev/ata/atareg.h | 6 +++- sys/dev/ata/atavar.h | 22 +++++++++++- sys/dev/ic/wdc.c | 18 ++++++++-- sys/dev/ic/wdcvar.h | 4 ++- sys/dev/scsipi/atapi_wdc.c | 69 +++++++++++++++++++++++++++++++++----- 7 files changed, 174 insertions(+), 24 deletions(-) diff --git a/sys/dev/ata/ata.c b/sys/dev/ata/ata.c index aa3531c45ee1..63e533915f3f 100644 --- a/sys/dev/ata/ata.c +++ b/sys/dev/ata/ata.c @@ -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 -__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 */ diff --git a/sys/dev/ata/ata_wdc.c b/sys/dev/ata/ata_wdc.c index f6bb36e31215..664bc43b574f 100644 --- a/sys/dev/ata/ata_wdc.c +++ b/sys/dev/ata/ata_wdc.c @@ -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 -__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; diff --git a/sys/dev/ata/atareg.h b/sys/dev/ata/atareg.h index 5a94cb55aecc..f45125c0ab37 100644 --- a/sys/dev/ata/atareg.h +++ b/sys/dev/ata/atareg.h @@ -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 + /* 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 */ diff --git a/sys/dev/ata/atavar.h b/sys/dev/ata/atavar.h index 94cd09fdc81b..b15d26282863 100644 --- a/sys/dev/ata/atavar.h +++ b/sys/dev/ata/atavar.h @@ -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 #include +#include + /* XXX For scsipi_adapter and scsipi_channel. */ #include #include @@ -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 */ diff --git a/sys/dev/ic/wdc.c b/sys/dev/ic/wdc.c index 98f795c284f1..65148c54a303 100644 --- a/sys/dev/ic/wdc.c +++ b/sys/dev/ic/wdc.c @@ -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 -__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 diff --git a/sys/dev/ic/wdcvar.h b/sys/dev/ic/wdcvar.h index 3dafa22d287e..213f69f0a824 100644 --- a/sys/dev/ic/wdcvar.h +++ b/sys/dev/ic/wdcvar.h @@ -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); diff --git a/sys/dev/scsipi/atapi_wdc.c b/sys/dev/scsipi/atapi_wdc.c index 6efc7a22c115..bca449c9dfba 100644 --- a/sys/dev/scsipi/atapi_wdc.c +++ b/sys/dev/scsipi/atapi_wdc.c @@ -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 -__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 "