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