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

📄 tmscp.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
		 * No more requests for this drive, remove		 * from controller queue and look at next drive.		 * We know we're at the head of the controller queue.		 */		dp->b_active = 0;		um->um_tab.b_actf = dp->b_forw;		continue;		/* Need to check for loop */		}	um->um_tab.b_active++;	tmscpaddr = (struct tmscpdevice *)um->um_addr;	ui = tmsdinfo[(TMSUNIT(bp->b_dev))];	tms = &tms_info[ui->ui_unit];	if ((tmscpaddr->tmscpsa&TMSCP_ERR) || sc->sc_state != S_RUN)		{		tprintf(tms->tms_tpr,		    "tms%d: hard error bn%d\n",		    minor(bp->b_dev)&03, bp->b_blkno);		log(TMS_PRI, "tmscp%d: sa 0%o, state %d\n",um->um_ctlr,				tmscpaddr->tmscpsa&0xffff, sc->sc_state);		(void)tmscpinit(um->um_ctlr);		/* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE TMSCPRESET */		break;		}	/*	 * Default is that last command was NOT a write command;	 * if a write command is done it will be detected in tmscprsp.	 */	tms->tms_lastiow = 0;	if (ui->ui_flags == 0)		{        /* not online */		if ((mp = tmscpgetcp(um)) == NULL)			break;		mp->mscp_opcode = M_OP_ONLIN;		mp->mscp_unit = ui->ui_slave;		dp->b_active = 2;		um->um_tab.b_actf = dp->b_forw; /* remove from controller q */		*((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT;		if (tmscpaddr->tmscpsa&TMSCP_ERR)			printf("tmscp%d fatal error (0%o)\n",um->um_ctlr,					tmscpaddr->tmscpsa&0xffff);		i = tmscpaddr->tmscpip;		continue;		}	switch (cpu) {	case VAX_8600:	case VAX_780:		i = UBA_NEEDBDP|UBA_CANTWAIT;		break;	case VAX_750:		i = um->um_ubinfo|UBA_HAVEBDP|UBA_CANTWAIT;		break;	case VAX_730:	case VAX_630:		i = UBA_CANTWAIT;		break;	}   /* end switch (cpu) */	/*	 * If command is an ioctl command then set the ioctl flag for later use.	 * If not (i.e. it is a read or write) then attempt	 * to set up a buffer pointer.	 */	ioctl = 0;	if (bp == &ctmscpbuf[um->um_ctlr])		ioctl = 1;	else		if ((i = ubasetup(um->um_ubanum, bp, i)) == 0)			{			if(dp->b_qsize != 0)				break; /* When a command completes and */				     /* frees a bdp tmscpstart will be called */			if ((mp = tmscpgetcp(um)) == NULL)				break;#			ifdef DEBUG			printd("tmscpstart: GTUNT %d ubasetup = %d\n",ui->ui_unit, i);			if(tmscpdebug)DELAY(10000);#			endif			mp->mscp_opcode = M_OP_GTUNT;			mp->mscp_unit = ui->ui_slave;			*((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT;			if (tmscpaddr->tmscpsa&TMSCP_ERR)				printf("tmscp%d: fatal error (0%o)\n",um->um_ctlr,					    tmscpaddr->tmscpsa&0xffff);			i = tmscpaddr->tmscpip;	/* initiate polling */			break;			}#	if defined(VAX750)	if (cpu == VAX_750)		tempi = i & 0xfffffff;			/* mask off bdp */	else#	endif		tempi = i;	if ((mp = tmscpgetcp(um)) == NULL)		{		if (!ioctl)		/* only need to release if NOT ioctl */			ubarelse(um->um_ubanum,&tempi);		break;		}	mp->mscp_cmdref = (long)bp;		/* pointer to get back */	mp->mscp_unit = ui->ui_slave;	/*	 * If its an ioctl-type command then set up the appropriate	 * tmscp command;  by doing a switch on the "b_resid" field where	 * the command mneumonic is stored.	 */	if (ioctl)		{#		ifdef DEBUG		printd("tmscpstart: doing ioctl cmd %d\n", bp->b_resid);#		endif		/*		 * The reccnt and tmkcnt fields are set to zero by the getcp		 * routine (as bytecnt and buffer fields).  Thus reccnt and		 * tmkcnt are only modified here if they need to be set to		 * a non-zero value.		 */		switch ((int)bp->b_resid) {		case TMS_WRITM:			mp->mscp_opcode = M_OP_WRITM;			break;		case TMS_FSF:			mp->mscp_opcode = M_OP_REPOS;			mp->mscp_tmkcnt = bp->b_bcount;			break;		case TMS_BSF:			mp->mscp_opcode = M_OP_REPOS;			mp->mscp_modifier = M_MD_REVRS;			mp->mscp_tmkcnt = bp->b_bcount;			break;		case TMS_FSR:			mp->mscp_opcode = M_OP_REPOS;			mp->mscp_modifier = M_MD_OBJCT;			mp->mscp_reccnt = bp->b_bcount;			break;		case TMS_BSR:			mp->mscp_opcode = M_OP_REPOS;			mp->mscp_modifier = M_MD_REVRS | M_MD_OBJCT;			mp->mscp_reccnt = bp->b_bcount;			break;		/*		 * Clear serious exception is done for Rewind & Available cmds		 */		case TMS_REW:			mp->mscp_opcode = M_OP_REPOS;			mp->mscp_modifier = M_MD_REWND | M_MD_CLSEX;			if (bp->b_bcount == 0)				mp->mscp_modifier |= M_MD_IMMED;			tms->tms_serex = 0;			break;		case TMS_OFFL:			mp->mscp_opcode = M_OP_AVAIL;			mp->mscp_modifier = M_MD_UNLOD | M_MD_CLSEX;			tms->tms_serex = 0;			break;		case TMS_SENSE:			mp->mscp_opcode = M_OP_GTUNT;			break;		case TMS_CACHE:			mp->mscp_opcode = M_OP_STUNT;			tms->tms_unitflgs |= M_UF_WBKNV;			mp->mscp_unitflgs = tms->tms_unitflgs;			mp->mscp_format = tms->tms_format;			/* default device dependant parameters */			mp->mscp_mediaid = 0;			break;		case TMS_NOCACHE:			mp->mscp_opcode = M_OP_STUNT;			tms->tms_unitflgs &= ~(M_UF_WBKNV);			mp->mscp_unitflgs = tms->tms_unitflgs;			mp->mscp_format = tms->tms_format;			/* default device dependant parameters */			mp->mscp_mediaid = 0;			break;		case TMS_CSE:			/*			 * This is a no-op command. It performs a 			 * clear serious exception only.  (Done on a			 * non-rewinding close after a serious exception.)			 */			mp->mscp_opcode = M_OP_REPOS;			mp->mscp_modifier = M_MD_CLSEX;			tms->tms_serex = 0;			tms->tms_clserex = 1;			break;		case TMS_LOWDENSITY:			/*			 * Set the unit to low density			 */			mp->mscp_opcode = M_OP_STUNT;			mp->mscp_unitflgs = tms->tms_unitflgs;			mp->mscp_mediaid = 0;	/* default device dependant parameters */			if ((tms->tms_fmtmenu & M_TF_800) != 0)				mp->mscp_format = M_TF_800;			else				mp->mscp_format = M_TF_PE & tms->tms_fmtmenu;			tms->tms_format = mp->mscp_format;			break;		case TMS_HIDENSITY:			/*			 * Set the unit to high density (format == 0)			 */			mp->mscp_opcode = M_OP_STUNT;			mp->mscp_unitflgs = tms->tms_unitflgs;			mp->mscp_mediaid = 0;	/* default device dependant parameters */			mp->mscp_format = 0;			tms->tms_format = 0;			break;		default:			printf("Bad ioctl on tms unit %d\n", ui->ui_unit);			/* Need a no-op. Reposition no amount */			mp->mscp_opcode = M_OP_REPOS;			break;		}   /* end switch (bp->b_resid) */		}	else    /* Its a read/write command (not an ioctl) */		{		mp->mscp_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE;		mp->mscp_bytecnt = bp->b_bcount;		mp->mscp_buffer = UBAI_ADDR(i) | (UBAI_BDP(i) << 24);		bp->b_ubinfo = tempi;			/* save mapping info */		}	if (tms->tms_serex == 2)			/* if tape mark read */		{		mp->mscp_modifier |= M_MD_CLSEX;	/*  clear serious exc */		tms->tms_serex = 0;		}	*((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT;#	ifdef DEBUG	printd("tmscpstart: opcode 0%o mod %o unit %d cnt %d\n",mp->mscp_opcode,mp->mscp_modifier,mp->mscp_unit,mp->mscp_bytecnt);	if(tmscpdebug)DELAY(100000);#	endif	i = tmscpaddr->tmscpip;              /* initiate polling */	dp->b_qsize++;	/*	 * Move drive to the end of the controller queue	 */	if (dp->b_forw != NULL)		{		um->um_tab.b_actf = dp->b_forw;		um->um_tab.b_actl->b_forw = dp;		um->um_tab.b_actl = dp;		dp->b_forw = NULL;		}	/*	 * Move buffer to I/O wait queue	 */	dp->b_actf = bp->av_forw;	dp = &tmscpwtab[um->um_ctlr];	bp->av_forw = dp;	bp->av_back = dp->av_back;	dp->av_back->av_forw = bp;	dp->av_back = bp;	if (tmscpaddr->tmscpsa&TMSCP_ERR)		{		printf("tmscp%d: fatal error (0%o)\n", um->um_ctlr, tmscpaddr->tmscpsa&0xffff);		(void)tmscpinit(um->um_ctlr);		break;		}    }   /* end for */    /*     * Check for response ring transitions lost in the     * Race condition     */    for (i = sc->sc_lastrsp;; i++)	    {	    i %= NRSP;	    if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN)		    break;	    tmscprsp(um, tm, sc, i);	    tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN;	    }    sc->sc_lastrsp = i;}/* * Process a response packet */tmscprsp(um, tm, sc, i)	register struct uba_ctlr *um;	register struct tmscp *tm;	register struct tmscp_softc *sc;	int i;{	register struct mscp *mp;	register struct tms_info *tms;	struct uba_device *ui;	struct buf *dp, *bp;	int st;	mp = &tm->tmscp_rsp[i];	mp->mscp_header.tmscp_msglen = mscp_msglen;	sc->sc_credits += mp->mscp_header.tmscp_credits & 0xf;  /* low 4 bits */	if ((mp->mscp_header.tmscp_credits & 0xf0) > 0x10)	/* Check */		return;#	ifdef DEBUG	printd("tmscprsp, opcode 0%o status 0%o\n",mp->mscp_opcode,mp->mscp_status&M_ST_MASK);#	endif		/*	 * If it's an error log message (datagram),	 * pass it on for more extensive processing.	 */	if ((mp->mscp_header.tmscp_credits & 0xf0) == 0x10)		{	/* check */		tmserror(um, (struct mslg *)mp);		return;		}	st = mp->mscp_status&M_ST_MASK;	/*	 * The controller interrupts as drive 0.	 * This means that you must check for controller interrupts	 * before you check to see if there is a drive 0.	 */	if((M_OP_STCON|M_OP_END) == mp->mscp_opcode)		{		if (st == M_ST_SUCC)			{#		  	ifdef DEBUG			printd("ctlr has %d credits\n", mp->mscp_header.tmscp_credits & 0xf);			printd("ctlr timeout = %d\n", mp->mscp_cnttmo);#			endif			sc->sc_state = S_RUN;			}		else			sc->sc_state = S_IDLE;		um->um_tab.b_active = 0;		wakeup((caddr_t)um);		return;		}	if (mp->mscp_unit >= NTMS)		return;	if ((ui = tmscpip[um->um_ctlr][mp->mscp_unit]) == 0)		return;	tms = &tms_info[ui->ui_unit];	/*	 * Save endcode, endflags, and status for mtioctl get unit status.	 * NOTE: Don't do this on Clear serious exception (reposition no-op);	 *    which is done on close since this would	 *    overwrite the real status we want.	 */	if (tms->tms_clserex != 1)		{		tms->tms_endcode = mp->mscp_opcode;		tms->tms_flags = mp->mscp_flags;		tms->tms_status = st;		}	else tms->tms_clserex = 0;	switch (mp->mscp_opcode) {	case M_OP_ONLIN|M_OP_END:		tms->tms_type = mp->mscp_mediaid;		dp = &tmsutab[ui->ui_unit];		if (st == M_ST_SUCC)			{			/*			 * Link the drive onto the controller queue			 */			dp->b_forw = NULL;			if (um->um_tab.b_actf == NULL)				um->um_tab.b_actf = dp;			else				um->um_tab.b_actl->b_forw = dp;			um->um_tab.b_actl = dp;			ui->ui_flags = 1;       /* mark it online */			tms->tms_dsize=(daddr_t)mp->mscp_maxwrt;#			ifdef DEBUG			printd("tmscprsp: unit %d online\n", mp->mscp_unit);#			endif						/* 			 * This define decodes the Media type identifier			 */#	        	define F_to_C(x,i)     ( ((x)->mscp_mediaid) >> (i*5+7) & 0x1f ? ( ( (((x)->mscp_mediaid) >>( i*5 + 7)) & 0x1f) + 'A' - 1): ' ')#			ifdef DEBUG			printd("tmscprsp: unit %d online %x %c%c %c%c%c%d\n"				,mp->mscp_unit, mp->mscp_mediaid ,F_to_C(mp,4)				,F_to_C(mp,3), F_to_C(mp,2)				,F_to_C(mp,1), F_to_C(mp,0), mp->mscp_mediaid & 0x7f);#			endif							dp->b_active = 1;			}	/* end if st == M_ST_SUCC */		else 			{			if (bp = dp->b_actf)				tprintf(tms->tms_tpr,				    "tms%d: hard error bn%d: OFFLINE\n",				    minor(bp->b_dev)&03, bp->b_blkno);			else				tprintf(tms->tms_tpr,				    "tms%d: hard error: OFFLINE\n",				    ui->ui_unit);			while (bp = dp->b_actf)				{				dp->b_actf = bp->av_forw;				bp->b_flags |= B_ERROR;				iodone(bp);				}			}		if(mp->mscp_cmdref!=NULL)			/* Seems to get lost sometimes in uda */			wakeup((caddr_t)mp->mscp_cmdref);		break;	/*	 * The AVAILABLE ATTENTION message occurs when the	 * unit becomes available after loading,	 * marking the unit offline (ui_flags = 0) will force an	 * online command prior to using the unit.	 */	case M_OP_AVATN:		ui->ui_flags = 0;		tms->tms_type = mp->mscp_mediaid;		break;	case M_OP_END:		/*		 * An endcode without an opcode (0200) is an invalid command.		 * The mscp specification states that this would be a protocol		 * type error, such as illegal opcodes. The mscp spec. also		 * states that parameter error type of invalid commands should		 * return the normal end message for the command. This does not appear		 * to be the case. An invalid logical block number returned an endcode		 * of 0200 instead of the 0241 (read) that was expected.		 */					printf("tmscp%d: invalid cmd, endcode = %o, status=%o\n",			um->um_ctlr, mp->mscp_opcode, st);		bp = (struct buf *)mp->mscp_cmdref;		/*		 * Unlink buffer from I/O wait queue.		 * And signal iodone, so the higher level command can exit!		 *		 */		bp->av_back->av_forw = bp->av_forw;		bp->av_forw->av_back = bp->av_back;		dp = &tmsutab[ui->ui_unit];		dp->b_qsize--;		iodone(bp);		break;	case M_OP_WRITE|M_OP_END:		/* mark the last io op as a write */		tms->tms_lastiow = 1;	case M_OP_READ|M_OP_END:	case M_OP_WRITM|M_OP_END:	case M_OP_REPOS|M_OP_END:	case M_OP_STUNT|M_OP_END:	/*	 * The AVAILABLE message occurs when the mt ioctl "rewoffl" is	 * issued.  For the ioctl, "rewoffl", a tmscp AVAILABLE command is	 * done with the UNLOAD modifier.  This performs a rewind, followed	 * by marking the unit offline.  So mark the unit offline	 * software wise as well (ui_flags = 0 and 	 * tms->tms_openf = 0).	 */	case M_OP_AVAIL|M_OP_END:#		ifdef DEBUG		printd("tmscprsp: position = %d\n", mp->mscp_lbn);#		endif		bp = (struct buf *)mp->mscp_cmdref;		/*		 * Only need to release buffer if the command was read or write.		 * No ubasetup was done in "tmscpstart" if it was an ioctl cmd.		 */		if (mp->mscp_opcode == (M_OP_READ|M_OP_END) || 		    mp->mscp_opcode == (M_OP_WRITE|M_OP_END))			ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo);		/*		 * Unlink buffer from I/O wait queue.		 */		bp->av_back->av_forw = bp->av_forw;		bp->av_forw->av_back = bp->av_back;#		if defined(VAX750)		if (cpu == VAX_750) { 		    if ((tmscpwtab[um->um_ctlr].av_forw == &tmscpwtab[um->um_ctlr]) &&					(um->um_ubinfo != 0)) {			ubarelse(um->um_ubanum, &um->um_ubinfo);		    }		    else {			if (mp->mscp_opcode == (M_OP_READ|M_OP_END) ||		    	    mp->mscp_opcode == (M_OP_WRITE|M_OP_END))				UBAPURGE(uba_hd[um->um_ubanum].uh_uba,(um->um_ubinfo >>28) & 0x0f);		    }		}#		endif		dp = &tmsutab[ui->ui_unit];		dp->b_qsize--;		if (st == M_ST_OFFLN || st == M_ST_AVLBL)			{			ui->ui_flags = 0;       /* mark unit offline */			tms->tms_openf = 0;			tms->tms_type = mp->mscp_mediaid;			/*			 * Link the buffer onto the front of the drive queue			 */			if ((bp->av_forw = dp->b_actf) == 0)				dp->b_actl = bp;			dp->b_actf = bp;			/*			 * Link the drive onto the controller queue			 */			if (dp->b_active == 0)				{				dp->b_forw = NULL;				if (um->um_tab.b_actf == NULL)					um->um_tab.b_actf = dp;				else					um->um_tab.b_actl->b_forw = dp;				um->um_tab.b_actl = dp;				dp->b_active = 1;				}#			if defined(VAX750)			if (cpu == VAX_750 && um->um_ubinfo == 0)				um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t)0, 0, UBA_NEEDBDP);#			endif			return;			}		if (st != M_ST_SUCC)			{			if (mp->mscp_flags & M_EF_SEREX)				tms->tms_serex = 1;			if (st != M_ST_TAPEM)				{				tprintf(tms->tms_tpr,				    "tms%d: hard error bn%d\n",				    minor(bp->b_dev)&03, bp->b_blkno);				errinfo(st);		/* produces more info */#				ifdef DEBUG				printd("tmscprsp: error; status sub-code = 0%o, flags = 0%o\n",					(mp->mscp_status & 177740)>>5, mp->mscp_flags);#				endif				bp->b_flags |= B_ERROR;				}			else				/* Hit a tape mark - Set serex flag to				 * a special value so we can clear the

⌨️ 快捷键说明

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