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

📄 matcd.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		outb(port+CMD,*cp++);	/*must be sent within 10msec or*/	}				/*the drive will ignore the cmd*/	splx(level);	/*------------------------------------------------*/	return;}/*---------------------------------------------------------------------------	draincmd - Makes certain the bus is idle and throws away		any residual data from the drive if there is any.		Called as preface to most commands.		Added in Edit 5.		This was added because switching drive modes causes		the drive to emit buffers that were meant to be sent		to the D-to-A to be sent to the host.  See setmode.---------------------------------------------------------------------------*/void draincmd(int port,int cdrive,int ldrive){	int i,z;	i=inb(port+STATUS);	if ((i & (DTEN|STEN)) == (DTEN|STEN)) return;	printf("matcd%d: in draincmd: bus not idle %x - trying to fix\n",	       ldrive,inb(port+STATUS));	if ((i & (DTEN|STEN)) == STEN) {#ifdef DEBUGCMD		printf("matcd%d: Data present READING - ",ldrive);#endif /*DEBUGCMD*/		i=0;		outb(port+PHASE,1);	/*<16>Enable data read*/		while ((inb(port+STATUS) & (DTEN|STEN)) == STEN) {			inb(port+DATA);		/*<21>Ok for Creative*/			inb(port+ALTDATA);	/*<21>Ok for others*/			i++;		}		outb(port+PHASE,0);#ifdef DEBUGCMD		printf("%d bytes read\n",i);#endif /*DEBUGCMD*/	}#ifdef DEBUGCMD	printf("matcd%d: Now read status: ",ldrive);#endif /*DEBUGCMD*/	i=get_stat(port,ldrive);	/*Read status byte*/	z=inb(port+STATUS);		/*Read bus status*/#ifdef DEBUGCMD	printf("Data byte %x and status is now %x\n",i,z);#endif /*DEBUGCMD*/	if ((z & (DTEN|STEN)) != (DTEN|STEN)) {		printf("matcd%d: Bus not idle %x - resetting\n",		       cdrive,inb(port+STATUS));		doreset(port,cdrive);	}	return;}/*---------------------------------------------------------------------------	selectdrive - Swaps drive select bits	On Creative SB/SB16/stand-alone adapters, possibly to make them	hard to reverse engineer, the drive select signals are swapped.---------------------------------------------------------------------------*/void selectdrive(int port,int drive){	switch(drive) {	case 0:				/*0x00 -> 0x00*/		outb(port+SELECT,CRDRIVE0);		break;	case 1:				/*0x01 -> 0x02*/		outb(port+SELECT,CRDRIVE1);		break;	case 2:				/*0x02 -> 0x01*/		outb(port+SELECT,CRDRIVE2);		break;	case 3:				/*0x03 -> 0x03*/		outb(port+SELECT,CRDRIVE3);		break;	}	return;}/*---------------------------------------------------------------------------	matcd_pread - Read small blocks of control data from a drive---------------------------------------------------------------------------*/void matcd_pread(int port, int count, unsigned char * data){	int	i;	for (i=0; i<count; i++) {		*data++ = inb(port+CMD);	}	return;}/*---------------------------------------------------------------------------	matcd_setmode - Configures disc to run in the desired data mode	This routine assumes the drive is already idle.NOTE -	Undocumented action of hardware:  If you change (or reaffirm) data	modes with MODESELECT + BLOCKPARAM immediately after a command was	issued that aborted a DA play operation, the drive will unexpectedly	return 2532 bytes of data in a data phase on the first or second	subsequent command.	Original Symptom: drive will refuse to go idle after reading data	and status expected for a command.  State mechanics for this are	not fully understood.---------------------------------------------------------------------------*/static intmatcd_setmode(int ldrive, int mode){	struct	matcd_data *cd;	int retries;	int i,port,cdrive;	unsigned char cmd[MAXCMDSIZ];	cd = matcd_data + ldrive;	retries=3;	cdrive=ldrive&0x03;	port=cd->iobase;	if (cd->drivemode==mode) {		return(0);		/*Drive already set*/	}/*	The drive is not in the right mode, so we need to set it.*/	zero_cmd(cmd);	cmd[0]=MODESELECT;		/*Set drive transfer modes*//*	cmd[1]=BLOCKPARAM;		  BLOCKPARAM==0*/	cmd[2]=mode;	switch(mode) {	case MODE_DATA:		cmd[3]=0x08;		/*2048 bytes*/		break;	case MODE_USER:		cmd[3]=0x09;		/*2352 bytes*/		cmd[4]=0x30;		break;	case MODE_DA:		cmd[3]=0x09;		/*2352 bytes*/		cmd[4]=0x30;		break;	}	i=0;	while(retries-- > 0) {		i=matcd_fastcmd(port,ldrive,cdrive,cmd);		get_stat(port,ldrive);	/*Read and toss status byte*/		if (i==0) {			cd->drivemode=mode;	/*Set new mode*/			return(i);		}		get_error(port,ldrive,cdrive);	}	cd->drivemode=MODE_UNKNOWN;	/*We failed*/	return(i);}/*---------------------------------------------------------------------------	matcd_volinfo - Read information from disc Table of Contents---------------------------------------------------------------------------*/static	int	matcd_volinfo(int ldrive){	struct	matcd_data *cd;	int	port,i;	int	z,cdrive;	int	retry;	unsigned char cmd[MAXCMDSIZ];	unsigned char data[12];	retry=10;			/*<16>This may take a long time*/	cd = &matcd_data[ldrive];	cdrive=ldrive&0x03;	port=cd->iobase;#ifdef DEBUGOPEN	printf("matcd%d: In volinfo, port %x\n",ldrive,port);#endif /*DEBUGOPEN*/	while(retry>0) {		zero_cmd(cmd);		cmd[0]=READDINFO;	/*Read Disc Info*/		matcd_slowcmd(port,ldrive,cdrive,cmd);		i=waitforit(10*TICKRES,DTEN,port,"matvinf");		if (i) {		/*THIS SHOULD NOT HAPPEN*/			z=get_stat(port,ldrive);/*Read status byte*/			printf("matcd%d: command failed, status %x\n",			       ldrive,z);			return(-1);		}		matcd_pread(port, 6, data);	/*Read data returned*/		z=get_stat(port,ldrive);/*Read status byte*/#ifdef DEBUGOPEN		printf("matcd%d: Data got was %x %x %x %x %x %x   ",ldrive,		       data[0],data[1],data[2], data[3],data[4],data[5]);		printf("status byte %x\n",z);#endif	/*DEBUGOPEN*/		if ((z & MATCD_ST_ERROR)==0)			break;		/*No Error*//*	If media change or other error, you have to read error data or	the drive will reject subsequent commands.*/		if (chk_error(get_error(port, ldrive, cdrive))==ERR_FATAL) {#ifdef DEBUGOPEN			printf("matcd%d: command failed, status %x\n",			       ldrive,z);#endif /*DEBUGOPEN*/			return(-1);		}		tsleep((caddr_t)&nextcontroller, PRIBIO, "matvi2", hz);		if ((--retry)==0) return(-1);#ifdef DEBUGOPEN		printf("matcd%d: Retrying",ldrive);#endif /*DEBUGOPEN*/	}#ifdef DEBUGOPEN	printf("matcd%d: Status port %x  \n",ldrive,inb(port+STATUS));#endif /*DEBUGOPEN*/	cd->volinfo.type=data[0];	cd->volinfo.trk_high=data[2];	cd->volinfo.trk_low=data[1];	cd->volinfo.vol_msf[0]=data[3];	cd->volinfo.vol_msf[1]=data[4];	cd->volinfo.vol_msf[2]=data[5];	if (cd->volinfo.trk_low + cd->volinfo.trk_high) {		cd->flags |= MATCDLABEL;		return(0);	}	return(-1);}/*---------------------------------------------------------------------------	blk_to_msf - Convert block numbers into CD disk block ids---------------------------------------------------------------------------*/static void blk_to_msf(int blk, unsigned char *msf){	blk=blk+150;			/*2 seconds skip required to					  reach ISO data*/	msf[0]=blk/4500;	blk=blk%4500;	msf[1]=blk/75;	msf[2]=blk%75;	return;}/*---------------------------------------------------------------------------	msf_to_blk - Convert CD disk block ids into block numbers---------------------------------------------------------------------------*/static int msf_to_blk(unsigned char * cd){	return(((cd[0]*60)		/*Convert MSF to*/	       +cd[1])*75		/*Blocks minus 2*/	       +cd[2]-150);		/*seconds*/}/*---------------------------------------------------------------------------	matcd_blockread - Performs actual background disc I/O operations	This routine is handed the block number to read, issues the	command to the drive, waits for it to complete, reads the	data or error, retries if needed, and returns the results	to the host.---------------------------------------------------------------------------*/static void matcd_blockread(int state){	struct	matcd_mbx *mbx;	int	ldrive,cdrive;	int	port, controller;	short	iftype;	struct	buf *bp;	struct	matcd_data *cd;	int	i;	struct	matcd_read2 rbuf;	int	blknum;	caddr_t addr;	int	status;	int	errtyp;	int	phase;	unsigned char cmd[MAXCMDSIZ];	mbx = &matcd_data[state & 0x0f].mbx;	ldrive=mbx->ldrive;		/*ldrive is logical drive #*/	cdrive=ldrive & 0x03;		/*cdrive is drive # on a controller*/	port=mbx->port;			/*port is base port for i/f*/	iftype=mbx->iftype;	bp= mbx->bp;	cd=&matcd_data[ldrive];	controller = cd->mbx.controller;#ifdef DEBUGIO	printf("matcd%d: Show state %x cdrive %d partition %d\n",	       ldrive,state,cdrive,mbx->partition);#endif /*DEBUGIO*/loop:#ifdef DEBUGIO	printf("matcd%d: Top  dp %x\n",ldrive,(unsigned int)dp);#endif /*DEBUGIO*/	switch (state & 0xf0) {	case	MATCD_READ_1:#ifdef DEBUGIO		printf("matcd%d: State 1 cd->flags %x\n",ldrive,cd->flags);#endif /*DEBUGIO*/		/* to check for raw/cooked mode */		if (cd->partflags[mbx->partition] & MATCDREADRAW) {			mbx->sz = MATCDRBLK;			i=matcd_setmode(ldrive, MODE_DA);#ifdef DEBUGIO			printf("matcd%d: Set MODE_DA result %d\n",ldrive,i);#endif /*DEBUGIO*/		} else {			mbx->sz = cd->blksize;			i=matcd_setmode(ldrive, MODE_DATA);#ifdef DEBUGIO			printf("matcd%d: Set MODE_DATA result %d\n",ldrive,i);#endif /*DEBUGIO*/		}		/*for first block*/#ifdef DEBUGIO		printf("matcd%d: A mbx %x bp %x b_bcount %x sz %x\n",		       ldrive,(unsigned int)mbx,(unsigned int)bp,		       (unsigned int)bp->b_bcount,mbx->sz);#endif /*DEBUGIO*/		mbx->nblk = (bp->b_bcount + (mbx->sz-1)) / mbx->sz;		mbx->skip=0;nextblock:#ifdef DEBUGIO		printf("matcd%d: at Nextblock b_blkno %d\n",		       ldrive,(unsigned int)bp->b_blkno);#endif /*DEBUGIO*/		blknum=(bp->b_blkno / (mbx->sz/DEV_BSIZE))		       + mbx->p_offset + mbx->skip/mbx->sz;		blk_to_msf(blknum,rbuf.start_msf);		zero_cmd(cmd);		cmd[0]=READ;		/*Get drive ID*/		cmd[1]=rbuf.start_msf[0];		cmd[2]=rbuf.start_msf[1];		cmd[3]=rbuf.start_msf[2];		cmd[6]=1;		/*Xfer only one block*/		matcd_slowcmd(port,ldrive,cdrive,cmd);/*	Now that we have issued the command, check immediately to	see if data is ready.   The drive has read-ahead caching, so	it is possible the data is already in the drive buffer.	If the data is not ready, schedule a wakeup and later on this	code will run again to see if the data is ready then.*/	case MATCD_READ_2:		state=MATCD_READ_2+ldrive;		phase = (inb(port+STATUS)) & (DTEN|STEN);#ifdef DEBUGIO		printf("matcd%d: In state 2 status %x  ",ldrive,phase);#endif /*DEBUGIO*/		switch(phase) {		case (DTEN|STEN):	/*DTEN==H  STEN==H*/#ifdef DEBUGIO			printf("matcd%d: Sleeping\n",ldrive);#endif /*DEBUGIO*/			timeout((timeout_func_t)matcd_blockread,		

⌨️ 快捷键说明

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