📄 scsi_disk.c
字号:
* we will think the partition table is good, but * it will be the default pt not the one read from the disk. */ if ((sz_part[unit].pt_valid == 0) || (sz_unit_online[unit] == 0)) { stp = sc->sc_dstp[targid]; for( i = 0; i < 8; i++ ) { sz_part[unit].pt_part[i].pi_nblocks = stp[i].nblocks; sz_part[unit].pt_part[i].pi_blkoff = stp[i].blkoffs; } sz_part[unit].pt_valid = PT_VALID; /* * Default partition are now set. Call rsblk to set * the driver's partition tables, if any exists, from * the "a" partition superblock */ /* * TODO: this is a temporary fix! * If rsblk returns an error, revert * back to the default partition table. * * NOTE: the read by rsblk wipes out the current pt. * ABOVE comment wrong. * * Must get pt every time media changed! * RZ are fixed media disks, but..... */ i = rsblk(rzstrategy, dev, &sz_part[unit]); } /* So open nodelay doesn't falsely set on-line! */ if (dev_ready) sz_unit_online[unit] = 1; return (0);}/* TODO: need funct header */rzsize(dev){ register struct sz_softc *sc; register struct uba_device *ui; int unit = minor(dev) >> 3; int targid; int part; daddr_t psize; /* TODO: check meaning of ui_flags == 0 in udsize???? */ if (unit >= nNSZ || (ui = szdinfo[unit]) == 0 || ui->ui_alive == 0) return(-1); sc = &sz_softc[ ui->ui_ctlr ]; targid = ui->ui_slave; /* * Sanity check */ if ( sz_part[unit].pt_valid != PT_VALID ) panic("rzsize: invalid partition table "); part = minor(dev) & 7; if (sz_part[unit].pt_part[part].pi_nblocks != -1) psize = sz_part[unit].pt_part[part].pi_nblocks; else psize = sc->sc_disksize[targid] - sz_part[unit].pt_part[part].pi_blkoff; return(psize);}/* * rzcommand() - Execute a SCSI Command. * * Inputs: dev = The device major/minor number. * com = The SCSI command code. * count = The command count. * retry = The retry count. * * Return Value: * Returns 0 for SUCCESS, or error code. */intrzcommand (dev, com, count, retry)register dev_t dev;register int com;register int count;register int retry;{ int unit = minor(dev) >> 3; register struct buf *bp = &cszbuf[unit]; register struct sz_softc *sc; register struct uba_device *ui; register int s; int cntlr, targid, error; ui = szdinfo[unit]; cntlr = ui->ui_ctlr; targid = ui->ui_slave; sc = &sz_softc[cntlr]; if (error = rziowait (bp, sc->sc_rzspecial[targid])) { return (error); } /* * Load the buffer. The bp field usage is (see scsireg.h): * * b_bcount = The command count. * b_gid = The command mnemonic. * b_bufsize = The retry count. * * These two fields are "known" to be "save" to use for this purpose. * (Most other drivers also use these fields in this way.) */ bp->b_flags = B_BUSY|B_READ; bp->b_dev = dev; bp->b_comand = com; bp->b_bcount = count; bp->b_blkno = 0; bp->b_retry = retry; bp->b_error = 0; bp->b_proc = u.u_procp; rzstrategy(bp); iowait(bp); s = splbio(); if (bp->b_flags & B_WANTED) { wakeup ((caddr_t)bp); } splx(s); bp->b_flags &= ~(B_BUSY | B_WANTED); return (geterror (bp));}/* * rziowait() - Wait For Prior I/O To Complete (if busy). * * Inputs: bp = The buffer to check. * special = Special I/O active flag. * * Return Value: * Return 0 for SUCCESS, or EINTR if sleep interrupted. */static intrziowait (bp, special)register struct buf *bp;register int special;{ register int error = 0; register int s; s = splbio(); while (bp->b_flags & B_BUSY) { bp->b_flags |= B_WANTED; if (special) { if (sleep ((caddr_t)bp, (PCATCH | PZERO + 1))) { error = EINTR; } } else { (void) sleep ((caddr_t)bp, PRIBIO + 1); } } splx (s); return (error);}rzstrategy(bp) register struct buf *bp;{ register struct sz_softc *sc; struct uba_device *ui; register struct buf *dp; register int s; int unit = minor(bp->b_dev) >> 3; int targid; int cntlr; int bad, err; daddr_t sz, maxsz; int part; struct pt *pt; ui = szdinfo[unit]; targid = ui->ui_slave; cntlr = ui->ui_ctlr; sc = &sz_softc[cntlr]; /* TODO1: note - no queue sorting! */ /* * Validate things like block number, * unit number, on-line, etc. */ bad = 0; while(1) { if (unit >= nNSZ) { bad = 1; err = ENXIO; break; } /* * CDROM is read only! */ if ((sc->sc_devtyp[targid] & SZ_CDROM) && ((bp->b_flags & B_READ) == 0)) { bad = 1; err = EROFS; break; } /* * RSP says we must have this check. * It prevents open no delay burning us if the * disk's partition table is not valid. * We only do this check for data transfer commands. * House keeping commands (TUR, RDCAP, MODSEL, etc.) * also call rzstrategy. */ if (bp != &cszbuf[unit]) { if (sz_part[unit].pt_valid != PT_VALID) { if (sc->sc_szflags[targid] & SZ_NODEVICE) { bad = 1; err = ENXIO; break; } else { panic("rzstrategy: invalid partition table "); } } } /* TODO: check ui == 0 || ui->ui_alive == 0 here - someday */ /* TODO: EOM maybe, CSE - don't think so */ /* TODO: don't think this can happen for disks */ if ((sc->sc_flags[targid]&DEV_EOM) && !((sc->sc_flags[targid]&DEV_CSE) || (dis_eot_sz[unit] & DISEOT))) { bad = 1; err = ENOSPC; break; } /* * If SZ_NODEVICE is set, the device was opened * with FNDELAY, but the device didn't respond. * We'll try again to see if the device is here, * if it is not, return an error. */ if (sc->sc_szflags[targid] & SZ_NODEVICE) { DEV_UGH(sc->sc_device[targid], unit, "offline"); bad = 1; err = ENXIO; break; } /* * Check transfer size, * to be sure it does not overflow the * bounds of the partition. * Only check data transfer commands. */ if (bp == &cszbuf[unit]) break; part = minor(bp->b_dev) & 7; sz = (bp->b_bcount + 511) >> 9; pt = &sz_part[unit]; if (pt->pt_part[part].pi_nblocks == -1) maxsz = sc->sc_disksize[targid] - pt->pt_part[part].pi_blkoff; else maxsz = pt->pt_part[part].pi_nblocks; if ((bp->b_blkno < 0) || (bp->b_blkno+sz > maxsz) || (pt->pt_part[part].pi_blkoff >= sc->sc_disksize[targid])) { bad = 1; err = ENOSPC; break; } break; } if (bad) { bp->b_flags |= B_ERROR; bp->b_resid = bp->b_bcount; bp->b_error = err; biodone(bp); return; } /* TODO: DISKLOG stuff in uda.c?????? */#ifdef vax s = spl5();#endif vax#ifdef mips s = splbio();#endif mips dp = &szutab[unit]; if (dp->b_actf == NULL) dp->b_actf = bp; else dp->b_actl->av_forw = bp; dp->b_actl = bp; bp->av_forw = NULL; if ((dp->b_active == 0) && (sc->sc_active == 0)) { sc->sc_xstate[targid] = SZ_NEXT; sc->sc_xevent[targid] = SZ_BEGIN; sz_start(sc, targid); } splx(s);}rzread(dev, uio) register dev_t dev; register struct uio *uio;{ int unit = minor(dev) >> 3; return (physio(rzstrategy, &rszbuf[unit], dev, B_READ, minphys, uio));}rzwrite(dev, uio) register dev_t dev; register struct uio *uio;{ register struct sz_softc *sc; struct uba_device *ui; int unit = minor(dev) >> 3; int targid; ui = szdinfo[unit]; targid = ui->ui_slave; sc = &sz_softc[ui->ui_ctlr]; /* * CDROM is read only! */ if (sc->sc_devtyp[targid] & SZ_CDROM) return(EROFS); return (physio(rzstrategy, &rszbuf[unit], dev, B_WRITE, minphys, uio));}rzioctl(dev, cmd, data, flag) dev_t dev; register int cmd; caddr_t data; int flag;{ register struct sz_softc *sc; register struct uba_device *ui; register struct uba_ctlr *um; int unit = minor(dev) >> 3; int cntlr; int targid; register struct buf *bp = &cszbuf[unit]; struct devget *devget; int i; struct size *stp; struct pt *pt = (struct pt *)data; int error; struct scsi_devtab *sdp; struct sz_rdcap_dt *rdp; struct sz_rzmodsns_dt *msdp; struct page_code_3 *p3; struct page_code_4 *p4; struct page_code_5 *p5; DEVGEOMST *devgeom; ui = szdinfo[unit]; cntlr = ui->ui_ctlr; um = szminfo[cntlr]; targid = ui->ui_slave; sc = &sz_softc[cntlr]; sdp = (struct scsi_devtab *)sc->sc_devtab[targid]; switch (cmd) { case DIOCGETPT: /* Return disk partition table to user */ case DIOCDGTPT: /* Return default disk partition table */ if (cmd == DIOCGETPT) { /* * Copy pt structure into user's data area. */ *pt = sz_part[unit]; } else { /* * Copy the default partition table to user's data area. */ stp = sc->sc_dstp[targid]; for (i=0; i<8; i++) { pt->pt_part[i].pi_nblocks = stp[i].nblocks; pt->pt_part[i].pi_blkoff = stp[i].blkoffs; } } /* * Change all -1 nblocks to disk unit size. */ for (i=0; i<8; i++) { if (pt->pt_part[i].pi_nblocks == -1) pt->pt_part[i].pi_nblocks = sc->sc_disksize[targid] - pt->pt_part[i].pi_blkoff; } pt->pt_magic = PT_MAGIC; break; /* TODO1: what if user does this with open no delay? */ case DIOCSETPT: /* set the driver partition tables */ /* * Only super users can set the pack's partition table. */ if (!suser()) return(EACCES); /* * CDROM is read only, don't allow set partition table. */ if (sc->sc_devtyp[targid] & SZ_CDROM) return(EROFS); /* * Before we set the new partition tables make sure * that it will no corrupt any of the kernel data * structures. */ if ((error = ptcmp(dev, &sz_part[unit], pt)) != 0) return(error); /* * Using the user's data to set the partition table * for the pack */ sz_part[unit] = *pt; /* * See if we need to update the superblock of the * "a" partition of this disk. */ ssblk(dev, pt); /* * Just make sure that we set the valid bit. */ sz_part[unit].pt_valid = PT_VALID; break; case DEVIOCGET: /* device status */ devget = (struct devget *)data; bzero(devget,sizeof(struct devget)); devget->category = DEV_DISK;#ifdef vax devget->bus = DEV_NB; bcopy(DEV_VS_SCSI, devget->interface, strlen(DEV_VS_SCSI));#endif vax#ifdef mips devget->bus = DEV_SCSI; bcopy(DEV_SCSI_GEN, devget->interface, strlen(DEV_SCSI_GEN));#endif mips bcopy(sc->sc_device[targid], devget->device, DEV_SIZE); devget->adpt_num = um->um_adpt; devget->nexus_num = 0; devget->bus_num = 0; devget->ctlr_num = cntlr; devget->rctlr_num = 0; devget->slave_num = targid; bcopy("rz", devget->dev_name, 3); devget->unit_num = unit; devget->soft_count = sc->sc_softcnt[targid]; devget->hard_count = sc->sc_hardcnt[targid]; devget->stat = sc->sc_flags[targid]; if (sc->sc_devtyp[targid] & SZ_CDROM) { /* To make sure we don't break the installation! */ devget->stat |= DEV_WRTLCK; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -