📄 sr_ioctl.c
字号:
#include <linux/kernel.h>#include <linux/sched.h>#include <linux/mm.h>#include <linux/fs.h>#include <asm/segment.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/blk.h>#include "scsi.h"#include "hosts.h"#include "sr.h"#include <scsi/scsi_ioctl.h>#include <linux/cdrom.h>extern void get_sectorsize(int);extern void sr_photocd(struct inode *);#define IOCTL_RETRIES 3/* The CDROM is fairly slow, so we need a little extra time *//* In fact, it is very slow if it has to spin up first */#define IOCTL_TIMEOUT 3000static void sr_ioctl_done(Scsi_Cmnd * SCpnt){ struct request * req; req = &SCpnt->request; req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */ if (req->sem != NULL) { up(req->sem); }}/* 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, 1); { struct semaphore sem = MUTEX_LOCKED; SCpnt->request.sem = &sem; scsi_do_cmd(SCpnt, (void *) sr_cmd, buffer, buflength, sr_ioctl_done, IOCTL_TIMEOUT, IOCTL_RETRIES); down(&sem); } 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: /* CDROMCLOSETRAY should not print an error for caddy drives. */ if (!(sr_cmd[0] == START_STOP && sr_cmd[4] == 0x03)) 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.rq_status = RQ_INACTIVE; /* Deallocate */ wake_up(&SCpnt->device->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]; kdev_t dev = inode->i_rdev; int result, target, err; target = MINOR(dev); if (target >= sr_template.nr_dev || !scsi_CDs[target].device) return -ENXIO; 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; err = verify_area (VERIFY_READ, (void *) arg, sizeof (msf)); if (err) return err; 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 CDROMPLAYBLK: { struct cdrom_blk blk; err = verify_area (VERIFY_READ, (void *) arg, sizeof (blk)); if (err) return err; memcpy_fromfs(&blk, (void *) arg, sizeof(blk)); sr_cmd[0] = SCMD_PLAYAUDIO10; sr_cmd[1] = scsi_CDs[target].device->lun << 5; sr_cmd[2] = blk.from >> 24; sr_cmd[3] = blk.from >> 16; sr_cmd[4] = blk.from >> 8; sr_cmd[5] = blk.from; sr_cmd[6] = 0; sr_cmd[7] = blk.len >> 8; sr_cmd[8] = blk.len; sr_cmd[9] = 0; result = do_ioctl(target, sr_cmd, NULL, 255); return result; } case CDROMPLAYTRKIND: { struct cdrom_ti ti; err = verify_area (VERIFY_READ, (void *) arg, sizeof (ti)); if (err) return err; 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); 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); err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tochdr)); if (err) return err; memcpy_tofs ((void *) arg, &tochdr, sizeof (struct cdrom_tochdr)); return result; } case CDROMREADTOCENTRY: { struct cdrom_tocentry tocentry; unsigned char * buffer; err = verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_tocentry)); if (err) return err; memcpy_fromfs (&tocentry, (void *) arg, sizeof (struct cdrom_tocentry)); sr_cmd[0] = SCMD_READ_TOC; sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | (tocentry.cdte_format == CDROM_MSF ? 0x02 : 0); 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); 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]; scsi_free(buffer, 512); err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tocentry)); if (err) return err; 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 CDROMCLOSETRAY: sr_cmd[0] = START_STOP; sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5); sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -