|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /*
25: * dx - menu based device exerciser tool.
26: *
27: * HISTORY
28: * 19-Mar-91 Doug Mitchell at NeXT
29: * Created.
30: */
31:
32: #import <bsd/sys/types.h>
33: #import <bsd/libc.h>
34: #import <driverkit/IOClient.h>
35: #import <driverkit/SCSIDiskClient.h>
36: #import <bsd/dev/SCSITypes.h>
37: #import <mach/mach_error.h>
38: #import "defaults.h"
39: #import "buflib.h"
40:
41: /*
42: * prototypes for private functions.
43: */
44: static void usage(char **argv);
45: static void print_menu();
46: static void setupCDB();
47: static void setupScsiReq(scsiReq_t *scsiReq, SCSIDmaDir_t dir);
48:
49: /*
50: * Menu stuff.
51: */
52: struct menu_entry {
53: char menu_c;
54: char *name;
55: void (*men_fcn)();
56: };
57:
58: /*
59: * User commands.
60: */
61: static void dxRead();
62: static void dxWrite();
63: static void cdbRead();
64: static void cdbWrite();
65: static void setTarget();
66: static void setLun();
67: static void setCount();
68: static void setBlock();
69: static void dxQuery();
70: static void dxCheckReady();
71: static void setByteCount();
72: static void setLoopCount();
73: static void getForm();
74: static void setForm();
75: static void getRemove();
76: static void fillWbuf();
77: static void dumpRbuf();
78: static void quit();
79: static void getDname();
80: static void dxEject();
81:
82: struct menu_entry me_array[] = {
83:
84: {'r', "Read " , dxRead }, {'w', "Write " , dxWrite },
85: {'R', "cdbRead " , cdbRead }, {'W', "cdbWrite " , cdbWrite },
86: {'c', "Set Count " , setCount }, {'b', "Set Block " , setBlock },
87: {'T', "Set Target " , setTarget }, {'L', "Set lun " , setLun },
88: {'Q', "Query " , dxQuery }, {'u', "Check Ready " , dxCheckReady },
89: {'y', "Max ByteCount" , setByteCount}, {'l', "Loop Count " , setLoopCount },
90: {'f', "Get Formatted" , getForm }, {'F', "Set Formatted" , setForm },
91: {'v', "Get Removable" , getRemove }, {'C', "Set up CDB " , setupCDB },
92: {'D', "GetDriveName " , getDname }, {'e', "Eject " , dxEject },
93: {'1', "Fill buffer " , fillWbuf }, {'2', "Dump Buffer " , dumpRbuf },
94: {'x', "Exit " , quit }, {'h', "Help " , print_menu },
95: {0, NULL , NULL }
96: };
97:
98: #define BUFSIZE (64 * 1024)
99:
100: /*
101: * Static variables.
102: */
103: int ioTimeout = 10;
104: int target = 0;
105: int lun = 0;
106: id clientId;
107: int count = 1024;
108: int block = 0;
109: int byteCountMax = 4096;
110: int loopCount = 1;
111: u_char cdb[12];
112: char *hostname=HOST_DEFAULT;
113: char *devname=DEVICE_DEFAULT;
114: char *rbuf, *wbuf;
115: IOErrorString errorstr;
116:
117: int main(int argc, char **argv)
118: {
119: int arg;
120: char instr[80];
121: struct menu_entry *mep;
122: int ok;
123: IOReturn rtn;
124: kern_return_t krtn;
125:
126: /*
127: * Get standard defaults from environment or defaults.h
128: */
129: get_default_t("hostname", &hostname, HOST_DEFAULT);
130: get_default_t("devname", &devname, DEVICE_DEFAULT);
131:
132: for(arg=1; arg<argc; arg++) {
133: switch(argv[arg][0]) {
134: case 'h':
135: hostname = &argv[arg][2];
136: break;
137: case 'd':
138: devname = &argv[arg][2];
139: break;
140: default:
141: usage(argv);
142: }
143: }
144:
145: /*
146: * Instantiate and init the client object. Use SCSIDiskClient as
147: * default.
148: */
149: rtn = [SCSIDiskClient clientOpen:devname
150: hostName:hostname
151: intentions:IO_INT_READ|IO_INT_WRITE
152: idp:&clientId];
153: if(rtn) {
154: /*
155: * try opening read only.
156: */
157: rtn = [SCSIDiskClient clientOpen:devname
158: hostName:hostname
159: intentions:IO_INT_READ
160: idp:&clientId];
161: if(rtn) {
162: [SCSIDiskClient ioError:rtn
163: logString:"Open"
164: outString:errorstr];
165: printf("%s...aborting\n", errorstr);
166: exit(1);
167: }
168: else
169: printf("...Warning: Device is Read-Only\n");
170: }
171:
172: /*
173: * Allocate and init read and write buffers.
174: */
175: krtn = vm_allocate(task_self(),
176: (vm_address_t *)&rbuf,
177: (vm_size_t)BUFSIZE,
178: TRUE);
179: if(krtn) {
180: mach_error("vm_allocate", krtn);
181: exit(1);
182: }
183: krtn = vm_allocate(task_self(),
184: (vm_address_t *)&wbuf,
185: (vm_size_t)BUFSIZE,
186: TRUE);
187: if(krtn) {
188: mach_error("vm_allocate", krtn);
189: exit(1);
190: }
191: bzero(rbuf, BUFSIZE);
192: bzero(wbuf, BUFSIZE);
193:
194: /*
195: * Enter main loop.
196: */
197: print_menu();
198: while(1) {
199: printf("Enter Selection: ");
200: gets(instr);
201: mep = me_array;
202: ok = 0;
203: while(mep->menu_c) {
204: if(mep->menu_c == instr[0]) {
205: ok = 1;
206: (*mep->men_fcn)();
207: break;
208: }
209: else
210: mep++;
211: }
212: if(!ok)
213: printf("***Illegal Selection\n");
214: }
215: return(0);
216: }
217:
218: static void usage(char **argv)
219: {
220: printf("usage: %s d[h=hostname] [d=devname]\n", argv[0]);
221: exit(1);
222: }
223:
224: static void print_menu() {
225:
226: struct menu_entry *mep;
227:
228: printf("\n");
229: mep = me_array;
230: while(mep->menu_c) {
231: printf(" %c: %s ",mep->menu_c,mep->name);
232: mep++;
233: if(mep->menu_c) {
234: printf(" %c: %s ",mep->menu_c,mep->name);
235: mep++;
236: }
237: printf("\n");
238: }
239: printf("\n");
240: } /* print_menu() */
241:
242: static void cdbRead()
243: {
244: scsiReq_t scsiReq;
245: scStatus rtn;
246:
247: setupScsiReq(&scsiReq, SCSI_DMA_READ);
248: rtn = [clientId sdCdbRead:&scsiReq buf:rbuf];
249: if(rtn) {
250: [IOClient ioError:rtn
251: logString:"sdCdbRead"
252: outString:errorstr];
253: printf("%s", errorstr);
254: }
255: else if(scsiReq.ioStatus)
256: printf("...sdCdbRead: ioStatus = %d\n", scsiReq.ioStatus);
257: else
258: printf("...OK\n");
259: }
260:
261: static void cdbWrite()
262: {
263: scsiReq_t scsiReq;
264: scStatus rtn;
265:
266: setupScsiReq(&scsiReq, SCSI_DMA_WRITE);
267: rtn = [clientId sdCdbWrite:&scsiReq buf:wbuf];
268: if(rtn)
269: if(rtn) {
270: [IOClient ioError:rtn
271: logString:"sdCdbWrite"
272: outString:errorstr];
273: printf("%s", errorstr);
274: }
275: else if(scsiReq.ioStatus)
276: printf("...sdCdbWrite: ioStatus = %d\n", scsiReq.ioStatus);
277: else
278: printf("...OK\n");
279: }
280:
281: static void setTarget()
282: {
283: char instr[100];
284:
285: printf("Enter new target (CR = %d): ", target);
286: gets(instr);
287: if(instr[0])
288: target = atoi(instr);
289: }
290:
291: static void setLun()
292: {
293: char instr[100];
294:
295: printf("Enter new lun (CR = %d): ", lun);
296: gets(instr);
297: if(instr[0])
298: lun = atoi(instr);
299: }
300:
301: static void setCount()
302: {
303: printf("Enter new count (CR = %d): ", count);
304: count = get_num(count, DEC);
305: }
306:
307: static void setBlock()
308: {
309: printf("Enter new block (CR = %d): ", block);
310: block = get_num(block, DEC);
311: }
312:
313: static void dxQuery()
314: {
315: u_int queryData;
316: IOReturn rtn;
317:
318: rtn = [clientId ioQuery:&queryData];
319: if(rtn) {
320: [IOClient ioError:rtn
321: logString:"ioQuery"
322: outString:errorstr];
323: printf(errorstr);
324: return;
325: }
326: printf(" queryData = 0x%X\n", queryData);
327: if(queryData & DQF_READABLE)
328: printf("\tDQF_READABLE\n");
329: if(queryData & DQF_WRITEABLE)
330: printf("\tDQF_WRITABLE\n");
331: if(queryData & DQF_RAND_ACC)
332: printf("\tDQF_RAND_ACC\n");
333: if(queryData & DQF_CAN_QUEUE)
334: printf("\tDQF_CAN_QUEUE\n");
335: if(queryData & DQF_CAN_RD_LOCK)
336: printf("\tDQF_CAN_RD_LOCK\n");
337: if(queryData & DQF_CAN_WRT_LOCK)
338: printf("\tDQF_CAN_WRT_LOCK\n");
339: if(queryData & DQF_IS_RD_LOCK)
340: printf("\tDQF_IS_RD_LOCK\n");
341: if(queryData & DQF_IS_WRT_LOCK)
342: printf("\tDQF_IS_WRT_LOCK\n");
343: if(queryData & DQF_EXCLUSIVE)
344: printf("\tDQF_EXCLUSIVE\n");
345: #ifdef notdef
346: printf(" block_size = 0x%X dev_size = %d\n",
347: queryData.block_size, queryData.dev_size);
348: #endif notdef
349: }
350:
351: static void dxRead()
352: {
353: u_int bytesXfr;
354: IOReturn rtn;
355:
356: rtn = [clientId ioRead:block
357: bytesReq:count
358: buf:rbuf
359: bytesXfr:&bytesXfr];
360: if(rtn) {
361: [IOClient ioError:rtn
362: logString:"ioRead"
363: outString:errorstr];
364: printf("%s", errorstr);
365: return;
366: }
367: if(bytesXfr != count) {
368: printf("bytesXfr = 0x%x, expected 0x%x\n",
369: bytesXfr, count);
370: }
371: }
372:
373: static void dxWrite()
374: {
375: u_int bytesXfr;
376: IOReturn rtn;
377:
378: rtn = [clientId ioWrite:block
379: bytesReq:count
380: buf:wbuf
381: bytesXfr:&bytesXfr];
382: if(rtn) {
383: [IOClient ioError:rtn
384: logString:"ioWrite"
385: outString:errorstr];
386: printf("%s", errorstr);
387: return;
388: }
389: if(bytesXfr != count) {
390: printf("bytesXfr = 0x%x, expected 0x%x\n",
391: bytesXfr, count);
392: }
393: }
394:
395: static void dxCheckReady()
396: {
397: DiskReadyState ready;
398: IOReturn rtn;
399:
400: rtn = [clientId updateReadyState:&ready];
401: if(rtn) {
402: [IOClient ioError:rtn
403: logString:"CheckReady"
404: outString:errorstr];
405: printf("%s", errorstr);
406: return;
407: }
408: switch(ready) {
409: case IO_Ready:
410: printf("...Disk Ready\n");
411: break;
412: case IO_NotReady:
413: printf("...Disk Not Ready\n");
414: break;
415: case IO_NoDisk:
416: printf("...No Disk\n");
417: break;
418: case IO_Ejecting:
419: printf("...Ejecting\n");
420: break;
421: }
422: return;
423: }
424:
425: static void setByteCount()
426: {
427: printf("Enter new max byte count (CR = %d): ", byteCountMax);
428: byteCountMax = get_num(byteCountMax, DEC);
429:
430: }
431:
432: static void setLoopCount()
433: {
434: printf("Enter new loop count (CR = %d): ", loopCount);
435: loopCount = get_num(loopCount, DEC);
436: }
437:
438: static void setupCDB()
439: {
440: char instr[80];
441: int i;
442:
443: printf("Hit ESC anytime to quit.\n");
444: for(i=0; i<12; i++) {
445: printf("Enter CDB byte %d (CR = 0x%x): ", i, cdb[i]);
446: gets(instr);
447: switch(instr[0]) {
448: case '\0':
449: break; /* take default */
450: case 0x1b:
451: return; /* ESC - done */
452: default:
453: cdb[i] = atoh(instr);
454: break;
455: }
456: }
457: }
458:
459: static void getForm()
460: {
461: u_int formFlag;
462: IOReturn rtn;
463:
464: rtn = [clientId getFormatted:&formFlag];
465: if(rtn) {
466: [IOClient ioError:rtn
467: logString:"getFormatted"
468: outString:errorstr];
469: printf("%s", errorstr);
470: return;
471: }
472: if(formFlag)
473: printf("...Disk Formatted\n");
474: else
475: printf("...Disk Unformatted\n");
476: }
477:
478: static void setForm()
479: {
480: u_int formFlag;
481: IOReturn rtn;
482: char instr[80];
483:
484: printf("New formatted value (0/1): ");
485: gets(instr);
486: if(instr[0] == '1')
487: formFlag = 1;
488: else
489: formFlag = 0;
490: rtn = [clientId setFormatted:formFlag];
491: if(rtn) {
492: [IOClient ioError:rtn
493: logString:"setFormatted"
494: outString:errorstr];
495: printf("%s", errorstr);
496: return;
497: }
498: else
499: printf("...OK\n");
500: }
501:
502: static void getRemove()
503: {
504: u_int removeFlag;
505: IOReturn rtn;
506:
507: rtn = [clientId getRemovable:&removeFlag];
508: if(rtn) {
509: [IOClient ioError:rtn
510: logString:"getRemovable"
511: outString:errorstr];
512: printf("%s", errorstr);
513: return;
514: }
515: if(removeFlag)
516: printf("...Removable Disk\n");
517: else
518: printf("...Fixed Disk\n");
519: }
520:
521: static void fillWbuf()
522: {
523: char instr[80];
524: int i;
525:
526: printf("z = zero\ni = incrementing\nd = decrementing\n");
527: printf("Enter pattern: ");
528: gets(instr);
529: switch(instr[0]) {
530: case 'z':
531: bzero(wbuf, BUFSIZE);
532: break;
533: case 'i':
534: for(i=0; i<BUFSIZE; i++)
535: wbuf[i] = i;
536: break;
537: case 'd':
538: for(i=0; i<BUFSIZE; i++)
539: wbuf[i] = BUFSIZE - i;
540: break;
541: default:
542: printf("***Illegal selection***\n");
543: break;
544: }
545: }
546:
547: static void dumpRbuf()
548: {
549: dump_buf((u_char *)rbuf, BUFSIZE);
550: }
551:
552: static void getDname()
553: {
554: /* const char *name; */
555:
556: printf("...getDriveName not supported\n");
557: return;
558: #ifdef notdef
559: name = [clientId getDriveName];
560: if(name == NULL) {
561: printf("NULL drivename\n");
562: return;
563: }
564: printf("Drive Name = %s\n", name);
565: return;
566: #endif notdef
567: }
568:
569: static void dxEject()
570: {
571: IOReturn rtn;
572:
573: rtn = [clientId eject];
574: if(rtn) {
575: [IOClient ioError:rtn
576: logString:"eject"
577: outString:errorstr];
578: printf("%s", errorstr);
579: return;
580: }
581: printf("...OK\n");
582: }
583:
584: /*
585: * Internal functions.
586: */
587: static void setupScsiReq(scsiReq_t *scsiReq, SCSIDmaDir_t dir)
588: {
589: bzero(scsiReq, sizeof(scsiReq_t));
590: scsiReq->target = target;
591: scsiReq->lun = lun;
592: scsiReq->cdb = *(cdb_t *)cdb;
593: scsiReq->dmaDir = dir;
594: scsiReq->dmaMax = byteCountMax;
595: scsiReq->ioTimeout = ioTimeout;
596: scsiReq->disconnect = 1;
597: }
598:
599: static void quit()
600: {
601: exit(0);
602: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.