|
|
1.1 root 1: /*
2: * scsi_commands.c: scsi command functions
3: *
4: * History
5: * -------
6: * 02-Feb-93 Erik Kay at NeXT
7: * i386 support
8: * Tue Sep 3 15:00:13 PDT 1991 James C. Lee at NeXT
9: * Created (copied a lot of data structures & functions calls from
10: * perftest.c by Mike DeMoney)
11: */
12:
13: #import "scsi_commands.h"
14: #import <sys/time.h>
15: #import <bsd/dev/disk.h>
16: #import <bsd/dev/scsireg.h>
17: #import <stdio.h>
18: #import <libc.h>
19: #import <stdlib.h>
20:
21:
22: void fatal(const char *msg, ...)
23: {
24: va_list ap;
25:
26: va_start(ap, msg);
27: /* fprintf(stderr, "%s: ", progname);*/
28: vfprintf(stderr, msg, ap);
29: fprintf(stderr, "\n");
30: va_end(ap);
31:
32: exit(1);
33: }
34:
35: inline int is_pow2(int i)
36: {
37: return (i & (i - 1)) == 0;
38: }
39:
40: int do_inquiry(int fd, struct inquiry_reply *irp, struct esense_reply *erp)
41: {
42: struct scsi_req sr;
43: struct cdb_6 *c6p;
44: int err;
45:
46: bzero((char *)&sr, sizeof(sr));
47:
48: c6p = (struct cdb_6 *)&sr.sr_cdb;
49: c6p->c6_opcode = C6OP_INQUIRY;
50: c6p->c6_len = sizeof(*irp);
51:
52: sr.sr_addr = (char *)irp;
53: sr.sr_dma_max = sizeof(*irp);
54: sr.sr_ioto = 5;
55: sr.sr_dma_dir = SR_DMA_RD;
56:
57: err = ioctl(fd, SDIOCSRQ, &sr);
58: *erp = sr.sr_esense;
59: return err | sr.sr_io_status;
60: }
61:
62: int do_testunitready(int fd, struct timeval *tvp, struct esense_reply *erp)
63: {
64: struct scsi_req sr;
65: struct cdb_6 *c6p;
66: int err;
67:
68: bzero((char *)&sr, sizeof(sr));
69:
70: c6p = (struct cdb_6 *)&sr.sr_cdb;
71: c6p->c6_opcode = C6OP_TESTRDY;
72:
73: sr.sr_addr = NULL;
74: sr.sr_dma_max = 0;
75: sr.sr_ioto = 5;
76: sr.sr_dma_dir = SR_DMA_RD;
77:
78: err = ioctl(fd, SDIOCSRQ, &sr);
79:
80: *tvp = sr.sr_exec_time;
81:
82: *erp = sr.sr_esense;
83: return err | sr.sr_io_status;
84: }
85:
86: int do_modesense(int fd, struct mode_sense_reply *msrp, int page,
87: struct esense_reply *erp)
88: {
89: struct scsi_req sr;
90: struct mode_sense_cmd *mscp;
91: int err;
92:
93: bzero((char *)&sr, sizeof(sr));
94:
95: mscp = (struct mode_sense_cmd *)&sr.sr_cdb;
96: mscp->msc_opcode = C6OP_MODESENSE;
97: mscp->msc_pcf = 0; /* report current values */
98: mscp->msc_page = page;
99: mscp->msc_len = sizeof(*msrp);
100:
101: sr.sr_addr = (char *)msrp;
102: sr.sr_dma_max = sizeof(*msrp);
103: /*
104: * Extend timeout so Quantum drive works with test.
105: */
106: sr.sr_ioto = 50;
107: sr.sr_dma_dir = SR_DMA_RD;
108:
109: err = ioctl(fd, SDIOCSRQ, &sr);
110:
111: printf("sr.sr_io_status: %d\n", sr.sr_io_status);
112: *erp = sr.sr_esense;
113: return err | sr.sr_io_status;
114: }
115:
116: int do_readcapacity(int fd, struct capacity_reply *crp,
117: struct esense_reply *erp)
118: {
119: struct scsi_req sr;
120: struct cdb_10 *c10p;
121: int err;
122:
123: bzero((char *)&sr, sizeof(sr.sr_cdb));
124:
125: c10p = (struct cdb_10 *)&sr.sr_cdb;
126: c10p->c10_opcode = C10OP_READCAPACITY;
127:
128: sr.sr_addr = (char *)crp;
129: sr.sr_dma_max = sizeof(*crp);
130: sr.sr_ioto = 5;
131: sr.sr_dma_dir = SR_DMA_RD;
132:
133: err = ioctl(fd, SDIOCSRQ, &sr);
134: *erp = sr.sr_esense;
135: return err | sr.sr_io_status;
136: }
137:
138: int do_seek(int fd, int lba, struct timeval *tvp, struct esense_reply *erp)
139: {
140: struct scsi_req sr;
141: struct cdb_6 *c6p;
142: int err;
143:
144: bzero((char *)&sr, sizeof(sr));
145:
146: c6p = (struct cdb_6 *)&sr.sr_cdb;
147: c6p->c6_opcode = C6OP_SEEK;
148: #ifdef i386
149: if (lba > 0) {
150: c6p->c6_lba0 = lba & 0xFF;
151: c6p->c6_lba1 = (lba >> 8) & 0xFF;
152: c6p->c6_lba2 = (lba >> 16) & 0xFF;
153: } else
154: c6p->c6_lba0 = c6p->c6_lba1 = c6p->c6_lba2 = 0;
155: #else
156: c6p->c6_lba = lba;
157: #endif
158:
159: sr.sr_addr = 0;
160: sr.sr_dma_max = 0; /* don't really do I/O to memory */
161: sr.sr_ioto = 5;
162: sr.sr_dma_dir = SR_DMA_RD;
163:
164: err = ioctl(fd, SDIOCSRQ, &sr);
165:
166: *tvp = sr.sr_exec_time;
167:
168: *erp = sr.sr_esense;
169: return err | sr.sr_io_status;
170: }
171:
172: int do_read(int fd, int lba, int nblks, struct timeval *tvp,
173: struct esense_reply *erp)
174: {
175: struct scsi_req sr;
176: struct cdb_6 *c6p;
177: int err;
178:
179: if (nblks > 256)
180: fatal("Too many blocks for read: %d", nblks);
181: if (nblks == 256)
182: nblks = 0;
183:
184: bzero((char *)&sr, sizeof(sr));
185:
186: c6p = (struct cdb_6 *)&sr.sr_cdb;
187: c6p->c6_opcode = C6OP_READ;
188: #ifdef i386
189: if (lba > 0) {
190: c6p->c6_lba0 = lba & 0xFF;
191: c6p->c6_lba1 = (lba >> 8) & 0xFF;
192: c6p->c6_lba2 = (lba >> 16) & 0xFF;
193: } else
194: c6p->c6_lba0 = c6p->c6_lba1 = c6p->c6_lba2 = 0;
195: #else
196: c6p->c6_lba = lba;
197: #endif
198: c6p->c6_len = nblks;
199:
200: sr.sr_addr = NULL;
201: sr.sr_dma_max = 0; /* don't really do I/O to memory */
202: sr.sr_ioto = 5;
203: sr.sr_dma_dir = SR_DMA_RD;
204:
205: err = ioctl(fd, SDIOCSRQ, &sr);
206:
207: *tvp = sr.sr_exec_time;
208:
209: if (sr.sr_dma_xfr != 0)
210: fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
211:
212: *erp = sr.sr_esense;
213: return err | sr.sr_io_status;
214: }
215:
216: int do_write(int fd, int lba, int nblks, struct timeval *tvp,
217: struct esense_reply *erp)
218: {
219: struct scsi_req sr;
220: struct cdb_6 *c6p;
221: int err;
222:
223: if (nblks > 256)
224: fatal("Too many blocks for read: %d", nblks);
225: if (nblks == 256)
226: nblks = 0;
227:
228: bzero((char *)&sr, sizeof(sr));
229:
230: c6p = (struct cdb_6 *)&sr.sr_cdb;
231: c6p->c6_opcode = C6OP_WRITE;
232: #ifdef i386
233: if (lba > 0) {
234: c6p->c6_lba0 = lba & 0xFF;
235: c6p->c6_lba1 = (lba >> 8) & 0xFF;
236: c6p->c6_lba2 = (lba >> 16) & 0xFF;
237: } else
238: c6p->c6_lba0 = c6p->c6_lba1 = c6p->c6_lba2 = 0;
239: #else
240: c6p->c6_lba = lba;
241: #endif
242: c6p->c6_len = nblks;
243:
244: sr.sr_addr = NULL;
245: sr.sr_dma_max = 0; /* don't really do I/O to memory */
246: sr.sr_ioto = 5;
247: sr.sr_dma_dir = SR_DMA_WR;
248:
249: err = ioctl(fd, SDIOCSRQ, &sr);
250:
251: *tvp = sr.sr_exec_time;
252:
253: if (sr.sr_dma_xfr != 0)
254: fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
255:
256: *erp = sr.sr_esense;
257: return err | sr.sr_io_status;
258: }
259:
260: #if 0
261: int do_readbuffer(int fd, int alloc_len, int *avail_len, struct timeval *tvp,
262: struct esense_reply *erp)
263: {
264: struct scsi_req sr;
265: struct cdb_10 *c10p;
266: int err;
267:
268: bzero((char *)&sr, sizeof(sr));
269:
270: c10p = (struct cdb_10 *)&sr.sr_cdb;
271: c10p->c10_opcode = 0x3C;
272: c10p->c10_len = alloc_len;
273:
274: sr.sr_addr = (char *)avail_len;
275: sr.sr_dma_max = alloc_len > 4 ? 0 : alloc_len;
276: sr.sr_ioto = 5;
277: sr.sr_dma_dir = SR_DMA_RD;
278:
279: err = ioctl(fd, SDIOCSRQ, &sr);
280:
281: *tvp = sr.sr_exec_time;
282:
283: *erp = sr.sr_esense;
284: return err | sr.sr_io_status;
285: }
286:
287: int do_writebuffer(int fd, int alloc_len, struct timeval *tvp,
288: struct esense_reply *erp)
289: {
290: struct scsi_req sr;
291: struct cdb_10 *c10p;
292: int err;
293:
294: bzero((char *)&sr, sizeof(sr));
295:
296: c10p = (struct cdb_10 *)&sr.sr_cdb;
297: c10p->c10_opcode = 0x3B;
298: c10p->c10_len = alloc_len;
299:
300: sr.sr_addr = NULL;
301: sr.sr_dma_max = 0;
302: sr.sr_ioto = 5;
303: sr.sr_dma_dir = SR_DMA_WR;
304:
305: err = ioctl(fd, SDIOCSRQ, &sr);
306:
307: *tvp = sr.sr_exec_time;
308:
309: *erp = sr.sr_esense;
310: return err | sr.sr_io_status;
311: }
312: #endif
313:
314:
315: void sprint_er(char *string, struct esense_reply *erp)
316: {
317: #ifdef i386
318: unsigned int errinfo;
319: #endif
320: sprintf(string, " Valid : %d\n", erp->er_ibvalid);
321: sprintf(string, "%s ErCode : 0x%x\n", string,
322: erp->er_class << (4+erp->er_code));
323: sprintf(string, "%s Segment : %d\n", string, erp->er_segment);
324: sprintf(string, "%s ILI : %d\n", string, erp->er_badlen);
325: sprintf(string, "%s SenseKey : 0x%x\n", string, erp->er_sensekey);
326: #ifdef i386
327: errinfo = erp->er_info2 << 16 + erp->er_info1 << 8 + erp->er_info0;
328: sprintf(string, "%s Info : 0x%x%x\n", string,
329: erp->er_info3, errinfo);
330: #else
331: sprintf(string, "%s Info : 0x%x%x\n", string,
332: erp->er_infomsb, erp->er_info);
333: #endif
334: sprintf(string, "%s AddSenseLength : %d\n", string, erp->er_addsenselen);
335: sprintf(string, "%s CmdInfo : %d\n", string, erp->er_rsvd8);
336: sprintf(string, "%s AddSenseCode : 0x%x\n", string,
337: erp->er_addsensecode);
338: sprintf(string, "%s AddSenseCodeQual: 0x%x\n", string, erp->er_qualifier);
339:
340: return;
341: }
342:
343: #if 0
344: void fprint_er(int fd, struct esense_reply *erp)
345: {
346: fprintf(fd, " Valid : %d\n", erp->er_ibvalid);
347: fprintf(fd, " ErCode : 0x%x\n",
348: erp->er_class<<4+erp->er_code);
349: fprintf(fd, " Segment : %d\n", erp->er_segment);
350: fprintf(fd, " ILI : %d\n", erp->er_badlen);
351: fprintf(fd, " SenseKey : 0x%x\n", erp->er_sensekey);
352: fprintf(fd, " Info : 0x%x%x\n", erp->er_infomsb,
353: erp->er_info);
354: fprintf(fd, " AddSenseLength : %d\n", erp->er_addsenselen);
355: fprintf(fd, " CmdInfo : %d\n", erp->er_rsvd8);
356: fprintf(fd, " AddSenseCode : 0x%x\n", erp->er_addsensecode);
357: fprintf(fd, " AddSenseCodeQual: 0x%x\n", erp->er_qualifier);
358:
359: return;
360: }
361: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.