|
|
1.1 root 1: #include <linux/config.h>
2: #ifdef CONFIG_SCSI
3:
4: #include <asm/io.h>
5: #include <asm/segment.h>
6: #include <asm/system.h>
7:
1.1.1.2 ! root 8: #include <linux/errno.h>
1.1 root 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
1.1.1.2 ! root 19: #define MAX_BUF 8192
1.1 root 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: *
1.1.1.2 ! root 47: * dev is the SCSI device struct ptr, *(int *) arg is the length of the
! 48: * input data, if any, not including the command string & counts,
! 49: * *((int *)arg + 1) is the output buffer size in bytes.
1.1 root 50: *
1.1.1.2 ! root 51: * *(char *) ((int *) arg)[2] the actual command byte.
1.1 root 52: *
1.1.1.2 ! root 53: * Note that no more than MAX_BUF data bytes will be transfered. Since
1.1 root 54: * SCSI block device size is 512 bytes, I figured 1K was good.
1.1.1.2 ! root 55: * but (WDE) changed it to 8192 to handle large bad track buffers.
1.1 root 56: *
1.1.1.2 ! root 57: * This size *does not* include the initial lengths that were passed.
1.1 root 58: *
1.1.1.2 ! root 59: * The SCSI command is read from the memory location immediately after the
! 60: * length words, and the input data is right after the command. The SCSI
! 61: * routines know the command size based on the opcode decode.
1.1 root 62: *
1.1.1.2 ! root 63: * The output area is then filled in starting from the command byte.
1.1 root 64: */
65:
66: static int the_result[MAX_SCSI_HOSTS];
67:
68: static void scsi_ioctl_done (int host, int result)
69: {
70: the_result[host] = result;
71: }
72:
73: static int ioctl_command(Scsi_Device *dev, void *buffer)
74: {
75: char buf[MAX_BUF];
76: char cmd[10];
77: char * cmd_in;
78: unsigned char opcode;
79: int inlen, outlen, cmdlen, temp, host;
80:
81: if (!buffer)
82: return -EINVAL;
83:
84: inlen = get_fs_long((int *) buffer);
1.1.1.2 ! root 85: outlen = get_fs_long( ((int *) buffer) + 1);
1.1 root 86:
87: cmd_in = (char *) ( ((int *)buffer) + 2);
88: opcode = get_fs_byte(cmd_in);
89:
1.1.1.2 ! root 90: memcpy_fromfs ((void *) cmd, cmd_in, cmdlen = COMMAND_SIZE (opcode));
! 91: memcpy_fromfs ((void *) buf, (void *) (cmd_in + cmdlen), inlen);
1.1 root 92: host = dev->host_no;
93:
94: #ifndef DEBUG_NO_CMD
95: do {
96: cli();
97: if (the_result[host]) {
98: sti();
99: while(the_result[host])
100: /* nothing */;
101: } else {
102: the_result[host]=-1;
103: sti();
104: break;
105: }
106: } while (1);
107:
1.1.1.2 ! root 108: scsi_do_cmd(host, dev->id, cmd, buf, ((outlen > MAX_BUF) ?
! 109: MAX_BUF : outlen), scsi_ioctl_done, MAX_TIMEOUT,
! 110: buf, MAX_RETRIES);
1.1 root 111:
112: while (the_result[host] == -1)
113: /* nothing */;
114: temp = the_result[host];
1.1.1.2 ! root 115: the_result[host] = 0;
! 116: memcpy_tofs ((void *) cmd_in, buf, (outlen > MAX_BUF) ? MAX_BUF : outlen);
1.1 root 117: return temp;
118: #else
119: {
120: int i;
1.1.1.2 ! root 121: printk("scsi_ioctl : device %d. command = ", dev->id);
1.1 root 122: for (i = 0; i < 10; ++i)
123: printk("%02x ", cmd[i]);
124: printk("\r\nbuffer =");
125: for (i = 0; i < 20; ++i)
126: printk("%02x ", buf[i]);
127: printk("\r\n");
1.1.1.2 ! root 128: printk("inlen = %d, outlen = %d, cmdlen = %d\n",
! 129: inlen, outlen, cmdlen);
! 130: printk("buffer = %d, cmd_in = %d\n", buffer, cmd_in);
1.1 root 131: }
132: return 0;
133: #endif
134: }
135:
136:
137: /*
138: the scsi_ioctl() function differs from most ioctls in that it does
139: not take a major/minor number as the dev filed. Rather, it takes
1.1.1.2 ! root 140: a pointer to a scsi_devices[] element, a structure.
1.1 root 141: */
1.1.1.2 ! root 142: int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
1.1 root 143: {
1.1.1.2 ! root 144: if ((cmd != 0 && dev->id > NR_SCSI_DEVICES))
1.1 root 145: return -ENODEV;
1.1.1.2 ! root 146: if ((cmd == 0 && dev->host_no > MAX_SCSI_HOSTS))
1.1 root 147: return -ENODEV;
148:
149: switch (cmd) {
150: case SCSI_IOCTL_PROBE_HOST:
1.1.1.2 ! root 151: return ioctl_probe(dev->host_no, arg);
1.1 root 152: case SCSI_IOCTL_SEND_COMMAND:
153: return ioctl_command((Scsi_Device *) dev, arg);
154: default :
155: return -EINVAL;
156: }
157: }
158: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.