|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26: /*
27: * File: rz_cpu.c
28: * Author: Alessandro Forin, Carnegie Mellon University
29: * Date: 7/91
30: *
31: * Top layer of the SCSI driver: interface with the MI.
32: * This file contains operations specific to CPU-like devices.
33: *
34: * We handle here the case of simple devices which do not use any
35: * sophisticated host-to-host communication protocol, they look
36: * very much like degenerative cases of TAPE devices.
37: *
38: * For documentation and debugging, we also provide code to act like one.
39: */
40:
41: #include <mach/std_types.h>
42: #include <scsi/compat_30.h>
43:
44: #include <scsi/scsi.h>
45: #include <scsi/scsi_defs.h>
46: #include <scsi/rz.h>
47:
48: #if (NSCSI > 0)
49:
50: void sccpu_act_as_target(); /* forwards */
51: void sccpu_start();
52:
53: /*
54: * This function decides which 'protocol' we well speak
55: * to a cpu target. For now the decision is left to a
56: * global var. XXXXXXX
57: */
58: extern scsi_devsw_t scsi_host;
59: scsi_devsw_t *scsi_cpu_protocol = /* later &scsi_host*/
60: &scsi_devsw[SCSI_CPU];
61:
62: void sccpu_new_initiator(self, initiator)
63: target_info_t *self, *initiator;
64: {
65: initiator->dev_ops = scsi_cpu_protocol;
66: if (initiator == self) {
67: self->flags = TGT_DID_SYNCH|TGT_FULLY_PROBED|TGT_ONLINE|
68: TGT_ALIVE|TGT_US;
69: self->dev_info.cpu.req_pending = FALSE;
70: } else {
71: initiator->flags = TGT_ONLINE|TGT_ALIVE;
72: initiator->dev_info.cpu.req_pending = TRUE;
73: }
74: }
75:
76: void sccpu_strategy(ior)
77: register io_req_t ior;
78: {
79: void sccpu_start();
80:
81: rz_simpleq_strategy(ior, sccpu_start);
82: }
83:
84: void sccpu_start(tgt, done)
85: target_info_t *tgt;
86: boolean_t done;
87: {
88: io_req_t head, ior;
89: scsi_ret_t ret;
90:
91: /* this is to the doc & debug code mentioned in the beginning */
92: if (!done && tgt->dev_info.cpu.req_pending) {
93: panic("sccpu_act_as_target called");
94: #if 0
95: sccpu_act_as_target( tgt);
96: #endif
97: return;
98: }
99:
100: ior = tgt->ior;
101: if (ior == 0)
102: return;
103:
104: if (done) {
105:
106: /* see if we must retry */
107: if ((tgt->done == SCSI_RET_RETRY) &&
108: ((ior->io_op & IO_INTERNAL) == 0)) {
109: delay(1000000);/*XXX*/
110: goto start;
111: } else
112: /* got a bus reset ? shouldn't matter */
113: if ((tgt->done == (SCSI_RET_ABORTED|SCSI_RET_RETRY)) &&
114: ((ior->io_op & IO_INTERNAL) == 0)) {
115: goto start;
116: } else
117:
118: /* check completion status */
119:
120: if (tgt->cur_cmd == SCSI_CMD_REQUEST_SENSE) {
121: scsi_sense_data_t *sns;
122:
123: ior->io_op = ior->io_temporary;
124: ior->io_error = D_IO_ERROR;
125: ior->io_op |= IO_ERROR;
126:
127: sns = (scsi_sense_data_t *)tgt->cmd_ptr;
128: if (scsi_debug)
129: scsi_print_sense_data(sns);
130:
131: if (scsi_check_sense_data(tgt, sns)) {
132: if (sns->u.xtended.ili) {
133: if (ior->io_op & IO_READ) {
134: int residue;
135:
136: residue = sns->u.xtended.info0 << 24 |
137: sns->u.xtended.info1 << 16 |
138: sns->u.xtended.info2 << 8 |
139: sns->u.xtended.info3;
140: if (scsi_debug)
141: printf("Cpu Short Read (%d)\n", residue);
142: /*
143: * NOTE: residue == requested - actual
144: * We only care if > 0
145: */
146: if (residue < 0) residue = 0;/* sanity */
147: ior->io_residual += residue;
148: ior->io_error = 0;
149: ior->io_op &= ~IO_ERROR;
150: /* goto ok */
151: }
152: }
153: }
154: }
155:
156: else if (tgt->done != SCSI_RET_SUCCESS) {
157:
158: if (tgt->done == SCSI_RET_NEED_SENSE) {
159:
160: ior->io_temporary = ior->io_op;
161: ior->io_op = IO_INTERNAL;
162: if (scsi_debug)
163: printf("[NeedSns x%x x%x]", ior->io_residual, ior->io_count);
164: scsi_request_sense(tgt, ior, 0);
165: return;
166:
167: } else if (tgt->done == SCSI_RET_RETRY) {
168: /* only retry here READs and WRITEs */
169: if ((ior->io_op & IO_INTERNAL) == 0) {
170: ior->io_residual = 0;
171: goto start;
172: } else{
173: ior->io_error = D_WOULD_BLOCK;
174: ior->io_op |= IO_ERROR;
175: }
176: } else {
177: ior->io_error = D_IO_ERROR;
178: ior->io_op |= IO_ERROR;
179: }
180: }
181:
182: if (scsi_debug)
183: printf("[Resid x%x]", ior->io_residual);
184:
185: /* dequeue next one */
186: head = ior;
187:
188: simple_lock(&tgt->target_lock);
189: ior = head->io_next;
190: tgt->ior = ior;
191: if (ior)
192: ior->io_prev = head->io_prev;
193: simple_unlock(&tgt->target_lock);
194:
195: iodone(head);
196:
197: if (ior == 0)
198: return;
199: }
200: ior->io_residual = 0;
201: start:
202: if (ior->io_op & IO_READ) {
203: ret = scsi_receive( tgt, ior );
204: } else if ((ior->io_op & IO_INTERNAL) == 0) {
205: ret = scsi_send( tgt, ior );
206: }
207: }
208:
209:
210: #if 0
211: /* XX turned off this code because it's impossible
212: to reference 'end' and other such magic symbols
213: from boot modules. */
214: /*
215: * This is a simple code to make us act as a dumb
216: * processor type. Use for debugging only.
217: */
218: static struct io_req sccpu_ior;
219: vm_offset_t sccpu_buffer; /* set this with debugger */
220:
221: void sccpu_act_as_target(self)
222: target_info_t *self;
223: {
224: static char inq_data[] = "\3\0\1\0\040\0\0\0Mach3.0 Processor Link v0.1";
225: static char sns_data[] = "\160\0\0\0\0\0\0\0\0";
226:
227: self->dev_info.cpu.req_pending = FALSE;
228: sccpu_ior.io_next = 0;
229: #define MAXSIZE 1024*64
230: sccpu_ior.io_count = (MAXSIZE < self->dev_info.cpu.req_len) ?
231: MAXSIZE : self->dev_info.cpu.req_len;
232:
233: switch (self->dev_info.cpu.req_cmd) {
234: case SCSI_CMD_INQUIRY:
235: sccpu_ior.io_data = inq_data; break;
236: case SCSI_CMD_REQUEST_SENSE:
237: sccpu_ior.io_data = sns_data; break;
238: default:
239: if (sccpu_buffer == 0) {
240: /* ( read my lips :-) */
241: /* extern char end[]; */
242: sccpu_buffer = trunc_page(kalloc(MAXSIZE));
243: }
244: sccpu_ior.io_data = (char*)sccpu_buffer; break;
245: }
246:
247: if (self->dev_info.cpu.req_cmd == SCSI_CMD_SEND) {
248: self->cur_cmd = SCSI_CMD_READ;
249: sccpu_ior.io_op = IO_READ;
250: } else {
251: self->cur_cmd = SCSI_CMD_WRITE;
252: sccpu_ior.io_op = IO_WRITE;
253: }
254: self->ior = &sccpu_ior;
255: }
256: #endif
257:
258: /*#define PERF*/
259: #ifdef PERF
260: int test_read_size = 512;
261: int test_read_nreads = 1000;
262: int test_read_bdev = 0;
263: int test_read_or_write = 1;
264:
265: #include <sys/time.h>
266: #include <machine/machspl.h> /* spl */
267:
268: test_read(max)
269: {
270: int i, ssk, usecs;
271: struct timeval start, stop;
272: spl_t s;
273:
274: if (max != 0)
275: test_read_nreads = max;
276:
277: s = spl0();
278: start = time;
279: if (test_read_or_write) read_test(); else write_test();
280: stop = time;
281: splx(s);
282:
283: usecs = stop.tv_usec - start.tv_usec;
284: if (usecs < 0) {
285: stop.tv_sec -= 1;
286: usecs += 1000000;
287: }
288: printf("Size %d count %d time %3d sec %d us\n",
289: test_read_size, test_read_nreads,
290: stop.tv_sec - start.tv_sec, usecs);
291: }
292:
293: read_test()
294: {
295: struct io_req io, io1;
296: register int i;
297:
298: bzero(&io, sizeof(io));
299: io.io_unit = test_read_bdev;
300: io.io_op = IO_READ;
301: io.io_count = test_read_size;
302: io.io_data = (char*)sccpu_buffer;
303: io1 = io;
304:
305: sccpu_strategy(&io);
306: for (i = 1; i < test_read_nreads; i += 2) {
307: io1.io_op = IO_READ;
308: sccpu_strategy(&io1);
309: iowait(&io);
310: io.io_op = IO_READ;
311: sccpu_strategy(&io);
312: iowait(&io1);
313: }
314: iowait(&io);
315: }
316:
317: write_test()
318: {
319: struct io_req io, io1;
320: register int i;
321:
322: bzero(&io, sizeof(io));
323: io.io_unit = test_read_bdev;
324: io.io_op = IO_WRITE;
325: io.io_count = test_read_size;
326: io.io_data = (char*)sccpu_buffer;
327: io1 = io;
328:
329: sccpu_strategy(&io);
330: for (i = 1; i < test_read_nreads; i += 2) {
331: io1.io_op = IO_WRITE;
332: sccpu_strategy(&io1);
333: iowait(&io);
334: io.io_op = IO_WRITE;
335: sccpu_strategy(&io);
336: iowait(&io1);
337: }
338: iowait(&io);
339: }
340:
341: tur_test()
342: {
343: struct io_req io;
344: register int i;
345: char *a;
346: struct timeval start, stop;
347: spl_t s;
348: target_info_t *tgt;
349:
350: bzero(&io, sizeof(io));
351: io.io_unit = test_read_bdev;
352: io.io_data = (char*)&io;/*unused but kernel space*/
353:
354: rz_check(io.io_unit, &a, &tgt);
355: s = spl0();
356: start = time;
357: for (i = 0; i < test_read_nreads; i++) {
358: io.io_op = IO_INTERNAL;
359: scsi_test_unit_ready(tgt,&io);
360: }
361: stop = time;
362: splx(s);
363: i = stop.tv_usec - start.tv_usec;
364: if (i < 0) {
365: stop.tv_sec -= 1;
366: i += 1000000;
367: }
368: printf("%d test-unit-ready took %3d sec %d us\n",
369: test_read_nreads,
370: stop.tv_sec - start.tv_sec, i);
371: }
372:
373: /*#define MEM_PERF*/
374: #ifdef MEM_PERF
375: int mem_read_size = 1024; /* ints! */
376: int mem_read_nreads = 1000;
377: volatile int *mem_read_address = (volatile int*)0xb0080000;
378: volatile int *mem_write_address = (volatile int*)0xb0081000;
379:
380: mem_test(max, which)
381: {
382: int i, ssk, usecs;
383: struct timeval start, stop;
384: int (*fun)(), mwrite_test(), mread_test(), mcopy_test();
385: spl_t s;
386:
387: if (max == 0)
388: max = mem_read_nreads;
389:
390: switch (which) {
391: case 1: fun = mwrite_test; break;
392: case 2: fun = mcopy_test; break;
393: default:fun = mread_test; break;
394: }
395:
396: s = spl0();
397: start = time;
398: for (i = 0; i < max; i++)
399: (*fun)(mem_read_size);
400: stop = time;
401: splx(s);
402:
403: usecs = stop.tv_usec - start.tv_usec;
404: if (usecs < 0) {
405: stop.tv_sec -= 1;
406: usecs += 1000000;
407: }
408: printf("Size %d count %d time %3d sec %d us\n",
409: mem_read_size*4, max,
410: stop.tv_sec - start.tv_sec, usecs);
411: }
412:
413: mread_test(max)
414: register int max;
415: {
416: register int i;
417: register volatile int *addr = mem_read_address;
418:
419: for (i = 0; i < max; i++) {
420: register int j = *addr++;
421: }
422: }
423: mwrite_test(max)
424: register int max;
425: {
426: register int i;
427: register volatile int *addr = mem_read_address;
428:
429: for (i = 0; i < max; i++) {
430: *addr++ = i;
431: }
432: }
433:
434: mcopy_test(max)
435: register int max;
436: {
437: register volatile int *from = mem_read_address;
438: register volatile int *to = mem_write_address;
439: register volatile int *endaddr;
440:
441: endaddr = to + max;
442: while (to < endaddr)
443: *to++ = *from++;
444:
445: }
446: #endif /*MEM_PERF*/
447:
448: #endif /*PERF*/
449:
450: #endif /* NSCSI > 0 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.