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

📄 sr_ioctl.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
字号:
#include <linux/kernel.h>#include <linux/sched.h>#include <linux/fs.h>#include <asm/segment.h>#include <linux/errno.h>#include "../block/blk.h"#include "scsi.h"#include "hosts.h"#include "sr.h"#include "scsi_ioctl.h"#include <linux/cdrom.h>#define IOCTL_RETRIES 3/* The CDROM is fairly slow, so we need a little extra time */#define IOCTL_TIMEOUT 200extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);static void sr_ioctl_done(Scsi_Cmnd * SCpnt){  struct request * req;  struct task_struct * p;    req = &SCpnt->request;  req->dev = 0xfffe; /* Busy, but indicate request done */    if ((p = req->waiting) != NULL) {    req->waiting = NULL;    p->state = TASK_RUNNING;    if (p->counter > current->counter)      need_resched = 1;  }}/* We do our own retries because we want to know what the specific   error code is.  Normally the UNIT_ATTENTION code will automatically   clear after one error */static int do_ioctl(int target, unsigned char * sr_cmd, void * buffer, unsigned buflength){	Scsi_Cmnd * SCpnt;	int result;	SCpnt = allocate_device(NULL, scsi_CDs[target].device->index, 1);	scsi_do_cmd(SCpnt,		    (void *) sr_cmd, buffer, buflength, sr_ioctl_done, 		    IOCTL_TIMEOUT, IOCTL_RETRIES);	if (SCpnt->request.dev != 0xfffe){	  SCpnt->request.waiting = current;	  current->state = TASK_UNINTERRUPTIBLE;	  while (SCpnt->request.dev != 0xfffe) schedule();	};	result = SCpnt->result;/* Minimal error checking.  Ignore cases we know about, and report the rest. */	if(driver_byte(result) != 0)	  switch(SCpnt->sense_buffer[2] & 0xf) {	  case UNIT_ATTENTION:	    scsi_CDs[target].device->changed = 1;	    printk("Disc change detected.\n");	    break;	  case NOT_READY: /* This happens if there is no disc in drive */	    printk("CDROM not ready.  Make sure there is a disc in the drive.\n");	    break;	  case ILLEGAL_REQUEST:	    printk("CDROM (ioctl) reports ILLEGAL REQUEST.\n");	    break;	  default:	    printk("SCSI CD error: host %d id %d lun %d return code = %03x\n", 		   scsi_CDs[target].device->host->host_no, 		   scsi_CDs[target].device->id,		   scsi_CDs[target].device->lun,		   result);	    printk("\tSense class %x, sense error %x, extended sense %x\n",		   sense_class(SCpnt->sense_buffer[0]), 		   sense_error(SCpnt->sense_buffer[0]),		   SCpnt->sense_buffer[2] & 0xf);	    	};	result = SCpnt->result;	SCpnt->request.dev = -1; /* Deallocate */	wake_up(&scsi_devices[SCpnt->index].device_wait);	/* Wake up a process waiting for device*/      	return result;}int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg){        u_char 	sr_cmd[10];	int dev = inode->i_rdev;	int result, target;	target = MINOR(dev);	if (target >= NR_SR) return -ENODEV;	switch (cmd) 		{		/* Sun-compatible */		case CDROMPAUSE:			sr_cmd[0] = SCMD_PAUSE_RESUME;			sr_cmd[1] = scsi_CDs[target].device->lun << 5;			sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0;			sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0;			sr_cmd[8] = 0;			sr_cmd[9] = 0;			result = do_ioctl(target, sr_cmd, NULL, 255);			return result;		case CDROMRESUME:			sr_cmd[0] = SCMD_PAUSE_RESUME;			sr_cmd[1] = scsi_CDs[target].device->lun << 5;			sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0;			sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0;			sr_cmd[8] = 1;			sr_cmd[9] = 0;			result = do_ioctl(target, sr_cmd, NULL, 255);			return result;		case CDROMPLAYMSF:			{			struct cdrom_msf msf;			memcpy_fromfs(&msf, (void *) arg, sizeof(msf));			sr_cmd[0] = SCMD_PLAYAUDIO_MSF;			sr_cmd[1] = scsi_CDs[target].device->lun << 5;			sr_cmd[2] = 0;			sr_cmd[3] = msf.cdmsf_min0;			sr_cmd[4] = msf.cdmsf_sec0;			sr_cmd[5] = msf.cdmsf_frame0;			sr_cmd[6] = msf.cdmsf_min1;			sr_cmd[7] = msf.cdmsf_sec1;			sr_cmd[8] = msf.cdmsf_frame1;			sr_cmd[9] = 0;			result = do_ioctl(target, sr_cmd, NULL, 255);			return result;			}		case CDROMPLAYTRKIND:			{			struct cdrom_ti ti;			memcpy_fromfs(&ti, (void *) arg, sizeof(ti));			sr_cmd[0] = SCMD_PLAYAUDIO_TI;			sr_cmd[1] = scsi_CDs[target].device->lun << 5;			sr_cmd[2] = 0;			sr_cmd[3] = 0;			sr_cmd[4] = ti.cdti_trk0;			sr_cmd[5] = ti.cdti_ind0;			sr_cmd[6] = 0;			sr_cmd[7] = ti.cdti_trk1;			sr_cmd[8] = ti.cdti_ind1;			sr_cmd[9] = 0;			result = do_ioctl(target, sr_cmd, NULL, 255);			return result;			}		case CDROMREADTOCHDR:			{			struct cdrom_tochdr tochdr;			char * buffer;			sr_cmd[0] = SCMD_READ_TOC;			sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;    /* MSF format */			sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;			sr_cmd[6] = 0;			sr_cmd[7] = 0;              /* MSB of length (12) */			sr_cmd[8] = 12;             /* LSB of length */			sr_cmd[9] = 0;			buffer = (unsigned char *) scsi_malloc(512);			if(!buffer) return -ENOMEM;			result = do_ioctl(target, sr_cmd, buffer, 12);			tochdr.cdth_trk0 = buffer[2];			tochdr.cdth_trk1 = buffer[3];			scsi_free(buffer, 512);			verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tochdr));			memcpy_tofs ((void *) arg, &tochdr, sizeof (struct cdrom_tochdr));						return result;		        }		case CDROMREADTOCENTRY:			{			struct cdrom_tocentry tocentry;			char * buffer;			verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_tocentry));			memcpy_fromfs (&tocentry, (void *) arg, sizeof (struct cdrom_tocentry));			sr_cmd[0] = SCMD_READ_TOC;			sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;    /* MSF format */			sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;			sr_cmd[6] = tocentry.cdte_track;			sr_cmd[7] = 0;             /* MSB of length (12)  */			sr_cmd[8] = 12;            /* LSB of length */			sr_cmd[9] = 0;			buffer = (unsigned char *) scsi_malloc(512);			if(!buffer) return -ENOMEM;			result = do_ioctl (target, sr_cmd, buffer, 12);			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];			  tocentry.cdte_ctrl = buffer[5] & 0xf;			}			else			  tocentry.cdte_addr.lba = (int) buffer[0];			scsi_free(buffer, 512);			verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tocentry));			memcpy_tofs ((void *) arg, &tocentry, sizeof (struct cdrom_tocentry));			return result;		        }		case CDROMSTOP:		        sr_cmd[0] = START_STOP;			sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;			sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;			sr_cmd[4] = 0;			result = do_ioctl(target, sr_cmd, NULL, 255);			return result;					case CDROMSTART:		        sr_cmd[0] = START_STOP;			sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;			sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;			sr_cmd[4] = 1;			result = do_ioctl(target, sr_cmd, NULL, 255);			return result;		case CDROMEJECT:			if (scsi_CDs[target].device -> access_count == 1)			  sr_ioctl (inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0);		        sr_cmd[0] = START_STOP;			sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 1;			sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;			sr_cmd[4] = 0x02;			if (!(result = do_ioctl(target, sr_cmd, NULL, 255)))			  scsi_CDs[target].device -> changed = 1;			return result;		case CDROMVOLCTRL:			{			  char * buffer, * mask;			  struct cdrom_volctrl volctrl;			  verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_volctrl));			  memcpy_fromfs (&volctrl, (void *) arg, sizeof (struct cdrom_volctrl));			  /* First we get the current params so we can just twiddle the volume */			  sr_cmd[0] = MODE_SENSE;			  sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5;			  sr_cmd[2] = 0xe;    /* Want mode page 0xe, CDROM audio params */			  sr_cmd[3] = 0;			  sr_cmd[4] = 28;			  sr_cmd[5] = 0;			  buffer = (unsigned char *) scsi_malloc(512);			  if(!buffer) return -ENOMEM;			  if ((result = do_ioctl (target, sr_cmd, buffer, 28))) {			    printk ("Hosed while obtaining audio mode page\n");			    scsi_free(buffer, 512);			    return result;			  }			  sr_cmd[0] = MODE_SENSE;			  sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5;			  sr_cmd[2] = 0x4e;   /* Want the mask for mode page 0xe */			  sr_cmd[3] = 0;			  sr_cmd[4] = 28;			  sr_cmd[5] = 0;			  mask = (unsigned char *) scsi_malloc(512);			  if(!mask) {			    scsi_free(buffer, 512);			    return -ENOMEM;			  };			  if ((result = do_ioctl (target, sr_cmd, mask, 28))) {			    printk ("Hosed while obtaining mask for audio mode page\n");			    scsi_free(buffer, 512);			    scsi_free(mask, 512);			    return result;			  }			  /* Now mask and substitute our own volume and reuse the rest */			  buffer[0] = 0;  /* Clear reserved field */			  buffer[21] = volctrl.channel0 & mask[21];			  buffer[23] = volctrl.channel1 & mask[23];			  buffer[25] = volctrl.channel2 & mask[25];			  buffer[27] = volctrl.channel3 & mask[27];			  sr_cmd[0] = MODE_SELECT;			  sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 0x10;    /* Params are SCSI-2 */			  sr_cmd[2] = sr_cmd[3] = 0;			  sr_cmd[4] = 28;			  sr_cmd[5] = 0;			  result = do_ioctl (target, sr_cmd, buffer, 28);			  scsi_free(buffer, 512);			  scsi_free(mask, 512);			  return result;			}		case CDROMSUBCHNL:			{			  struct cdrom_subchnl subchnl;			  char * buffer;			  			  sr_cmd[0] = SCMD_READ_SUBCHANNEL;			  sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;    /* MSF format */			  sr_cmd[2] = 0x40;    /* I do want the subchannel info */			  sr_cmd[3] = 0x01;    /* Give me current position info */			  sr_cmd[4] = sr_cmd[5] = 0;			  sr_cmd[6] = 0;			  sr_cmd[7] = 0;			  sr_cmd[8] = 16;			  sr_cmd[9] = 0;			  buffer = (unsigned char*) scsi_malloc(512);			  if(!buffer) return -ENOMEM;			  result = do_ioctl(target, sr_cmd, buffer, 16);			  subchnl.cdsc_audiostatus = buffer[1];			  subchnl.cdsc_format = CDROM_MSF;			  subchnl.cdsc_ctrl = buffer[5] & 0xf;			  subchnl.cdsc_trk = buffer[6];			  subchnl.cdsc_ind = buffer[7];			  subchnl.cdsc_reladdr.msf.minute = buffer[13];			  subchnl.cdsc_reladdr.msf.second = buffer[14];			  subchnl.cdsc_reladdr.msf.frame = buffer[15];			  subchnl.cdsc_absaddr.msf.minute = buffer[9];			  subchnl.cdsc_absaddr.msf.second = buffer[10];			  subchnl.cdsc_absaddr.msf.frame = buffer[11];			  scsi_free(buffer, 512);			  verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_subchnl));			  memcpy_tofs ((void *) arg, &subchnl, sizeof (struct cdrom_subchnl));			  return result;			}		case CDROMREADMODE2:			return -EINVAL;		case CDROMREADMODE1:			return -EINVAL;		RO_IOCTLS(dev,arg);		default:			return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg);		}}

⌨️ 快捷键说明

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