⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sf.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	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 + -