|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1993-1989 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: scsi.c
28: * Author: Alessandro Forin, Carnegie Mellon University
29: * Date: 9/90
30: *
31: * Middle layer of the SCSI driver: chip independent functions
32: * This file contains Controller and Device-independent functions
33: */
34:
35: #include <scsi.h>
36:
37: #if NSCSI > 0
38: #include <platforms.h>
39:
40: #include <machine/machspl.h> /* spl definitions */
41:
42: #include <mach/std_types.h>
43: #include <sys/types.h>
44: #include <scsi/compat_30.h>
45:
46: #include <chips/busses.h>
47: #include <scsi/scsi.h>
48: #include <scsi/scsi2.h>
49: #include <scsi/scsi_defs.h>
50: #include <machine/machspl.h>
51:
52:
53:
54: #ifdef VAXSTATION
55: /* We run some of this code on the interrupt stack */
56: #undef spl0
57: #define spl0() spl1()
58: #endif /*VAXSTATION*/
59:
60: /*
61: * Overall driver state
62: */
63:
64: target_info_t scsi_target_data[NSCSI*8]; /* per target state */
65: scsi_softc_t scsi_softc_data[NSCSI]; /* per HBA state */
66: scsi_softc_t *scsi_softc[NSCSI]; /* quick access&checking */
67:
68: /*
69: * If a specific target should NOT be asked to go synchronous
70: * then its bit in this bitmap should be set. Each SCSI controller
71: * (Host Bus Adapter) can hold at most 8 targets --> use one
72: * byte per controller. A bit set to one means NO synchronous.
73: * Patch with adb if necessary.
74: */
75: unsigned char scsi_no_synchronous_xfer[NSCSI];
76:
77: /*
78: * For certain targets it is wise to use the long form of the
79: * read/write commands even if their capacity would not necessitate
80: * it. Same as above for usage.
81: */
82: unsigned char scsi_use_long_form[NSCSI];
83:
84:
85: /*
86: * Control over disconnect-reconnect mode.
87: */
88: unsigned char scsi_might_disconnect[NSCSI] = /* do it if deemed appropriate */
89: { 0xff, 0xff, 0xff, 0xff, 0xff};/* Fix by hand viz NSCSI */
90: unsigned char scsi_should_disconnect[NSCSI] = /* just do it */
91: { 0,};
92: unsigned char scsi_initiator_id[NSCSI] = /* our id on the bus(ses) */
93: { 7, 7, 7, 7, 7};
94:
95: /*
96: * Miscellaneus config
97: */
98: boolean_t scsi_exabyte_filemarks = FALSE; /* use short filemarks */
99: int scsi_watchdog_period = 10; /* but exabyte needs >=30 for bspace */
100: int scsi_delay_after_reset = 1000000;/* microseconds */
101: boolean_t scsi_no_automatic_bbr = FALSE; /* revector bad blocks automatically */
102:
103: #ifdef MACH_KERNEL
104: #else
105: /* This covers Exabyte's max record size */
106: unsigned int scsi_per_target_virtual = 256*1024;
107: #endif MACH_KERNEL
108:
109:
110: /*
111: * Device-specific operations are switched off this table
112: */
113:
114: extern char
115: *scdisk_name(), *sctape_name(), *scprt_name(),
116: *sccpu_name(), *scworm_name(), *sccdrom_name(),
117: *scscn_name(), *scmem_name(), *scjb_name(), *sccomm_name();
118: extern void
119: sctape_optimize();
120: extern scsi_ret_t
121: scdisk_open(), sctape_open(), sctape_close(),
122: sccomm_open(), sccomm_close();
123: extern int
124: scdisk_strategy(), sctape_strategy(), sccpu_strategy(),
125: sccomm_strategy();
126: extern void
127: scdisk_start(), sctape_start(), sccpu_start(), sccomm_start();
128:
129: extern io_return_t
130: scdisk_set_status(), scdisk_get_status(),
131: sctape_set_status(), sctape_get_status(),
132: sccomm_set_status(), sccomm_get_status();
133:
134: scsi_devsw_t scsi_devsw[] = {
135:
136: /* SCSI_DISK */ { scdisk_name, SCSI_OPTIMIZE_NULL,
137: scdisk_open, SCSI_CLOSE_NULL,
138: scdisk_strategy, scdisk_start,
139: scdisk_get_status, scdisk_set_status },
140:
141: /* SCSI_TAPE */ { sctape_name, sctape_optimize,
142: sctape_open, sctape_close,
143: sctape_strategy, sctape_start,
144: sctape_get_status, sctape_set_status },
145:
146: /* SCSI_PRINTER */ { scprt_name, SCSI_OPTIMIZE_NULL, /*XXX*/},
147:
148: /* SCSI_CPU */ { sccpu_name, SCSI_OPTIMIZE_NULL,
149: SCSI_OPEN_NULL, SCSI_CLOSE_NULL,
150: sccpu_strategy, sccpu_start,},
151:
152: /* SCSI_WORM */ { scworm_name, SCSI_OPTIMIZE_NULL,
153: scdisk_open, SCSI_CLOSE_NULL,
154: scdisk_strategy, scdisk_start,
155: scdisk_get_status, scdisk_set_status },
156:
157: /* SCSI_CDROM */ { sccdrom_name, SCSI_OPTIMIZE_NULL,
158: scdisk_open, SCSI_CLOSE_NULL,
159: scdisk_strategy, scdisk_start,
160: scdisk_get_status, scdisk_set_status },
161: /* scsi2 */
162: /* SCSI_SCANNER */ { scscn_name, SCSI_OPTIMIZE_NULL, /*XXX*/ },
163:
164: /* SCSI_MEMORY */ { scmem_name, SCSI_OPTIMIZE_NULL,
165: scdisk_open, SCSI_CLOSE_NULL,
166: scdisk_strategy, scdisk_start,
167: scdisk_get_status, scdisk_set_status },
168:
169: /* SCSI_J_BOX */ { scjb_name, SCSI_OPTIMIZE_NULL, /*XXX*/ },
170:
171: /* SCSI_COMM */ { sccomm_name, SCSI_OPTIMIZE_NULL,
172: #if (NCENDATA>0)
173: sccomm_open, sccomm_close,
174: sccomm_strategy, sccomm_start,
175: sccomm_get_status, sccomm_set_status
176: #endif
177: },
178: 0
179: };
180:
181: /*
182: * Allocation routines for state structures
183: */
184: scsi_softc_t *
185: scsi_master_alloc(unit, hw)
186: unsigned unit;
187: char *hw;
188: {
189: scsi_softc_t *sc;
190:
191: if (unit < NSCSI) {
192: sc = &scsi_softc_data[unit];
193: scsi_softc[unit] = sc;
194: sc->masterno = unit;
195: sc->hw_state = hw;
196: return sc;
197: }
198: return 0;
199: }
200:
201: target_info_t *
202: scsi_slave_alloc(unit, slave, hw)
203: unsigned unit, slave;
204: char *hw;
205: {
206: target_info_t *tgt;
207:
208: tgt = &scsi_target_data[(unit<<3) + slave];
209: tgt->hw_state = hw;
210: tgt->dev_ops = 0; /* later */
211: tgt->target_id = slave;
212: tgt->masterno = unit;
213: tgt->block_size = 1; /* default */
214: tgt->flags = TGT_ALIVE;
215: tgt->sync_period = 0;
216: tgt->sync_offset = 0;
217: simple_lock_init(&tgt->target_lock);
218:
219: scsi_softc[unit]->target[slave] = tgt;
220: return tgt;
221: }
222:
223: void
224: zero_ior(
225: io_req_t ior )
226: {
227: ior->io_next = ior->io_prev = 0;
228: ior->io_count = 0;
229: ior->io_op = IO_INTERNAL;
230: ior->io_error = 0;
231: }
232:
233: /*
234: * Slave routine:
235: * See if the slave description (controller, unit, ..)
236: * matches one of the slaves found during probe
237: *
238: * Implementation:
239: * Send out an INQUIRY command to see what sort of device
240: * the slave is.
241: * Notes:
242: * At this time the driver is fully functional and works
243: * off interrupts.
244: * TODO:
245: * The SCSI2 spec says what exactly must happen: see F.2.3
246: */
247: int scsi_slave( ui, reg)
248: struct bus_device *ui;
249: unsigned reg;
250: {
251: scsi_softc_t *sc = scsi_softc[(unsigned char)ui->ctlr];
252: target_info_t *tgt = sc->target[(unsigned char)ui->slave];
253: scsi2_inquiry_data_t *inq;
254: int scsi_std;
255: int ptype, s;
256:
257: if (!tgt || !(tgt->flags & TGT_ALIVE))
258: return 0;
259:
260: /* Might have scanned already */
261: if (tgt->dev_ops)
262: goto out;
263:
264: #ifdef SCSI2
265: This is what should happen:
266: - for all LUNs
267: INQUIRY
268: scsi_verify_state (see)
269: scsi_initialize (see)
270: #endif SCSI2
271:
272: tgt->unit_no = ui->slave; /* incorrect, but needed early */
273:
274: s = spl0(); /* we need interrupts */
275:
276: if (BGET(scsi_no_synchronous_xfer,(unsigned char)sc->masterno,tgt->target_id))
277: tgt->flags |= TGT_DID_SYNCH;
278:
279: /*
280: * Ok, it is time to see what type of device this is,
281: * send an INQUIRY cmd and wait till done.
282: * Possibly do the synch negotiation here.
283: */
284: scsi_inquiry(tgt, SCSI_INQ_STD_DATA);
285:
286: inq = (scsi2_inquiry_data_t*)tgt->cmd_ptr;
287: ptype = inq->periph_type;
288:
289: switch (ptype) {
290: case SCSI_CDROM :
291: tgt->flags |= TGT_READONLY;
292: /* fall through */
293: case SCSI_DISK :
294: case SCSI_TAPE :
295: case SCSI_PRINTER :
296: case SCSI_CPU :
297: case SCSI_WORM :
298: case SCSI_SCANNER :
299: case SCSI_MEMORY :
300: case SCSI_J_BOX :
301: case SCSI_COMM :
302: /* case SCSI_PREPRESS1 : reserved, really
303: case SCSI_PREPRESS2 : */
304: tgt->dev_ops = &scsi_devsw[ptype];
305: break;
306: default:
307: printf("scsi%d: %s %d (x%x). ", ui->ctlr,
308: "Unsupported device type at SCSI id", ui->slave,
309: inq->periph_type);
310: scsi_print_inquiry((scsi2_inquiry_data_t*)inq,
311: SCSI_INQ_STD_DATA, 0);
312: tgt->flags = 0;
313: splx(s);
314: return 0;
315: }
316:
317: if (inq->rmb)
318: tgt->flags |= TGT_REMOVABLE_MEDIA;
319:
320: /*
321: * Tell the user we know this target, then see if we
322: * can be a bit smart about it.
323: */
324: scsi_print_inquiry((scsi2_inquiry_data_t*)inq,
325: SCSI_INQ_STD_DATA, tgt->tgt_name);
326: if (scsi_debug)
327: scsi_print_inquiry((scsi2_inquiry_data_t*)inq,
328: SCSI_INQ_STD_DATA, 0);
329:
330: /*
331: * The above says if it currently behaves as a scsi2,
332: * however scsi1 might just be the default setting.
333: * The spec say that even if in scsi1 mode the target
334: * should answer to the full scsi2 inquiry spec.
335: */
336: scsi_std = (inq->ansi == 2 || inq->response_fmt == 2) ? 2 : 1;
337: #if nosey
338: if (scsi_std == 2) {
339: unsigned char supp_pages[256], i;
340: scsi2_impl_opdef_page_t *impl;
341:
342: scsi_inquiry(tgt, SCSI_INQ_SUPP_PAGES);
343: impl = (scsi2_impl_opdef_page_t *)inq;
344: npages = impl->page_len - 2;
345: bcopy(impl->supp_opdef, supp_pages, npages);
346:
347: for (i = 0; i < npages; i++) {
348: scsi_inquiry(tgt, supp_pages[i]);
349: scsi_print_inquiry(inq, supp_pages[i], 0);
350: }
351: }
352:
353: if (scsi_std == 2) {
354: scsi2_impl_opdef_page_t *impl;
355: int i;
356:
357: scsi_inquiry(tgt, SCSI_INQ_IMPL_OPDEF);
358: impl = (scsi2_impl_opdef_page_t *)inq;
359: for (i = 0; i < impl->page_len - 2; i++)
360: if (impl->supp_opdef[i] == SCSI2_OPDEF) {
361: scsi_change_definition(tgt, SCSI2_OPDEF);
362: /* if success .. */
363: tgt->flags |= TGT_SCSI_2_MODE;
364: break;
365: }
366: }
367: #endif nosey
368:
369: splx(s);
370: out:
371: return (strcmp(ui->name, (*tgt->dev_ops->driver_name)(TRUE)) == 0);
372: }
373:
374: #ifdef SCSI2
375: scsi_verify_state(...)
376: {
377: verify_state: send test_unit_ready up to 3 times, each time it fails
378: (with check condition) send a requeste_sense. It is ok to get UNIT ATTENTION
379: the first time only, NOT READY the second, only GOOD the last time.
380: If you get BUSY or RESERVATION CONFLICT retry.
381: }
382:
383: scsi_initialize(...)
384: {
385:
386: initialize: send start_unit with immed=0 (->disconnect), if fails
387: with check condition send requeste_sense and if "illegal request"
388: proceed anyways. Retry on BUSY.
389: Do a verify_state, then
390: disks:
391: - mode_sense (current) if ANSI2 or needed by vendor (!!!!)
392: and if check-condition&illegal-request goto capacity
393: - mode_sense (changeable)
394: - if needed do a mode_select (yes, 512)
395: - read_capacity
396: tapes:
397:
398: }
399: #endif SCSI2
400:
401: /*
402: * Attach routine:
403: * Fill in all the relevant per-slave data and make
404: * the slave operational.
405: *
406: * Implementation:
407: * Get target's status, start the unit and then
408: * switch off to device-specific functions to gather
409: * as much info as possible about the slave.
410: */
411: void scsi_attach(ui)
412: register struct bus_device *ui;
413: {
414: scsi_softc_t *sc = scsi_softc[ui->mi->unit];
415: target_info_t *tgt = sc->target[(unsigned char)ui->slave];
416: int i;
417: spl_t s;
418:
419: printf(" (%s %s) ", (*tgt->dev_ops->driver_name)(FALSE),tgt->tgt_name);
420:
421: if (tgt->flags & TGT_US) {
422: printf(" [this cpu]");
423: return;
424: }
425:
426: s = spl0();
427:
428: /* sense return from inquiry */
429: scsi_request_sense(tgt, 0, 0);
430:
431: /*
432: * Do this twice, certain targets need it
433: */
434: if (tgt->dev_ops != &scsi_devsw[SCSI_CPU]) {
435: (void) scsi_start_unit(tgt, SCSI_CMD_SS_START, 0);
436: i = 0;
437: while (scsi_start_unit(tgt, SCSI_CMD_SS_START, 0) == SCSI_RET_RETRY) {
438: if (i++ == 5)
439: printf(".. not yet online ..");
440: delay(1000000);
441: if (i == 60) {
442: printf(" seems hopeless.");
443: break;
444: }
445: }
446: }
447:
448: /*
449: * See if it is up and about
450: */
451: scsi_test_unit_ready(tgt, 0);
452:
453: if (tgt->dev_ops->optimize != SCSI_OPTIMIZE_NULL)
454: (*tgt->dev_ops->optimize)(tgt);
455:
456: tgt->flags |= TGT_FULLY_PROBED;
457:
458: splx(s);
459: }
460:
461: /*
462: * Probe routine:
463: * See if a device answers. Used AFTER autoconf.
464: *
465: * Implementation:
466: * First ask the HBA to see if anyone is there at all, then
467: * call the scsi_slave and scsi_attach routines with a fake ui.
468: */
469: boolean_t
470: scsi_probe( sc, tgt_ptr, target_id, ior)
471: scsi_softc_t *sc;
472: target_info_t **tgt_ptr;
473: int target_id;
474: io_req_t ior;
475: {
476: struct bus_device ui;
477: target_info_t *tgt;
478:
479: if (!sc->probe || target_id > 7 || target_id == sc->initiator_id)
480: return FALSE; /* sanity */
481:
482: if (sc->target[target_id] == 0)
483: scsi_slave_alloc( sc->masterno, target_id, sc->hw_state);
484: tgt = sc->target[target_id];
485: tgt->flags = 0;/* we donno yet */
486: tgt->dev_ops = 0;
487:
488: /* mildly enquire */
489: if (!(sc->probe)(tgt, ior))
490: goto fail;
491:
492: /* There is something there, see what it is */
493: bzero(&ui, sizeof(ui));
494: ui.ctlr = sc->masterno;
495: ui.unit =
496: ui.slave = target_id;
497: ui.name = "";
498:
499: /* this fails on the name for sure */
500: (void) scsi_slave( &ui, 0 /* brrrr */);
501: if ((tgt->flags & TGT_ALIVE) == 0)
502: goto fail;
503:
504: {
505: struct bus_ctlr mi;
506:
507: mi.unit = sc->masterno;
508: ui.mi = &mi;
509: printf("%s at slave %d ",
510: (*tgt->dev_ops->driver_name)(TRUE), target_id);
511: scsi_attach(&ui);
512: }
513:
514: *tgt_ptr = tgt;
515: return TRUE;
516: fail:
517: tgt->flags = 0;
518: return FALSE;
519: }
520:
521:
522: /*
523: * Watchdog routine:
524: * Issue a SCSI bus reset if a target holds up the
525: * bus for too long.
526: *
527: * Implementation:
528: * Each HBA that wants to use this should have a
529: * watchdog_t structure at the head of its hardware
530: * descriptor. This variable is set by this periodic
531: * routine and reset on bus activity. If it is not reset on
532: * time (say some ten seconds or so) we reset the
533: * SCSI bus.
534: * NOTE:
535: * An HBA must be ready to accept bus reset interrupts
536: * properly in order to use this.
537: */
538: void scsi_watchdog(hw)
539: watchdog_t *hw;
540: {
541: spl_t s = splbio();
542:
543: switch (hw->watchdog_state) {
544: case SCSI_WD_EXPIRED:
545:
546: /* double check first */
547: if (hw->nactive == 0) {
548: hw->watchdog_state = SCSI_WD_INACTIVE;
549: break;
550: }
551: if (scsi_debug)
552: printf("SCSI Watchdog expired\n");
553: hw->watchdog_state = SCSI_WD_INACTIVE;
554: (*hw->reset)(hw);
555: break;
556:
557: case SCSI_WD_ACTIVE:
558:
559: hw->watchdog_state = SCSI_WD_EXPIRED;
560: break;
561:
562: case SCSI_WD_INACTIVE:
563:
564: break;
565: }
566:
567: /* do this here, fends against powered down devices */
568: if (scsi_watchdog_period != 0)
569: timeout((int(*)())scsi_watchdog, (char*)hw, scsi_watchdog_period * hz);
570:
571: splx(s);
572: }
573:
574:
575: /*
576: * BusReset Notification:
577: * Called when the HBA sees a BusReset interrupt
578: *
579: * Implementation:
580: * Go through the list of targets, redo the synch
581: * negotiation, and restart whatever operation was
582: * in progress for that target.
583: */
584: void scsi_bus_was_reset(sc)
585: scsi_softc_t *sc;
586: {
587: register target_info_t *tgt;
588: int i;
589: /*
590: * Redo the synch negotiation
591: */
592: for (i = 0; i < 8; i++) {
593: io_req_t ior;
594: spl_t s;
595:
596: if (i == sc->initiator_id)
597: continue;
598: tgt = sc->target[i];
599: if (!tgt || !(tgt->flags & TGT_ALIVE))
600: continue;
601:
602: tgt->flags &= ~(TGT_DID_SYNCH|TGT_DISCONNECTED);
603: #if 0
604: /* the standard does *not* imply this gets reset too */
605: tgt->sync_period = 0;
606: tgt->sync_offset = 0;
607: #endif
608:
609: /*
610: * retry the synch negotiation
611: */
612: ior = tgt->ior;
613: tgt->ior = 0;
614: printf(".. tgt %d ", tgt->target_id);
615: if (BGET(scsi_no_synchronous_xfer,(unsigned char)sc->masterno,tgt->target_id))
616: tgt->flags |= TGT_DID_SYNCH;
617: else {
618: s = spl0();
619: scsi_test_unit_ready(tgt, 0);
620: splx(s);
621: }
622: tgt->ior = ior;
623: }
624:
625: /*
626: * Notify each target of the accident
627: */
628: for (i = 0; i < 8; i++) {
629: if (i == sc->initiator_id)
630: continue;
631: tgt = sc->target[i];
632: if (!tgt)
633: continue;
634: tgt->done = SCSI_RET_ABORTED|SCSI_RET_RETRY;
635: if (tgt->ior)
636: (*tgt->dev_ops->restart)( tgt, TRUE);
637: }
638:
639: printf("%s", " reset complete\n");
640: }
641:
642: #endif NSCSI > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.