📄 sr.c
字号:
state = un->un_last_state; New_state(un, SR_STATE_OPENING); if (sr_unit_ready(dev) == 0) { sr_not_ready(devp); un->un_state = un->un_last_state; un->un_last_state = state; return (ENXIO); } state = un->un_last_state; New_state(un, SR_STATE_OPENING); if (sr_read_capacity(devp) != 0) { un->un_state = un->un_last_state; un->un_last_state = state; return (ENXIO); } un->un_state = un->un_last_state; un->un_last_state = state; /* * now lock the drive door, if it is the first time open */ if ((un->un_open0 == 0) && (un->un_open1 == 0)) { state = un->un_last_state; New_state(un, SR_STATE_OPENING); if (sr_medium_removal(dev, SR_REMOVAL_PREVENT) != 0) { un->un_state = un->un_last_state; un->un_last_state = state; return (ENXIO); } un->un_state = un->un_last_state; un->un_last_state = state; } } else if (un->un_state == SR_STATE_DETACHING) { u_char state; if (sr_unit_ready(dev) == 0) { return (ENXIO); } /* * disk now back on line... */ New_state(un, SR_STATE_OPENING); printf("%s%d: disk okay\n", DNAME, DUNIT); if (sr_read_capacity(devp) != 0) { return (ENXIO); } /* now lock the drive door */ state = un->un_last_state; New_state(un, SR_STATE_OPENING); if (sr_medium_removal(dev, SR_REMOVAL_PREVENT) != 0) { un->un_state = un->un_last_state; un->un_last_state = state; return (ENXIO); } un->un_state = un->un_last_state; un->un_last_state = state; } New_state(un, SR_STATE_OPEN);#ifndef FIVETWELVE /* * to be safe, set the block size to 2048 here */ (void)sr_two_k(devp);#endif FIVETWELVE /* * set up open and exclusive open flags */ sr_setup_openflags(devp, un, major(dev)); if (flag & FEXCL) { un->un_exclopen = 1; } return (0);}/* * sr_setup_openflags: setup un->un_open0, un->un_open1 * * Look, this is a *hack* to make the driver to distinguish * between the close() call on the character device and the * the close() call on the block device. We have to assume * that the major numbers of the block device and character * device are DIFFERENT. This is the only way to let the * driver to unlock the drive and set the state to CLOSED * on the very last close() call. */static voidsr_setup_openflags(devp, un, major_num)register struct scsi_device *devp;register struct scsi_disk *un;int major_num;{ /* * set up open flag and exclusive open flag if necessary */ if ((un->un_open0 == 0) && (un->un_open1 == 0)) { un->un_open0 = major_num; } else if ((un->un_open0 != major_num) && (un->un_open1 != major_num)) { if (un->un_open0 == 0) { un->un_open0 = major_num; } else if (un->un_open1 == 0) { un->un_open1 = major_num; } else { printf("%s%d: sropen: open flags corrupted\n", DNAME, DUNIT); } }}intsrclose(dev)dev_t dev;{ register struct scsi_device *devp; register struct scsi_disk *un; int unit; DPRINTF("sr: last close on dev %d.%d\n", major(dev), minor(dev)); if ((unit = SRUNIT(dev)) >= nsr) { return (ENXIO); } else if (!(devp = srunits[unit]) || !devp->sd_present) { return (ENXIO); } else if (!(un = UPTR) || un->un_state < SR_STATE_OPEN) { return (ENXIO); } if (un->un_open0 == major(dev)) { un->un_open0 = 0; } else if (un->un_open1 == major(dev)) { un->un_open1 = 0; } else { printf("%s%d: srclose: open flags corrupted\n", DNAME, DUNIT); } if (un->un_exclopen) { un->un_exclopen = 0; } DPRINTF("un->un_state is %d\n", un->un_state); if ((un->un_open0 == 0) && (un->un_open1 == 0)) { if (un->un_state == SR_STATE_DETACHING) { sr_offline(devp); } else if (un->un_state != SR_STATE_EJECTED) { if (sr_medium_removal(dev, SR_REMOVAL_ALLOW) != 0) { return (ENXIO); }#ifdef OPENPROMS (void) remdk((int) un->un_dkn);#endif OPENPROMS } New_state(un, SR_STATE_CLOSED); /* * here is where we would invalidate the whole * schmeer, so that the next open would go out * and make sure people hadn't switched things * out from under us. I haven't put it in yet * because I need to fiddle with the attach * routine to not bother to print a label in * cases where the disk isn't actually changed */ } return (0);}intsrsize(dev)dev_t dev;{ struct scsi_device *devp; int unit; DPRINTF("srsize:\n"); if ((unit = SRUNIT(dev)) >= nsr) { return (-1); } else if (!(devp = srunits[unit]) || !devp->sd_present) { return (-1); } return (UPTR->un_capacity);}/* * These routines perform raw i/o operations. */srread(dev, uio)dev_t dev;struct uio *uio;{ DPRINTF("in srread:\n"); return (srrw(dev, uio, B_READ));}static voidsrmin(bp)struct buf *bp;{ if (bp->b_bcount > maxphys) bp->b_bcount = maxphys;}static intsrrw(dev, uio, flag)dev_t dev;struct uio *uio;int flag;{ struct scsi_device *devp; register int unit; DPRINTF("srrw\n"); if ((unit = SRUNIT(dev)) >= nsr) { return (ENXIO); } else if (!(devp = srunits[unit]) || !devp->sd_present) { return (ENXIO); } else if ((uio->uio_fmode & FSETBLK) == 0 && (uio->uio_offset & (SECSIZE - 1)) != 0) { DPRINTF("srrw: file offset not modulo %d\n", SECSIZE); return (EINVAL); } else if (uio->uio_iov->iov_len & (SECSIZE - 1)) { DPRINTF("srrw: block length not modulo %d\n", SECSIZE); return (EINVAL); } return (physio(srstrategy, UPTR->un_rbufp, dev, flag, srmin, uio));}/* * * strategy routine * */intsrstrategy(bp)register struct buf *bp;{ register struct scsi_device *devp; register struct scsi_disk *un; register struct diskhd *dp; register s; DPRINTF("srstrategy\n"); devp = srunits[SRUNIT(bp->b_dev)]; if (!devp || !devp->sd_present || !(un = UPTR)) {nothere: bp->b_resid = bp->b_bcount; bp->b_flags |= B_ERROR; bp->b_error = ENXIO; iodone(bp); return; } if ((bp != un->un_sbufp) && (bp != un->un_rbufp) && (un->un_state == SR_STATE_MODE2)) { goto nothere; } if (bp != un->un_sbufp && un->un_state == SR_STATE_DETACHING) { if (sr_unit_ready(bp->b_dev) == 0) { goto nothere; } New_state(un, SR_STATE_OPEN); printf("%s%d: disk okay\n", DNAME, DUNIT); /* * disk now back on line... */ } bp->b_flags &= ~(B_DONE|B_ERROR); bp->b_resid = 0; bp->av_forw = 0; DPRINTF("bp->b_bcount is %d\n", bp->b_bcount); dp = &un->un_utab; if (bp != un->un_sbufp) { /* * this is regular read, therefore, it needs to be in * mode one. *//* s = splr(srpri); while (un->un_state == SR_STATE_MODE2) { (void) sleep((caddr_t)un, PRIBIO); } (void) splx(s);*/#ifdef FIVETWELVE DPRINTF("dkblock(bp) is %d\n", dkblock(bp)); if (dkblock(bp) > (un->un_capacity - 1)) {#else DPRINTF("dkblock(bp) >> 2 is %d\n", dkblock(bp)>>2); if ((dkblock(bp) >> 2) > (un->un_capacity - 1)) {#endif FIVETWELVEDPRINTF("%s%d: Requested Block number is greater than disc's capacity\n", DNAME, DUNIT); bp->b_flags |= B_ERROR; bp->b_resid = bp->b_bcount; iodone(bp); } if (bp->b_bcount & (SECSIZE - 1)) { bp->b_resid = bp->b_bcount; bp->b_flags |= B_ERROR; } else { /* * sort by absolute block number */ bp->b_resid = dkblock(bp); BP_PKT(bp) = 0; } } else { DPRINTF_IOCTL("srstrategy: special\n"); } if ((s = (bp->b_flags & (B_DONE|B_ERROR))) == 0) { s = splr(srpri); /* * We are doing it a bit non-standard. That is, the * head of the b_actf chain is *not* the active command- * it is just the head of the wait queue. The reason * we do this is that the head of the b_actf chain is * guaranteed to not be moved by disksort(), so that * our actual current active command (pointed to by * b_forw) and the head of the wait queue (b_actf) can * have resources granted without it getting lost in * the queue at some later point (where we would have * to go and look for it). */ disksort(dp, bp);#ifdef CHECK_OVERLAP check_overlap(devp);#endif if (dp->b_forw == NULL) { /* this device inactive? */ srstart(devp); } else if (BP_PKT(dp->b_actf) == 0) { /* * try and map this one */ make_sr_cmd(devp, dp->b_actf, NULL_FUNC); } (void) splx(s); } else if ((s & B_DONE) == 0) { iodone(bp); }}#ifdef CHECK_OVERLAPcheck_overlap(devp)struct scsi_device *devp;{ struct scsi_disk *un = UPTR; register struct buf *bp;}#endif/* * This routine implements the ioctl calls. It is called * from the device switch at normal priority. *//* * XX- what is 'flag' used for? *//*ARGSUSED3*/srioctl(dev, cmd, data, flag)dev_t dev;int cmd;caddr_t data;int flag;{ extern char *strcpy(); register struct scsi_device *devp; register struct scsi_disk *un; struct dk_info *info; struct dk_conf *conf; struct dk_diag *diag; int unit, i; if ((unit = SRUNIT(dev)) >= nsr) { return (ENXIO); } else if (!(devp = srunits[unit]) || !devp->sd_present ||!(un=UPTR)) { return (ENXIO); } else if (un->un_state == SR_STATE_DETACHING) { return (ENXIO); } switch (cmd) { /* * Return info concerning the controller. */ case DKIOCINFO: DPRINTF_IOCTL("srioctl: get info\n"); info = (struct dk_info *)data;#ifdef OPENPROMS info->dki_ctlr = (int) devp->sd_dev->devi_parent->devi_reg->reg_addr; info->dki_unit = (Tgt(devp)<<3)|Lun(devp);#else info->dki_ctlr = getdevaddr(devp->sd_dev->md_mc->mc_addr); info->dki_unit = devp->sd_dev->md_slave;#endif switch (un->un_dp->ctype) { case CTYPE_MD21: info->dki_ctype = DKC_MD21; break; case CTYPE_ACB4000: info->dki_ctype = DKC_ACB4000; break; default: info->dki_ctype = DKC_SCSI_CCS; break; } info->dki_flags = DKI_FMTVOL; return (0); /* * Return the geometry of the specified unit. */ case DKIOCGGEOM: DPRINTF_IOCTL("srioctl: get geometry\n"); *(struct dk_geom *)data = un->un_g; return (0); /* * Set the geometry of the specified unit. */ case DKIOCSGEOM: DPRINTF_IOCTL("srioctl: set geometry\n"); un->un_g = *(struct dk_geom *)data; return (0); /* * Return the map for the specified logical partition. * This has been made obsolete by the get all partitions * command. */ case DKIOCGPART: DPRINTF_IOCTL("srioctl: get partitions\n"); bzero((caddr_t)data, sizeof (struct dk_map)); return (0); /* * Return configuration info */ case DKIOCGCONF: DPRINTF_IOCTL("srioctl: get configuration info\n"); conf = (struct dk_conf *)data; switch (un->un_dp->ctype) { case CTYPE_MD21: conf->dkc_ctype = DKC_MD21; break; case CTYPE_ACB4000: conf->dkc_ctype = DKC_ACB4000; break; default: conf->dkc_ctype = DKC_SCSI_CCS; break; } conf->dkc_dname[0] = 's'; conf->dkc_dname[1] = 'r'; conf->dkc_dname[2] = 0; conf->dkc_flags = DKI_FMTVOL;#ifndef OPENPROMS conf->dkc_cnum = devp->sd_dev->md_mc->mc_ctlr; conf->dkc_addr = getdevaddr(devp->sd_dev->md_mc->mc_addr); conf->dkc_space = devp->sd_dev->md_mc->mc_space; conf->dkc_prio = devp->sd_dev->md_mc->mc_intpri; if (devp->sd_dev->md_mc->mc_intr) conf->dkc_vec = devp->sd_dev->md_mc->mc_intr->v_vec; else conf->dkc_vec = 0; (void) strncpy(conf->dkc_cname, devp->sd_dev->md_driver->mdr_cname, DK_DEVLEN); conf->dkc_unit = devp->sd_dev->md_unit; conf->dkc_slave = devp->sd_dev->md_slave;#else OPENPROMS conf->dkc_cnum = devp->sd_dev->devi_parent->devi_unit; conf->dkc_addr = (int) devp->sd_dev->devi_parent->devi_reg->reg_addr; conf->dkc_space = devp->sd_dev->devi_parent->devi_reg->reg_bustype; conf->dkc_prio = ipltospl(devp->sd_dev->devi_parent->devi_intr->int_pri); (void) strcpy(conf->dkc_cname, CNAME); conf->dkc_cname[3] = CUNIT; conf->dkc_unit = unit; conf->dkc_slave = (Tgt(devp)<<3)|Lun(devp);#endif OPENPROMS return (0); /* * Return the map for all logical partitions. */ case DKIOCGAPART: DPRINTF_IOCTL("srioctl: get all logical partitions\n"); for (i = 0; i < NDKMAP; i++) ((struct dk_map *)data)[i] = un->un_map[i]; return (0); /* * Get error status from last command. */ case DKIOCGDIAG: DPRINTF_IOCTL("srioctl: get error status\n"); diag = (struct dk_diag *) data; diag->dkd_errcmd = un->un_last_cmd; diag->dkd_errsect = un->un_err_blkno; diag->dkd_errno = un->un_status; diag->dkd_severe = un->un_err_severe; un->un_last_cmd = 0; /* Reset */ un->un_err_blkno = 0; un->un_err_code = 0; un->un_err_severe = 0; return (0); case CDROMPAUSE: return (sr_pause_resume(dev, (caddr_t)1)); case CDROMRESUME: return (sr_pause_resume(dev, (caddr_t)0)); case CDROMPLAYMSF: return (sr_play_msf(dev, data)); case CDROMPLAYTRKIND: return (sr_play_trkind(dev, data)); case CDROMREADTOCHDR: return (sr_read_tochdr(dev, data)); case CDROMREADTOCENTRY: return (sr_read_tocentry(dev, data)); case CDROMSTOP: return (sr_start_stop(dev, (caddr_t)0)); case CDROMSTART: return (sr_start_stop(dev, (caddr_t)1)); case FDKEJECT: /* for eject command */ case CDROMEJECT: return (sr_eject(dev)); case CDROMVOLCTRL: return (sr_volume_ctrl(dev, data)); case CDROMSUBCHNL: return (sr_read_subchannel(dev, data)); case CDROMREADMODE2: return (sr_read_mode2(dev, data)); case CDROMREADMODE1: return (sr_read_mode1(dev, data)); /* * Run a generic scsi command (CDROM) * user-scsi command */ case USCSICMD: return (srioctl_cmd(dev, data, 0)); /* * Handle unknown ioctls here. */ default: DPRINTF_IOCTL("srioctl: unknown ioctl %x\n", cmd); return (ENOTTY); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -