📄 wd.c
字号:
*/ outb(wdc+wd_precomp, 0xff);/* sometimes this is head bit 3 */ outb(wdc+wd_seccnt, 1); outb(wdc+wd_sector, LABELSECTOR+1); /*if (bp->b_dev == bootdev) { (wdc+wd_cyl_lo = cyloffset & 0xff; (wdc+wd_cyl_hi = cyloffset >> 8; } else { (wdc+wd_cyl_lo = 0; (wdc+wd_cyl_hi = 0; }*/ outb(wdc+wd_cyl_lo, (cyloffset & 0xff)); outb(wdc+wd_cyl_hi, (cyloffset >> 8)); outb(wdc+wd_sdh, WDSD_IBM | (unit << 4)); outb(wdc+wd_command, WDCC_READ); du->dk_state = RDLABEL; return(0); case RDLABEL: if ((stat = inb(wdc+wd_status)) & WDCS_ERR) { if (++wdtab.b_errcnt < RETRIES) goto retry; printf("wd%d: read label", unit); goto badopen; } insw(wdc+wd_data, bp->b_un.b_addr, 256); if (((struct disklabel *) (bp->b_un.b_addr + LABELOFFSET))->d_magic == DISKMAGIC) { du->dk_dd = * (struct disklabel *) (bp->b_un.b_addr + LABELOFFSET); } else { printf("wd%d: bad disk label\n", du->dk_unit); du->dk_state = OPENRAW; } s = splbio(); /* not called from intr level ... */ while ((stat = inb(wdc+wd_status)) & WDCS_BUSY); wdsetctlr(bp->b_dev, du); outb(wdc+wd_seccnt, 0); splx(s); if (du->dk_state == RDLABEL) du->dk_state = RDBADTBL; /* * The rest of the initialization can be done * by normal means. */ return(1); default: panic("wdcontrol"); } /* NOTREACHED */badopen: printf(": status %b error %b\n", stat, WDCS_BITS, inb(wdc+wd_error), WDERR_BITS); du->dk_state = OPENRAW; return(1);}wdsetctlr(dev, du) dev_t dev; struct disk *du; { int stat; outb(wdc+wd_cyl_lo, du->dk_dd.d_ncylinders); outb(wdc+wd_cyl_hi, (du->dk_dd.d_ncylinders)>>8); outb(wdc+wd_sdh, WDSD_IBM | (wdunit(dev) << 4) + du->dk_dd.d_ntracks-1); outb(wdc+wd_seccnt, du->dk_dd.d_nsectors); outb(wdc+wd_command, 0x91); while ((stat = inb(wdc+wd_status)) & WDCS_BUSY) ; stat = inb(wdc+wd_error); return(stat);}/* ARGSUSED */wdclose(dev, flags, fmt) dev_t dev; int flags, fmt;{ register struct disk *du; du = &wddrives[wdunit(dev)]; du->dk_open-- ; /*if (du->dk_open == 0) du->dk_state = CLOSED ; does not work */}wdioctl(dev,cmd,addr,flag) dev_t dev; caddr_t addr;{ int unit = wdunit(dev); register struct disk *du; int error = 0; struct uio auio; struct iovec aiov; /*int wdformat();*/ du = &wddrives[unit]; switch (cmd) { case DIOCGDINFO: *(struct disklabel *)addr = du->dk_dd; break; case DIOCGPART: ((struct partinfo *)addr)->disklab = &du->dk_dd; ((struct partinfo *)addr)->part = &du->dk_dd.d_partitions[wdpart(dev)]; break; case DIOCSDINFO: if ((flag & FWRITE) == 0) error = EBADF; else error = setdisklabel(&du->dk_dd, (struct disklabel *)addr, 0 /*(dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart*/); /*if (error == 0 && dk->dk_state == OPENRAW && vdreset_drive(vddinfo[unit])) dk->dk_state = OPEN;*/ wdsetctlr(dev, du); break; case DIOCWLABEL: if ((flag & FWRITE) == 0) error = EBADF; else du->dk_wlabel = *(int *)addr; break; case DIOCWDINFO: if ((flag & FWRITE) == 0) error = EBADF; else if ((error = setdisklabel(&du->dk_dd, (struct disklabel *)addr, 0/*(dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart*/)) == 0) { int wlab; /*if (error == 0 && dk->dk_state == OPENRAW && vdreset_drive(vddinfo[unit])) dk->dk_state = OPEN; */ wdsetctlr(dev, du); /* simulate opening partition 0 so write succeeds */ /* dk->dk_openpart |= (1 << 0); /* XXX */ wlab = du->dk_wlabel; du->dk_wlabel = 1; error = writedisklabel(dev, wdstrategy, &du->dk_dd,wdpart(dev)); /*dk->dk_openpart = dk->dk_copenpart | dk->dk_bopenpart;*/ du->dk_wlabel = wlab; } break;#ifdef notyet case DIOCGDINFOP: *(struct disklabel **)addr = &(du->dk_dd); break; case DIOCWFORMAT: if ((flag & FWRITE) == 0) error = EBADF; else { register struct format_op *fop; fop = (struct format_op *)addr; aiov.iov_base = fop->df_buf; aiov.iov_len = fop->df_count; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_resid = fop->df_count; auio.uio_segflg = 0; auio.uio_offset = fop->df_startblk * du->dk_dd.d_secsize; error = physio(wdformat, &rwdbuf[unit], dev, B_WRITE, minphys, &auio); fop->df_count -= auio.uio_resid; fop->df_reg[0] = du->dk_status; fop->df_reg[1] = du->dk_error; } break;#endif default: error = ENOTTY; break; } return (error);}/*wdformat(bp) struct buf *bp;{ bp->b_flags |= B_FORMAT; return (wdstrategy(bp));}*//* * Routines to do raw IO for a unit. */wdread(dev, uio) /* character read routine */ dev_t dev; struct uio *uio;{ int unit = wdunit(dev) ; if (unit >= NWD) return(ENXIO); return(physio(wdstrategy, &rwdbuf[unit], dev, B_READ, minphys, uio));}wdwrite(dev, uio) /* character write routine */ dev_t dev; struct uio *uio;{ int unit = wdunit(dev) ; if (unit >= NWD) return(ENXIO); return(physio(wdstrategy, &rwdbuf[unit], dev, B_WRITE, minphys, uio));}wdsize(dev) dev_t dev;{ register unit = wdunit(dev); register part = wdpart(dev); register struct disk *du; register val ; if (unit >= NWD) return(-1); if (wddrives[unit].dk_state == 0) { val = wdopen (dev, 0); if (val < 0) return (-1); } du = &wddrives[unit]; return((int)((u_long)du->dk_dd.d_partitions[part].p_size * du->dk_dd.d_secsize / 512));}extern char *vmmap; /* poor name! */wddump(dev) /* dump core after a system crash */ dev_t dev;{ register struct disk *du; /* disk unit to do the IO */ register struct bt_bad *bt_ptr; long num; /* number of sectors to write */ int unit, part; long cyloff, blknum, blkcnt; long cylin, head, sector, stat; long secpertrk, secpercyl, nblocks, i; char *addr; extern int Maxmem; static wddoingadump = 0 ; extern CMAP1; extern char CADDR1[]; #ifdef ARGOoutb(0x461,0); /* disable failsafe timer */#endif addr = (char *) 0; /* starting address */ /* size of memory to dump */ num = Maxmem; unit = wdunit(dev); /* eventually support floppies? */ part = wdpart(dev); /* file system */ /* check for acceptable drive number */ if (unit >= NWD) return(ENXIO); du = &wddrives[unit]; /* was it ever initialized ? */ if (du->dk_state < OPEN) return (ENXIO) ; /* Convert to disk sectors */ num = (u_long) num * NBPG / du->dk_dd.d_secsize; /* check if controller active */ /*if (wdtab.b_active) return(EFAULT); */ if (wddoingadump) return(EFAULT); secpertrk = du->dk_dd.d_nsectors; secpercyl = du->dk_dd.d_secpercyl; nblocks = du->dk_dd.d_partitions[part].p_size; cyloff = du->dk_dd.d_partitions[part].p_offset / secpercyl;/*pg("xunit %x, nblocks %d, dumplo %d num %d\n", part,nblocks,dumplo,num);*/ /* check transfer bounds against partition size */ if ((dumplo < 0) || ((dumplo + num) > nblocks)) return(EINVAL); /*wdtab.b_active = 1; /* mark controller active for if we panic during the dump */ wddoingadump = 1 ; i = 100000 ; while ((inb(wdc+wd_status) & WDCS_BUSY) && (i-- > 0)) ; outb(wdc+wd_sdh, WDSD_IBM | (unit << 4)); outb(wdc+wd_command, WDCC_RESTORE | WD_STEP); while (inb(wdc+wd_status) & WDCS_BUSY) ; /* some compaq controllers require this ... */ wdsetctlr(dev, du); blknum = dumplo; while (num > 0) {#ifdef notdef if (blkcnt > MAXTRANSFER) blkcnt = MAXTRANSFER; if ((blknum + blkcnt - 1) / secpercyl != blknum / secpercyl) blkcnt = secpercyl - (blknum % secpercyl); /* keep transfer within current cylinder */#endif pmap_enter(kernel_pmap, vmmap, addr, VM_PROT_READ, TRUE); /* compute disk address */ cylin = blknum / secpercyl; head = (blknum % secpercyl) / secpertrk; sector = blknum % secpertrk; cylin += cyloff;#ifdef notyet /* * See if the current block is in the bad block list. * (If we have one.) */ for (bt_ptr = dkbad[unit].bt_bad; bt_ptr->bt_cyl != -1; bt_ptr++) { if (bt_ptr->bt_cyl > cylin) /* Sorted list, and we passed our cylinder. quit. */ break; if (bt_ptr->bt_cyl == cylin && bt_ptr->bt_trksec == (head << 8) + sector) { /* * Found bad block. Calculate new block addr. * This starts at the end of the disk (skip the * last track which is used for the bad block list), * and works backwards to the front of the disk. */ blknum = (du->dk_dd.d_secperunit) - du->dk_dd.d_nsectors - (bt_ptr - dkbad[unit].bt_bad) - 1; cylin = blknum / secpercyl; head = (blknum % secpercyl) / secpertrk; sector = blknum % secpertrk; break; }#endif sector++; /* origin 1 */ /* select drive. */ outb(wdc+wd_sdh, WDSD_IBM | (unit<<4) | (head & 0xf)); while ((inb(wdc+wd_status) & WDCS_READY) == 0) ; /* transfer some blocks */ outb(wdc+wd_sector, sector); outb(wdc+wd_seccnt,1); outb(wdc+wd_cyl_lo, cylin); outb(wdc+wd_cyl_hi, cylin >> 8);#ifdef notdef /* lets just talk about this first...*/ pg ("sdh 0%o sector %d cyl %d addr 0x%x", inb(wdc+wd_sdh), inb(wdc+wd_sector), inb(wdc+wd_cyl_hi)*256+inb(wdc+wd_cyl_lo), addr) ;#endif#ifdef ODYSSEUSif(cylin < 46 || cylin > 91)pg("oops");#endif#ifdef PRIAMif(cylin < 40 || cylin > 79)pg("oops");#endif outb(wdc+wd_command, WDCC_WRITE); /* Ready to send data? */ while ((inb(wdc+wd_status) & WDCS_DRQ) == 0) ; if (inb(wdc+wd_status) & WDCS_ERR) return(EIO) ; outsw (wdc+wd_data, CADDR1+((int)addr&(NBPG-1)), 256); (int) addr += 512; if (inb(wdc+wd_status) & WDCS_ERR) return(EIO) ; /* Check data request (should be done). */ if (inb(wdc+wd_status) & WDCS_DRQ) return(EIO) ; /* wait for completion */ for ( i = 1000000 ; inb(wdc+wd_status) & WDCS_BUSY ; i--) { if (i < 0) return (EIO) ; } /* error check the xfer */ if (inb(wdc+wd_status) & WDCS_ERR) return(EIO) ; /* update block count */ num--; blknum++ ;if (num % 100 == 0) printf(".") ; } return(0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -