diff options
author | obrien <obrien@FreeBSD.org> | 1998-04-18 13:25:49 +0000 |
---|---|---|
committer | obrien <obrien@FreeBSD.org> | 1998-04-18 13:25:49 +0000 |
commit | fd66256f3f5e5ed27e2606aa2fdbca79f3adce7e (patch) | |
tree | 7391dd237aa049c6749fe81bade5479b6ef4ee75 | |
parent | 116081d5f2f15798830c767e3781af1616223bfd (diff) | |
download | FreeBSD-src-fd66256f3f5e5ed27e2606aa2fdbca79f3adce7e.zip FreeBSD-src-fd66256f3f5e5ed27e2606aa2fdbca79f3adce7e.tar.gz |
MFC (reduce diff w/-CUR, with hopes of getting DMA support into -STABLE)
1.128 (FUNCTIONAL: better sleep handling)
1.131 (STYLE: labels w/o stmt)
1.132 (STYLE: remove unused #includes)
1.141 (FUNCTIONAL: devfs bug, 2nd controler not showing)
1.144 (STYLE: dont shadow other vars)
1.150 (FUNCTIONAL: fix search bug)
-rw-r--r-- | sys/i386/isa/wd.c | 416 |
1 files changed, 98 insertions, 318 deletions
diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c index 13119bb..674211d 100644 --- a/sys/i386/isa/wd.c +++ b/sys/i386/isa/wd.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)wd.c 7.2 (Berkeley) 5/9/91 - * $Id: wd.c,v 1.155 1998/04/10 08:00:24 sos Exp $ + * $Id: wd.c,v 1.119.2.10 1998/01/16 22:28:44 pst Exp $ */ /* TODO: @@ -61,15 +61,11 @@ #endif #include "wdc.h" +#include "opt_wd.h" +#include "opt_atapi.h" #if NWDC > 0 -#include "opt_atapi.h" -#include "opt_devfs.h" -#include "opt_hw_wdog.h" -#include "opt_wd.h" -#include "pci.h" - #include <sys/param.h> #include <sys/dkbad.h> #include <sys/systm.h> @@ -114,8 +110,6 @@ extern void wdstart(int ctrlr); /* can't handle that in all cases */ #define WDOPT_32BIT 0x8000 #define WDOPT_SLEEPHACK 0x4000 -#define WDOPT_DMA 0x2000 -#define WDOPT_LBA 0x1000 #define WDOPT_FORCEHD(x) (((x)&0x0f00)>>8) #define WDOPT_MULTIMASK 0x00ff @@ -162,13 +156,11 @@ struct disk { #endif int dk_unit; /* physical unit number */ int dk_lunit; /* logical unit number */ - int dk_interface; /* interface (two ctrlrs per interface) */ char dk_state; /* control state */ u_char dk_status; /* copy of status reg. */ u_char dk_error; /* copy of error reg. */ u_char dk_timeout; /* countdown to next timeout */ int dk_port; /* i/o port base */ - int dk_altport; /* altstatus port base */ #ifdef DEVFS void *dk_bdev; /* devfs token for whole disk */ void *dk_cdev; /* devfs token for raw whole disk */ @@ -181,18 +173,12 @@ struct disk { #define DKFL_32BIT 0x00100 /* use 32-bit i/o mode */ #define DKFL_MULTI 0x00200 /* use multi-i/o mode */ #define DKFL_BADSCAN 0x00400 /* report all errors */ -#define DKFL_USEDMA 0x00800 /* use DMA for data transfers */ -#define DKFL_DMA 0x01000 /* using DMA on this transfer-- DKFL_SINGLE - * overrides this - */ -#define DKFL_LBA 0x02000 /* use LBA for data transfers */ struct wdparams dk_params; /* ESDI/IDE drive/controller parameters */ int dk_dkunit; /* disk stats unit number */ int dk_multi; /* multi transfers */ int dk_currentiosize; /* current io size */ struct diskgeom dk_dd; /* device configuration data */ struct diskslices *dk_slices; /* virtual drives */ - void *dk_dmacookie; /* handle for DMA services */ }; #define WD_COUNT_RETRIES @@ -201,6 +187,7 @@ static int wdtest = 0; static struct disk *wddrives[NWD]; /* table of units */ static struct buf_queue_head drive_queue[NWD]; /* head of queue per drive */ static struct { + int b_errcnt; int b_active; } wdutab[NWD]; /* @@ -212,7 +199,7 @@ static struct { int b_active; } wdtab[NWDC]; -struct wddma wddma[NWDC]; +struct wddma wddma; #ifdef notyet static struct buf rwdbuf[NWD]; /* buffers for raw IO */ @@ -228,7 +215,6 @@ static int wdsetctlr(struct disk *du); #if 0 static int wdwsetctlr(struct disk *du); #endif -static int wdsetmode(int mode, void *wdinfo); static int wdgetctlr(struct disk *du); static void wderror(struct buf *bp, struct disk *du, char *mesg); static void wdflushirq(struct disk *du, int old_ipl); @@ -255,7 +241,7 @@ static d_psize_t wdsize; static struct cdevsw wd_cdevsw; static struct bdevsw wd_bdevsw = { wdopen, wdclose, wdstrategy, wdioctl, /*0*/ - wddump, wdsize, D_DISK, "wd", &wd_cdevsw, -1 }; + wddump, wdsize, 0, "wd", &wd_cdevsw, -1 }; #ifdef CMD640 static int atapictrlr; @@ -284,7 +270,6 @@ static int wdprobe(struct isa_device *dvp) { int unit = dvp->id_unit; - int interface; struct disk *du; if (unit >= NWDC) @@ -295,21 +280,8 @@ wdprobe(struct isa_device *dvp) return (0); bzero(du, sizeof *du); du->dk_ctrlr = dvp->id_unit; - interface = du->dk_ctrlr / 2; - du->dk_interface = interface; -#if !defined(DISABLE_PCI_IDE) && (NPCI > 0) - if (wddma[interface].wdd_candma) { - du->dk_dmacookie = wddma[interface].wdd_candma(dvp->id_iobase, du->dk_ctrlr); - du->dk_port = dvp->id_iobase; - du->dk_altport = wddma[interface].wdd_altiobase(du->dk_dmacookie); - } else { - du->dk_port = dvp->id_iobase; - du->dk_altport = du->dk_port + wd_ctlr; - } -#else du->dk_port = dvp->id_iobase; - du->dk_altport = du->dk_port + wd_ctlr; -#endif + /* check if we have registers that work */ outb(du->dk_port + wd_sdh, WDSD_IBM); /* set unit 0 */ @@ -339,16 +311,14 @@ wdprobe(struct isa_device *dvp) goto reset_ok; #endif DELAY(RECOVERYTIME); - if (wdreset(du) != 0) { + if (wdreset(du) != 0) goto nodevice; - } reset_ok: /* execute a controller only command */ if (wdcommand(du, 0, 0, 0, 0, WDCC_DIAGNOSE) != 0 - || wdwait(du, 0, TIMEOUT) < 0) { + || wdwait(du, 0, TIMEOUT) < 0) goto nodevice; - } /* * drive(s) did not time out during diagnostic : @@ -362,6 +332,7 @@ reset_ok: * drive 2. (This seems to contradict the ATA spec.) */ du->dk_error = inb(du->dk_port + wd_error); + /* printf("Error : %x\n", du->dk_error); */ if(du->dk_error != 0x01 && du->dk_error != 0) { if(du->dk_error & 0x80) { /* drive 1 failure */ @@ -410,7 +381,6 @@ wdattach(struct isa_device *dvp) int unit, lunit; struct isa_device *wdup; struct disk *du; - struct wdparams *wp; if (dvp->id_unit >= NWDC) return (0); @@ -419,13 +389,13 @@ wdattach(struct isa_device *dvp) if (eide_quirks & Q_CMD640B) { if (dvp->id_unit == PRIMARY) { printf("wdc0: CMD640B workaround enabled\n"); - bufq_init(&wdtab[PRIMARY].controller_queue); + TAILQ_INIT( &wdtab[PRIMARY].controller_queue); } } else - bufq_init(&wdtab[dvp->id_unit].controller_queue); + TAILQ_INIT( &wdtab[dvp->id_unit].controller_queue); #else - bufq_init(&wdtab[dvp->id_unit].controller_queue); + TAILQ_INIT( &wdtab[dvp->id_unit].controller_queue); #endif for (wdup = isa_biotab_wdc; wdup->id_driver != 0; wdup++) { @@ -443,7 +413,7 @@ wdattach(struct isa_device *dvp) if (wddrives[lunit] != NULL) panic("drive attached twice"); wddrives[lunit] = du; - bufq_init(&drive_queue[lunit]); + TAILQ_INIT( &drive_queue[lunit]); bzero(du, sizeof *du); du->dk_ctrlr = dvp->id_unit; #ifdef CMD640 @@ -457,7 +427,6 @@ wdattach(struct isa_device *dvp) du->dk_lunit = lunit; du->dk_port = dvp->id_iobase; - du->dk_altport = du->dk_port + wd_ctlr; /* * Use the individual device flags or the controller * flags. @@ -474,10 +443,6 @@ wdattach(struct isa_device *dvp) dvp->id_unit, unit, lunit, sizeof du->dk_params.wdp_model, du->dk_params.wdp_model); - if (du->dk_flags & DKFL_LBA) - printf(", LBA"); - if (du->dk_flags & DKFL_USEDMA) - printf(", DMA"); if (du->dk_flags & DKFL_32BIT) printf(", 32-bit"); if (du->dk_multi > 1) @@ -500,17 +465,6 @@ wdattach(struct isa_device *dvp) du->dk_dd.d_nsectors, du->dk_dd.d_secsize); - if (bootverbose) { - wp = &du->dk_params; - printf( -"wd%d: ATA INQUIRE valid = %04x, dmamword = %04x, apio = %04x, udma = %04x\n", - du->dk_lunit, - wp->wdp_atavalid, - wp->wdp_dmamword, - wp->wdp_eidepiomodes, - wp->wdp_udmamode); - } - /* * Start timeout routine for this drive. * XXX timeout should be per controller. @@ -518,15 +472,15 @@ wdattach(struct isa_device *dvp) wdtimeout(du); #ifdef DEVFS - mynor = dkmakeminor(lunit, WHOLE_DISK_SLICE, RAW_PART); + mynor = dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART); du->dk_bdev = devfs_add_devswf(&wd_bdevsw, mynor, DV_BLK, UID_ROOT, GID_OPERATOR, 0640, - "wd%d", lunit); + "wd%d", unit); du->dk_cdev = devfs_add_devswf(&wd_cdevsw, mynor, DV_CHR, UID_ROOT, GID_OPERATOR, 0640, - "rwd%d", lunit); + "rwd%d", unit); #endif if (dk_ndrive < DK_NDRIVE) { @@ -642,7 +596,7 @@ wdstrategy(register struct buf *bp) /* queue transfer on drive, activate drive and controller if idle */ s = splbio(); - bufqdisksort(&drive_queue[lunit], bp); + tqdisksort(&drive_queue[lunit], bp); if (wdutab[lunit].b_active == 0) wdustart(du); /* start drive */ @@ -716,14 +670,14 @@ wdustart(register struct disk *du) return; - bp = bufq_first(&drive_queue[du->dk_lunit]); + bp = drive_queue[du->dk_lunit].tqh_first; if (bp == NULL) { /* yes, an assign */ return; } - bufq_remove(&drive_queue[du->dk_lunit], bp); + TAILQ_REMOVE( &drive_queue[du->dk_lunit], bp, b_act); /* link onto controller queue */ - bufq_insert_tail(&wdtab[ctrlr].controller_queue, bp); + TAILQ_INSERT_TAIL( &wdtab[ctrlr].controller_queue, bp, b_act); /* mark the drive unit as busy */ wdutab[du->dk_lunit].b_active = 1; @@ -765,7 +719,7 @@ wdstart(int ctrlr) return; #endif /* is there a drive for the controller to do a transfer with? */ - bp = bufq_first(&wdtab[ctrlr].controller_queue); + bp = wdtab[ctrlr].controller_queue.tqh_first; if (bp == NULL) { #ifdef ATAPI #ifdef CMD640 @@ -803,7 +757,7 @@ wdstart(int ctrlr) (bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount, blknum); else - printf(" %d)%x", du->dk_skip, inb(du->dk_altport)); + printf(" %d)%x", du->dk_skip, inb(du->dk_port + wd_altsts)); #endif lp = &du->dk_dd; @@ -840,23 +794,12 @@ wdstart(int ctrlr) u_int count1; long cylin, head, sector; - if (du->dk_flags & DKFL_LBA) { - sector = (blknum >> 0) & 0xff; - cylin = (blknum >> 8) & 0xffff; - head = ((blknum >> 24) & 0xf) | WDSD_LBA; - } - else { - cylin = blknum / secpercyl; - head = (blknum % secpercyl) / secpertrk; - sector = blknum % secpertrk; - } - /* - * XXX this looks like an attempt to skip bad sectors - * on write. - */ + cylin = blknum / secpercyl; + head = (blknum % secpercyl) / secpertrk; + sector = blknum % secpertrk; + if (wdtab[ctrlr].b_errcnt && (bp->b_flags & B_READ) == 0) du->dk_bc += DEV_BSIZE; - count1 = howmany( du->dk_bc, DEV_BSIZE); du->dk_flags &= ~DKFL_MULTI; @@ -876,19 +819,7 @@ wdstart(int ctrlr) count1 = 1; du->dk_currentiosize = 1; } else { - if((du->dk_flags & DKFL_USEDMA) && - wddma[du->dk_interface].wdd_dmaverify(du->dk_dmacookie, - (void *)((int)bp->b_data + - du->dk_skip * DEV_BSIZE), - du->dk_bc, - bp->b_flags & B_READ)) { - du->dk_flags |= DKFL_DMA; - if( bp->b_flags & B_READ) - command = WDCC_READ_DMA; - else - command = WDCC_WRITE_DMA; - du->dk_currentiosize = count1; - } else if( (count1 > 1) && (du->dk_multi > 1)) { + if( (count1 > 1) && (du->dk_multi > 1)) { du->dk_flags |= DKFL_MULTI; if( bp->b_flags & B_READ) { command = WDCC_READ_MULTI; @@ -924,14 +855,6 @@ wdstart(int ctrlr) if(du->dk_dkunit >= 0) { dk_busy |= 1 << du->dk_dkunit; } - - if ((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA) { - wddma[du->dk_interface].wdd_dmaprep(du->dk_dmacookie, - (void *)((int)bp->b_data + - du->dk_skip * DEV_BSIZE), - du->dk_bc, - bp->b_flags & B_READ); - } while (wdcommand(du, cylin, head, sector, count1, command) != 0) { wderror(bp, du, @@ -941,8 +864,8 @@ wdstart(int ctrlr) #ifdef WDDEBUG printf("cylin %ld head %ld sector %ld addr %x sts %x\n", cylin, head, sector, - (int)bp->b_data + du->dk_skip * DEV_BSIZE, - inb(du->dk_altport)); + (int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE, + inb(du->dk_port + wd_altsts)); #endif } @@ -951,9 +874,6 @@ wdstart(int ctrlr) * unmarked bad blocks can take 3 seconds! Then it is not good that * we retry 5 times. * - * On the first try, we give it 10 seconds, for drives that may need - * to spin up. - * * XXX wdtimeout() doesn't increment the error count so we may loop * forever. More seriously, the loop isn't forever but causes a * crash. @@ -963,16 +883,7 @@ wdstart(int ctrlr) * think). Discarding them would be OK if the (special) file offset * was not advanced. */ - if (wdtab[ctrlr].b_errcnt == 0) - du->dk_timeout = 1 + 10; - else - du->dk_timeout = 1 + 3; - - /* if this is a DMA op, start DMA and go away until it's done. */ - if ((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA) { - wddma[du->dk_interface].wdd_dmastart(du->dk_dmacookie); - return; - } + du->dk_timeout = 1 + 3; /* If this is a read operation, just go away until it's done. */ if (bp->b_flags & B_READ) @@ -1004,11 +915,11 @@ wdstart(int ctrlr) if (du->dk_flags & DKFL_32BIT) outsl(du->dk_port + wd_data, - (void *)((int)bp->b_data + du->dk_skip * DEV_BSIZE), + (void *)((int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE), (count * DEV_BSIZE) / sizeof(long)); else outsw(du->dk_port + wd_data, - (void *)((int)bp->b_data + du->dk_skip * DEV_BSIZE), + (void *)((int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE), (count * DEV_BSIZE) / sizeof(short)); du->dk_bc -= DEV_BSIZE * count; if (du->dk_dkunit >= 0) { @@ -1028,13 +939,11 @@ wdstart(int ctrlr) * the next request. Also check for a partially done transfer, and * continue with the next chunk if so. */ - void wdintr(int unit) { register struct disk *du; register struct buf *bp; - int dmastat = 0; /* Shut up GCC */ #ifdef CMD640 int ctrlr_atapi; @@ -1076,21 +985,10 @@ wdintr(int unit) return; } #endif - bp = bufq_first(&wdtab[unit].controller_queue); + bp = wdtab[unit].controller_queue.tqh_first; du = wddrives[dkunit(bp->b_dev)]; - - /* finish off DMA */ - if (du->dk_flags & (DKFL_DMA|DKFL_USEDMA)) { - /* XXX SMP boxes sometimes generate an early intr. Why? */ - if ((wddma[du->dk_interface].wdd_dmastatus(du->dk_dmacookie) & WDDS_INTERRUPT) - == 0) - return; - dmastat = wddma[du->dk_interface].wdd_dmadone(du->dk_dmacookie); - } - du->dk_timeout = 0; - /* check drive status/failure */ if (wdwait(du, 0, TIMEOUT) < 0) { wderror(bp, du, "wdintr: timeout waiting for status"); du->dk_status |= WDCS_ERR; /* XXX */ @@ -1111,32 +1009,16 @@ wdintr(int unit) } /* have we an error? */ - if ((du->dk_status & (WDCS_ERR | WDCS_ECCCOR)) - || (((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA) - && dmastat != WDDS_INTERRUPT)) { - - unsigned int errstat; + if (du->dk_status & (WDCS_ERR | WDCS_ECCCOR)) { oops: /* - * XXX bogus inb() here + * XXX bogus inb() here, register 0 is assumed and intr status + * is reset. */ - errstat = inb(du->dk_port + wd_error); - - if(((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA) && - (errstat & WDERR_ABORT)) { - wderror(bp, du, "reverting to PIO mode"); - du->dk_flags &= ~DKFL_USEDMA; - } else if((du->dk_flags & DKFL_MULTI) && - (errstat & WDERR_ABORT)) { + if( (du->dk_flags & DKFL_MULTI) && (inb(du->dk_port) & WDERR_ABORT)) { wderror(bp, du, "reverting to non-multi sector mode"); du->dk_multi = 1; } - - if (!(du->dk_status & (WDCS_ERR | WDCS_ECCCOR)) && - (((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA) && - (dmastat != WDDS_INTERRUPT))) - printf("wd%d: DMA failure, DMA status %b\n", - du->dk_lunit, dmastat, WDDS_BITS); #ifdef WDDEBUG wderror(bp, du, "wdintr"); #endif @@ -1163,7 +1045,7 @@ oops: bp->b_error = EIO; bp->b_flags |= B_ERROR; /* flag the error */ } - } else if (du->dk_status & WDCS_ECCCOR) + } else wderror(bp, du, "soft ecc"); } @@ -1171,7 +1053,6 @@ oops: * If this was a successful read operation, fetch the data. */ if (((bp->b_flags & (B_READ | B_ERROR)) == B_READ) - && !((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA) && wdtab[unit].b_active) { int chk, dummy, multisize; multisize = chk = du->dk_currentiosize * DEV_BSIZE; @@ -1195,11 +1076,11 @@ oops: /* suck in data */ if( du->dk_flags & DKFL_32BIT) insl(du->dk_port + wd_data, - (void *)((int)bp->b_data + du->dk_skip * DEV_BSIZE), + (void *)((int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE), chk / sizeof(long)); else insw(du->dk_port + wd_data, - (void *)((int)bp->b_data + du->dk_skip * DEV_BSIZE), + (void *)((int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE), chk / sizeof(short)); du->dk_bc -= chk; @@ -1213,20 +1094,6 @@ oops: dk_wds[du->dk_dkunit] += chk >> 6; } - /* final cleanup on DMA */ - if (((bp->b_flags & B_ERROR) == 0) - && ((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA) - && wdtab[unit].b_active) { - int iosize; - - iosize = du->dk_currentiosize * DEV_BSIZE; - - du->dk_bc -= iosize; - - if (du->dk_dkunit >= 0) - dk_wds[du->dk_dkunit] += iosize >> 6; - } - outt: if (wdtab[unit].b_active) { if ((bp->b_flags & B_ERROR) == 0) { @@ -1258,11 +1125,12 @@ outt: done: ; /* done with this transfer, with or without error */ - du->dk_flags &= ~(DKFL_SINGLE|DKFL_DMA); - bufq_remove( &wdtab[unit].controller_queue, bp); + du->dk_flags &= ~DKFL_SINGLE; + TAILQ_REMOVE(&wdtab[unit].controller_queue, bp, b_act); wdtab[unit].b_errcnt = 0; bp->b_resid = bp->b_bcount - du->dk_skip * DEV_BSIZE; wdutab[du->dk_lunit].b_active = 0; + wdutab[du->dk_lunit].b_errcnt = 0; du->dk_skip = 0; biodone(bp); } @@ -1279,7 +1147,7 @@ done: ; /* anything more for controller to do? */ #ifndef ATAPI /* This is not valid in ATAPI mode. */ - if (bufq_first(&wdtab[unit].controller_queue) != NULL) + if (wdtab[unit].controller_queue.tqh_first) #endif wdstart(unit); } @@ -1312,7 +1180,6 @@ wdopen(dev_t dev, int flags, int fmt, struct proc *p) du->dk_flags &= ~DKFL_BADSCAN; - /* spin waiting for anybody else reading the disk label */ while (du->dk_flags & DKFL_LABELLING) tsleep((caddr_t)&du->dk_flags, PZERO - 1, "wdopen", 1); #if 1 @@ -1567,20 +1434,15 @@ wdcommand(struct disk *du, u_int cylinder, u_int head, u_int sector, return (1); if( command == WDCC_FEATURES) { outb(wdc + wd_features, count); - if ( count == WDFEA_SETXFER ) - outb(wdc + wd_seccnt, sector); } else { outb(wdc + wd_precomp, du->dk_dd.d_precompcyl / 4); outb(wdc + wd_cyl_lo, cylinder); outb(wdc + wd_cyl_hi, cylinder >> 8); outb(wdc + wd_sdh, WDSD_IBM | (du->dk_unit << 4) | head); - if (head & WDSD_LBA) - outb(wdc + wd_sector, sector); - else - outb(wdc + wd_sector, sector + 1); + outb(wdc + wd_sector, sector + 1); outb(wdc + wd_seccnt, count); } - if (wdwait(du, (command == WDCC_DIAGNOSE || command == WDCC_IDC) + if (wdwait(du, command == WDCC_DIAGNOSE || command == WDCC_IDC ? 0 : WDCS_READY, TIMEOUT) < 0) return (1); outb(wdc + wd_command, command); @@ -1624,44 +1486,42 @@ wdsetctlr(struct disk *du) du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks, du->dk_dd.d_nsectors); #endif - if (!(du->dk_flags & DKFL_LBA)) { - if (du->dk_dd.d_ntracks == 0 || du->dk_dd.d_ntracks > 16) { - struct wdparams *wp; - - printf("wd%d: can't handle %lu heads from partition table ", - du->dk_lunit, du->dk_dd.d_ntracks); - /* obtain parameters */ - wp = &du->dk_params; - if (wp->wdp_heads > 0 && wp->wdp_heads <= 16) { - printf("(controller value %u restored)\n", - wp->wdp_heads); - du->dk_dd.d_ntracks = wp->wdp_heads; - } - else { - printf("(truncating to 16)\n"); - du->dk_dd.d_ntracks = 16; - } + if (du->dk_dd.d_ntracks == 0 || du->dk_dd.d_ntracks > 16) { + struct wdparams *wp; + + printf("wd%d: can't handle %lu heads from partition table ", + du->dk_lunit, du->dk_dd.d_ntracks); + /* obtain parameters */ + wp = &du->dk_params; + if (wp->wdp_heads > 0 && wp->wdp_heads <= 16) { + printf("(controller value %u restored)\n", + wp->wdp_heads); + du->dk_dd.d_ntracks = wp->wdp_heads; } - - if (du->dk_dd.d_nsectors == 0 || du->dk_dd.d_nsectors > 255) { - printf("wd%d: cannot handle %lu sectors (max 255)\n", - du->dk_lunit, du->dk_dd.d_nsectors); - error = 1; + else { + printf("(truncating to 16)\n"); + du->dk_dd.d_ntracks = 16; } - if (error) { + } + + if (du->dk_dd.d_nsectors == 0 || du->dk_dd.d_nsectors > 255) { + printf("wd%d: cannot handle %lu sectors (max 255)\n", + du->dk_lunit, du->dk_dd.d_nsectors); + error = 1; + } + if (error) { #ifdef CMD640 - wdtab[du->dk_ctrlr_cmd640].b_errcnt += RETRIES; + wdtab[du->dk_ctrlr_cmd640].b_errcnt += RETRIES; #else - wdtab[du->dk_ctrlr].b_errcnt += RETRIES; + wdtab[du->dk_ctrlr].b_errcnt += RETRIES; #endif - return (1); - } - if (wdcommand(du, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks - 1, 0, - du->dk_dd.d_nsectors, WDCC_IDC) != 0 - || wdwait(du, WDCS_READY, TIMEOUT) < 0) { - wderror((struct buf *)NULL, du, "wdsetctlr failed"); - return (1); - } + return (1); + } + if (wdcommand(du, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks - 1, 0, + du->dk_dd.d_nsectors, WDCC_IDC) != 0 + || wdwait(du, WDCS_READY, TIMEOUT) < 0) { + wderror((struct buf *)NULL, du, "wdsetctlr failed"); + return (1); } wdsetmulti(du); @@ -1698,26 +1558,6 @@ wdwsetctlr(struct disk *du) #endif /* - * gross little callback function for wdddma interface. returns 1 for - * success, 0 for failure. - */ -static int -wdsetmode(int mode, void *wdinfo) -{ - int i; - struct disk *du; - - du = wdinfo; - if (bootverbose) - printf("wd%d: wdsetmode() setting transfer mode to %02x\n", - du->dk_lunit, mode); - i = wdcommand(du, 0, 0, mode, WDFEA_SETXFER, - WDCC_FEATURES) == 0 && - wdwait(du, WDCS_READY, TIMEOUT) == 0; - return i; -} - -/* * issue READP to drive to ask it what it is. */ static int @@ -1872,23 +1712,6 @@ failed: du->dk_multi = wp->wdp_nsecperint & 0xff; wdsetmulti(du); - /* - * check drive's DMA capability - */ - if (wddma[du->dk_interface].wdd_candma) { - du->dk_dmacookie = wddma[du->dk_interface].wdd_candma(du->dk_port, du->dk_ctrlr); - /* does user want this? */ - if ((du->cfg_flags & WDOPT_DMA) && - /* have we got a DMA controller? */ - du->dk_dmacookie && - /* can said drive do DMA? */ - wddma[du->dk_interface].wdd_dmainit(du->dk_dmacookie, wp, wdsetmode, du)) { - du->dk_flags |= DKFL_USEDMA; - } - } else { - du->dk_dmacookie = NULL; - } - #ifdef WDDEBUG printf( "\nwd(%d,%d): wdgetctlr: gc %x cyl %d trk %d sec %d type %d sz %d model %s\n", @@ -1899,40 +1722,11 @@ failed: /* update disklabel given drive information */ du->dk_dd.d_secsize = DEV_BSIZE; - if ((du->cfg_flags & WDOPT_LBA) && wp->wdp_lbasize) { - du->dk_dd.d_nsectors = 63; - if (wp->wdp_lbasize < 16*63*1024) { /* <=528.4 MB */ - du->dk_dd.d_ntracks = 16; - } - else if (wp->wdp_lbasize < 32*63*1024) { /* <=1.057 GB */ - du->dk_dd.d_ntracks = 32; - } - else if (wp->wdp_lbasize < 64*63*1024) { /* <=2.114 GB */ - du->dk_dd.d_ntracks = 64; - } - else if (wp->wdp_lbasize < 128*63*1024) { /* <=4.228 GB */ - du->dk_dd.d_ntracks = 128; - } - else if (wp->wdp_lbasize < 128*63*1024) { /* <=8.422 GB */ - du->dk_dd.d_ntracks = 255; - } - else { /* >8.422 GB */ - du->dk_dd.d_ntracks = 255; /* XXX */ - } - du->dk_dd.d_secpercyl= du->dk_dd.d_ntracks*du->dk_dd.d_nsectors; - du->dk_dd.d_ncylinders = wp->wdp_lbasize/du->dk_dd.d_secpercyl; - du->dk_dd.d_secperunit = wp->wdp_lbasize; - du->dk_flags |= DKFL_LBA; - } - else { - du->dk_dd.d_ncylinders = wp->wdp_cylinders; /* +- 1 */ - du->dk_dd.d_ntracks = wp->wdp_heads; - du->dk_dd.d_nsectors = wp->wdp_sectors; - du->dk_dd.d_secpercyl = - du->dk_dd.d_ntracks * du->dk_dd.d_nsectors; - du->dk_dd.d_secperunit = - du->dk_dd.d_secpercyl * du->dk_dd.d_ncylinders; - } + du->dk_dd.d_ncylinders = wp->wdp_cylinders; /* +- 1 */ + du->dk_dd.d_ntracks = wp->wdp_heads; + du->dk_dd.d_nsectors = wp->wdp_sectors; + du->dk_dd.d_secpercyl = du->dk_dd.d_ntracks * du->dk_dd.d_nsectors; + du->dk_dd.d_secperunit = du->dk_dd.d_secpercyl * du->dk_dd.d_ncylinders; if (WDOPT_FORCEHD(du->cfg_flags)) { du->dk_dd.d_ntracks = WDOPT_FORCEHD(du->cfg_flags); du->dk_dd.d_secpercyl = @@ -1976,7 +1770,7 @@ wdioctl(dev_t dev, int cmd, caddr_t addr, int flags, struct proc *p) wdsleep(du->dk_ctrlr, "wdioct"); error = dsioctl("wd", dev, cmd, addr, flags, &du->dk_slices, wdstrategy1, (ds_setgeom_t *)NULL); - if (error != ENOIOCTL) + if (error != -1) return (error); switch (cmd) { @@ -2279,28 +2073,25 @@ wdflushirq(struct disk *du, int old_ipl) static int wdreset(struct disk *du) { - int err = 0; - - if ((du->dk_flags & (DKFL_DMA|DKFL_USEDMA)) && du->dk_dmacookie) - wddma[du->dk_interface].wdd_dmadone(du->dk_dmacookie); + int wdc, err = 0; + wdc = du->dk_port; (void)wdwait(du, 0, TIMEOUT); - outb(du->dk_altport, WDCTL_IDS | WDCTL_RST); + outb(wdc + wd_ctlr, WDCTL_IDS | WDCTL_RST); DELAY(10 * 1000); - outb(du->dk_altport, WDCTL_IDS); + outb(wdc + wd_ctlr, WDCTL_IDS); #ifdef ATAPI if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0) err = 1; /* no IDE drive found */ - du->dk_error = inb(du->dk_port + wd_error); + du->dk_error = inb(wdc + wd_error); if (du->dk_error != 0x01) err = 1; /* the drive is incompatible */ #else - if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0) { - printf("wdreset: error1: 0x%x\n", du->dk_error); + if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0 + || (du->dk_error = inb(wdc + wd_error)) != 0x01) return (1); - } #endif - outb(du->dk_altport, WDCTL_4BIT); + outb(wdc + wd_ctlr, WDCTL_4BIT); return (err); } @@ -2332,19 +2123,11 @@ wdtimeout(void *cdu) du = (struct disk *)cdu; x = splbio(); if (du->dk_timeout != 0 && --du->dk_timeout == 0) { - if(timeouts++ <= 5) { - char *msg; - - msg = (timeouts > 5) ? -"Last time I say: interrupt timeout. Probably a portable PC." : -"interrupt timeout"; - wderror((struct buf *)NULL, du, msg); - if (du->dk_dmacookie) - printf("wd%d: wdtimeout() DMA status %b\n", - du->dk_lunit, - wddma[du->dk_interface].wdd_dmastatus(du->dk_dmacookie), - WDDS_BITS); - } + if(timeouts++ == 5) + wderror((struct buf *)NULL, du, + "Last time I say: interrupt timeout. Probably a portable PC."); + else if(timeouts++ < 5) + wderror((struct buf *)NULL, du, "interrupt timeout"); wdunwedge(du); wdflushirq(du, x); du->dk_skip = 0; @@ -2453,9 +2236,8 @@ wdwait(struct disk *du, u_char bits_wanted, int timeout) * command completion. */ } - if ((status & bits_wanted) == bits_wanted) { + if ((status & bits_wanted) == bits_wanted) return (status & WDCS_ERR); - } } if (timeout < TIMEOUT) /* @@ -2477,8 +2259,6 @@ static void wd_drvinit(void *unused) { if( ! wd_devsw_installed ) { - if (wd_bdevsw.d_maxio == 0) - wd_bdevsw.d_maxio = 248 * 512; bdevsw_add_generic(BDEV_MAJOR,CDEV_MAJOR, &wd_bdevsw); wd_devsw_installed = 1; } |