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

📄 matcd.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*---------------------------------------------------------------------------	matcdclose - Close the device	Close may not do much other than clear some driver settings.	Note that audio playback will continue.<15>	If you define LOCKDRIVE, and the drive has been opened using<15>	one of the locking minor numbers, code in close will unlock<15>	the drive.---------------------------------------------------------------------------*/int matcdclose(dev_t dev, int flags, int fmt,	       struct proc *p){	int	ldrive,cdrive,port,partition,controller,lock;	struct matcd_data *cd;#ifdef LOCKDRIVE	unsigned char cmd[MAXCMDSIZ];#endif /*LOCKDRIVE*/	ldrive=matcd_ldrive(dev);	cdrive=matcd_cdrive(dev);	lock=matcd_lockable(dev);	cd=matcd_data+ldrive;	port=cd->iobase;		/*and port#*/	if (ldrive >= TOTALDRIVES)		return(ENXIO);	partition = matcd_partition(dev);	controller=matcd_controller(dev);#ifdef DEBUGOPEN	printf("matcd%d: Close partition=%d flags %x openflags %x partflags %x\n",	       ldrive,partition,cd->flags,cd->openflags,	       cd->partflags[partition]);#endif /*DEBUGOPEN*/	if (!(cd->flags & MATCDINIT))		return(ENXIO);	cd->partflags[partition] &= ~(MATCDOPEN|MATCDREADRAW);	cd->openflags &= ~(1<<(partition+lock));	if (cd->openflags==0) {			/*<24>Really last close?*/#ifdef LOCKDRIVE		if (cd->flags & MATCDLOCK) {	/*<24>Was drive locked?*/			zero_cmd(cmd);		/*Yes, so unlock it*/			cmd[0]=LOCK;		/*Unlock drive*/			docmd(cmd,ldrive,cdrive,controller,port);		}#endif /*LOCKDRIVE*/		cd->flags &= ~(MATCDWARN|MATCDLOCK);						/*<15>Clear warning flag*/	}	return(0);}/*---------------------------------------------------------------------------	matcdstrategy - Accepts I/O requests from kernel for processing	This routine accepts a read request block pointer (historically	but somewhat inaccurately called *bp for buffer pointer).	Various sanity checks are performed on the request.	When we are happy with the request and the state of the device,	the request is added to the queue of requests for the interface	that the drive is connected to.  We support multiple interfaces	so there are multiple queues.  Once the request is added, we	call the matcd_start routine to start the device in case it isn't	doing something already.   All I/O including ioctl requests	rely on the current request starting the next one before exiting.---------------------------------------------------------------------------*/void matcdstrategy(struct buf *bp){	struct matcd_data *cd;	int s;	int ldrive,controller;	ldrive=matcd_ldrive(bp->b_dev);	controller=matcd_controller(bp->b_dev);	cd= &matcd_data[ldrive];#ifdef DEBUGIO	printf("matcd%d: Strategy: buf=0x%lx, block#=%ld bcount=%ld\n",		ldrive,(unsigned long)bp,bp->b_blkno,bp->b_bcount);#endif /*DEBUGIO*/	if (ldrive >= TOTALDRIVES || bp->b_blkno < 0) {		printf("matcd%d: Bogus parameters received - kernel may be corrupted\n",ldrive);		bp->b_error=EINVAL;		goto bad;	}	if (!(cd->flags & MATCDLABEL)) {		bp->b_error = EIO;		goto bad;	}	if (!(bp->b_flags & B_READ)) {		bp->b_error = EROFS;		goto bad;	}	if (bp->b_bcount==0)		/*Request is zero-length - all done*/		goto done;	if (matcd_partition(bp->b_dev) != RAW_PART) {		if (bounds_check_with_label(bp,&cd->dlabel,1) <= 0) {			goto done;		}	} else {		bp->b_pblkno=bp->b_blkno;		bp->b_resid=0;	}	s=splbio();			/*Make sure we don't get intr'ed*/	bufqdisksort(&request_head[controller], bp);/*Add new request (bp) to queue (dp					  and sort the requests in a way that					  may not be ideal for CD-ROM media*/	matcd_start(controller);		/*Ok, with our newly sorted queue,					  see if we can start an I/O operation					  right now*/	splx(s);			/*Return priorities to normal*/	return;				/*All done*/bad:	bp->b_flags |= B_ERROR;		/*Request bad in some way*/done:	bp->b_resid = bp->b_bcount;	/*Show amount of data un read*/	biodone(bp);			/*Signal we have done all we plan to*/	return;}/*---------------------------------------------------------------------------	matcd_start - Pull a request from the queue and consider doing it.---------------------------------------------------------------------------*/static void matcd_start(int controller){	struct matcd_data *cd;	struct buf *bp;	struct partition *p;	int part,ldrive;	bp = bufq_first(&request_head[controller]);	if (bp == NULL) {	/*Nothing on read queue to do?*/		wakeup((caddr_t)&matcd_data->status);	/*Wakeup any blocked*/		return;					/* opens, ioctls, etc*/	}	ldrive=matcd_ldrive(bp->b_dev);	/*Get logical drive#*/	cd=&matcd_data[ldrive];		/*Get pointer to data for this drive*/#ifdef DEBUGIO	printf("matcd%d: In start controller %d\n",ldrive,controller);#endif	/*DEBUGIO*/	if (if_state[controller] & BUSBUSY) {#ifdef DEBUGIO		printf("matcd%d: Dropping thread in start,  controller %d\n",	       		ldrive,controller);#endif	/*DEBUGIO*/		return;	}/*	Ok, the controller is idle (not necessarily the drive) and so	get the command to do and issue it*/	bufq_remove(&request_head[controller], bp);	part=matcd_partition(bp->b_dev);	p=cd->dlabel.d_partitions + part;	if_state[controller] |= BUSBUSY;/*<18>Mark bus as busy*/	cd->mbx.ldrive=ldrive;		/*Save current logical drive*/	cd->mbx.controller=controller;	/*and controller*/	cd->mbx.partition=part;		/*and partition (2048 vs 2532)*/	cd->mbx.port=cd->iobase;	/*and port#*/	cd->mbx.iftype=cd->iftype;	/*<20>interface type*/	cd->mbx.retry=MATCD_RETRYS;	/*and the retry count*/	cd->mbx.bp=bp;			/*and the bp*/	cd->mbx.p_offset=p->p_offset;	/*and where the data will go*/	matcd_blockread(MATCD_READ_1+ldrive);	/*Actually start the read*/	return;				/*Dropping thread.  matcd_blockread					  must have scheduled a timeout or					  we will go to sleep forever*/}/*---------------------------------------------------------------------------	matcdioctl - Process things that aren't block reads	In this driver, ioctls are used mainly to change	the mode the drive is running in, play audio and other	things that don't fit into the block read scheme of things.---------------------------------------------------------------------------*/int matcdioctl(dev_t dev, int command, caddr_t addr,	       int flags, struct proc *p){	struct	matcd_data *cd;	int	ldrive,cdrive,partition;	int	port, controller;#ifdef DEBUGIOCTL	int	i;#endif	/*DEBUGIOCTL*/	ldrive=matcd_ldrive(dev);	cdrive=matcd_cdrive(dev);	partition=matcd_partition(dev);	controller=ldrive>>2;	cd = &matcd_data[ldrive];	port=cd->iobase;#ifdef DEBUGIOCTL	printf("matcd%d: ioctl %x cdrive %x parms ",ldrive,command,cdrive);	for (i=0;i<10;i++) {		printf("%02x ",(unsigned int)addr[i]);	}	printf("  flags %x\n",cd->flags);#endif	/*DEBUGIOCTL*/	if (command==CDIOCCLOSE)	/*<16>Allow close if door open*/		return(matcd_doorclose(ldrive, cdrive, controller));	if (!(cd->flags & MATCDLABEL))	/*Did we read TOC OK?*/		return(EIO);		/*<16>then drive really isn't ready*/	switch(command) {	case	DIOCSBAD:		return(EINVAL);	case	DIOCGDINFO:		*(struct disklabel *) addr = cd->dlabel;		return(0);	case	DIOCGPART:		((struct partinfo *) addr)->disklab=&cd->dlabel;		((struct partinfo *) addr)->part=		    &cd->dlabel.d_partitions[matcd_partition(dev)];		return(0);	case	DIOCWDINFO:	case	DIOCSDINFO:		if ((flags & FWRITE) == 0) {			return(EBADF);		}		else {			return setdisklabel(&cd->dlabel,				            (struct disklabel *) addr, 0);		}	case	DIOCWLABEL:		return(EBADF);	case	CDIOCEJECT:		return(matcd_eject(ldrive, cdrive, controller));	case	CDIOCALLOW:		return(matcd_dlock(ldrive, cdrive,		       controller,0));	case	CDIOCPREVENT:		return(matcd_dlock(ldrive, cdrive,		       controller, MATCDLOCK));#ifdef FULLDRIVER	case	CDIOCPLAYTRACKS:		return(matcd_playtracks(ldrive, cdrive, controller,		       (struct ioc_play_track *) addr));	case	CDIOCPLAYMSF:		return(matcd_playmsf(ldrive, cdrive, controller,		       (struct ioc_play_msf *) addr));	case	CDIOCRESUME:		return(matcd_pause(ldrive, cdrive, controller,RESUME));	case	CDIOCPAUSE:		return(matcd_pause(ldrive, cdrive, controller,0));	case	CDIOCSTOP:		return(matcd_stop(ldrive, cdrive, controller));	case	CDIOCGETVOL:	case	CDIOCSETVOL:		return(matcd_level(ldrive, cdrive, controller,		       (struct ioc_vol *) addr, command));	case	CDIOCSETMONO:		/*<12>This drive can't do mono*/		return(EINVAL);		/*<12>but it looks like it should*/					/*<12>SRC OUT	SRC OUT*/	case	CDIOCSETSTEREO:		/*<12>0 -> L	1 -> R*/	case	CDIOCSETMUTE:		/*<12>0 -> NULL	1 -> NULL*/	case	CDIOCSETLEFT:		/*<12>0 -> L&R	1 -> NULL*/	case	CDIOCSETRIGHT:		/*<12>0 -> NULL	1 -> L&R*/					/*<12>Adjust audio routing*/		return(matcd_route(ldrive, cdrive, controller,		       command));	case	CDIOCSETPATCH:		/*<12>Allow precise routing*/		return(matcd_patch(ldrive, cdrive, controller,		       (struct ioc_patch *) addr));	case	CDIOCPITCH:		/*<12>Adjust playback speed*/		return(matcd_pitch(ldrive, cdrive, controller,		       (struct ioc_pitch *) addr));	case	CDIOCSTART:		/*<12>Only reason this isn't*/		return(EINVAL);		/*<12>implemented is I can't find out*/					/*<12>what it should do!*/#endif	/*FULLDRIVER*/	case	CDIOREADTOCHEADER:		return(matcd_toc_header(ldrive, cdrive, controller,		       (struct ioc_toc_header *) addr));	case	CDIOREADTOCENTRYS:		return(matcd_toc_entries(ldrive, cdrive, controller,		       (struct ioc_read_toc_entry *) addr));	case	CDIOCREADSUBCHANNEL:		return(matcd_read_subq(ldrive, cdrive, controller,		       (struct ioc_read_subchannel *) addr));	case	CDIOCCAPABILITY:	/*<16>Request drive/driver capability*/		return(matcd_igot((struct ioc_capability *) addr));	case	CDIOCRESET:		/*<12>There is no way to hard reset*/		return(EINVAL);		/*<12>just one drive*/	default:		return(ENOTTY);	}}/*---------------------------------------------------------------------------	matcdsize - Reports how many blocks exist on the disc.---------------------------------------------------------------------------*/int	matcdsize(dev_t dev){	int	size,blksize;	int	ldrive,part;	struct	matcd_data *cd;	ldrive=matcd_ldrive(dev);	part=matcd_partition(dev);	if (part==RAW_PART)		blksize=MATCDRBLK;	/*2352*/	else		blksize=MATCDBLK;	/*2048*/	cd = &matcd_data[ldrive];	if (matcd_volinfo(ldrive) >= 0) {		cd->blksize=blksize;		size=msf_to_blk((char * )&cd->volinfo.vol_msf);		cd->disksize=size*(blksize/DEV_BSIZE);#ifdef DEBUGOPEN	printf("matcd%d: Media size %d\n",ldrive,size);#endif /*DEBUGOPEN*/		return(0);	}	return(-1);}/*---------------------------------------------------------------------------	matcd_probe - Search for host interface/adapters	The probe routine hunts for the first drive on the interface since	there is no way to locate just the adapter.   It also resets the	entire drive chain while it is there.  matcd_attach() takes care of	the rest of the initialization.	The probe routine can be compiled two ways.  In AUTOHUNT mode,	the kernel config file can say "port?" and we will check all ports	listed in the port_hint array (see above).	Without AUTOHUNT set, the config file must list a specific port	address to check.	Note that specifying the explicit addresses makes boot-up a lot	faster.	The probe will locate Panasonic/Creative interface on the following

⌨️ 快捷键说明

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