This source file includes following definitions.
- isp_attach
- ispminphys
- ispcmd_slow
- isp_add2_blocked_queue
- ispcmd
- isp_polled_cmd
- isp_done
- isp_wdog
- isp_uninit
- isp_requeue
- isp_trestart
- isp_restart
- isp_async
- isp_prt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 #define EXPENSIVE_INLINE
45 #include <dev/ic/isp_openbsd.h>
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 #define _XT(xs) ((((xs)->timeout/1000) * hz) + (3 * hz))
64
65 static void ispminphys(struct buf *);
66 static int32_t ispcmd_slow(XS_T *);
67 static int32_t ispcmd(XS_T *);
68
69 static struct scsi_device isp_dev = { NULL, NULL, NULL, NULL };
70
71 static int isp_polled_cmd (struct ispsoftc *, XS_T *);
72 static void isp_wdog (void *);
73 static void isp_requeue(void *);
74 static void isp_trestart(void *);
75 static void isp_restart(struct ispsoftc *);
76
77 struct cfdriver isp_cd = {
78 NULL, "isp", DV_DULL
79 };
80
81
82
83
84
85 void
86 isp_attach(struct ispsoftc *isp)
87 {
88 struct scsibus_attach_args saa;
89 struct scsi_link *lptr = &isp->isp_osinfo._link[0];
90 isp->isp_osinfo._adapter.scsi_minphys = ispminphys;
91
92 isp->isp_state = ISP_RUNSTATE;
93
94
95
96
97
98 isp->isp_osinfo.wqf = isp->isp_osinfo.wqt = NULL;
99
100 lptr->adapter_softc = isp;
101 lptr->device = &isp_dev;
102 lptr->adapter = &isp->isp_osinfo._adapter;
103 lptr->openings = imin(isp->isp_maxcmds, MAXISPREQUEST(isp));
104 isp->isp_osinfo._adapter.scsi_cmd = ispcmd_slow;
105 if (IS_FC(isp)) {
106 lptr->adapter_buswidth = MAX_FC_TARG;
107
108
109 } else {
110 sdparam *sdp = isp->isp_param;
111 lptr->adapter_buswidth = MAX_TARGETS;
112
113 lptr->adapter_target = sdp->isp_initiator_id;
114 isp->isp_osinfo.discovered[0] = 1 << sdp->isp_initiator_id;
115 if (IS_DUALBUS(isp)) {
116 struct scsi_link *lptrb = &isp->isp_osinfo._link[1];
117 lptrb->adapter_softc = isp;
118 lptrb->device = &isp_dev;
119 lptrb->adapter = &isp->isp_osinfo._adapter;
120 lptrb->openings = lptr->openings;
121 lptrb->adapter_buswidth = MAX_TARGETS;
122 lptrb->adapter_target = sdp->isp_initiator_id;
123 lptrb->flags = SDEV_2NDBUS;
124 isp->isp_osinfo.discovered[1] =
125 1 << (sdp+1)->isp_initiator_id;
126 }
127 }
128
129
130
131
132
133
134
135
136 if (IS_SCSI(isp)) {
137 int bus = 0;
138 ISP_LOCK(isp);
139 (void) isp_control(isp, ISPCTL_RESET_BUS, &bus);
140 if (IS_DUALBUS(isp)) {
141 bus++;
142 (void) isp_control(isp, ISPCTL_RESET_BUS, &bus);
143 }
144 ISP_UNLOCK(isp);
145
146
147
148 delay(4 * 1000000);
149 } else {
150 fcparam *fcp = isp->isp_param;
151 int defid = MAX_FC_TARG;
152 delay(2 * 1000000);
153 ISP_LOCK(isp);
154 isp_fc_runstate(isp, 10 * 1000000);
155 if (fcp->isp_fwstate == FW_READY &&
156 fcp->isp_loopstate >= LOOP_PDB_RCVD) {
157 defid = fcp->isp_loopid;
158 }
159 ISP_UNLOCK(isp);
160 lptr->adapter_target = defid;
161 }
162
163 bzero(&saa, sizeof(saa));
164 saa.saa_sc_link = lptr;
165
166
167
168
169 config_found((void *)isp, &saa, scsiprint);
170 if (IS_DUALBUS(isp)) {
171 lptr++;
172 bzero(&saa, sizeof(saa));
173 saa.saa_sc_link = lptr;
174 config_found((void *)isp, &saa, scsiprint);
175 }
176 }
177
178
179
180
181
182
183
184
185
186 static void
187 ispminphys(struct buf *bp)
188 {
189
190
191
192 if (bp->b_bcount >= (1 << 24)) {
193 bp->b_bcount = (1 << 24);
194 }
195 minphys(bp);
196 }
197
198 static int32_t
199 ispcmd_slow(XS_T *xs)
200 {
201 sdparam *sdp;
202 int tgt, chan;
203 u_int16_t f;
204 struct ispsoftc *isp = XS_ISP(xs);
205
206 if (IS_FC(isp)) {
207 if (cold == 0) {
208 isp->isp_osinfo.no_mbox_ints = 0;
209 isp->isp_osinfo._adapter.scsi_cmd = ispcmd;
210 }
211 return (ispcmd(xs));
212 }
213
214
215
216
217 sdp = isp->isp_param;
218 tgt = XS_TGT(xs);
219 chan = XS_CHANNEL(xs);
220 sdp += chan;
221 if ((xs->flags & SCSI_POLL) != 0 ||
222 (isp->isp_osinfo.discovered[chan] & (1 << tgt)) != 0) {
223 return (ispcmd(xs));
224 }
225 if (cold == 0) {
226 isp->isp_osinfo.no_mbox_ints = 0;
227 }
228
229 f = DPARM_DEFAULT;
230 if (xs->sc_link->quirks & SDEV_NOSYNC) {
231 f &= ~DPARM_SYNC;
232 }
233 if (xs->sc_link->quirks & SDEV_NOWIDE) {
234 f &= ~DPARM_WIDE;
235 }
236 if (xs->sc_link->quirks & SDEV_NOTAGS) {
237 f &= ~DPARM_TQING;
238 }
239
240
241
242
243
244 sdp->isp_devparam[tgt].goal_flags = f;
245 sdp->isp_devparam[tgt].dev_update = 1;
246 isp->isp_update |= (1 << chan);
247
248
249
250
251
252
253
254
255
256
257 isp->isp_osinfo.discovered[chan] |= (1 << tgt);
258
259 #if 0
260 sdp = isp->isp_param;
261 for (chan = 0; chan < (IS_12X0(isp)? 2 : 1); chan++, sdp++) {
262 f = 0xffff & ~(1 << sdp->isp_initiator_id);
263 if (isp->isp_osinfo.discovered[chan] != f) {
264 break;
265 }
266 }
267 if (chan == (IS_12X0(isp)? 2 : 1)) {
268 isp->isp_osinfo._adapter.scsipi_cmd = ispcmd;
269 if (IS_12X0(isp))
270 isp->isp_update |= 2;
271 }
272 #endif
273 return (ispcmd(xs));
274 }
275
276 static INLINE void isp_add2_blocked_queue(struct ispsoftc *, XS_T *);
277
278 static INLINE void
279 isp_add2_blocked_queue(struct ispsoftc *isp, XS_T *xs)
280 {
281 if (isp->isp_osinfo.wqf != NULL) {
282 isp->isp_osinfo.wqt->free_list.le_next = xs;
283 } else {
284 isp->isp_osinfo.wqf = xs;
285 }
286 isp->isp_osinfo.wqt = xs;
287 xs->free_list.le_next = NULL;
288 }
289
290 static int32_t
291 ispcmd(XS_T *xs)
292 {
293 struct ispsoftc *isp;
294 int result;
295
296
297
298
299
300 isp = XS_ISP(xs);
301
302 timeout_set(&xs->stimeout, isp_wdog, isp);
303
304 if (XS_LUN(xs) >= isp->isp_maxluns) {
305 xs->error = XS_SELTIMEOUT;
306 return (COMPLETE);
307 }
308
309 ISP_LOCK(isp);
310 if (isp->isp_state < ISP_RUNSTATE) {
311 DISABLE_INTS(isp);
312 isp_init(isp);
313 if (isp->isp_state != ISP_INITSTATE) {
314 ENABLE_INTS(isp);
315 ISP_UNLOCK(isp);
316 XS_SETERR(xs, HBA_BOTCH);
317 return (CMD_COMPLETE);
318 }
319 isp->isp_state = ISP_RUNSTATE;
320 ENABLE_INTS(isp);
321 }
322
323
324
325
326 if (isp->isp_osinfo.blocked) {
327 if (xs->flags & SCSI_POLL) {
328 ISP_UNLOCK(isp);
329 return (TRY_AGAIN_LATER);
330 }
331 if (isp->isp_osinfo.blocked == 2) {
332 isp_restart(isp);
333 }
334 if (isp->isp_osinfo.blocked) {
335 isp_add2_blocked_queue(isp, xs);
336 ISP_UNLOCK(isp);
337 isp_prt(isp, ISP_LOGDEBUG0, "added to blocked queue");
338 return (SUCCESSFULLY_QUEUED);
339 }
340 }
341
342 if (xs->flags & SCSI_POLL) {
343 volatile u_int8_t ombi = isp->isp_osinfo.no_mbox_ints;
344 isp->isp_osinfo.no_mbox_ints = 1;
345 result = isp_polled_cmd(isp, xs);
346 isp->isp_osinfo.no_mbox_ints = ombi;
347 ISP_UNLOCK(isp);
348 return (result);
349 }
350
351 result = isp_start(xs);
352
353 switch (result) {
354 case CMD_QUEUED:
355 result = SUCCESSFULLY_QUEUED;
356 if (xs->timeout) {
357 timeout_add(&xs->stimeout, _XT(xs));
358 XS_CMD_S_TIMER(xs);
359 }
360 if (isp->isp_osinfo.hiwater < isp->isp_nactive) {
361 isp->isp_osinfo.hiwater = isp->isp_nactive;
362 isp_prt(isp, ISP_LOGDEBUG0,
363 "Active Hiwater Mark=%d", isp->isp_nactive);
364 }
365 break;
366 case CMD_EAGAIN:
367 isp->isp_osinfo.blocked |= 2;
368 isp_prt(isp, ISP_LOGDEBUG0, "blocking queue");
369 isp_add2_blocked_queue(isp, xs);
370 result = SUCCESSFULLY_QUEUED;
371 break;
372 case CMD_RQLATER:
373 result = SUCCESSFULLY_QUEUED;
374 isp_prt(isp, ISP_LOGDEBUG1, "retrying later for %d.%d",
375 XS_TGT(xs), XS_LUN(xs));
376 timeout_set(&xs->stimeout, isp_requeue, xs);
377 timeout_add(&xs->stimeout, hz);
378 XS_CMD_S_TIMER(xs);
379 break;
380 case CMD_COMPLETE:
381 result = COMPLETE;
382 break;
383 }
384 ISP_UNLOCK(isp);
385 return (result);
386 }
387
388 static int
389 isp_polled_cmd(struct ispsoftc *isp, XS_T *xs)
390 {
391 int result;
392 int infinite = 0, mswait;
393
394 result = isp_start(xs);
395
396 switch (result) {
397 case CMD_QUEUED:
398 result = SUCCESSFULLY_QUEUED;
399 break;
400 case CMD_RQLATER:
401 case CMD_EAGAIN:
402 result = TRY_AGAIN_LATER;
403 break;
404 case CMD_COMPLETE:
405 result = COMPLETE;
406 break;
407
408 }
409
410 if (result != SUCCESSFULLY_QUEUED) {
411 return (result);
412 }
413
414
415
416
417 if ((mswait = XS_TIME(xs)) == 0)
418 infinite = 1;
419
420 while (mswait || infinite) {
421 u_int16_t isr, sema, mbox;
422 if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
423 isp_intr(isp, isr, sema, mbox);
424 if (XS_CMD_DONE_P(xs)) {
425 break;
426 }
427 }
428 USEC_DELAY(1000);
429 mswait -= 1;
430 }
431
432
433
434
435
436 if (XS_CMD_DONE_P(xs) == 0) {
437 if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
438 isp_reinit(isp);
439 }
440 if (XS_NOERR(xs)) {
441 XS_SETERR(xs, HBA_BOTCH);
442 }
443 }
444 result = COMPLETE;
445 return (result);
446 }
447
448 void
449 isp_done(XS_T *xs)
450 {
451 XS_CMD_S_DONE(xs);
452 if (XS_CMD_WDOG_P(xs) == 0) {
453 struct ispsoftc *isp = XS_ISP(xs);
454 if (XS_CMD_TIMER_P(xs)) {
455 timeout_del(&xs->stimeout);
456 XS_CMD_C_TIMER(xs);
457 }
458 if (XS_CMD_GRACE_P(xs)) {
459 struct ispsoftc *isp = XS_ISP(xs);
460 isp_prt(isp, ISP_LOGWARN,
461 "finished command on borrowed time");
462 }
463 XS_CMD_S_CLEAR(xs);
464 scsi_done(xs);
465 if (isp->isp_osinfo.blocked == 2) {
466 isp->isp_osinfo.blocked = 0;
467 isp_prt(isp, ISP_LOGDEBUG0, "restarting blocked queue");
468 isp_restart(isp);
469 }
470 }
471 }
472
473 static void
474 isp_wdog(void *arg)
475 {
476 XS_T *xs = arg;
477 struct ispsoftc *isp = XS_ISP(xs);
478 u_int32_t handle;
479
480
481
482
483
484
485 ISP_LOCK(isp);
486 handle = isp_find_handle(isp, xs);
487 if (handle) {
488 u_int16_t isr, sema, mbox;
489
490 if (XS_CMD_DONE_P(xs)) {
491 isp_prt(isp, ISP_LOGDEBUG1,
492 "watchdog found done cmd (handle 0x%x)",
493 handle);
494 ISP_UNLOCK(isp);
495 return;
496 }
497
498 if (XS_CMD_WDOG_P(xs)) {
499 isp_prt(isp, ISP_LOGDEBUG1,
500 "recursive watchdog (handle 0x%x)",
501 handle);
502 ISP_UNLOCK(isp);
503 return;
504 }
505
506 XS_CMD_S_WDOG(xs);
507
508 if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
509 isp_intr(isp, isr, sema, mbox);
510 }
511
512 if (XS_CMD_DONE_P(xs)) {
513 isp_prt(isp, ISP_LOGINFO,
514 "watchdog cleanup for handle 0x%x", handle);
515 XS_CMD_C_WDOG(xs);
516 isp_done(xs);
517 } else if (XS_CMD_GRACE_P(xs)) {
518
519
520
521
522 (void) isp_control(isp, ISPCTL_ABORT_CMD, arg);
523
524
525
526
527 if (XS_XFRLEN(xs)) {
528 ISP_DMAFREE(isp, xs, handle);
529 }
530 isp_prt(isp, ISP_LOGWARN,
531 "watchdog timeout on handle %x", handle);
532 isp_destroy_handle(isp, handle);
533 XS_SETERR(xs, XS_TIMEOUT);
534 XS_CMD_S_CLEAR(xs);
535 isp_done(xs);
536 } else {
537 u_int16_t nxti, optr;
538 ispreq_t local, *mp = &local, *qe;
539
540 isp_prt(isp, ISP_LOGWARN,
541 "possible command timeout on handle %x", handle);
542
543 XS_CMD_C_WDOG(xs);
544 timeout_add(&xs->stimeout, _XT(xs));
545 XS_CMD_S_TIMER(xs);
546 if (isp_getrqentry(isp, &nxti, &optr, (void **) &qe)) {
547 ISP_UNLOCK(isp);
548 return;
549 }
550 XS_CMD_S_GRACE(xs);
551 MEMZERO((void *) mp, sizeof (*mp));
552 mp->req_header.rqs_entry_count = 1;
553 mp->req_header.rqs_entry_type = RQSTYPE_MARKER;
554 mp->req_modifier = SYNC_ALL;
555 mp->req_target = XS_CHANNEL(xs) << 7;
556 isp_put_request(isp, mp, qe);
557 ISP_ADD_REQUEST(isp, nxti);
558 }
559 } else if (isp->isp_dblev) {
560 isp_prt(isp, ISP_LOGDEBUG1, "watchdog with no command");
561 }
562 ISP_UNLOCK(isp);
563 }
564
565
566
567
568
569
570
571
572 void
573 isp_uninit(struct ispsoftc *isp)
574 {
575 ISP_LOCK(isp);
576
577
578
579 DISABLE_INTS(isp);
580
581 ISP_UNLOCK(isp);
582 }
583
584
585
586
587 static void
588 isp_requeue(void *arg)
589 {
590 int r;
591 struct scsi_xfer *xs = arg;
592 struct ispsoftc *isp = XS_ISP(xs);
593 ISP_LOCK(isp);
594 r = isp_start(xs);
595 switch (r) {
596 case CMD_QUEUED:
597 isp_prt(isp, ISP_LOGDEBUG1, "restarted command for %d.%d",
598 XS_TGT(xs), XS_LUN(xs));
599 if (xs->timeout) {
600 timeout_set(&xs->stimeout, isp_wdog, isp);
601 timeout_add(&xs->stimeout, _XT(xs));
602 XS_CMD_S_TIMER(xs);
603 }
604 break;
605 case CMD_EAGAIN:
606 isp_prt(isp, ISP_LOGDEBUG0, "blocked cmd again");
607 isp->isp_osinfo.blocked |= 2;
608 isp_add2_blocked_queue(isp, xs);
609 break;
610 case CMD_RQLATER:
611 isp_prt(isp, ISP_LOGDEBUG0, "%s for %d.%d",
612 (r == CMD_EAGAIN)? "CMD_EAGAIN" : "CMD_RQLATER",
613 XS_TGT(xs), XS_LUN(xs));
614 timeout_set(&xs->stimeout, isp_requeue, xs);
615 timeout_add(&xs->stimeout, hz);
616 XS_CMD_S_TIMER(xs);
617 break;
618 case CMD_COMPLETE:
619
620 if (XS_NOERR(xs))
621 XS_SETERR(xs, XS_DRIVER_STUFFUP);
622 isp_done(xs);
623 break;
624 }
625 ISP_UNLOCK(isp);
626 }
627
628
629
630
631
632 static void
633 isp_trestart(void *arg)
634 {
635 struct ispsoftc *isp = arg;
636 struct scsi_xfer *list;
637
638 ISP_LOCK(isp);
639 isp->isp_osinfo.rtpend = 0;
640 list = isp->isp_osinfo.wqf;
641 if (isp->isp_osinfo.blocked == 0 && list != NULL) {
642 int nrestarted = 0;
643
644 isp->isp_osinfo.wqf = NULL;
645 ISP_UNLOCK(isp);
646 do {
647 struct scsi_xfer *xs = list;
648 list = xs->free_list.le_next;
649 xs->free_list.le_next = NULL;
650 isp_requeue(xs);
651 if (isp->isp_osinfo.wqf == NULL)
652 nrestarted++;
653 } while (list != NULL);
654 isp_prt(isp, ISP_LOGDEBUG0, "requeued %d commands", nrestarted);
655 } else {
656 ISP_UNLOCK(isp);
657 }
658 }
659
660 static void
661 isp_restart(struct ispsoftc *isp)
662 {
663 struct scsi_xfer *list;
664
665 list = isp->isp_osinfo.wqf;
666 if (isp->isp_osinfo.blocked == 0 && list != NULL) {
667 int nrestarted = 0;
668
669 isp->isp_osinfo.wqf = NULL;
670 do {
671 struct scsi_xfer *xs = list;
672 list = xs->free_list.le_next;
673 xs->free_list.le_next = NULL;
674 isp_requeue(xs);
675 if (isp->isp_osinfo.wqf == NULL)
676 nrestarted++;
677 } while (list != NULL);
678 isp_prt(isp, ISP_LOGDEBUG0, "requeued %d commands", nrestarted);
679 }
680 }
681
682 int
683 isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg)
684 {
685 int bus, tgt;
686
687 switch (cmd) {
688 case ISPASYNC_NEW_TGT_PARAMS:
689 if (IS_SCSI(isp) && isp->isp_dblev) {
690 sdparam *sdp = isp->isp_param;
691 char *wt;
692 int mhz, flags, period;
693
694 tgt = *((int *) arg);
695 bus = (tgt >> 16) & 0xffff;
696 tgt &= 0xffff;
697 sdp += bus;
698 flags = sdp->isp_devparam[tgt].actv_flags;
699 period = sdp->isp_devparam[tgt].actv_period;
700
701 if ((flags & DPARM_SYNC) && period &&
702 (sdp->isp_devparam[tgt].actv_offset) != 0) {
703
704
705
706
707
708
709 if (sdp->isp_lvdmode || period < 0xc) {
710 switch (period) {
711 case 0x9:
712 mhz = 80;
713 break;
714 case 0xa:
715 mhz = 40;
716 break;
717 case 0xb:
718 mhz = 33;
719 break;
720 case 0xc:
721 mhz = 25;
722 break;
723 default:
724 mhz = 1000 / (period * 4);
725 break;
726 }
727 } else {
728 mhz = 1000 / (period * 4);
729 }
730 } else {
731 mhz = 0;
732 }
733 switch (flags & (DPARM_WIDE|DPARM_TQING)) {
734 case DPARM_WIDE:
735 wt = ", 16 bit wide";
736 break;
737 case DPARM_TQING:
738 wt = ", Tagged Queueing Enabled";
739 break;
740 case DPARM_WIDE|DPARM_TQING:
741 wt = ", 16 bit wide, Tagged Queueing Enabled";
742 break;
743 default:
744 wt = " ";
745 break;
746 }
747 if (mhz) {
748 isp_prt(isp, ISP_LOGINFO,
749 "Bus %d Target %d at %dMHz Max Offset %d%s",
750 bus, tgt, mhz, sdp->isp_devparam[tgt].actv_offset,
751 wt);
752 } else {
753 isp_prt(isp, ISP_LOGINFO,
754 "Bus %d Target %d Async Mode%s", bus, tgt, wt);
755 }
756 break;
757 }
758 case ISPASYNC_BUS_RESET:
759 if (arg)
760 bus = *((int *) arg);
761 else
762 bus = 0;
763 isp_prt(isp, ISP_LOGINFO, "SCSI bus %d reset detected", bus);
764 break;
765 case ISPASYNC_LOOP_DOWN:
766
767
768
769
770 isp->isp_osinfo.blocked |= 1;
771 isp_prt(isp, ISP_LOGINFO, "Loop DOWN");
772 break;
773 case ISPASYNC_LOOP_UP:
774 isp->isp_osinfo.blocked &= ~1;
775 if (isp->isp_osinfo.rtpend == 0) {
776 timeout_set(&isp->isp_osinfo.rqt, isp_trestart, isp);
777 isp->isp_osinfo.rtpend = 1;
778 }
779 timeout_add(&isp->isp_osinfo.rqt, 1);
780 isp_prt(isp, ISP_LOGINFO, "Loop UP");
781 break;
782 case ISPASYNC_PROMENADE:
783 if (IS_FC(isp) && isp->isp_dblev) {
784 const char *fmt = "Target %d (Loop 0x%x) Port ID 0x%x "
785 "role %s %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x";
786 const static char *roles[4] = {
787 "No", "Target", "Initiator", "Target/Initiator"
788 };
789 fcparam *fcp = isp->isp_param;
790 int tgt = *((int *) arg);
791 struct lportdb *lp = &fcp->portdb[tgt];
792
793 isp_prt(isp, ISP_LOGINFO, fmt, tgt, lp->loopid, lp->portid,
794 roles[lp->roles & 0x3],
795 (lp->valid)? "Arrived" : "Departed",
796 (u_int32_t) (lp->port_wwn >> 32),
797 (u_int32_t) (lp->port_wwn & 0xffffffffLL),
798 (u_int32_t) (lp->node_wwn >> 32),
799 (u_int32_t) (lp->node_wwn & 0xffffffffLL));
800 break;
801 }
802 case ISPASYNC_CHANGE_NOTIFY:
803 if (arg == (void *) 1) {
804 isp_prt(isp, ISP_LOGINFO,
805 "Name Server Database Changed");
806 } else {
807 isp_prt(isp, ISP_LOGINFO,
808 "Name Server Database Changed");
809 }
810 break;
811 case ISPASYNC_FABRIC_DEV:
812 {
813 int target, base, lim;
814 fcparam *fcp = isp->isp_param;
815 struct lportdb *lp = NULL;
816 struct lportdb *clp = (struct lportdb *) arg;
817 char *pt;
818
819 switch (clp->port_type) {
820 case 1:
821 pt = " N_Port";
822 break;
823 case 2:
824 pt = " NL_Port";
825 break;
826 case 3:
827 pt = "F/NL_Port";
828 break;
829 case 0x7f:
830 pt = " Nx_Port";
831 break;
832 case 0x81:
833 pt = " F_port";
834 break;
835 case 0x82:
836 pt = " FL_Port";
837 break;
838 case 0x84:
839 pt = " E_port";
840 break;
841 default:
842 pt = " ";
843 break;
844 }
845
846 isp_prt(isp, ISP_LOGINFO,
847 "%s Fabric Device @ PortID 0x%x", pt, clp->portid);
848
849
850
851
852
853
854
855 if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) {
856 break;
857 }
858
859
860
861
862
863 if (fcp->isp_portid == clp->portid) {
864 break;
865 }
866
867
868
869
870
871
872
873
874 if (fcp->isp_topo == TOPO_FL_PORT)
875 base = FC_SNS_ID+1;
876 else
877 base = 0;
878
879 if (fcp->isp_topo == TOPO_N_PORT)
880 lim = 1;
881 else
882 lim = MAX_FC_TARG;
883
884
885
886
887 for (target = base; target < lim; target++) {
888 if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
889 continue;
890 }
891 lp = &fcp->portdb[target];
892 if (lp->port_wwn == clp->port_wwn &&
893 lp->node_wwn == clp->node_wwn) {
894 lp->fabric_dev = 1;
895 break;
896 }
897 }
898 if (target < lim) {
899 break;
900 }
901 for (target = base; target < lim; target++) {
902 if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
903 continue;
904 }
905 lp = &fcp->portdb[target];
906 if (lp->port_wwn == 0) {
907 break;
908 }
909 }
910 if (target == lim) {
911 isp_prt(isp, ISP_LOGWARN,
912 "out of space for fabric devices");
913 break;
914 }
915 lp->port_type = clp->port_type;
916 lp->fc4_type = clp->fc4_type;
917 lp->node_wwn = clp->node_wwn;
918 lp->port_wwn = clp->port_wwn;
919 lp->portid = clp->portid;
920 lp->fabric_dev = 1;
921 break;
922 }
923 case ISPASYNC_FW_CRASH:
924 {
925 u_int16_t mbox1, mbox6;
926 mbox1 = ISP_READ(isp, OUTMAILBOX1);
927 if (IS_DUALBUS(isp)) {
928 mbox6 = ISP_READ(isp, OUTMAILBOX6);
929 } else {
930 mbox6 = 0;
931 }
932 isp_prt(isp, ISP_LOGERR,
933 "Internal Firmware Error on bus %d @ RISC Address 0x%x",
934 mbox6, mbox1);
935 #ifdef ISP_FW_CRASH_DUMP
936 if (IS_FC(isp)) {
937 isp->isp_osinfo.blocked |= 1;
938 isp_fw_dump(isp);
939 }
940 isp_reinit(isp);
941 isp_async(isp, ISPASYNC_FW_RESTART, NULL);
942 #endif
943 break;
944 }
945 default:
946 break;
947 }
948 return (0);
949 }
950
951 void
952 isp_prt(struct ispsoftc *isp, int level, const char *fmt, ...)
953 {
954 va_list ap;
955 if (level != ISP_LOGALL && (level & isp->isp_dblev) == 0) {
956 return;
957 }
958 printf("%s: ", isp->isp_name);
959 va_start(ap, fmt);
960 vprintf(fmt, ap);
961 va_end(ap);
962 printf("\n");
963 }