Annotation of Gnu-Mach/i386/i386at/gpl/linux/scsi/scsi_ioctl.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Don't import our own symbols, as this would severely mess up our
        !             3:  * symbol tables.
        !             4:  */
        !             5: #define _SCSI_SYMS_VER_
        !             6: #define __NO_VERSION__
        !             7: #include <linux/module.h>
        !             8: 
        !             9: #include <asm/io.h>
        !            10: #include <asm/segment.h>
        !            11: #include <asm/system.h>
        !            12: 
        !            13: #include <linux/errno.h>
        !            14: #include <linux/kernel.h>
        !            15: #include <linux/sched.h>
        !            16: #include <linux/mm.h>
        !            17: #include <linux/string.h>
        !            18: 
        !            19: #include <linux/blk.h>
        !            20: #include "scsi.h"
        !            21: #include "hosts.h"
        !            22: #include "scsi_ioctl.h"
        !            23: 
        !            24: #define MAX_RETRIES 5   
        !            25: #define MAX_TIMEOUT 900
        !            26: #define MAX_BUF 4096
        !            27: 
        !            28: #define max(a,b) (((a) > (b)) ? (a) : (b))
        !            29: 
        !            30: /*
        !            31:  * If we are told to probe a host, we will return 0 if  the host is not
        !            32:  * present, 1 if the host is present, and will return an identifying
        !            33:  * string at *arg, if arg is non null, filling to the length stored at
        !            34:  * (int *) arg
        !            35:  */
        !            36: 
        !            37: static int ioctl_probe(struct Scsi_Host * host, void *buffer)
        !            38: {
        !            39:     int temp, result;
        !            40:     unsigned int len,slen;
        !            41:     const char * string;
        !            42:     
        !            43:     if ((temp = host->hostt->present) && buffer) {
        !            44:         result = verify_area(VERIFY_READ, buffer, sizeof(long));
        !            45:         if (result) return result;
        !            46: 
        !            47:        len = get_user ((unsigned int *) buffer);
        !            48:        if(host->hostt->info)
        !            49:            string = host->hostt->info(host);
        !            50:        else 
        !            51:            string = host->hostt->name;
        !            52:        if(string) {
        !            53:            slen = strlen(string);
        !            54:            if (len > slen)
        !            55:                len = slen + 1;
        !            56:             result = verify_area(VERIFY_WRITE, buffer, len);
        !            57:             if (result) return result;
        !            58: 
        !            59:            memcpy_tofs (buffer, string, len);
        !            60:        }
        !            61:     }
        !            62:     return temp;
        !            63: }
        !            64: 
        !            65: /*
        !            66:  * 
        !            67:  * The SCSI_IOCTL_SEND_COMMAND ioctl sends a command out to the SCSI host.
        !            68:  * The MAX_TIMEOUT and MAX_RETRIES  variables are used.  
        !            69:  * 
        !            70:  * dev is the SCSI device struct ptr, *(int *) arg is the length of the
        !            71:  * input data, if any, not including the command string & counts, 
        !            72:  * *((int *)arg + 1) is the output buffer size in bytes.
        !            73:  * 
        !            74:  * *(char *) ((int *) arg)[2] the actual command byte.   
        !            75:  * 
        !            76:  * Note that no more than MAX_BUF data bytes will be transfered.  Since
        !            77:  * SCSI block device size is 512 bytes, I figured 1K was good.
        !            78:  * but (WDE) changed it to 8192 to handle large bad track buffers.
        !            79:  * ERY: I changed this to a dynamic allocation using scsi_malloc - we were
        !            80:  * getting a kernel stack overflow which was crashing the system when we
        !            81:  * were using 8192 bytes.
        !            82:  * 
        !            83:  * This size *does not* include the initial lengths that were passed.
        !            84:  * 
        !            85:  * The SCSI command is read from the memory location immediately after the
        !            86:  * length words, and the input data is right after the command.  The SCSI
        !            87:  * routines know the command size based on the opcode decode.  
        !            88:  * 
        !            89:  * The output area is then filled in starting from the command byte. 
        !            90:  */
        !            91: 
        !            92: static void scsi_ioctl_done (Scsi_Cmnd * SCpnt)
        !            93: {
        !            94:     struct request * req;
        !            95:     
        !            96:     req = &SCpnt->request;
        !            97:     req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */
        !            98:     
        !            99:     if (req->sem != NULL) {
        !           100:        up(req->sem);
        !           101:     }
        !           102: }   
        !           103: 
        !           104: static int ioctl_internal_command(Scsi_Device *dev, char * cmd)
        !           105: {
        !           106:     int result;
        !           107:     Scsi_Cmnd * SCpnt;
        !           108:     
        !           109:     SCpnt = allocate_device(NULL, dev, 1);
        !           110:     {
        !           111:        struct semaphore sem = MUTEX_LOCKED;
        !           112:        SCpnt->request.sem = &sem;
        !           113:        scsi_do_cmd(SCpnt,  cmd, NULL,  0,
        !           114:                    scsi_ioctl_done,  MAX_TIMEOUT,
        !           115:                    MAX_RETRIES);
        !           116:        down(&sem);
        !           117:     }
        !           118:     
        !           119:     if(driver_byte(SCpnt->result) != 0)
        !           120:        switch(SCpnt->sense_buffer[2] & 0xf) {
        !           121:        case ILLEGAL_REQUEST:
        !           122:            if(cmd[0] == ALLOW_MEDIUM_REMOVAL) dev->lockable = 0;
        !           123:            else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n");
        !           124:            break;
        !           125:        case NOT_READY: /* This happens if there is no disc in drive */
        !           126:            if(dev->removable){
        !           127:                printk(KERN_INFO "Device not ready.  Make sure there is a disc in the drive.\n");
        !           128:                break;
        !           129:            };
        !           130:        case UNIT_ATTENTION:
        !           131:            if (dev->removable){
        !           132:                dev->changed = 1;
        !           133:                SCpnt->result = 0; /* This is no longer considered an error */
        !           134:                printk(KERN_INFO "Disc change detected.\n");
        !           135:                break;
        !           136:            };
        !           137:        default: /* Fall through for non-removable media */
        !           138:            printk("SCSI error: host %d id %d lun %d return code = %x\n",
        !           139:                   dev->host->host_no,
        !           140:                   dev->id,
        !           141:                   dev->lun,
        !           142:                   SCpnt->result);
        !           143:            printk("\tSense class %x, sense error %x, extended sense %x\n",
        !           144:                   sense_class(SCpnt->sense_buffer[0]),
        !           145:                   sense_error(SCpnt->sense_buffer[0]),
        !           146:                   SCpnt->sense_buffer[2] & 0xf);
        !           147:            
        !           148:        };
        !           149:     
        !           150:     result = SCpnt->result;
        !           151:     SCpnt->request.rq_status = RQ_INACTIVE;
        !           152:     wake_up(&SCpnt->device->device_wait);
        !           153:     return result;
        !           154: }
        !           155: 
        !           156: /*
        !           157:  * This interface is depreciated - users should use the scsi generics
        !           158:  * interface instead, as this is a more flexible approach to performing
        !           159:  * generic SCSI commands on a device.
        !           160:  */
        !           161: static int ioctl_command(Scsi_Device *dev, void *buffer)
        !           162: {
        !           163:     char * buf;
        !           164:     char cmd[12];
        !           165:     char * cmd_in;
        !           166:     Scsi_Cmnd * SCpnt;
        !           167:     unsigned char opcode;
        !           168:     int inlen, outlen, cmdlen;
        !           169:     int needed, buf_needed;
        !           170:     int result;
        !           171:     
        !           172:     if (!buffer)
        !           173:        return -EINVAL;
        !           174:     
        !           175: 
        !           176:     /*
        !           177:      * Verify that we can read at least this much.
        !           178:      */
        !           179:     result = verify_area(VERIFY_READ, buffer, 2*sizeof(long) + 1);
        !           180:     if (result) return result;
        !           181: 
        !           182:     /*
        !           183:      * The structure that we are passed should look like:
        !           184:      *
        !           185:      * struct sdata{
        !           186:      * int inlen;
        !           187:      * int outlen;
        !           188:      * char cmd[];  # However many bytes are used for cmd.
        !           189:      * char data[];
        !           190:      */
        !           191:     inlen = get_user((unsigned int *) buffer);
        !           192:     outlen = get_user( ((unsigned int *) buffer) + 1);
        !           193:     
        !           194:     /*
        !           195:      * We do not transfer more than MAX_BUF with this interface.
        !           196:      * If the user needs to transfer more data than this, they
        !           197:      * should use scsi_generics instead.
        !           198:      */
        !           199:     if( inlen > MAX_BUF ) inlen = MAX_BUF;
        !           200:     if( outlen > MAX_BUF ) outlen = MAX_BUF;
        !           201: 
        !           202:     cmd_in = (char *) ( ((int *)buffer) + 2);
        !           203:     opcode = get_user(cmd_in); 
        !           204:     
        !           205:     needed = buf_needed = (inlen > outlen ? inlen : outlen);
        !           206:     if(buf_needed){
        !           207:        buf_needed = (buf_needed + 511) & ~511;
        !           208:        if (buf_needed > MAX_BUF) buf_needed = MAX_BUF;
        !           209:        buf = (char *) scsi_malloc(buf_needed);
        !           210:        if (!buf) return -ENOMEM;
        !           211:        memset(buf, 0, buf_needed);
        !           212:     } else
        !           213:        buf = NULL;
        !           214:     
        !           215:     /*
        !           216:      * Obtain the command from the user's address space.
        !           217:      */
        !           218:     cmdlen = COMMAND_SIZE(opcode);
        !           219: 
        !           220:     result = verify_area(VERIFY_READ, cmd_in, 
        !           221:                          cmdlen + inlen > MAX_BUF ? MAX_BUF : inlen);
        !           222:     if (result) return result;
        !           223: 
        !           224:     memcpy_fromfs ((void *) cmd,  cmd_in,  cmdlen);
        !           225:     
        !           226:     /*
        !           227:      * Obtain the data to be sent to the device (if any).
        !           228:      */
        !           229:     memcpy_fromfs ((void *) buf,  
        !           230:                    (void *) (cmd_in + cmdlen), 
        !           231:                    inlen);
        !           232:     
        !           233:     /*
        !           234:      * Set the lun field to the correct value.
        !           235:      */
        !           236:     cmd[1] = ( cmd[1] & 0x1f ) | (dev->lun << 5);
        !           237:     
        !           238: #ifndef DEBUG_NO_CMD
        !           239:     
        !           240:     SCpnt = allocate_device(NULL, dev, 1);
        !           241: 
        !           242:     {
        !           243:        struct semaphore sem = MUTEX_LOCKED;
        !           244:        SCpnt->request.sem = &sem;
        !           245:        scsi_do_cmd(SCpnt,  cmd,  buf, needed,  scsi_ioctl_done,  MAX_TIMEOUT, 
        !           246:                    MAX_RETRIES);
        !           247:        down(&sem);
        !           248:     }
        !           249:     
        !           250:     /* 
        !           251:      * If there was an error condition, pass the info back to the user. 
        !           252:      */
        !           253:     if(SCpnt->result) {
        !           254:         result = verify_area(VERIFY_WRITE, 
        !           255:                              cmd_in, 
        !           256:                              sizeof(SCpnt->sense_buffer));
        !           257:         if (result) return result;
        !           258:         memcpy_tofs((void *) cmd_in,  
        !           259:                     SCpnt->sense_buffer, 
        !           260:                     sizeof(SCpnt->sense_buffer));
        !           261:     } else {
        !           262:         result = verify_area(VERIFY_WRITE, cmd_in, outlen);
        !           263:         if (result) return result;
        !           264:         memcpy_tofs ((void *) cmd_in,  buf,  outlen);
        !           265:     }
        !           266:     result = SCpnt->result;
        !           267: 
        !           268:     SCpnt->request.rq_status = RQ_INACTIVE;
        !           269: 
        !           270:     if (buf) scsi_free(buf, buf_needed);
        !           271:     
        !           272:     if(SCpnt->device->scsi_request_fn)
        !           273:        (*SCpnt->device->scsi_request_fn)();
        !           274:     
        !           275:     wake_up(&SCpnt->device->device_wait);
        !           276:     return result;
        !           277: #else
        !           278:     {
        !           279:        int i;
        !           280:        printk("scsi_ioctl : device %d.  command = ", dev->id);
        !           281:        for (i = 0; i < 12; ++i)
        !           282:            printk("%02x ", cmd[i]);
        !           283:        printk("\nbuffer =");
        !           284:        for (i = 0; i < 20; ++i)
        !           285:            printk("%02x ", buf[i]);
        !           286:        printk("\n");
        !           287:        printk("inlen = %d, outlen = %d, cmdlen = %d\n",
        !           288:               inlen, outlen, cmdlen);
        !           289:        printk("buffer = %d, cmd_in = %d\n", buffer, cmd_in);
        !           290:     }
        !           291:     return 0;
        !           292: #endif
        !           293: }
        !           294: 
        !           295: /*
        !           296:  * the scsi_ioctl() function differs from most ioctls in that it does
        !           297:  * not take a major/minor number as the dev filed.  Rather, it takes
        !           298:  * a pointer to a scsi_devices[] element, a structure. 
        !           299:  */
        !           300: int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
        !           301: {
        !           302:     int result;
        !           303:     char scsi_cmd[12];
        !           304:     
        !           305:     /* No idea how this happens.... */
        !           306:     if (!dev) return -ENXIO;
        !           307:     
        !           308:     switch (cmd) {
        !           309:     case SCSI_IOCTL_GET_IDLUN:
        !           310:         result = verify_area(VERIFY_WRITE, (void *) arg, 2*sizeof(long));
        !           311:         if (result) return result;
        !           312: 
        !           313:        put_user(dev->id 
        !           314:                  + (dev->lun << 8) 
        !           315:                  + (dev->channel << 16)
        !           316:                  + ((dev->host->hostt->proc_dir->low_ino & 0xff) << 24),
        !           317:                    (unsigned long *) arg);
        !           318:         put_user( dev->host->unique_id, (unsigned long *) arg+1);
        !           319:        return 0;
        !           320:     case SCSI_IOCTL_TAGGED_ENABLE:
        !           321:        if(!suser())  return -EACCES;
        !           322:        if(!dev->tagged_supported) return -EINVAL;
        !           323:        dev->tagged_queue = 1;
        !           324:        dev->current_tag = 1;
        !           325:        break;
        !           326:     case SCSI_IOCTL_TAGGED_DISABLE:
        !           327:        if(!suser())  return -EACCES;
        !           328:        if(!dev->tagged_supported) return -EINVAL;
        !           329:        dev->tagged_queue = 0;
        !           330:        dev->current_tag = 0;
        !           331:        break;
        !           332:     case SCSI_IOCTL_PROBE_HOST:
        !           333:        return ioctl_probe(dev->host, arg);
        !           334:     case SCSI_IOCTL_SEND_COMMAND:
        !           335:        if(!suser())  return -EACCES;
        !           336:        return ioctl_command((Scsi_Device *) dev, arg);
        !           337:     case SCSI_IOCTL_DOORLOCK:
        !           338:        if (!dev->removable || !dev->lockable) return 0;
        !           339:        scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
        !           340:        scsi_cmd[1] = dev->lun << 5;
        !           341:        scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
        !           342:        scsi_cmd[4] = SCSI_REMOVAL_PREVENT;
        !           343:        return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
        !           344:        break;
        !           345:     case SCSI_IOCTL_DOORUNLOCK:
        !           346:        if (!dev->removable || !dev->lockable) return 0;
        !           347:        scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
        !           348:        scsi_cmd[1] = dev->lun << 5;
        !           349:        scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
        !           350:        scsi_cmd[4] = SCSI_REMOVAL_ALLOW;
        !           351:        return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
        !           352:     case SCSI_IOCTL_TEST_UNIT_READY:
        !           353:        scsi_cmd[0] = TEST_UNIT_READY;
        !           354:        scsi_cmd[1] = dev->lun << 5;
        !           355:        scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
        !           356:        scsi_cmd[4] = 0;
        !           357:        return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
        !           358:        break;
        !           359:     default :           
        !           360:        return -EINVAL;
        !           361:     }
        !           362:     return -EINVAL;
        !           363: }
        !           364: 
        !           365: /*
        !           366:  * Just like scsi_ioctl, only callable from kernel space with no 
        !           367:  * fs segment fiddling.
        !           368:  */
        !           369: 
        !           370: int kernel_scsi_ioctl (Scsi_Device *dev, int cmd, void *arg) {
        !           371:     unsigned long oldfs;
        !           372:     int tmp;
        !           373:     oldfs = get_fs();
        !           374:     set_fs(get_ds());
        !           375:     tmp = scsi_ioctl (dev, cmd, arg);
        !           376:     set_fs(oldfs);
        !           377:     return tmp;
        !           378: }
        !           379: 
        !           380: /*
        !           381:  * Overrides for Emacs so that we almost follow Linus's tabbing style.
        !           382:  * Emacs will notice this stuff at the end of the file and automatically
        !           383:  * adjust the settings for this buffer only.  This must remain at the end
        !           384:  * of the file.
        !           385:  * ---------------------------------------------------------------------------
        !           386:  * Local variables:
        !           387:  * c-indent-level: 4
        !           388:  * c-brace-imaginary-offset: 0
        !           389:  * c-brace-offset: -4
        !           390:  * c-argdecl-indent: 4
        !           391:  * c-label-offset: -4
        !           392:  * c-continued-statement-offset: 4
        !           393:  * c-continued-brace-offset: 0
        !           394:  * indent-tabs-mode: nil
        !           395:  * tab-width: 8
        !           396:  * End:
        !           397:  */

unix.superglobalmegacorp.com

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