|
|
1.1 ! root 1: #include <linux/config.h> ! 2: #ifdef CONFIG_SCSI ! 3: ! 4: #include <errno.h> ! 5: #include <asm/io.h> ! 6: #include <asm/segment.h> ! 7: #include <asm/system.h> ! 8: ! 9: #include <linux/kernel.h> ! 10: #include <linux/sched.h> ! 11: #include <linux/string.h> ! 12: ! 13: #include "scsi.h" ! 14: #include "hosts.h" ! 15: #include "scsi_ioctl.h" ! 16: ! 17: #define MAX_RETRIES 5 ! 18: #define MAX_TIMEOUT 200 ! 19: #define MAX_BUF 1024 ! 20: ! 21: #define max(a,b) (((a) > (b)) ? (a) : (b)) ! 22: ! 23: /* ! 24: * If we are told to probe a host, we will return 0 if the host is not ! 25: * present, 1 if the host is present, and will return an identifying ! 26: * string at *arg, if arg is non null, filling to the length stored at ! 27: * (int *) arg ! 28: */ ! 29: ! 30: static int ioctl_probe(int dev, void *buffer) ! 31: { ! 32: int temp; ! 33: int len; ! 34: ! 35: if ((temp = scsi_hosts[dev].present) && buffer) { ! 36: len = get_fs_long ((int *) buffer); ! 37: memcpy_tofs (buffer, scsi_hosts[dev].info(), len); ! 38: } ! 39: return temp; ! 40: } ! 41: ! 42: /* ! 43: * ! 44: * The SCSI_IOCTL_SEND_COMMAND ioctl sends a command out to the SCSI host. ! 45: * The MAX_TIMEOUT and MAX_RETRIES variables are used. ! 46: * ! 47: * dev is the SCSI device number, *(int *) arg the length of the input ! 48: * data, *((int *)arg + 1) the output buffer. ! 49: * ! 50: * *(char *) ((int *) arg)[1] the actual command. ! 51: * ! 52: * Note that no more than MAX_BUF bytes will be transfered. Since ! 53: * SCSI block device size is 512 bytes, I figured 1K was good. ! 54: * ! 55: * This size * does * include the initial lengths that were passed. ! 56: * ! 57: * The SCSI command is read from the memory location immediately after the ! 58: * length words, and the out data after the command. The SCSI routines know the ! 59: * command size based on the length byte. ! 60: * ! 61: * The area is then filled in from the byte at offset 0. ! 62: */ ! 63: ! 64: static int the_result[MAX_SCSI_HOSTS]; ! 65: ! 66: static void scsi_ioctl_done (int host, int result) ! 67: { ! 68: the_result[host] = result; ! 69: } ! 70: ! 71: static int ioctl_command(Scsi_Device *dev, void *buffer) ! 72: { ! 73: char buf[MAX_BUF]; ! 74: char cmd[10]; ! 75: char * cmd_in; ! 76: unsigned char opcode; ! 77: int inlen, outlen, cmdlen, temp, host; ! 78: ! 79: if (!buffer) ! 80: return -EINVAL; ! 81: ! 82: inlen = get_fs_long((int *) buffer); ! 83: outlen = get_fs_long(((int *) buffer) + 1); ! 84: ! 85: cmd_in = (char *) ( ((int *)buffer) + 2); ! 86: opcode = get_fs_byte(cmd_in); ! 87: ! 88: memcpy_fromfs ((void *) cmd, cmd_in, cmdlen = COMMAND_SIZE (opcode)); ! 89: memcpy_fromfs ((void *) buf, (void *) (cmd_in + cmdlen), inlen); ! 90: host = dev->host_no; ! 91: ! 92: #ifndef DEBUG_NO_CMD ! 93: do { ! 94: cli(); ! 95: if (the_result[host]) { ! 96: sti(); ! 97: while(the_result[host]) ! 98: /* nothing */; ! 99: } else { ! 100: the_result[host]=-1; ! 101: sti(); ! 102: break; ! 103: } ! 104: } while (1); ! 105: ! 106: scsi_do_cmd(host, dev->id, cmd, buf, ((outlen > MAX_BUF) ? ! 107: MAX_BUF : outlen), scsi_ioctl_done, MAX_TIMEOUT, ! 108: buf, MAX_RETRIES); ! 109: ! 110: while (the_result[host] == -1) ! 111: /* nothing */; ! 112: temp = the_result[host]; ! 113: the_result[host]=0; ! 114: memcpy_tofs (buffer, buf, (outlen > MAX_BUF) ? MAX_BUF : outlen); ! 115: return temp; ! 116: #else ! 117: { ! 118: int i; ! 119: printk("scsi_ioctl : device %d. command = ", dev); ! 120: for (i = 0; i < 10; ++i) ! 121: printk("%02x ", cmd[i]); ! 122: printk("\r\nbuffer ="); ! 123: for (i = 0; i < 20; ++i) ! 124: printk("%02x ", buf[i]); ! 125: printk("\r\n"); ! 126: } ! 127: return 0; ! 128: #endif ! 129: } ! 130: ! 131: ! 132: /* ! 133: the scsi_ioctl() function differs from most ioctls in that it does ! 134: not take a major/minor number as the dev filed. Rather, it takes ! 135: an index in scsi_devices[] ! 136: */ ! 137: int scsi_ioctl (int dev, int cmd, void *arg) ! 138: { ! 139: if ((cmd != 0 && dev > NR_SCSI_DEVICES) || dev < 0) ! 140: return -ENODEV; ! 141: if ((cmd == 0 && dev > MAX_SCSI_HOSTS)) ! 142: return -ENODEV; ! 143: ! 144: switch (cmd) { ! 145: case SCSI_IOCTL_PROBE_HOST: ! 146: return ioctl_probe(dev, arg); ! 147: case SCSI_IOCTL_SEND_COMMAND: ! 148: return ioctl_command((Scsi_Device *) dev, arg); ! 149: default : ! 150: return -EINVAL; ! 151: } ! 152: } ! 153: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.