📄 sf.c
字号:
printf("sf: last close on dev %x\n",dev);#endif if((unit = SFUNIT(dev)) >= nsf) { return ENXIO; } else if (!(devp = sfunits[unit]) || !devp->sd_present) { return ENXIO; } else if (!(un = UPTR) || un->un_state < SF_STATE_OPEN) { return ENXIO; } un->un_open &= ~(1<<SFPART(dev)); if (un->un_open == 0) { un->un_state = SF_STATE_CLOSED; } return (0);}intsfsize(dev)dev_t dev;{ int unit = SFUNIT(dev); struct scsi_device *devp; if (unit >= nsf || !(devp = sfunits[unit]) || !devp->sd_present) return (-1); else return ((2*(1<<20))>>9);/*XXX*/}/* * These routines perform raw i/o operations. */sfread(dev, uio)dev_t dev;struct uio *uio;{ return sfrw(dev,uio,B_READ);}sfwrite(dev, uio)dev_t dev;struct uio *uio;{ return sfrw(dev,uio,B_WRITE);}static intsfrw(dev, uio, flag)dev_t dev;struct uio *uio;int flag;{ struct scsi_device *devp; register int unit; DPRINTF("sfrw:\n"); if ((unit = SFUNIT(dev)) >= nsf) { return ENXIO; } else if (!(devp = sfunits[unit]) || !devp->sd_present || !UPTR->un_gvalid) { return ENXIO; } else if ((uio->uio_fmode & FSETBLK) == 0 && uio->uio_offset % DEV_BSIZE != 0) { DPRINTF("sfrw: file offset not modulo %d\n",DEV_BSIZE); return (EINVAL); } else if (uio->uio_iov->iov_len % DEV_BSIZE != 0) { DPRINTF("sfrw: block length not modulo %d\n",DEV_BSIZE); return (EINVAL); } return physio(sfstrategy, UPTR->un_rbufp, dev, flag, minphys, uio);}/* * * strategy routine * */intsfstrategy(bp)register struct buf *bp;{ register struct scsi_device *devp; register struct scsi_floppy *un; register struct diskhd *dp; register s; DPRINTF("sfstrategy\n"); devp = sfunits[SFUNIT(bp->b_dev)]; if (!devp || !devp->sd_present || !(un = UPTR)) { bp->b_resid = bp->b_bcount; bp->b_flags |= B_ERROR; bp->b_error = ENXIO; iodone(bp); return; } bp->b_flags &= ~(B_DONE|B_ERROR); bp->b_resid = 0; bp->av_forw = 0; dp = &un->un_utab; if (bp != un->un_sbufp) {#ifdef NOT int part = SFPART(bp->b_dev); struct dk_map *lp = &un->un_map[part]; register daddr_t bn = dkblock(bp); if (bn == lp->dkl_nblk) { /* * Not an error, resid == count */ bp->b_resid = bp->b_bcount; iodone(bp); } else if (bn > lp->dkl_nblk) { bp->b_flags |= B_ERROR; /* * This should really be: * * ... if (bp->b_bcount & (un->un_lbasize-1)) ... * * but only if I put in support to handle SECSIZE * size requests on disks that have a 1024 byte * lbasize. */ } else if (bp->b_bcount & (SECSIZE-1)) { bp->b_resid = bp->b_bcount; bp->b_flags |= B_ERROR; /* if b_error == 0 ==> u.u_error == EIO */ } else { /* * sort by absolute block number. */ bp->b_resid = bn + lp->dkl_cylno * un->un_g.dkg_nhead * un->un_g.dkg_nsect; /* * zero out av_back - this will be a signal * to sdstart to go and fetch the resources */ BP_PKT(bp) = 0; }#else NOT BP_PKT(bp) = 0; bp->b_resid = dkblock(bp);#endif } if ((s = (bp->b_flags & (B_DONE|B_ERROR))) == 0) { s = splr(sfpri); disksort(dp,bp); if (dp->b_forw == NULL) /* this device inactive? */ sfstart(devp); (void) splx(s); } else if((s & B_DONE) == 0) { iodone(bp); }}/* * This routine implements the ioctl calls. It is called * from the device switch at normal priority. *//* * XX- what is 'flag' used for? *//*ARGSUSED3*/sfioctl(dev, cmd, data, flag)dev_t dev;int cmd;caddr_t data;int flag;{ return (ENOTTY);}static intsfioctl_cmd(dev,data)dev_t dev;caddr_t data;{ register struct scsi_device *devp; register struct buf *bp; int err = 0, flag, s; struct dk_cmd *com; faultcode_t fault_err = -1; /* * Checking for sanity done in sfioctl */ devp = sfunits[SFUNIT(dev)]; com = (struct dk_cmd *)data; switch (com->dkc_cmd) { case SCMD_READ: if (com->dkc_buflen & (SECSIZE-1)) return EINVAL; /*FALLTHRU*/ case SCMD_MODE_SENSE: flag = B_READ; break; case SCMD_WRITE: if (com->dkc_buflen & (SECSIZE-1)) return EINVAL; /*FALLTHRU*/ case SCMD_MODE_SELECT: case SCMD_TEST_UNIT_READY: case SCMD_REZERO_UNIT: flag = B_WRITE; break; default: return EINVAL; } if (DEBUGGING_ALL) { printf("sfioctl_cmd: cmd= %x blk= %x buflen= 0x%x\n", com->dkc_cmd, com->dkc_blkno, com->dkc_buflen); if (flag == B_WRITE && com->dkc_buflen) { auto u_int i, amt = min(64,com->dkc_buflen); char buf [64]; if (copyin(com->dkc_bufaddr,buf,amt)) { return EFAULT; } printf("user's buf:"); for (i = 0; i < amt; i++) { printf(" 0x%x",buf[i]&0xff); } printf("\n"); } } /* * Get buffer resources... */ bp = UPTR->un_sbufp; s = splr(sfpri); while (bp->b_flags & B_BUSY) { bp->b_flags |= B_WANTED; (void) sleep((caddr_t) bp, PRIBIO); } bzero((caddr_t) bp, sizeof (struct buf)); bp->b_flags = B_BUSY | flag; (void) splx(s); /* * Set options. */ UPTR->un_soptions = 0; if ((com->dkc_flags & DK_SILENT) && !(DEBUGGING_ALL)) { UPTR->un_soptions |= DK_SILENT; } if (com->dkc_flags & DK_ISOLATE) UPTR->un_soptions |= DK_ISOLATE; /* * NB: * I don't know why, but changing the order of some of these things * below causes panics in kmem_free later on when ioctl(sys_generic.c) * attempt to kmem_free something it shouldn't. */ /* * Fill in the buffer with information we need * */ bp->b_forw = (struct buf *) com; bp->b_dev = dev; if ((bp->b_bcount = com->dkc_buflen) > 0) bp->b_un.b_addr = com->dkc_bufaddr; bp->b_blkno = com->dkc_blkno; if (com->dkc_buflen & (1<<31)) { /* * mapped in kernel address... */ com->dkc_buflen ^= (1<<31); bp->b_bcount = com->dkc_buflen; bp->b_un.b_addr = com->dkc_bufaddr; } else if (com->dkc_buflen) { bp->b_flags |= B_PHYS; bp->b_proc = u.u_procp; u.u_procp->p_flag |= SPHYSIO; /* * Fault lock the address range of the buffer. */ fault_err = as_fault(u.u_procp->p_as, bp->b_un.b_addr, (u_int)bp->b_bcount, F_SOFTLOCK, (bp->b_flags & B_READ) ? S_WRITE : S_READ); if (fault_err != 0) { if (FC_CODE(fault_err) == FC_OBJERR) err = FC_ERRNO(fault_err); else err = EFAULT; } else if (buscheck(bp) < 0) { err = EFAULT; } } /* * If no errors, make and run the command. */ if (err == 0) { make_sf_cmd(devp,bp,SLEEP_FUNC); sfstrategy(bp); s = splr(sfpri); while((bp->b_flags & B_DONE) == 0) { sleep((caddr_t) bp, PRIBIO); } (void) splx(s); /* * Release the resources. * */ err = geterror(bp); if (fault_err == 0) { (void) as_fault(u.u_procp->p_as,bp->b_un.b_addr, (u_int)bp->b_bcount, F_SOFTUNLOCK, (bp->b_flags&B_READ)? S_WRITE: S_READ); u.u_procp->p_flag &= ~SPHYSIO; bp->b_flags &= ~B_PHYS; } scsi_resfree(BP_PKT(bp)); } s = splr(sfpri); if (bp->b_flags & B_WANTED) wakeup((caddr_t)bp); UPTR->un_soptions = 0; bp->b_flags &= ~(B_BUSY|B_WANTED); (void) splx(s); DPRINTF_IOCTL("returning %d from ioctl\n",err); return (err);}/************************************************************************ ************************************************************************ * * * * * Unit start and Completion * * * * * ************************************************************************ ************************************************************************/static voidsfstart(devp)register struct scsi_device *devp;{ register struct buf *bp; register struct scsi_floppy *un = UPTR; register struct diskhd *dp = &un->un_utab; if (dp->b_forw) { printf("sfstart: busy already\n"); return; } else if((bp = dp->b_actf) == NULL) { DPRINTF("%s%d: sfstart idle\n",DNAME,DUNIT); return; } if (!BP_PKT(bp)) { make_sf_cmd(devp,bp,sfrunout); if (!BP_PKT(bp)) { un->un_last_state = un->un_state; un->un_state = SF_STATE_RWAIT; return; } else { un->un_last_state = un->un_state; un->un_state = SF_STATE_OPEN; } } dp->b_forw = bp; dp->b_actf = bp->b_actf; bp->b_actf = 0; if (pkt_transport(BP_PKT(bp)) == 0) { printf("%s%d: transport rejected\n",DNAME,DUNIT); bp->b_flags |= B_ERROR; sfdone(devp); }}static intsfrunout(){ register i, s = splr(sfpri); register struct scsi_device *devp; register struct scsi_floppy *un; for (i = 0; i < nsf; i++) { devp = sfunits[i]; if (devp && devp->sd_present && un->un_state == SF_STATE_RWAIT) { DPRINTF("%s%d: resource retry\n",DNAME,DUNIT); sfstart(devp); if (un->un_state == SF_STATE_RWAIT) { (void) splx(s); return (0); } DPRINTF("%s%d: resource gotten\n",DNAME,DUNIT); } } (void) splx(s); return (1);}static voidsfdone(devp)register struct scsi_device *devp;{ register struct buf *bp; register struct scsi_floppy *un = UPTR; register struct diskhd *dp = &un->un_utab; bp = dp->b_forw; dp->b_forw = NULL; /* * Start the next one before releasing resources on this one */ if (dp->b_actf) { DPRINTF("%s%d: sfdone calling sdstart\n",DNAME,DUNIT); sfstart(devp); } if (bp != un->un_sbufp) { scsi_resfree(BP_PKT(bp)); iodone(bp); DPRINTF("regular done\n"); } else { DPRINTF("special done\n"); bp->b_flags |= B_DONE; wakeup((caddr_t) bp); }}static voidmake_sf_cmd(devp,bp,func)register struct scsi_device *devp;register struct buf *bp;int (*func)();{ register struct scsi_pkt *pkt; register struct scsi_floppy *un = UPTR; register daddr_t blkno = 0; int tval = DEFAULT_SF_TIMEOUT, count, com, flags; flags = (scsi_options & SCSI_OPTIONS_DR) ? 0: FLAG_NODISCON; DPRINTF("make_sf_cmd: "); if (bp != un->un_sbufp) { struct dk_map *lp = &un->un_map[SFPART(bp->b_dev)]; pkt = scsi_resalloc(ROUTE,CDB_GROUP0,1,(opaque_t)bp,func); if ((BP_PKT(bp) = pkt) == (struct scsi_pkt *) 0) { return; } count = bp->b_bcount >> SECDIV; blkno = dkblock(bp) + (lp->dkl_cylno * un->un_g.dkg_nhead * un->un_g.dkg_nsect); if (bp->b_flags & B_READ) { DPRINTF("read"); com = SCMD_READ; } else { DPRINTF("write"); com = SCMD_WRITE; } DPRINTF(" %d amt 0x%x\n",blkno,bp->b_bcount); makecom_g0(pkt, devp, flags, com, (int) blkno, count); } else { struct buf *abp = bp; int g1 = 0; /* * Some commands are group 1 commands, some are group 0. * It is legitimate to allocate a cdb sufficient for any. * Therefore, we'll ask for a GROUP 1 cdb. */ /* * stored in bp->b_forw is a pointer to the dk_cmd */ com = ((struct dk_cmd *) bp->b_forw)->dkc_cmd; blkno = bp->b_blkno; count = bp->b_bcount; switch(com) { case SCMD_WRITE: case SCMD_READ: DPRINTF_IOCTL("special %s\n",(com==SCMD_READ)?"read": "write"); count = bp->b_bcount >> SECDIV; break; case SCMD_MODE_SELECT: DPRINTF_IOCTL("mode select\n"); break; case SCMD_MODE_SENSE: DPRINTF_IOCTL("mode sense: pcf = 0x%x, page %x\n", blkno>>5,blkno&0x1f); blkno <<= 8; break; case SCMD_FORMAT: DPRINTF_IOCTL("format\n"); if (bp->b_blkno & 0x80000000) { /* * interleave */ count = bp->b_blkno&0xff; blkno = (bp->b_blkno>>8)&0xff; /* * data pattern */ blkno |= (((bp->b_blkno>>16)&0xff)<<8); /* * format parameter bits */ blkno |= (((bp->b_blkno>>24)&0x1f)<<16); } else { blkno = (FPB_DATA|FPB_CMPLT|FPB_BFI)<<16; count = 1;/* interleave */ } tval = 30*60; break; case SCMD_TEST_UNIT_READY: case SCMD_REZERO_UNIT: DPRINTF_IOCTL("%s\n",(com == SCMD_TEST_UNIT_READY)? "tur":"rezero"); /* * no data transfer... */ abp = (struct buf *) 0; break; default: panic("unknown special command in make_sf_cmd"); /*NOTREACHED*/ } pkt = scsi_resalloc(ROUTE,CDB_GROUP1,1, (opaque_t)abp,SLEEP_FUNC); if (g1) { makecom_g1(pkt, devp, flags, com, (int) blkno, count); } else { makecom_g0(pkt, devp, flags, com, (int) blkno, count); } } pkt->pkt_comp = sfintr; pkt->pkt_time = tval; pkt->pkt_private = (opaque_t) bp; pkt->pkt_pmon = -1; BP_PKT(bp) = pkt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -