bsdi_ioctl.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 772 行 · 第 1/2 页

C
772
字号
	switch	(s->type)		{		case	DVD_STRUCT_PHYSICAL:			return dvd_read_physical(fd, s);		case	DVD_STRUCT_COPYRIGHT:			return dvd_read_copyright(fd, s);		case	DVD_STRUCT_DISCKEY:			return dvd_read_disckey(fd, s);		case	DVD_STRUCT_BCA:			return dvd_read_bca(fd, s);		case	DVD_STRUCT_MANUFACT:			return dvd_read_manufact(fd, s);		default:			return EINVAL;		}	}static	u_char scsi_cdblen[8] = {6, 10, 10, 12, 12, 12, 10, 10};static int scsi_cmd(int fd, cgc_t *cgc)	{	int	i, scsistatus, cdblen;	unsigned char	*cp;	struct	scsi_user_cdb suc;    /* safety checks */	if	(cgc->rw != SUC_READ && cgc->rw != SUC_WRITE)		return(EINVAL);	suc.suc_flags = cgc->rw;	cdblen = scsi_cdblen[(cgc->cdb[0] >> 5) & 7];	suc.suc_cdblen = cdblen;	bcopy(cgc->cdb, suc.suc_cdb, cdblen);	suc.suc_data = cgc->buf;	suc.suc_datalen = cgc->buflen;	suc.suc_timeout = cgc->timeout;	if	(ioctl(fd, SCSIRAWCDB, &suc) == -1)		return(errno);	scsistatus = suc.suc_sus.sus_status;/* * If the device returns a scsi sense error and debugging is enabled print * some hopefully useful information on stderr.*/	if	(scsistatus && debug)		{		cp = suc.suc_sus.sus_sense;		fprintf(stderr,"scsistatus = %x cdb =",			scsistatus);		for	(i = 0; i < cdblen; i++)			fprintf(stderr, " %x", cgc->cdb[i]);		fprintf(stderr, "\nsense =");		for	(i = 0; i < 16; i++)			fprintf(stderr, " %x", cp[i]);		fprintf(stderr, "\n");		}	if	(cgc->sus)		bcopy(&suc.suc_sus, cgc->sus, sizeof (struct scsi_user_sense));	if	(scsistatus)		return(EIO);	/* generic i/o error for unsuccessful status */	return(0);	}/* * The entry point for the DVDioctls for BSD/OS.*/static int dvd_ioctl(int fd, u_long cmd, void *arg)	{	int	ret;	switch	(cmd)		{		case	DVD_READ_STRUCT:			ret = dvd_read_struct(fd, (dvd_struct *)arg);			if	(ret)				errno = ret;			return(ret ? -1 : 0);		case	DVD_AUTH:			ret = dvd_do_auth(fd, (dvd_authinfo *)arg);			if	(ret)				errno = ret;			return(ret ? -1 : 0);		default:			errno = EINVAL;			return(-1);		}	}/* * The entry point for the CDROMioctls for BSD/OS*/static int cdrom_read_block(int, cgc_t *, int, int, int, int);static int cdrom_read_cd(int, cgc_t *, int, int, int );	int cdrom_blocksize(int, int );static inlineint msf_to_lba(char m, char s, char f){	return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;}cdrom_ioctl(int fd, u_long cmd, void *arg)	{	int	ret;	cgc_t	cgc;	switch	(cmd)		{		case	CDROMREADRAW:		case	CDROMREADMODE1:		case	CDROMREADMODE2:			{			struct cdrom_msf *msf;			int blocksize = 0, format = 0, lba;					switch	(cmd)				{				case	CDROMREADRAW:					blocksize = CD_FRAMESIZE_RAW;					break;				case	CDROMREADMODE1:					blocksize = CD_FRAMESIZE;					format = 2;					break;				case	CDROMREADMODE2:					blocksize = CD_FRAMESIZE_RAW0;					break;				}			msf = (struct cdrom_msf *)arg;			lba = msf_to_lba(msf->cdmsf_min0,msf->cdmsf_sec0,				msf->cdmsf_frame0);			ret = EINVAL;			if	(lba < 0)				break;			cgc_init(&cgc, arg, blocksize, SUC_READ);			ret = cdrom_read_block(fd, &cgc, lba, 1, format,							blocksize);			if	(ret)				{/* * SCSI-II devices are not required to support CMD_READ_CD (which specifies * the blocksize to read) so try switching the block size with a mode select, * doing the normal read sector command and then changing the sector size back * to 2048. * * If the program dies before changing the blocksize back sdopen() * in the kernel will fail opens with a message that looks something like: * * "sr1: blksize 2336 not multiple of 512: cannot use" * * At that point the drive has to be power cycled (or reset in some other way).*/				if	(ret = cdrom_blocksize(fd, blocksize))					break;				ret = cdrom_read_cd(fd, &cgc, lba, blocksize, 1);				ret |= cdrom_blocksize(fd, 2048);				}			break;			}		case	CDROMREADTOCHDR:			{			struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;			u_char buffer[12];						cgc_init(&cgc, buffer, sizeof (buffer), SUC_READ);			cgc.cdb[0] = CMD_READ_TOC_PMA_ATIP;			cgc.cdb[1] = 0x2;	/* MSF */			cgc.cdb[8] = 12;	/* LSB of length */			ret = scsi_cmd(fd, &cgc);			if	(!ret)				{				tochdr->cdth_trk0 = buffer[2];				tochdr->cdth_trk1 = buffer[3];				}			break;			}		case	CDROMREADTOCENTRY:			{			struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg;			u_char	buffer[12];			cgc_init(&cgc, buffer, sizeof (buffer), SUC_READ);			cgc.cdb[0] = CMD_READ_TOC_PMA_ATIP;			cgc.cdb[1] = (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;			cgc.cdb[6] = tocentry->cdte_track;			cgc.cdb[8] = 12;		/* LSB of length */			ret = scsi_cmd(fd, &cgc);			if	(ret)				break;			tocentry->cdte_ctrl = buffer[5] & 0xf;			tocentry->cdte_adr = buffer[5] >> 4;			tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0;			if	(tocentry->cdte_format == CDROM_MSF)				{				tocentry->cdte_addr.msf.minute = buffer[9];				tocentry->cdte_addr.msf.second = buffer[10];				tocentry->cdte_addr.msf.frame = buffer[11];				}			else				tocentry->cdte_addr.lba = (((((buffer[8] << 8)						+ buffer[9]) << 8)						+ buffer[10]) << 8)						+ buffer[11];			break;			}		case	CDROMEJECT:		/* NO-OP for now */			ret = cdrom_tray_move(fd, 1);			break;		case	CDROMCLOSETRAY:			ret = cdrom_tray_move(fd, 0);			break;/* * This sucks but emulates the expected behaviour.  Instead of the return * value being the actual status a success/fail indicator should have been * returned and the 3rd arg to the ioctl should have been an 'int *' to update * with the actual status.   Both the drive and disc status ioctl calls are * similarily braindamaged.*/		case	CDROM_DRIVE_STATUS:			return(CDS_NO_INFO);	/* XXX */		case	CDROM_DISC_STATUS:			{			tracktype tracks;			int	cnt;			cdrom_count_tracks(fd, &tracks);			if	(tracks.error)				return(tracks.error);			if	(tracks.audio > 0)				{				cnt = tracks.data + tracks.cdi + tracks.xa;				if	(cnt == 0)					return(CDS_AUDIO);				else					return(CDS_MIXED);				}			if	(tracks.cdi)				return(CDS_XA_2_2);			if	(tracks.xa)				return(CDS_XA_2_1);			if	(tracks.data)				return(CDS_DATA_1);			return(CDS_NO_INFO);			}		}	errno = ret;	return(ret ? -1 : 0);	}static int cdrom_read_cd(int fd, cgc_t *cgc, int lba, int blocksize, int nblocks)	{	memset(&cgc->cdb, 0, sizeof(cgc->cdb));	cgc->cdb[0] = CMD_READ_10;	cgc->cdb[2] = (lba >> 24) & 0xff;	cgc->cdb[3] = (lba >> 16) & 0xff;	cgc->cdb[4] = (lba >>  8) & 0xff;	cgc->cdb[5] = lba & 0xff;	cgc->cdb[6] = (nblocks >> 16) & 0xff;	cgc->cdb[7] = (nblocks >>  8) & 0xff;	cgc->cdb[8] = nblocks & 0xff;	cgc->buflen = blocksize * nblocks;	return(scsi_cmd(fd, cgc));	}static int cdrom_read_block(int fd, cgc_t *cgc,			    int lba, int nblocks, int format, int blksize)	{	memset(&cgc->cdb, 0, sizeof(cgc->cdb));	cgc->cdb[0] = CMD_READ_CD;	/* expected sector size - cdda,mode1,etc. */	cgc->cdb[1] = format << 2;	/* starting address */	cgc->cdb[2] = (lba >> 24) & 0xff;	cgc->cdb[3] = (lba >> 16) & 0xff;	cgc->cdb[4] = (lba >>  8) & 0xff;	cgc->cdb[5] = lba & 0xff;	/* number of blocks */	cgc->cdb[6] = (nblocks >> 16) & 0xff;	cgc->cdb[7] = (nblocks >>  8) & 0xff;	cgc->cdb[8] = nblocks & 0xff;	cgc->buflen = blksize * nblocks;		/* set the header info returned */	switch	(blksize)		{		case	CD_FRAMESIZE_RAW0:			cgc->cdb[9] = 0x58;			break;		case	CD_FRAMESIZE_RAW1:			cgc->cdb[9] = 0x78;			break;		case	CD_FRAMESIZE_RAW:			cgc->cdb[9] = 0xf8;			break;		default:			cgc->cdb[9] = 0x10;		}	return(scsi_cmd(fd, cgc));	}static void cdrom_count_tracks(int fd, tracktype *tracks)	{	struct	cdrom_tochdr header;	struct	cdrom_tocentry entry;	int	ret, i;	memset(tracks, 0, sizeof (*tracks));	ret = cdrom_ioctl(fd, CDROMREADTOCHDR, &header);/* * This whole business is a crock anyhow so we don't bother distinguishing * between no media, drive not ready, etc and on any error just say we have * no info.*/	if	(ret)		{		tracks->error = CDS_NO_INFO;		return;		}	entry.cdte_format = CDROM_MSF;	for	(i = header.cdth_trk0; i <= header.cdth_trk1; i++)		{		entry.cdte_track = i;		if	(cdrom_ioctl(fd, CDROMREADTOCENTRY, &entry))			{			tracks->error = CDS_NO_INFO;			return;			}		if	(entry.cdte_ctrl & CDROM_DATA_TRACK)			{			if	(entry.cdte_format == 0x10)				tracks->cdi++;			else if	(entry.cdte_format == 0x20)				tracks->xa++;			else				tracks->data++;			}		else			tracks->audio++;		}	return;	}static int cdrom_tray_move(int fd, int flag)	{	cgc_t	cgc;	cgc_init(&cgc, NULL, 0, SUC_READ);	cgc.cdb[0] = CMD_START_STOP_UNIT;	cgc.cdb[1] = 1;			/* immediate */	cgc.cdb[4] = flag ? 0x2 : 0x3;	/* eject : close */	return(scsi_cmd(fd, &cgc));	}/* * Required when we need to use READ_10 to issue other than 2048 block * reads */int cdrom_blocksize(int fd, int size)	{	cgc_t	cgc;	struct modesel_head mh;	memset(&mh, 0, sizeof(mh));	mh.block_desc_length = 0x08;	mh.block_length_med = (size >> 8) & 0xff;	mh.block_length_lo = size & 0xff;	memset(&cgc, 0, sizeof(cgc));	cgc.cdb[0] = 0x15;	cgc.cdb[1] = 1 << 4;	cgc.cdb[4] = 12;	cgc.buflen = sizeof(mh);	cgc.buf = (u_char *) &mh;	cgc.rw = SUC_WRITE;	mh.block_desc_length = 0x08;	mh.block_length_med = (size >> 8) & 0xff;	mh.block_length_lo = size & 0xff;	return(scsi_cmd(fd, &cgc));	}

⌨️ 快捷键说明

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