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

📄 scsi_disk.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
		/*		 * 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);}/* * * Name:		rzsize		-Disk partition size routine * * Abstract:		This routine returns the size of the specified *			disk partition in 512 byte blocks. The partition *			number is the 3 LSB if the minor device number. * * Inputs: * * dev			ULTRIX major/minor device number. * * Outputs:		None. * * Return Values: * * psize		Size of requested partition in 512 byte blocks. * -1			Invalid device. * * Side Effects: *			panic: invalid partition table * * */rzsize(dev){	register struct sz_softc *sc = sz_softc;	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 += 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);}/* * * Name:		rzcommand	-Disk command rountine * * Abstract:		This routine is called to execute non data transfer *			commands (test unit ready, read capacity, etc.). It *			sets up the command in cszbuf and calls rzstrategy *			to queue the command. * * Inputs: * * dev			ULTRIX major/minor device number. * com			SCSI command type (see scsivar.h). * count		Count argument to some commands. * retry		If 1, retry command if it fails. * * Outputs: *			B_ERROR can be set in bp->b_flags. * * Return Values:	None. * * Side Effects: *			iowait() on all commands (all have count >= 1). *			sleep() called. *			rzstrategy() called. * */rzcommand(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 int s;	int error;	register struct uba_device *ui = szdinfo[unit];	int cntlr = ui->ui_ctlr;	int targid = ui->ui_slave;	register struct sz_softc *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 = spl5();	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 = spl5();	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);}/* * Name:		rzstrategy	-Disk strategy routine * * Abstract:		This routine is called to queue a command for *			execution. The routine validates the command *			parameters then places it on the I/O queue *			of the specified unit. sz_start() is called *			if there is not activity. * * Inputs: * * bp			Buffer pointer of command to be queued. * * Outputs: *			Possible error messages (unit offline). * * Return Values:	None. * * bp->b_error: * ENXIO		Unit does not exist. * EROFS		Write to a write locked device (CDROM). * ENOSPC		End of media. * * Side Effects: *			panic: invalid partition table *			IPL raised to 15 to queue buffer. * */rzstrategy(bp)	register struct buf *bp;{	register struct uba_ctlr *um;	register struct buf *dp;	register int s;	int unit = minor(bp->b_dev) >> 3;	int targid;	int cntlr;	register struct sz_softc *sc;	struct uba_device *ui;	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];	/* TODO: 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 = ENXIO;		    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?????? */	s = spl5();	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);}/* * * Name:		rzread		-Disk physio read routine * * Abstract:		This routine is called to for RAW I/O reads. *			Calls physio() with appropriate arguments. * * Inputs: * * dev			ULTRIX major/minor device number. * uio			Pointer to user I/O (uio) structure. * * Outputs:		None. * * Return Values: *			Returns value returned by physio(). * * Side Effects: *			physio() and rzstrategy() called. *			minphys() limits maximum transfer size. * */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));}/* * * Name:		rzwrite		-Disk physio write routine * * Abstract:		This routine is called to for RAW I/O writes. *			Calls physio() with appropriate arguments. * * Inputs: * * dev			ULTRIX major/minor device number. * uio			Pointer to user I/O (uio) structure. * * Outputs:		None. * * Return Values: *			Returns value returned by physio(). * EROFS		Returned if write to CDROM attempted. * * Side Effects: *			physio() and rzstrategy() called. *			minphys() limits maximum transfer size. * */rzwrite(dev, uio)	register dev_t dev;	register struct uio *uio;{	register struct sz_softc *sc;	register struct uba_device *ui;	int unit = minor(dev) >> 3;	ui = szdinfo[unit];	sc = &sz_softc[ui->ui_ctlr];	/*	 * CDROM is read only!	 */	if (sc->sc_devtyp[ui->ui_slave] & SZ_CDROM)	    return(EROFS);	return (physio(rzstrategy, &rszbuf[unit], dev, B_WRITE, minphys, uio));}/* * * Name:		rzioctl		-Disk ioctl routine * * Abstract:		This routine is called via the ioctl system call *			to perform various non data transfer functions, *			such as get/set disk partition table. * * Inputs: * * dev			ULTRIX major/minor device number. * cmd			The ioctl to execute. * data			Pointer to data bassed with ioctl. * flag			Flag passed with ioctl. * * Outputs: *			Some ioctls pass data back to the caller. * * Return Values: * * EACCES		Must be superuser to access this ioctl. * EROFS		Can't set partition table on CDROM. * error		Value returned from call to ptcmp(). * ENXIO		Non supported ioctl. * 0			Success. * * Side Effects: *			Several other routines called. * */rzioctl(dev, cmd, data, flag)	dev_t dev;	register int cmd;	caddr_t data;	int flag;{	register struct uba_device *ui;	int unit = minor(dev) >> 3;	int cntlr;	int targid;	register struct sz_softc *sc;	register struct buf *bp = &cszbuf[unit];	struct devget *devget;	int i;	struct size *stp;	struct pt *pt = (struct pt *)data;	int error;	struct sz_rdcap_dt *rdp;	struct scsi_devtab *sdp;	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;	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;	/* TODO: 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.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -