|
|
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.