Annotation of linux/kernel/blk_drv/scsi/sr.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *      sr.c by David Giller
        !             3:  *
        !             4:  *      adapted from:
        !             5:  *     sd.c Copyright (C) 1992 Drew Eckhardt 
        !             6:  *     Linux scsi disk driver by
        !             7:  *             Drew Eckhardt 
        !             8:  *
        !             9:  *     <[email protected]>
        !            10:  */
        !            11: 
        !            12: #include <linux/config.h>
        !            13: 
        !            14: #ifdef CONFIG_BLK_DEV_SR
        !            15: 
        !            16: #include <linux/fs.h>
        !            17: #include <linux/kernel.h>
        !            18: #include <linux/sched.h>
        !            19: #include <linux/string.h>
        !            20: 
        !            21: #include "scsi.h"
        !            22: #include "sr.h"
        !            23: 
        !            24: #define MAJOR_NR 11
        !            25: 
        !            26: #include "../blk.h"
        !            27: 
        !            28: #define MAX_RETRIES 0
        !            29: #define SR_TIMEOUT 200
        !            30: 
        !            31: int NR_SR=0;
        !            32: Scsi_CD scsi_CDs[MAX_SR];
        !            33: static int sr_sizes[MAX_SR << 4];
        !            34: static unsigned long int this_count;
        !            35: 
        !            36: struct block_buffer
        !            37:        {
        !            38:        unsigned        block;
        !            39:        unsigned        start;
        !            40:        unsigned        use:1;
        !            41:        unsigned char   buffer[2048];
        !            42:        };
        !            43: 
        !            44: static struct block_buffer bb[MAX_SR];
        !            45: 
        !            46: static int sr_result;
        !            47: 
        !            48: static int sr_open(struct inode *, struct file *);
        !            49: 
        !            50: extern int sr_ioctl(struct inode *, struct file *, unsigned int, unsigned int);
        !            51: 
        !            52: static void sr_release(struct inode * inode, struct file * file)
        !            53: {
        !            54:        sync_dev(inode->i_rdev);
        !            55: }
        !            56: 
        !            57: static struct file_operations sr_fops = 
        !            58: {
        !            59:        NULL,                   /* lseek - default */
        !            60:        block_read,             /* read - general block-dev read */
        !            61:        block_write,            /* write - general block-dev write */
        !            62:        NULL,                   /* readdir - bad */
        !            63:        NULL,                   /* select */
        !            64:        sr_ioctl,               /* ioctl */
        !            65:        sr_open,                /* no special open code */
        !            66:        sr_release              /* release */
        !            67: };
        !            68: 
        !            69: /*
        !            70:  * The sense_buffer is where we put data for all mode sense commands performed.
        !            71:  */
        !            72: 
        !            73: static unsigned char sense_buffer[255];
        !            74: 
        !            75: /*
        !            76:  * rw_intr is the interrupt routine for the device driver.  It will be notified on the 
        !            77:  * end of a SCSI read / write, and will take on of several actions based on success or failure.
        !            78:  */
        !            79: 
        !            80: static void rw_intr (int host, int result)
        !            81: {
        !            82:        if (SR_HOST != host)            
        !            83:                {
        !            84:                panic ("sr.o : rw_intr() recieving interrupt for different host.");
        !            85:                }
        !            86: 
        !            87:        if (!result)
        !            88:                { /* No error */
        !            89:                if (bb[DEVICE_NR(CURRENT->dev)].use)
        !            90:                        {
        !            91:                        memcpy((char *)CURRENT->buffer, 
        !            92:                               bb[DEVICE_NR(CURRENT->dev)].buffer + 
        !            93:                               (bb[DEVICE_NR(CURRENT->dev)].start << 9), 
        !            94:                               this_count << 9);
        !            95:                        }
        !            96: 
        !            97:                CURRENT->nr_sectors -= this_count;
        !            98: 
        !            99: #ifdef DEBUG
        !           100:                printk("(%x %x %x) ",CURRENT->bh, CURRENT->nr_sectors, 
        !           101:                       this_count);
        !           102: #endif
        !           103:                if (CURRENT->nr_sectors)
        !           104:                        {        
        !           105:                        CURRENT->sector += this_count;
        !           106:                        CURRENT->errors = 0;
        !           107:                        if (!CURRENT->bh)
        !           108:                          {
        !           109:                            (char *) CURRENT->buffer += this_count << 9;
        !           110:                          } else {
        !           111:                            end_request(1);
        !           112:                            do_sr_request();
        !           113:                          }
        !           114:                        }
        !           115:                else 
        !           116:                        {
        !           117:                        end_request(1);  /* All done */
        !           118:                        do_sr_request();
        !           119:                        } 
        !           120:                }
        !           121: 
        !           122:        /* We only come through here if we have an error of some kind */
        !           123: 
        !           124:        if (driver_byte(result) != 0) {
        !           125:                bb[DEVICE_NR(CURRENT->dev)].block = -1;
        !           126:                
        !           127:                if ((sense_buffer[0] & 0x7f) == 0x70) {
        !           128:                        if ((sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
        !           129:                                /* detected disc change.  set a bit and quietly refuse  */
        !           130:                                /* further access.                                      */
        !           131:                    
        !           132:                                scsi_CDs[DEVICE_NR(CURRENT->dev)].changed = 1;
        !           133:                                end_request(0);
        !           134:                                return;
        !           135:                        }
        !           136:                }
        !           137:            
        !           138:                if (sense_buffer[2] == ILLEGAL_REQUEST) {
        !           139:                        printk("CD-ROM error: Drive reports ILLEGAL REQUEST.\n");
        !           140:                        if (scsi_CDs[DEVICE_NR(CURRENT->dev)].ten) {
        !           141:                                scsi_CDs[DEVICE_NR(CURRENT->dev)].ten = 0;
        !           142:                                do_sr_request();
        !           143:                                result = 0;
        !           144:                                return;
        !           145:                        } else {
        !           146:                                end_request(0);
        !           147:                                do_sr_request(); /* Do next request */
        !           148:                                return;
        !           149:                        }
        !           150: 
        !           151:                }
        !           152: 
        !           153:                if (sense_buffer[2] == NOT_READY) {
        !           154:                        printk("CDROM not ready.  Make sure you have a disc in the drive.\n");
        !           155:                        end_request(0);
        !           156:                        do_sr_request(); /* Do next request */
        !           157:                        return;
        !           158:                };
        !           159:              }
        !           160:        
        !           161:        /* We only get this far if we have an error we have not recognized */
        !           162:        if(result) {
        !           163:          printk("SCSI CD error : host %d id %d lun %d return code = %03x\n", 
        !           164:                 scsi_CDs[DEVICE_NR(CURRENT->dev)].device->host_no, 
        !           165:                 scsi_CDs[DEVICE_NR(CURRENT->dev)].device->id,
        !           166:                 scsi_CDs[DEVICE_NR(CURRENT->dev)].device->lun,
        !           167:                 result);
        !           168:            
        !           169:        if (status_byte(result) == CHECK_CONDITION)
        !           170:            printk("\tSense class %x, sense error %x, extended sense %x\n",
        !           171:                 sense_class(sense_buffer[0]), 
        !           172:                 sense_error(sense_buffer[0]),
        !           173:                 sense_buffer[2] & 0xf);
        !           174:        
        !           175:        end_request(0);
        !           176:        do_sr_request();
        !           177:        }
        !           178: }
        !           179: 
        !           180: static int sr_open(struct inode * inode, struct file * filp)
        !           181: {
        !           182:        if (filp->f_mode)
        !           183:                check_disk_change(inode->i_rdev);
        !           184:        return 0;
        !           185: }
        !           186: 
        !           187: /*
        !           188:  * do_sr_request() is the request handler function for the sr driver.  Its function in life 
        !           189:  * is to take block device requests, and translate them to SCSI commands.
        !           190:  */
        !           191:        
        !           192: void do_sr_request (void)
        !           193: {
        !           194:        unsigned int dev, block, realcount;
        !           195:        unsigned char cmd[10], *buffer, tries;
        !           196: 
        !           197:        tries = 2;
        !           198: 
        !           199:       repeat:
        !           200:        INIT_REQUEST;
        !           201:        dev =  MINOR(CURRENT->dev);
        !           202:        block = CURRENT->sector;        
        !           203: 
        !           204:        bb[dev].start = block % 4;
        !           205:        block = block / 4;
        !           206: 
        !           207:        if (dev >= NR_SR)
        !           208:                {
        !           209:                /* printk("CD-ROM request error: invalid device.\n");                   */
        !           210:                end_request(0);
        !           211:                tries = 2;
        !           212:                goto repeat;
        !           213:                }
        !           214: 
        !           215:        if (!scsi_CDs[dev].use)
        !           216:                {
        !           217:                /* printk("CD-ROM request error: device marked not in use.\n");         */
        !           218:                end_request(0);
        !           219:                tries = 2;
        !           220:                goto repeat;
        !           221:                }
        !           222: 
        !           223:        if (scsi_CDs[dev].changed)
        !           224:                {
        !           225: /* 
        !           226:  * quietly refuse to do anything to a changed disc until the changed bit has been reset
        !           227:  */
        !           228:                /* printk("CD-ROM has been changed.  Prohibiting further I/O.\n");      */
        !           229:                end_request(0);
        !           230:                tries = 2;
        !           231:                goto repeat;
        !           232:                }
        !           233:        
        !           234:        if (!CURRENT->bh)       
        !           235:                this_count = CURRENT->nr_sectors;
        !           236:        else
        !           237:                this_count = (CURRENT->bh->b_size / 512);
        !           238: 
        !           239:        if (bb[dev].start)
        !           240:                {                                 
        !           241:                bb[dev].use = 1;
        !           242: 
        !           243:                this_count = ((this_count > 4 - bb[dev].start) ? 
        !           244:                              (4 - bb[dev].start) : (this_count));
        !           245: 
        !           246:                if (bb[dev].block == block)
        !           247:                        {
        !           248:                          rw_intr(SR_HOST, 0);
        !           249:                          return;
        !           250:                        }
        !           251: 
        !           252:                buffer = bb[dev].buffer;
        !           253:                bb[dev].block = block;
        !           254:                } 
        !           255:        else if (this_count < 4)
        !           256:                {
        !           257:                bb[dev].use = 1;
        !           258: 
        !           259:                if (bb[dev].block == block)
        !           260:                        {
        !           261:                          rw_intr(SR_HOST, 0);
        !           262:                          return;
        !           263:                        }
        !           264: 
        !           265:                buffer = bb[dev].buffer;
        !           266:                bb[dev].block = block;
        !           267:                }
        !           268:        else
        !           269:                {
        !           270:                this_count -= this_count % 4;
        !           271:                buffer = CURRENT->buffer;
        !           272:                bb[dev].use = 0;
        !           273:                }
        !           274: 
        !           275:        realcount = (this_count + 3) / 4;
        !           276: 
        !           277:        switch (CURRENT->cmd)
        !           278:                {
        !           279:                case WRITE:             
        !           280:                        end_request(0);
        !           281:                        goto repeat;
        !           282:                        break;
        !           283:                case READ : 
        !           284:                        cmd[0] = READ_6;
        !           285:                        break;
        !           286:                default : 
        !           287:                        printk ("Unknown sr command %d\r\n", CURRENT->cmd);
        !           288:                        panic("");
        !           289:                }
        !           290:        
        !           291:        cmd[1] = (SR_LUN << 5) & 0xe0;
        !           292: 
        !           293:        if (((realcount > 0xff) || (block > 0x1fffff)) && scsi_CDs[dev].ten) 
        !           294:                {
        !           295:                if (realcount > 0xffff)
        !           296:                        {
        !           297:                        realcount = 0xffff;
        !           298:                        this_count = realcount * 4;
        !           299:                        }
        !           300: 
        !           301:                cmd[0] += READ_10 - READ_6 ;
        !           302:                cmd[2] = (unsigned char) (block >> 24) & 0xff;
        !           303:                cmd[3] = (unsigned char) (block >> 16) & 0xff;
        !           304:                cmd[4] = (unsigned char) (block >> 8) & 0xff;
        !           305:                cmd[5] = (unsigned char) block & 0xff;
        !           306:                cmd[6] = cmd[9] = 0;
        !           307:                cmd[7] = (unsigned char) (realcount >> 8) & 0xff;
        !           308:                cmd[8] = (unsigned char) realcount & 0xff;
        !           309:                }
        !           310:        else
        !           311:                {
        !           312:                if (realcount > 0xff)
        !           313:                        {
        !           314:                        realcount = 0xff;
        !           315:                        this_count = realcount * 4;
        !           316:                        }
        !           317:        
        !           318:                cmd[1] |= (unsigned char) ((block >> 16) & 0x1f);
        !           319:                cmd[2] = (unsigned char) ((block >> 8) & 0xff);
        !           320:                cmd[3] = (unsigned char) block & 0xff;
        !           321:                cmd[4] = (unsigned char) realcount;
        !           322:                cmd[5] = 0;
        !           323:                }   
        !           324: 
        !           325:        scsi_do_cmd (SR_HOST, SR_ID, (void *) cmd, buffer, realcount << 11, 
        !           326:                     rw_intr, SR_TIMEOUT, sense_buffer, MAX_RETRIES);
        !           327: }
        !           328: 
        !           329: void sr_init(void)
        !           330: {
        !           331:        int i;
        !           332: 
        !           333:        for (i = 0; i < NR_SR; ++i)
        !           334:                {
        !           335:                scsi_CDs[i].capacity = 0x1fffff;
        !           336:                scsi_CDs[i].sector_size = 2048;
        !           337:                scsi_CDs[i].use = 1;
        !           338:                scsi_CDs[i].ten = 1;
        !           339:                scsi_CDs[i].remap = 1;
        !           340:                scsi_CDs[i].changed = 0;
        !           341:                sr_sizes[i] = scsi_CDs[i].capacity;
        !           342: 
        !           343:                bb[i].block = -1;
        !           344:                }
        !           345: 
        !           346:        blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
        !           347:        blk_size[MAJOR_NR] = sr_sizes;  
        !           348:        blkdev_fops[MAJOR_NR] = &sr_fops; 
        !           349: }      
        !           350: #endif
        !           351: 
        !           352: 
        !           353: 
        !           354: 
        !           355: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.