FreeBSD/Linux Kernel Cross Reference
sys/scsi/scsi.c
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 Software.Distribution@CS.CMU.EDU
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 * HISTORY
28 * $Log: scsi.c,v $
29 * Revision 2.21 93/08/03 12:34:16 mrt
30 * Moved zero_ior() here.
31 * [93/07/29 23:37:16 af]
32 *
33 * Make CDROMs readonly.
34 * [93/05/06 10:07:01 af]
35 *
36 * Revision 2.20 93/05/15 19:43:07 mrt
37 * machparam.h -> machspl.h
38 *
39 * Revision 2.19 93/05/10 21:22:49 rvb
40 * Make CDROMs readonly.
41 * [93/05/06 10:07:01 af]
42 *
43 * Revision 2.18 93/03/09 10:57:52 danner
44 * By default, do not require any enquiry-time operations to
45 * be done on devices. The only case so far was a tape drive
46 * from <unnamed> who required a receive_diagnostics() at powerup.
47 * [93/03/06 af]
48 *
49 * Changes to make SCSI_MEMORY (optical direct access media) work.
50 * [93/02/17 jeffreyh]
51 *
52 * In scsi_bus_was_reset(). Fixed second loop to touch all
53 * targets for which we have a descriptor. The problem is
54 * with dynamic probe and spinup of disks, assuming the disk
55 * takes a loooong time we endup resetting the bus while
56 * the scsi_inquiry() routine is spinning on tgt->done.
57 * [93/02/06 af]
58 *
59 * Revision 2.17 93/01/14 17:55:45 danner
60 * Use SCSI_{OPEN,CLOSE,OPTIMIZE}_NULL
61 * [93/01/14 danner]
62 *
63 * Added initializers for up to 5 scsi busses. Proper spl typing.
64 * [92/12/01 af]
65 *
66 * Revision 2.16 92/08/03 17:54:24 jfriedl
67 * removed silly prototypes
68 * [92/08/02 jfriedl]
69 *
70 * Revision 2.15 92/05/21 17:24:02 jfriedl
71 * Cleanup to quiet gcc warnings.
72 * [92/05/16 jfriedl]
73 *
74 * Revision 2.14 92/05/05 10:47:14 danner
75 * Reduced reset delay; knows about not probing itself;
76 * do not clear synch params on reset.
77 * [92/05/04 17:17:45 af]
78 *
79 * Revision 2.13 92/02/23 22:44:40 elf
80 * Changed the interface of a number of functions not to
81 * require the scsi_softc pointer any longer. It was
82 * mostly unused, now it can be found via tgt->masterno.
83 * [92/02/22 19:30:58 af]
84 *
85 * Revision 2.12 91/08/24 12:28:21 af
86 * Spls defs, corrected scsi_master_alloc() to allocate
87 * as expected, support for processor devices,
88 * made it possible to avoid sync neg at all (for rb's sake),
89 * no start unit on processor devices, understand our
90 * own descriptor.
91 * [91/08/02 04:01:50 af]
92 *
93 * Revision 2.11 91/07/09 23:22:46 danner
94 * Added gross luna88k ifdef to use <sd.h> instead of <scsi.h>. Will be
95 * fixed when I understand how to use the configuration tools.
96 * [91/07/09 11:08:15 danner]
97 *
98 * Revision 2.10 91/06/25 20:56:48 rpd
99 * Tweaks to make gcc happy.
100 *
101 * Revision 2.9 91/06/19 11:57:17 rvb
102 * mips->DECSTATION; vax->VAXSTATION
103 * [91/06/12 14:02:21 rvb]
104 *
105 * File moved here from mips/PMAX since it is now "MI" code, also
106 * used by Vax3100 and soon -- the omron luna88k.
107 * [91/06/04 rvb]
108 *
109 * Printing of 'unsupported..' in scsi_slave was screwed cuz
110 * ui->mi and ui->unit could be bogus at that point in time.
111 * [91/05/30 af]
112 *
113 * Revision 2.8 91/05/14 17:28:00 mrt
114 * Correcting copyright
115 *
116 * Revision 2.7 91/05/13 06:04:45 af
117 * Added flags to control use of disconnect-reconnect mode.
118 * Added device-specific close routine (for tapes).
119 * Wait for start_unit to complete properly and tell the user
120 * what we are waiting for.
121 * [91/05/12 16:21:16 af]
122 *
123 * Revision 2.6.1.1 91/03/29 16:59:15 af
124 * Added flags to control use of disconnect-reconnect mode.
125 * Added device-specific close routine (for tapes).
126 * Wait for start_unit to complete properly and tell the user
127 * what we are waiting for.
128 *
129 * Revision 2.6 91/02/05 17:44:35 mrt
130 * Added author notices
131 * [91/02/04 11:18:01 mrt]
132 *
133 * Changed to use new Mach copyright
134 * [91/02/02 12:16:40 mrt]
135 *
136 * Revision 2.5 90/12/05 23:34:36 af
137 * Cleanups, still awaits SCSI-2 fixes.
138 * [90/12/03 23:38:14 af]
139 *
140 * Revision 2.3.1.1 90/11/01 03:38:17 af
141 * Created.
142 * [90/09/03 af]
143 */
144 /*
145 * File: scsi.c
146 * Author: Alessandro Forin, Carnegie Mellon University
147 * Date: 9/90
148 *
149 * Middle layer of the SCSI driver: chip independent functions
150 * This file contains Controller and Device-independent functions
151 */
152
153 #include <scsi.h>
154
155 #if NSCSI > 0
156 #include <platforms.h>
157
158 #include <machine/machspl.h> /* spl definitions */
159
160 #include <mach/std_types.h>
161 #include <sys/types.h>
162 #include <scsi/compat_30.h>
163
164 #include <chips/busses.h>
165 #include <scsi/scsi.h>
166 #include <scsi/scsi2.h>
167 #include <scsi/scsi_defs.h>
168 #include <machine/machspl.h>
169
170
171
172 #ifdef VAXSTATION
173 /* We run some of this code on the interrupt stack */
174 #undef spl0
175 #define spl0() spl1()
176 #endif /*VAXSTATION*/
177
178 /*
179 * Overall driver state
180 */
181
182 target_info_t scsi_target_data[NSCSI*8]; /* per target state */
183 scsi_softc_t scsi_softc_data[NSCSI]; /* per HBA state */
184 scsi_softc_t *scsi_softc[NSCSI]; /* quick access&checking */
185
186 /*
187 * If a specific target should NOT be asked to go synchronous
188 * then its bit in this bitmap should be set. Each SCSI controller
189 * (Host Bus Adapter) can hold at most 8 targets --> use one
190 * byte per controller. A bit set to one means NO synchronous.
191 * Patch with adb if necessary.
192 */
193 unsigned char scsi_no_synchronous_xfer[NSCSI];
194
195 /*
196 * For certain targets it is wise to use the long form of the
197 * read/write commands even if their capacity would not necessitate
198 * it. Same as above for usage.
199 */
200 unsigned char scsi_use_long_form[NSCSI];
201
202
203 /*
204 * Control over disconnect-reconnect mode.
205 */
206 unsigned char scsi_might_disconnect[NSCSI] = /* do it if deemed appropriate */
207 { 0xff, 0xff, 0xff, 0xff, 0xff};/* Fix by hand viz NSCSI */
208 unsigned char scsi_should_disconnect[NSCSI] = /* just do it */
209 { 0,};
210 unsigned char scsi_initiator_id[NSCSI] = /* our id on the bus(ses) */
211 { 7, 7, 7, 7, 7};
212
213 /*
214 * Miscellaneus config
215 */
216 boolean_t scsi_exabyte_filemarks = FALSE; /* use short filemarks */
217 int scsi_watchdog_period = 10; /* but exabyte needs >=30 for bspace */
218 int scsi_delay_after_reset = 1000000;/* microseconds */
219 boolean_t scsi_no_automatic_bbr = FALSE; /* revector bad blocks automatically */
220
221 #ifdef MACH_KERNEL
222 #else
223 /* This covers Exabyte's max record size */
224 unsigned int scsi_per_target_virtual = 256*1024;
225 #endif MACH_KERNEL
226
227
228 /*
229 * Device-specific operations are switched off this table
230 */
231
232 extern char
233 *scdisk_name(), *sctape_name(), *scprt_name(),
234 *sccpu_name(), *scworm_name(), *sccdrom_name(),
235 *scscn_name(), *scmem_name(), *scjb_name(), *sccomm_name();
236 extern void
237 sctape_optimize();
238 extern scsi_ret_t
239 scdisk_open(), sctape_open(), sctape_close(),
240 sccomm_open(), sccomm_close();
241 extern int
242 scdisk_strategy(), sctape_strategy(), sccpu_strategy(),
243 sccomm_strategy();
244 extern void
245 scdisk_start(), sctape_start(), sccpu_start(), sccomm_start();
246
247 extern io_return_t
248 scdisk_set_status(), scdisk_get_status(),
249 sctape_set_status(), sctape_get_status(),
250 sccomm_set_status(), sccomm_get_status();
251
252 scsi_devsw_t scsi_devsw[] = {
253
254 /* SCSI_DISK */ { scdisk_name, SCSI_OPTIMIZE_NULL,
255 scdisk_open, SCSI_CLOSE_NULL,
256 scdisk_strategy, scdisk_start,
257 scdisk_get_status, scdisk_set_status },
258
259 /* SCSI_TAPE */ { sctape_name, sctape_optimize,
260 sctape_open, sctape_close,
261 sctape_strategy, sctape_start,
262 sctape_get_status, sctape_set_status },
263
264 /* SCSI_PRINTER */ { scprt_name, SCSI_OPTIMIZE_NULL, /*XXX*/},
265
266 /* SCSI_CPU */ { sccpu_name, SCSI_OPTIMIZE_NULL,
267 SCSI_OPEN_NULL, SCSI_CLOSE_NULL,
268 sccpu_strategy, sccpu_start,},
269
270 /* SCSI_WORM */ { scworm_name, SCSI_OPTIMIZE_NULL,
271 scdisk_open, SCSI_CLOSE_NULL,
272 scdisk_strategy, scdisk_start,
273 scdisk_get_status, scdisk_set_status },
274
275 /* SCSI_CDROM */ { sccdrom_name, SCSI_OPTIMIZE_NULL,
276 scdisk_open, SCSI_CLOSE_NULL,
277 scdisk_strategy, scdisk_start,
278 scdisk_get_status, scdisk_set_status },
279 /* scsi2 */
280 /* SCSI_SCANNER */ { scscn_name, SCSI_OPTIMIZE_NULL, /*XXX*/ },
281
282 /* SCSI_MEMORY */ { scmem_name, SCSI_OPTIMIZE_NULL,
283 scdisk_open, SCSI_CLOSE_NULL,
284 scdisk_strategy, scdisk_start,
285 scdisk_get_status, scdisk_set_status },
286
287 /* SCSI_J_BOX */ { scjb_name, SCSI_OPTIMIZE_NULL, /*XXX*/ },
288
289 /* SCSI_COMM */ { sccomm_name, SCSI_OPTIMIZE_NULL,
290 #if (NCENDATA>0)
291 sccomm_open, sccomm_close,
292 sccomm_strategy, sccomm_start,
293 sccomm_get_status, sccomm_set_status
294 #endif
295 },
296 0
297 };
298
299 /*
300 * Allocation routines for state structures
301 */
302 scsi_softc_t *
303 scsi_master_alloc(unit, hw)
304 unsigned unit;
305 char *hw;
306 {
307 scsi_softc_t *sc;
308
309 if (unit < NSCSI) {
310 sc = &scsi_softc_data[unit];
311 scsi_softc[unit] = sc;
312 sc->masterno = unit;
313 sc->hw_state = hw;
314 return sc;
315 }
316 return 0;
317 }
318
319 target_info_t *
320 scsi_slave_alloc(unit, slave, hw)
321 unsigned unit, slave;
322 char *hw;
323 {
324 target_info_t *tgt;
325
326 tgt = &scsi_target_data[(unit<<3) + slave];
327 tgt->hw_state = hw;
328 tgt->dev_ops = 0; /* later */
329 tgt->target_id = slave;
330 tgt->masterno = unit;
331 tgt->block_size = 1; /* default */
332 tgt->flags = TGT_ALIVE;
333 tgt->sync_period = 0;
334 tgt->sync_offset = 0;
335 simple_lock_init(&tgt->target_lock);
336
337 scsi_softc[unit]->target[slave] = tgt;
338 return tgt;
339 }
340
341 void
342 zero_ior(
343 io_req_t ior )
344 {
345 ior->io_next = ior->io_prev = 0;
346 ior->io_count = 0;
347 ior->io_op = IO_INTERNAL;
348 ior->io_error = 0;
349 }
350
351 /*
352 * Slave routine:
353 * See if the slave description (controller, unit, ..)
354 * matches one of the slaves found during probe
355 *
356 * Implementation:
357 * Send out an INQUIRY command to see what sort of device
358 * the slave is.
359 * Notes:
360 * At this time the driver is fully functional and works
361 * off interrupts.
362 * TODO:
363 * The SCSI2 spec says what exactly must happen: see F.2.3
364 */
365 int scsi_slave( ui, reg)
366 struct bus_device *ui;
367 unsigned reg;
368 {
369 scsi_softc_t *sc = scsi_softc[(unsigned char)ui->ctlr];
370 target_info_t *tgt = sc->target[(unsigned char)ui->slave];
371 scsi2_inquiry_data_t *inq;
372 int scsi_std;
373 int ptype, s;
374
375 if (!tgt || !(tgt->flags & TGT_ALIVE))
376 return 0;
377
378 /* Might have scanned already */
379 if (tgt->dev_ops)
380 goto out;
381
382 #ifdef SCSI2
383 This is what should happen:
384 - for all LUNs
385 INQUIRY
386 scsi_verify_state (see)
387 scsi_initialize (see)
388 #endif SCSI2
389
390 tgt->unit_no = ui->slave; /* incorrect, but needed early */
391
392 s = spl0(); /* we need interrupts */
393
394 if (BGET(scsi_no_synchronous_xfer,(unsigned char)sc->masterno,tgt->target_id))
395 tgt->flags |= TGT_DID_SYNCH;
396
397 /*
398 * Ok, it is time to see what type of device this is,
399 * send an INQUIRY cmd and wait till done.
400 * Possibly do the synch negotiation here.
401 */
402 scsi_inquiry(tgt, SCSI_INQ_STD_DATA);
403
404 inq = (scsi2_inquiry_data_t*)tgt->cmd_ptr;
405 ptype = inq->periph_type;
406
407 switch (ptype) {
408 case SCSI_CDROM :
409 tgt->flags |= TGT_READONLY;
410 /* fall through */
411 case SCSI_DISK :
412 case SCSI_TAPE :
413 case SCSI_PRINTER :
414 case SCSI_CPU :
415 case SCSI_WORM :
416 case SCSI_SCANNER :
417 case SCSI_MEMORY :
418 case SCSI_J_BOX :
419 case SCSI_COMM :
420 /* case SCSI_PREPRESS1 : reserved, really
421 case SCSI_PREPRESS2 : */
422 tgt->dev_ops = &scsi_devsw[ptype];
423 break;
424 default:
425 printf("scsi%d: %s %d (x%x). ", ui->ctlr,
426 "Unsupported device type at SCSI id", ui->slave,
427 inq->periph_type);
428 scsi_print_inquiry((scsi2_inquiry_data_t*)inq,
429 SCSI_INQ_STD_DATA, 0);
430 tgt->flags = 0;
431 splx(s);
432 return 0;
433 }
434
435 if (inq->rmb)
436 tgt->flags |= TGT_REMOVABLE_MEDIA;
437
438 /*
439 * Tell the user we know this target, then see if we
440 * can be a bit smart about it.
441 */
442 scsi_print_inquiry((scsi2_inquiry_data_t*)inq,
443 SCSI_INQ_STD_DATA, tgt->tgt_name);
444 if (scsi_debug)
445 scsi_print_inquiry((scsi2_inquiry_data_t*)inq,
446 SCSI_INQ_STD_DATA, 0);
447
448 /*
449 * The above says if it currently behaves as a scsi2,
450 * however scsi1 might just be the default setting.
451 * The spec say that even if in scsi1 mode the target
452 * should answer to the full scsi2 inquiry spec.
453 */
454 scsi_std = (inq->ansi == 2 || inq->response_fmt == 2) ? 2 : 1;
455 #if nosey
456 if (scsi_std == 2) {
457 unsigned char supp_pages[256], i;
458 scsi2_impl_opdef_page_t *impl;
459
460 scsi_inquiry(tgt, SCSI_INQ_SUPP_PAGES);
461 impl = (scsi2_impl_opdef_page_t *)inq;
462 npages = impl->page_len - 2;
463 bcopy(impl->supp_opdef, supp_pages, npages);
464
465 for (i = 0; i < npages; i++) {
466 scsi_inquiry(tgt, supp_pages[i]);
467 scsi_print_inquiry(inq, supp_pages[i], 0);
468 }
469 }
470
471 if (scsi_std == 2) {
472 scsi2_impl_opdef_page_t *impl;
473 int i;
474
475 scsi_inquiry(tgt, SCSI_INQ_IMPL_OPDEF);
476 impl = (scsi2_impl_opdef_page_t *)inq;
477 for (i = 0; i < impl->page_len - 2; i++)
478 if (impl->supp_opdef[i] == SCSI2_OPDEF) {
479 scsi_change_definition(tgt, SCSI2_OPDEF);
480 /* if success .. */
481 tgt->flags |= TGT_SCSI_2_MODE;
482 break;
483 }
484 }
485 #endif nosey
486
487 splx(s);
488 out:
489 return (strcmp(ui->name, (*tgt->dev_ops->driver_name)(TRUE)) == 0);
490 }
491
492 #ifdef SCSI2
493 scsi_verify_state(...)
494 {
495 verify_state: send test_unit_ready up to 3 times, each time it fails
496 (with check condition) send a requeste_sense. It is ok to get UNIT ATTENTION
497 the first time only, NOT READY the second, only GOOD the last time.
498 If you get BUSY or RESERVATION CONFLICT retry.
499 }
500
501 scsi_initialize(...)
502 {
503
504 initialize: send start_unit with immed=0 (->disconnect), if fails
505 with check condition send requeste_sense and if "illegal request"
506 proceed anyways. Retry on BUSY.
507 Do a verify_state, then
508 disks:
509 - mode_sense (current) if ANSI2 or needed by vendor (!!!!)
510 and if check-condition&illegal-request goto capacity
511 - mode_sense (changeable)
512 - if needed do a mode_select (yes, 512)
513 - read_capacity
514 tapes:
515
516 }
517 #endif SCSI2
518
519 /*
520 * Attach routine:
521 * Fill in all the relevant per-slave data and make
522 * the slave operational.
523 *
524 * Implementation:
525 * Get target's status, start the unit and then
526 * switch off to device-specific functions to gather
527 * as much info as possible about the slave.
528 */
529 void scsi_attach(ui)
530 register struct bus_device *ui;
531 {
532 scsi_softc_t *sc = scsi_softc[ui->mi->unit];
533 target_info_t *tgt = sc->target[(unsigned char)ui->slave];
534 int i;
535 spl_t s;
536
537 printf(" (%s %s) ", (*tgt->dev_ops->driver_name)(FALSE),tgt->tgt_name);
538
539 if (tgt->flags & TGT_US) {
540 printf(" [this cpu]");
541 return;
542 }
543
544 s = spl0();
545
546 /* sense return from inquiry */
547 scsi_request_sense(tgt, 0, 0);
548
549 /*
550 * Do this twice, certain targets need it
551 */
552 if (tgt->dev_ops != &scsi_devsw[SCSI_CPU]) {
553 (void) scsi_start_unit(tgt, SCSI_CMD_SS_START, 0);
554 i = 0;
555 while (scsi_start_unit(tgt, SCSI_CMD_SS_START, 0) == SCSI_RET_RETRY) {
556 if (i++ == 5)
557 printf(".. not yet online ..");
558 delay(1000000);
559 if (i == 60) {
560 printf(" seems hopeless.");
561 break;
562 }
563 }
564 }
565
566 /*
567 * See if it is up and about
568 */
569 scsi_test_unit_ready(tgt, 0);
570
571 if (tgt->dev_ops->optimize != SCSI_OPTIMIZE_NULL)
572 (*tgt->dev_ops->optimize)(tgt);
573
574 tgt->flags |= TGT_FULLY_PROBED;
575
576 splx(s);
577 }
578
579 /*
580 * Probe routine:
581 * See if a device answers. Used AFTER autoconf.
582 *
583 * Implementation:
584 * First ask the HBA to see if anyone is there at all, then
585 * call the scsi_slave and scsi_attach routines with a fake ui.
586 */
587 boolean_t
588 scsi_probe( sc, tgt_ptr, target_id, ior)
589 scsi_softc_t *sc;
590 target_info_t **tgt_ptr;
591 int target_id;
592 io_req_t ior;
593 {
594 struct bus_device ui;
595 target_info_t *tgt;
596
597 if (!sc->probe || target_id > 7 || target_id == sc->initiator_id)
598 return FALSE; /* sanity */
599
600 if (sc->target[target_id] == 0)
601 scsi_slave_alloc( sc->masterno, target_id, sc->hw_state);
602 tgt = sc->target[target_id];
603 tgt->flags = 0;/* we donno yet */
604 tgt->dev_ops = 0;
605
606 /* mildly enquire */
607 if (!(sc->probe)(tgt, ior))
608 goto fail;
609
610 /* There is something there, see what it is */
611 bzero(&ui, sizeof(ui));
612 ui.ctlr = sc->masterno;
613 ui.unit =
614 ui.slave = target_id;
615 ui.name = "";
616
617 /* this fails on the name for sure */
618 (void) scsi_slave( &ui, 0 /* brrrr */);
619 if ((tgt->flags & TGT_ALIVE) == 0)
620 goto fail;
621
622 {
623 struct bus_ctlr mi;
624
625 mi.unit = sc->masterno;
626 ui.mi = &mi;
627 printf("%s at slave %d ",
628 (*tgt->dev_ops->driver_name)(TRUE), target_id);
629 scsi_attach(&ui);
630 }
631
632 *tgt_ptr = tgt;
633 return TRUE;
634 fail:
635 tgt->flags = 0;
636 return FALSE;
637 }
638
639
640 /*
641 * Watchdog routine:
642 * Issue a SCSI bus reset if a target holds up the
643 * bus for too long.
644 *
645 * Implementation:
646 * Each HBA that wants to use this should have a
647 * watchdog_t structure at the head of its hardware
648 * descriptor. This variable is set by this periodic
649 * routine and reset on bus activity. If it is not reset on
650 * time (say some ten seconds or so) we reset the
651 * SCSI bus.
652 * NOTE:
653 * An HBA must be ready to accept bus reset interrupts
654 * properly in order to use this.
655 */
656 void scsi_watchdog(hw)
657 watchdog_t *hw;
658 {
659 spl_t s = splbio();
660
661 switch (hw->watchdog_state) {
662 case SCSI_WD_EXPIRED:
663
664 /* double check first */
665 if (hw->nactive == 0) {
666 hw->watchdog_state = SCSI_WD_INACTIVE;
667 break;
668 }
669 if (scsi_debug)
670 printf("SCSI Watchdog expired\n");
671 hw->watchdog_state = SCSI_WD_INACTIVE;
672 (*hw->reset)(hw);
673 break;
674
675 case SCSI_WD_ACTIVE:
676
677 hw->watchdog_state = SCSI_WD_EXPIRED;
678 break;
679
680 case SCSI_WD_INACTIVE:
681
682 break;
683 }
684
685 /* do this here, fends against powered down devices */
686 if (scsi_watchdog_period != 0)
687 timeout((int(*)())scsi_watchdog, (char*)hw, scsi_watchdog_period * hz);
688
689 splx(s);
690 }
691
692
693 /*
694 * BusReset Notification:
695 * Called when the HBA sees a BusReset interrupt
696 *
697 * Implementation:
698 * Go through the list of targets, redo the synch
699 * negotiation, and restart whatever operation was
700 * in progress for that target.
701 */
702 void scsi_bus_was_reset(sc)
703 scsi_softc_t *sc;
704 {
705 register target_info_t *tgt;
706 int i;
707 /*
708 * Redo the synch negotiation
709 */
710 for (i = 0; i < 8; i++) {
711 io_req_t ior;
712 spl_t s;
713
714 if (i == sc->initiator_id)
715 continue;
716 tgt = sc->target[i];
717 if (!tgt || !(tgt->flags & TGT_ALIVE))
718 continue;
719
720 tgt->flags &= ~(TGT_DID_SYNCH|TGT_DISCONNECTED);
721 #if 0
722 /* the standard does *not* imply this gets reset too */
723 tgt->sync_period = 0;
724 tgt->sync_offset = 0;
725 #endif
726
727 /*
728 * retry the synch negotiation
729 */
730 ior = tgt->ior;
731 tgt->ior = 0;
732 printf(".. tgt %d ", tgt->target_id);
733 if (BGET(scsi_no_synchronous_xfer,(unsigned char)sc->masterno,tgt->target_id))
734 tgt->flags |= TGT_DID_SYNCH;
735 else {
736 s = spl0();
737 scsi_test_unit_ready(tgt, 0);
738 splx(s);
739 }
740 tgt->ior = ior;
741 }
742
743 /*
744 * Notify each target of the accident
745 */
746 for (i = 0; i < 8; i++) {
747 if (i == sc->initiator_id)
748 continue;
749 tgt = sc->target[i];
750 if (!tgt)
751 continue;
752 tgt->done = SCSI_RET_ABORTED|SCSI_RET_RETRY;
753 if (tgt->ior)
754 (*tgt->dev_ops->restart)( tgt, TRUE);
755 }
756
757 printf("%s", " reset complete\n");
758 }
759
760 #endif NSCSI > 0
Cache object: f441a69c529a1ef432b43cf542980f84
|