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#ifdef __linux__
44#include "aic79xx_osm.h"
45#include "aic79xx_inline.h"
46#include "aicasm/aicasm_insformat.h"
47#else
48#include <dev/aic7xxx/aic79xx_osm.h>
49#include <dev/aic7xxx/aic79xx_inline.h>
50#include <dev/aic7xxx/aicasm/aicasm_insformat.h>
51#endif
52
53
54
55static char *ahd_chip_names[] =
56{
57 "NONE",
58 "aic7901",
59 "aic7902",
60 "aic7901A"
61};
62static const u_int num_chip_names = ARRAY_SIZE(ahd_chip_names);
63
64
65
66
67struct ahd_hard_error_entry {
68 uint8_t errno;
69 char *errmesg;
70};
71
72static struct ahd_hard_error_entry ahd_hard_errors[] = {
73 { DSCTMOUT, "Discard Timer has timed out" },
74 { ILLOPCODE, "Illegal Opcode in sequencer program" },
75 { SQPARERR, "Sequencer Parity Error" },
76 { DPARERR, "Data-path Parity Error" },
77 { MPARERR, "Scratch or SCB Memory Parity Error" },
78 { CIOPARERR, "CIOBUS Parity Error" },
79};
80static const u_int num_errors = ARRAY_SIZE(ahd_hard_errors);
81
82static struct ahd_phase_table_entry ahd_phase_table[] =
83{
84 { P_DATAOUT, MSG_NOOP, "in Data-out phase" },
85 { P_DATAIN, MSG_INITIATOR_DET_ERR, "in Data-in phase" },
86 { P_DATAOUT_DT, MSG_NOOP, "in DT Data-out phase" },
87 { P_DATAIN_DT, MSG_INITIATOR_DET_ERR, "in DT Data-in phase" },
88 { P_COMMAND, MSG_NOOP, "in Command phase" },
89 { P_MESGOUT, MSG_NOOP, "in Message-out phase" },
90 { P_STATUS, MSG_INITIATOR_DET_ERR, "in Status phase" },
91 { P_MESGIN, MSG_PARITY_ERROR, "in Message-in phase" },
92 { P_BUSFREE, MSG_NOOP, "while idle" },
93 { 0, MSG_NOOP, "in unknown phase" }
94};
95
96
97
98
99
100static const u_int num_phases = ARRAY_SIZE(ahd_phase_table) - 1;
101
102
103#include "aic79xx_seq.h"
104
105
106static void ahd_handle_transmission_error(struct ahd_softc *ahd);
107static void ahd_handle_lqiphase_error(struct ahd_softc *ahd,
108 u_int lqistat1);
109static int ahd_handle_pkt_busfree(struct ahd_softc *ahd,
110 u_int busfreetime);
111static int ahd_handle_nonpkt_busfree(struct ahd_softc *ahd);
112static void ahd_handle_proto_violation(struct ahd_softc *ahd);
113static void ahd_force_renegotiation(struct ahd_softc *ahd,
114 struct ahd_devinfo *devinfo);
115
116static struct ahd_tmode_tstate*
117 ahd_alloc_tstate(struct ahd_softc *ahd,
118 u_int scsi_id, char channel);
119#ifdef AHD_TARGET_MODE
120static void ahd_free_tstate(struct ahd_softc *ahd,
121 u_int scsi_id, char channel, int force);
122#endif
123static void ahd_devlimited_syncrate(struct ahd_softc *ahd,
124 struct ahd_initiator_tinfo *,
125 u_int *period,
126 u_int *ppr_options,
127 role_t role);
128static void ahd_update_neg_table(struct ahd_softc *ahd,
129 struct ahd_devinfo *devinfo,
130 struct ahd_transinfo *tinfo);
131static void ahd_update_pending_scbs(struct ahd_softc *ahd);
132static void ahd_fetch_devinfo(struct ahd_softc *ahd,
133 struct ahd_devinfo *devinfo);
134static void ahd_scb_devinfo(struct ahd_softc *ahd,
135 struct ahd_devinfo *devinfo,
136 struct scb *scb);
137static void ahd_setup_initiator_msgout(struct ahd_softc *ahd,
138 struct ahd_devinfo *devinfo,
139 struct scb *scb);
140static void ahd_build_transfer_msg(struct ahd_softc *ahd,
141 struct ahd_devinfo *devinfo);
142static void ahd_construct_sdtr(struct ahd_softc *ahd,
143 struct ahd_devinfo *devinfo,
144 u_int period, u_int offset);
145static void ahd_construct_wdtr(struct ahd_softc *ahd,
146 struct ahd_devinfo *devinfo,
147 u_int bus_width);
148static void ahd_construct_ppr(struct ahd_softc *ahd,
149 struct ahd_devinfo *devinfo,
150 u_int period, u_int offset,
151 u_int bus_width, u_int ppr_options);
152static void ahd_clear_msg_state(struct ahd_softc *ahd);
153static void ahd_handle_message_phase(struct ahd_softc *ahd);
154typedef enum {
155 AHDMSG_1B,
156 AHDMSG_2B,
157 AHDMSG_EXT
158} ahd_msgtype;
159static int ahd_sent_msg(struct ahd_softc *ahd, ahd_msgtype type,
160 u_int msgval, int full);
161static int ahd_parse_msg(struct ahd_softc *ahd,
162 struct ahd_devinfo *devinfo);
163static int ahd_handle_msg_reject(struct ahd_softc *ahd,
164 struct ahd_devinfo *devinfo);
165static void ahd_handle_ign_wide_residue(struct ahd_softc *ahd,
166 struct ahd_devinfo *devinfo);
167static void ahd_reinitialize_dataptrs(struct ahd_softc *ahd);
168static void ahd_handle_devreset(struct ahd_softc *ahd,
169 struct ahd_devinfo *devinfo,
170 u_int lun, cam_status status,
171 char *message, int verbose_level);
172#ifdef AHD_TARGET_MODE
173static void ahd_setup_target_msgin(struct ahd_softc *ahd,
174 struct ahd_devinfo *devinfo,
175 struct scb *scb);
176#endif
177
178static u_int ahd_sglist_size(struct ahd_softc *ahd);
179static u_int ahd_sglist_allocsize(struct ahd_softc *ahd);
180static bus_dmamap_callback_t
181 ahd_dmamap_cb;
182static void ahd_initialize_hscbs(struct ahd_softc *ahd);
183static int ahd_init_scbdata(struct ahd_softc *ahd);
184static void ahd_fini_scbdata(struct ahd_softc *ahd);
185static void ahd_setup_iocell_workaround(struct ahd_softc *ahd);
186static void ahd_iocell_first_selection(struct ahd_softc *ahd);
187static void ahd_add_col_list(struct ahd_softc *ahd,
188 struct scb *scb, u_int col_idx);
189static void ahd_rem_col_list(struct ahd_softc *ahd,
190 struct scb *scb);
191static void ahd_chip_init(struct ahd_softc *ahd);
192static void ahd_qinfifo_requeue(struct ahd_softc *ahd,
193 struct scb *prev_scb,
194 struct scb *scb);
195static int ahd_qinfifo_count(struct ahd_softc *ahd);
196static int ahd_search_scb_list(struct ahd_softc *ahd, int target,
197 char channel, int lun, u_int tag,
198 role_t role, uint32_t status,
199 ahd_search_action action,
200 u_int *list_head, u_int *list_tail,
201 u_int tid);
202static void ahd_stitch_tid_list(struct ahd_softc *ahd,
203 u_int tid_prev, u_int tid_cur,
204 u_int tid_next);
205static void ahd_add_scb_to_free_list(struct ahd_softc *ahd,
206 u_int scbid);
207static u_int ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,
208 u_int prev, u_int next, u_int tid);
209static void ahd_reset_current_bus(struct ahd_softc *ahd);
210static ahd_callback_t ahd_stat_timer;
211#ifdef AHD_DUMP_SEQ
212static void ahd_dumpseq(struct ahd_softc *ahd);
213#endif
214static void ahd_loadseq(struct ahd_softc *ahd);
215static int ahd_check_patch(struct ahd_softc *ahd,
216 struct patch **start_patch,
217 u_int start_instr, u_int *skip_addr);
218static u_int ahd_resolve_seqaddr(struct ahd_softc *ahd,
219 u_int address);
220static void ahd_download_instr(struct ahd_softc *ahd,
221 u_int instrptr, uint8_t *dconsts);
222static int ahd_probe_stack_size(struct ahd_softc *ahd);
223static int ahd_scb_active_in_fifo(struct ahd_softc *ahd,
224 struct scb *scb);
225static void ahd_run_data_fifo(struct ahd_softc *ahd,
226 struct scb *scb);
227
228#ifdef AHD_TARGET_MODE
229static void ahd_queue_lstate_event(struct ahd_softc *ahd,
230 struct ahd_tmode_lstate *lstate,
231 u_int initiator_id,
232 u_int event_type,
233 u_int event_arg);
234static void ahd_update_scsiid(struct ahd_softc *ahd,
235 u_int targid_mask);
236static int ahd_handle_target_cmd(struct ahd_softc *ahd,
237 struct target_cmd *cmd);
238#endif
239
240static int ahd_abort_scbs(struct ahd_softc *ahd, int target,
241 char channel, int lun, u_int tag,
242 role_t role, uint32_t status);
243static void ahd_alloc_scbs(struct ahd_softc *ahd);
244static void ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl,
245 u_int scbid);
246static void ahd_calc_residual(struct ahd_softc *ahd,
247 struct scb *scb);
248static void ahd_clear_critical_section(struct ahd_softc *ahd);
249static void ahd_clear_intstat(struct ahd_softc *ahd);
250static void ahd_enable_coalescing(struct ahd_softc *ahd,
251 int enable);
252static u_int ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl);
253static void ahd_freeze_devq(struct ahd_softc *ahd,
254 struct scb *scb);
255static void ahd_handle_scb_status(struct ahd_softc *ahd,
256 struct scb *scb);
257static struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase);
258static void ahd_shutdown(void *arg);
259static void ahd_update_coalescing_values(struct ahd_softc *ahd,
260 u_int timer,
261 u_int maxcmds,
262 u_int mincmds);
263static int ahd_verify_vpd_cksum(struct vpd_config *vpd);
264static int ahd_wait_seeprom(struct ahd_softc *ahd);
265static int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb,
266 int target, char channel, int lun,
267 u_int tag, role_t role);
268
269
270
271static __inline void
272ahd_assert_atn(struct ahd_softc *ahd)
273{
274 ahd_outb(ahd, SCSISIGO, ATNO);
275}
276
277
278
279
280
281
282
283static __inline int
284ahd_currently_packetized(struct ahd_softc *ahd)
285{
286 ahd_mode_state saved_modes;
287 int packetized;
288
289 saved_modes = ahd_save_modes(ahd);
290 if ((ahd->bugs & AHD_PKTIZED_STATUS_BUG) != 0) {
291
292
293
294
295
296 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
297 packetized = ahd_inb(ahd, LQISTATE) != 0;
298 } else {
299 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
300 packetized = ahd_inb(ahd, LQISTAT2) & PACKETIZED;
301 }
302 ahd_restore_modes(ahd, saved_modes);
303 return (packetized);
304}
305
306static __inline int
307ahd_set_active_fifo(struct ahd_softc *ahd)
308{
309 u_int active_fifo;
310
311 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
312 active_fifo = ahd_inb(ahd, DFFSTAT) & CURRFIFO;
313 switch (active_fifo) {
314 case 0:
315 case 1:
316 ahd_set_modes(ahd, active_fifo, active_fifo);
317 return (1);
318 default:
319 return (0);
320 }
321}
322
323static __inline void
324ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl)
325{
326 ahd_busy_tcl(ahd, tcl, SCB_LIST_NULL);
327}
328
329
330
331
332
333static __inline void
334ahd_update_residual(struct ahd_softc *ahd, struct scb *scb)
335{
336 uint32_t sgptr;
337
338 sgptr = ahd_le32toh(scb->hscb->sgptr);
339 if ((sgptr & SG_STATUS_VALID) != 0)
340 ahd_calc_residual(ahd, scb);
341}
342
343static __inline void
344ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb)
345{
346 uint32_t sgptr;
347
348 sgptr = ahd_le32toh(scb->hscb->sgptr);
349 if ((sgptr & SG_STATUS_VALID) != 0)
350 ahd_handle_scb_status(ahd, scb);
351 else
352 ahd_done(ahd, scb);
353}
354
355
356
357
358
359
360static void
361ahd_restart(struct ahd_softc *ahd)
362{
363
364 ahd_pause(ahd);
365
366 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
367
368
369 ahd_clear_msg_state(ahd);
370 ahd_outb(ahd, SCSISIGO, 0);
371 ahd_outb(ahd, MSG_OUT, MSG_NOOP);
372 ahd_outb(ahd, SXFRCTL1, ahd_inb(ahd, SXFRCTL1) & ~BITBUCKET);
373 ahd_outb(ahd, SEQINTCTL, 0);
374 ahd_outb(ahd, LASTPHASE, P_BUSFREE);
375 ahd_outb(ahd, SEQ_FLAGS, 0);
376 ahd_outb(ahd, SAVED_SCSIID, 0xFF);
377 ahd_outb(ahd, SAVED_LUN, 0xFF);
378
379
380
381
382
383
384
385
386 ahd_outb(ahd, TQINPOS, ahd->tqinfifonext);
387
388
389 ahd_outb(ahd, SCSISEQ1,
390 ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));
391 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
392
393
394
395
396
397
398 ahd_outb(ahd, CLRINT, CLRSEQINT);
399
400 ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
401 ahd_unpause(ahd);
402}
403
404static void
405ahd_clear_fifo(struct ahd_softc *ahd, u_int fifo)
406{
407 ahd_mode_state saved_modes;
408
409#ifdef AHD_DEBUG
410 if ((ahd_debug & AHD_SHOW_FIFOS) != 0)
411 printf("%s: Clearing FIFO %d\n", ahd_name(ahd), fifo);
412#endif
413 saved_modes = ahd_save_modes(ahd);
414 ahd_set_modes(ahd, fifo, fifo);
415 ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT);
416 if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
417 ahd_outb(ahd, CCSGCTL, CCSGRESET);
418 ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
419 ahd_outb(ahd, SG_STATE, 0);
420 ahd_restore_modes(ahd, saved_modes);
421}
422
423
424
425
426
427
428static void
429ahd_flush_qoutfifo(struct ahd_softc *ahd)
430{
431 struct scb *scb;
432 ahd_mode_state saved_modes;
433 u_int saved_scbptr;
434 u_int ccscbctl;
435 u_int scbid;
436 u_int next_scbid;
437
438 saved_modes = ahd_save_modes(ahd);
439
440
441
442
443 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
444 saved_scbptr = ahd_get_scbptr(ahd);
445 while ((ahd_inb(ahd, LQISTAT2) & LQIGSAVAIL) != 0) {
446 u_int fifo_mode;
447 u_int i;
448
449 scbid = ahd_inw(ahd, GSFIFO);
450 scb = ahd_lookup_scb(ahd, scbid);
451 if (scb == NULL) {
452 printf("%s: Warning - GSFIFO SCB %d invalid\n",
453 ahd_name(ahd), scbid);
454 continue;
455 }
456
457
458
459
460
461 fifo_mode = 0;
462rescan_fifos:
463 for (i = 0; i < 2; i++) {
464
465 fifo_mode ^= 1;
466 ahd_set_modes(ahd, fifo_mode, fifo_mode);
467
468 if (ahd_scb_active_in_fifo(ahd, scb) == 0)
469 continue;
470
471 ahd_run_data_fifo(ahd, scb);
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487 ahd_delay(200);
488 goto rescan_fifos;
489 }
490 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
491 ahd_set_scbptr(ahd, scbid);
492 if ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_LIST_NULL) == 0
493 && ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_FULL_RESID) != 0
494 || (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR)
495 & SG_LIST_NULL) != 0)) {
496 u_int comp_head;
497
498
499
500
501
502
503
504 ahd_outb(ahd, SCB_SCSI_STATUS, 0);
505 ahd_outb(ahd, SCB_SGPTR,
506 ahd_inb_scbram(ahd, SCB_SGPTR)
507 | SG_STATUS_VALID);
508 ahd_outw(ahd, SCB_TAG, scbid);
509 ahd_outw(ahd, SCB_NEXT_COMPLETE, SCB_LIST_NULL);
510 comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
511 if (SCBID_IS_NULL(comp_head)) {
512 ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, scbid);
513 ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
514 } else {
515 u_int tail;
516
517 tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL);
518 ahd_set_scbptr(ahd, tail);
519 ahd_outw(ahd, SCB_NEXT_COMPLETE, scbid);
520 ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
521 ahd_set_scbptr(ahd, scbid);
522 }
523 } else
524 ahd_complete_scb(ahd, scb);
525 }
526 ahd_set_scbptr(ahd, saved_scbptr);
527
528
529
530
531 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
532
533
534
535
536
537 while (((ccscbctl = ahd_inb(ahd, CCSCBCTL)) & (CCARREN|CCSCBEN)) != 0) {
538
539 if ((ccscbctl & (CCSCBDIR|CCARREN)) == (CCSCBDIR|CCARREN)) {
540 if ((ccscbctl & ARRDONE) != 0)
541 break;
542 } else if ((ccscbctl & CCSCBDONE) != 0)
543 break;
544 ahd_delay(200);
545 }
546
547
548
549
550
551
552
553 if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0)
554 ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN));
555
556
557
558
559
560 ahd_run_qoutfifo(ahd);
561
562 saved_scbptr = ahd_get_scbptr(ahd);
563
564
565
566
567 scbid = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
568 while (!SCBID_IS_NULL(scbid)) {
569 uint8_t *hscb_ptr;
570 u_int i;
571
572 ahd_set_scbptr(ahd, scbid);
573 next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
574 scb = ahd_lookup_scb(ahd, scbid);
575 if (scb == NULL) {
576 printf("%s: Warning - DMA-up and complete "
577 "SCB %d invalid\n", ahd_name(ahd), scbid);
578 continue;
579 }
580 hscb_ptr = (uint8_t *)scb->hscb;
581 for (i = 0; i < sizeof(struct hardware_scb); i++)
582 *hscb_ptr++ = ahd_inb_scbram(ahd, SCB_BASE + i);
583
584 ahd_complete_scb(ahd, scb);
585 scbid = next_scbid;
586 }
587 ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
588 ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
589
590 scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
591 while (!SCBID_IS_NULL(scbid)) {
592
593 ahd_set_scbptr(ahd, scbid);
594 next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
595 scb = ahd_lookup_scb(ahd, scbid);
596 if (scb == NULL) {
597 printf("%s: Warning - Complete Qfrz SCB %d invalid\n",
598 ahd_name(ahd), scbid);
599 continue;
600 }
601
602 ahd_complete_scb(ahd, scb);
603 scbid = next_scbid;
604 }
605 ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
606
607 scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD);
608 while (!SCBID_IS_NULL(scbid)) {
609
610 ahd_set_scbptr(ahd, scbid);
611 next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
612 scb = ahd_lookup_scb(ahd, scbid);
613 if (scb == NULL) {
614 printf("%s: Warning - Complete SCB %d invalid\n",
615 ahd_name(ahd), scbid);
616 continue;
617 }
618
619 ahd_complete_scb(ahd, scb);
620 scbid = next_scbid;
621 }
622 ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);
623
624
625
626
627 ahd_set_scbptr(ahd, saved_scbptr);
628 ahd_restore_modes(ahd, saved_modes);
629 ahd->flags |= AHD_UPDATE_PEND_CMDS;
630}
631
632
633
634
635
636static int
637ahd_scb_active_in_fifo(struct ahd_softc *ahd, struct scb *scb)
638{
639
640
641
642
643
644
645
646 if (ahd_get_scbptr(ahd) != SCB_GET_TAG(scb)
647 || ((ahd_inb(ahd, LONGJMP_ADDR+1) & INVALID_ADDR) != 0
648 && (ahd_inb(ahd, SEQINTSRC) & (CFG4DATA|SAVEPTRS)) == 0))
649 return (0);
650
651 return (1);
652}
653
654
655
656
657
658
659
660
661
662
663
664
665static void
666ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
667{
668 u_int seqintsrc;
669
670 seqintsrc = ahd_inb(ahd, SEQINTSRC);
671 if ((seqintsrc & CFG4DATA) != 0) {
672 uint32_t datacnt;
673 uint32_t sgptr;
674
675
676
677
678 sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
679 ahd_outb(ahd, SCB_SGPTR, sgptr);
680
681
682
683
684 datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);
685 if ((datacnt & AHD_DMA_LAST_SEG) != 0) {
686 sgptr |= LAST_SEG;
687 ahd_outb(ahd, SG_STATE, 0);
688 } else
689 ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
690 ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
691 ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
692 ahd_outb(ahd, SG_CACHE_PRE, sgptr);
693 ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
694
695
696
697
698 ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
699 ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
700
701
702
703
704 ahd_outb(ahd, SCB_FIFO_USE_COUNT,
705 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);
706
707
708
709
710 ahd_outw(ahd, LONGJMP_ADDR, 0);
711
712
713
714
715
716 ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
717 } else if ((seqintsrc & SAVEPTRS) != 0) {
718 uint32_t sgptr;
719 uint32_t resid;
720
721 if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
722
723
724
725
726
727 goto clrchn;
728 }
729
730
731
732
733
734 if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
735 ahd_outb(ahd, CCSGCTL, 0);
736 ahd_outb(ahd, SG_STATE, 0);
737
738
739
740
741
742 ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
743
744
745
746
747 sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
748 resid = ahd_inl(ahd, SHCNT);
749 resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
750 ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
751 if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
752
753
754
755
756
757
758
759 if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
760 && (sgptr & 0x80) == 0)
761 sgptr -= 0x100;
762 sgptr &= ~0xFF;
763 sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
764 & SG_ADDR_MASK;
765 ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
766 ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
767 } else if ((resid & AHD_SG_LEN_MASK) == 0) {
768 ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
769 sgptr | SG_LIST_NULL);
770 }
771
772
773
774 ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
775 ahd_outl(ahd, SCB_DATACNT, resid);
776 ahd_outl(ahd, SCB_SGPTR, sgptr);
777 ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
778 ahd_outb(ahd, SEQIMODE,
779 ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
780
781
782
783
784 if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
785 goto clrchn;
786 } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
787 uint32_t sgptr;
788 uint64_t data_addr;
789 uint32_t data_len;
790 u_int dfcntrl;
791
792
793
794
795
796
797 if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {
798 ahd_outb(ahd, CCSGCTL, 0);
799 ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
800 }
801
802
803
804
805
806
807
808 if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 0
809 && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) {
810
811
812
813
814
815 sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
816 sgptr &= SG_PTR_MASK;
817 if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
818 struct ahd_dma64_seg *sg;
819
820 sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
821 data_addr = sg->addr;
822 data_len = sg->len;
823 sgptr += sizeof(*sg);
824 } else {
825 struct ahd_dma_seg *sg;
826
827 sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
828 data_addr = sg->len & AHD_SG_HIGH_ADDR_MASK;
829 data_addr <<= 8;
830 data_addr |= sg->addr;
831 data_len = sg->len;
832 sgptr += sizeof(*sg);
833 }
834
835
836
837
838 ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, data_len >> 24);
839 ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
840
841
842
843
844 if (data_len & AHD_DMA_LAST_SEG) {
845 sgptr |= LAST_SEG;
846 ahd_outb(ahd, SG_STATE, 0);
847 }
848 ahd_outq(ahd, HADDR, data_addr);
849 ahd_outl(ahd, HCNT, data_len & AHD_SG_LEN_MASK);
850 ahd_outb(ahd, SG_CACHE_PRE, sgptr & 0xFF);
851
852
853
854
855 dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN;
856 if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {
857
858
859
860
861
862 dfcntrl |= SCSIENWRDIS;
863 }
864 ahd_outb(ahd, DFCNTRL, dfcntrl);
865 }
866 } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) {
867
868
869
870
871
872 ahd_outb(ahd, SCB_SGPTR,
873 ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
874 goto clrchn;
875 } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
876clrchn:
877
878
879
880
881
882 ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
883 ahd_outb(ahd, SCB_FIFO_USE_COUNT,
884 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);
885 ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
886 }
887}
888
889
890
891
892
893
894
895
896
897
898
899void
900ahd_run_qoutfifo(struct ahd_softc *ahd)
901{
902 struct ahd_completion *completion;
903 struct scb *scb;
904 u_int scb_index;
905
906 if ((ahd->flags & AHD_RUNNING_QOUTFIFO) != 0)
907 panic("ahd_run_qoutfifo recursion");
908 ahd->flags |= AHD_RUNNING_QOUTFIFO;
909 ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD);
910 for (;;) {
911 completion = &ahd->qoutfifo[ahd->qoutfifonext];
912
913 if (completion->valid_tag != ahd->qoutfifonext_valid_tag)
914 break;
915
916 scb_index = ahd_le16toh(completion->tag);
917 scb = ahd_lookup_scb(ahd, scb_index);
918 if (scb == NULL) {
919 printf("%s: WARNING no command for scb %d "
920 "(cmdcmplt)\nQOUTPOS = %d\n",
921 ahd_name(ahd), scb_index,
922 ahd->qoutfifonext);
923 ahd_dump_card_state(ahd);
924 } else if ((completion->sg_status & SG_STATUS_VALID) != 0) {
925 ahd_handle_scb_status(ahd, scb);
926 } else {
927 ahd_done(ahd, scb);
928 }
929
930 ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1);
931 if (ahd->qoutfifonext == 0)
932 ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID;
933 }
934 ahd->flags &= ~AHD_RUNNING_QOUTFIFO;
935}
936
937
938void
939ahd_handle_hwerrint(struct ahd_softc *ahd)
940{
941
942
943
944
945 int i;
946 int error;
947
948 error = ahd_inb(ahd, ERROR);
949 for (i = 0; i < num_errors; i++) {
950 if ((error & ahd_hard_errors[i].errno) != 0)
951 printf("%s: hwerrint, %s\n",
952 ahd_name(ahd), ahd_hard_errors[i].errmesg);
953 }
954
955 ahd_dump_card_state(ahd);
956 panic("BRKADRINT");
957
958
959 ahd_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,
960 CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_UNKNOWN,
961 CAM_NO_HBA);
962
963
964 ahd_free(ahd);
965}
966
967#ifdef AHD_DEBUG
968static void
969ahd_dump_sglist(struct scb *scb)
970{
971 int i;
972
973 if (scb->sg_count > 0) {
974 if ((scb->ahd_softc->flags & AHD_64BIT_ADDRESSING) != 0) {
975 struct ahd_dma64_seg *sg_list;
976
977 sg_list = (struct ahd_dma64_seg*)scb->sg_list;
978 for (i = 0; i < scb->sg_count; i++) {
979 uint64_t addr;
980 uint32_t len;
981
982 addr = ahd_le64toh(sg_list[i].addr);
983 len = ahd_le32toh(sg_list[i].len);
984 printf("sg[%d] - Addr 0x%x%x : Length %d%s\n",
985 i,
986 (uint32_t)((addr >> 32) & 0xFFFFFFFF),
987 (uint32_t)(addr & 0xFFFFFFFF),
988 sg_list[i].len & AHD_SG_LEN_MASK,
989 (sg_list[i].len & AHD_DMA_LAST_SEG)
990 ? " Last" : "");
991 }
992 } else {
993 struct ahd_dma_seg *sg_list;
994
995 sg_list = (struct ahd_dma_seg*)scb->sg_list;
996 for (i = 0; i < scb->sg_count; i++) {
997 uint32_t len;
998
999 len = ahd_le32toh(sg_list[i].len);
1000 printf("sg[%d] - Addr 0x%x%x : Length %d%s\n",
1001 i,
1002 (len & AHD_SG_HIGH_ADDR_MASK) >> 24,
1003 ahd_le32toh(sg_list[i].addr),
1004 len & AHD_SG_LEN_MASK,
1005 len & AHD_DMA_LAST_SEG ? " Last" : "");
1006 }
1007 }
1008 }
1009}
1010#endif
1011
1012void
1013ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
1014{
1015 u_int seqintcode;
1016
1017
1018
1019
1020
1021
1022 seqintcode = ahd_inb(ahd, SEQINTCODE);
1023 ahd_outb(ahd, CLRINT, CLRSEQINT);
1024 if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
1025
1026
1027
1028
1029
1030
1031 ahd_unpause(ahd);
1032 while (!ahd_is_paused(ahd))
1033 ;
1034 ahd_outb(ahd, CLRINT, CLRSEQINT);
1035 }
1036 ahd_update_modes(ahd);
1037#ifdef AHD_DEBUG
1038 if ((ahd_debug & AHD_SHOW_MISC) != 0)
1039 printf("%s: Handle Seqint Called for code %d\n",
1040 ahd_name(ahd), seqintcode);
1041#endif
1042 switch (seqintcode) {
1043 case ENTERING_NONPACK:
1044 {
1045 struct scb *scb;
1046 u_int scbid;
1047
1048 AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
1049 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
1050 scbid = ahd_get_scbptr(ahd);
1051 scb = ahd_lookup_scb(ahd, scbid);
1052 if (scb == NULL) {
1053
1054
1055
1056
1057
1058
1059 } else {
1060 ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid);
1061 ahd_outb(ahd, SAVED_LUN, scb->hscb->lun);
1062 ahd_outb(ahd, SEQ_FLAGS, 0x0);
1063 }
1064 if ((ahd_inb(ahd, LQISTAT2) & LQIPHASE_OUTPKT) != 0
1065 && (ahd_inb(ahd, SCSISIGO) & ATNO) != 0) {
1066
1067
1068
1069
1070
1071#ifdef AHD_DEBUG
1072 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
1073 printf("%s: Assuming LQIPHASE_NLQ with "
1074 "P0 assertion\n", ahd_name(ahd));
1075#endif
1076 }
1077#ifdef AHD_DEBUG
1078 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
1079 printf("%s: Entering NONPACK\n", ahd_name(ahd));
1080#endif
1081 break;
1082 }
1083 case INVALID_SEQINT:
1084 printf("%s: Invalid Sequencer interrupt occurred, "
1085 "resetting channel.\n",
1086 ahd_name(ahd));
1087#ifdef AHD_DEBUG
1088 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
1089 ahd_dump_card_state(ahd);
1090#endif
1091 ahd_reset_channel(ahd, 'A', TRUE);
1092 break;
1093 case STATUS_OVERRUN:
1094 {
1095 struct scb *scb;
1096 u_int scbid;
1097
1098 scbid = ahd_get_scbptr(ahd);
1099 scb = ahd_lookup_scb(ahd, scbid);
1100 if (scb != NULL)
1101 ahd_print_path(ahd, scb);
1102 else
1103 printf("%s: ", ahd_name(ahd));
1104 printf("SCB %d Packetized Status Overrun", scbid);
1105 ahd_dump_card_state(ahd);
1106 ahd_reset_channel(ahd, 'A', TRUE);
1107 break;
1108 }
1109 case CFG4ISTAT_INTR:
1110 {
1111 struct scb *scb;
1112 u_int scbid;
1113
1114 scbid = ahd_get_scbptr(ahd);
1115 scb = ahd_lookup_scb(ahd, scbid);
1116 if (scb == NULL) {
1117 ahd_dump_card_state(ahd);
1118 printf("CFG4ISTAT: Free SCB %d referenced", scbid);
1119 panic("For safety");
1120 }
1121 ahd_outq(ahd, HADDR, scb->sense_busaddr);
1122 ahd_outw(ahd, HCNT, AHD_SENSE_BUFSIZE);
1123 ahd_outb(ahd, HCNT + 2, 0);
1124 ahd_outb(ahd, SG_CACHE_PRE, SG_LAST_SEG);
1125 ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
1126 break;
1127 }
1128 case ILLEGAL_PHASE:
1129 {
1130 u_int bus_phase;
1131
1132 bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;
1133 printf("%s: ILLEGAL_PHASE 0x%x\n",
1134 ahd_name(ahd), bus_phase);
1135
1136 switch (bus_phase) {
1137 case P_DATAOUT:
1138 case P_DATAIN:
1139 case P_DATAOUT_DT:
1140 case P_DATAIN_DT:
1141 case P_MESGOUT:
1142 case P_STATUS:
1143 case P_MESGIN:
1144 ahd_reset_channel(ahd, 'A', TRUE);
1145 printf("%s: Issued Bus Reset.\n", ahd_name(ahd));
1146 break;
1147 case P_COMMAND:
1148 {
1149 struct ahd_devinfo devinfo;
1150 struct scb *scb;
1151 struct ahd_initiator_tinfo *targ_info;
1152 struct ahd_tmode_tstate *tstate;
1153 struct ahd_transinfo *tinfo;
1154 u_int scbid;
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167 scbid = ahd_get_scbptr(ahd);
1168 scb = ahd_lookup_scb(ahd, scbid);
1169 if (scb == NULL) {
1170 printf("Invalid phase with no valid SCB. "
1171 "Resetting bus.\n");
1172 ahd_reset_channel(ahd, 'A',
1173 TRUE);
1174 break;
1175 }
1176 ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb),
1177 SCB_GET_TARGET(ahd, scb),
1178 SCB_GET_LUN(scb),
1179 SCB_GET_CHANNEL(ahd, scb),
1180 ROLE_INITIATOR);
1181 targ_info = ahd_fetch_transinfo(ahd,
1182 devinfo.channel,
1183 devinfo.our_scsiid,
1184 devinfo.target,
1185 &tstate);
1186 tinfo = &targ_info->curr;
1187 ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
1188 AHD_TRANS_ACTIVE, TRUE);
1189 ahd_set_syncrate(ahd, &devinfo, 0,
1190 0, 0,
1191 AHD_TRANS_ACTIVE, TRUE);
1192
1193 ahd_outb(ahd, SCB_CDB_STORE, 0);
1194 ahd_outb(ahd, SCB_CDB_STORE+1, 0);
1195 ahd_outb(ahd, SCB_CDB_STORE+2, 0);
1196 ahd_outb(ahd, SCB_CDB_STORE+3, 0);
1197 ahd_outb(ahd, SCB_CDB_STORE+4, 0);
1198 ahd_outb(ahd, SCB_CDB_STORE+5, 0);
1199 ahd_outb(ahd, SCB_CDB_LEN, 6);
1200 scb->hscb->control &= ~(TAG_ENB|SCB_TAG_TYPE);
1201 scb->hscb->control |= MK_MESSAGE;
1202 ahd_outb(ahd, SCB_CONTROL, scb->hscb->control);
1203 ahd_outb(ahd, MSG_OUT, HOST_MSG);
1204 ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid);
1205
1206
1207
1208
1209 ahd_outb(ahd, SAVED_LUN, 0);
1210 ahd_outb(ahd, SEQ_FLAGS, 0);
1211 ahd_assert_atn(ahd);
1212 scb->flags &= ~SCB_PACKETIZED;
1213 scb->flags |= SCB_ABORT|SCB_EXTERNAL_RESET;
1214 ahd_freeze_devq(ahd, scb);
1215 ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
1216 ahd_freeze_scb(scb);
1217
1218
1219 ahd_send_async(ahd, devinfo.channel, devinfo.target,
1220 CAM_LUN_WILDCARD, AC_SENT_BDR);
1221
1222
1223
1224
1225
1226 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
1227 ahd_outb(ahd, CLRLQOINT1, CLRLQOPHACHGINPKT);
1228 if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {
1229 ahd_outb(ahd, CLRLQOINT1, 0);
1230 }
1231#ifdef AHD_DEBUG
1232 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
1233 ahd_print_path(ahd, scb);
1234 printf("Unexpected command phase from "
1235 "packetized target\n");
1236 }
1237#endif
1238 break;
1239 }
1240 }
1241 break;
1242 }
1243 case CFG4OVERRUN:
1244 {
1245 struct scb *scb;
1246 u_int scb_index;
1247
1248#ifdef AHD_DEBUG
1249 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
1250 printf("%s: CFG4OVERRUN mode = %x\n", ahd_name(ahd),
1251 ahd_inb(ahd, MODE_PTR));
1252 }
1253#endif
1254 scb_index = ahd_get_scbptr(ahd);
1255 scb = ahd_lookup_scb(ahd, scb_index);
1256 if (scb == NULL) {
1257
1258
1259
1260
1261 ahd_assert_atn(ahd);
1262 ahd_outb(ahd, MSG_OUT, HOST_MSG);
1263 ahd->msgout_buf[0] = MSG_ABORT_TASK;
1264 ahd->msgout_len = 1;
1265 ahd->msgout_index = 0;
1266 ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
1267
1268
1269
1270
1271 ahd_outb(ahd, SCB_CONTROL,
1272 ahd_inb_scbram(ahd, SCB_CONTROL)
1273 & ~STATUS_RCVD);
1274 }
1275 break;
1276 }
1277 case DUMP_CARD_STATE:
1278 {
1279 ahd_dump_card_state(ahd);
1280 break;
1281 }
1282 case PDATA_REINIT:
1283 {
1284#ifdef AHD_DEBUG
1285 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
1286 printf("%s: PDATA_REINIT - DFCNTRL = 0x%x "
1287 "SG_CACHE_SHADOW = 0x%x\n",
1288 ahd_name(ahd), ahd_inb(ahd, DFCNTRL),
1289 ahd_inb(ahd, SG_CACHE_SHADOW));
1290 }
1291#endif
1292 ahd_reinitialize_dataptrs(ahd);
1293 break;
1294 }
1295 case HOST_MSG_LOOP:
1296 {
1297 struct ahd_devinfo devinfo;
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310 ahd_fetch_devinfo(ahd, &devinfo);
1311 if (ahd->msg_type == MSG_TYPE_NONE) {
1312 struct scb *scb;
1313 u_int scb_index;
1314 u_int bus_phase;
1315
1316 bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;
1317 if (bus_phase != P_MESGIN
1318 && bus_phase != P_MESGOUT) {
1319 printf("ahd_intr: HOST_MSG_LOOP bad "
1320 "phase 0x%x\n", bus_phase);
1321
1322
1323
1324
1325 ahd_dump_card_state(ahd);
1326 ahd_clear_intstat(ahd);
1327 ahd_restart(ahd);
1328 return;
1329 }
1330
1331 scb_index = ahd_get_scbptr(ahd);
1332 scb = ahd_lookup_scb(ahd, scb_index);
1333 if (devinfo.role == ROLE_INITIATOR) {
1334 if (bus_phase == P_MESGOUT)
1335 ahd_setup_initiator_msgout(ahd,
1336 &devinfo,
1337 scb);
1338 else {
1339 ahd->msg_type =
1340 MSG_TYPE_INITIATOR_MSGIN;
1341 ahd->msgin_index = 0;
1342 }
1343 }
1344#ifdef AHD_TARGET_MODE
1345 else {
1346 if (bus_phase == P_MESGOUT) {
1347 ahd->msg_type =
1348 MSG_TYPE_TARGET_MSGOUT;
1349 ahd->msgin_index = 0;
1350 }
1351 else
1352 ahd_setup_target_msgin(ahd,
1353 &devinfo,
1354 scb);
1355 }
1356#endif
1357 }
1358
1359 ahd_handle_message_phase(ahd);
1360 break;
1361 }
1362 case NO_MATCH:
1363 {
1364
1365 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
1366 ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
1367
1368 printf("%s:%c:%d: no active SCB for reconnecting "
1369 "target - issuing BUS DEVICE RESET\n",
1370 ahd_name(ahd), 'A', ahd_inb(ahd, SELID) >> 4);
1371 printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, "
1372 "REG0 == 0x%x ACCUM = 0x%x\n",
1373 ahd_inb(ahd, SAVED_SCSIID), ahd_inb(ahd, SAVED_LUN),
1374 ahd_inw(ahd, REG0), ahd_inb(ahd, ACCUM));
1375 printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, "
1376 "SINDEX == 0x%x\n",
1377 ahd_inb(ahd, SEQ_FLAGS), ahd_get_scbptr(ahd),
1378 ahd_find_busy_tcl(ahd,
1379 BUILD_TCL(ahd_inb(ahd, SAVED_SCSIID),
1380 ahd_inb(ahd, SAVED_LUN))),
1381 ahd_inw(ahd, SINDEX));
1382 printf("SELID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, "
1383 "SCB_CONTROL == 0x%x\n",
1384 ahd_inb(ahd, SELID), ahd_inb_scbram(ahd, SCB_SCSIID),
1385 ahd_inb_scbram(ahd, SCB_LUN),
1386 ahd_inb_scbram(ahd, SCB_CONTROL));
1387 printf("SCSIBUS[0] == 0x%x, SCSISIGI == 0x%x\n",
1388 ahd_inb(ahd, SCSIBUS), ahd_inb(ahd, SCSISIGI));
1389 printf("SXFRCTL0 == 0x%x\n", ahd_inb(ahd, SXFRCTL0));
1390 printf("SEQCTL0 == 0x%x\n", ahd_inb(ahd, SEQCTL0));
1391 ahd_dump_card_state(ahd);
1392 ahd->msgout_buf[0] = MSG_BUS_DEV_RESET;
1393 ahd->msgout_len = 1;
1394 ahd->msgout_index = 0;
1395 ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
1396 ahd_outb(ahd, MSG_OUT, HOST_MSG);
1397 ahd_assert_atn(ahd);
1398 break;
1399 }
1400 case PROTO_VIOLATION:
1401 {
1402 ahd_handle_proto_violation(ahd);
1403 break;
1404 }
1405 case IGN_WIDE_RES:
1406 {
1407 struct ahd_devinfo devinfo;
1408
1409 ahd_fetch_devinfo(ahd, &devinfo);
1410 ahd_handle_ign_wide_residue(ahd, &devinfo);
1411 break;
1412 }
1413 case BAD_PHASE:
1414 {
1415 u_int lastphase;
1416
1417 lastphase = ahd_inb(ahd, LASTPHASE);
1418 printf("%s:%c:%d: unknown scsi bus phase %x, "
1419 "lastphase = 0x%x. Attempting to continue\n",
1420 ahd_name(ahd), 'A',
1421 SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)),
1422 lastphase, ahd_inb(ahd, SCSISIGI));
1423 break;
1424 }
1425 case MISSED_BUSFREE:
1426 {
1427 u_int lastphase;
1428
1429 lastphase = ahd_inb(ahd, LASTPHASE);
1430 printf("%s:%c:%d: Missed busfree. "
1431 "Lastphase = 0x%x, Curphase = 0x%x\n",
1432 ahd_name(ahd), 'A',
1433 SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)),
1434 lastphase, ahd_inb(ahd, SCSISIGI));
1435 ahd_restart(ahd);
1436 return;
1437 }
1438 case DATA_OVERRUN:
1439 {
1440
1441
1442
1443
1444
1445
1446
1447
1448 struct scb *scb;
1449 u_int scbindex;
1450#ifdef AHD_DEBUG
1451 u_int lastphase;
1452#endif
1453
1454 scbindex = ahd_get_scbptr(ahd);
1455 scb = ahd_lookup_scb(ahd, scbindex);
1456#ifdef AHD_DEBUG
1457 lastphase = ahd_inb(ahd, LASTPHASE);
1458 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
1459 ahd_print_path(ahd, scb);
1460 printf("data overrun detected %s. Tag == 0x%x.\n",
1461 ahd_lookup_phase_entry(lastphase)->phasemsg,
1462 SCB_GET_TAG(scb));
1463 ahd_print_path(ahd, scb);
1464 printf("%s seen Data Phase. Length = %ld. "
1465 "NumSGs = %d.\n",
1466 ahd_inb(ahd, SEQ_FLAGS) & DPHASE
1467 ? "Have" : "Haven't",
1468 ahd_get_transfer_length(scb), scb->sg_count);
1469 ahd_dump_sglist(scb);
1470 }
1471#endif
1472
1473
1474
1475
1476
1477 ahd_freeze_devq(ahd, scb);
1478 ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR);
1479 ahd_freeze_scb(scb);
1480 break;
1481 }
1482 case MKMSG_FAILED:
1483 {
1484 struct ahd_devinfo devinfo;
1485 struct scb *scb;
1486 u_int scbid;
1487
1488 ahd_fetch_devinfo(ahd, &devinfo);
1489 printf("%s:%c:%d:%d: Attempt to issue message failed\n",
1490 ahd_name(ahd), devinfo.channel, devinfo.target,
1491 devinfo.lun);
1492 scbid = ahd_get_scbptr(ahd);
1493 scb = ahd_lookup_scb(ahd, scbid);
1494 if (scb != NULL
1495 && (scb->flags & SCB_RECOVERY_SCB) != 0)
1496
1497
1498
1499
1500 ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),
1501 SCB_GET_CHANNEL(ahd, scb),
1502 SCB_GET_LUN(scb), SCB_GET_TAG(scb),
1503 ROLE_INITIATOR, 0,
1504 SEARCH_REMOVE);
1505 ahd_outb(ahd, SCB_CONTROL,
1506 ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE);
1507 break;
1508 }
1509 case TASKMGMT_FUNC_COMPLETE:
1510 {
1511 u_int scbid;
1512 struct scb *scb;
1513
1514 scbid = ahd_get_scbptr(ahd);
1515 scb = ahd_lookup_scb(ahd, scbid);
1516 if (scb != NULL) {
1517 u_int lun;
1518 u_int tag;
1519 cam_status error;
1520
1521 ahd_print_path(ahd, scb);
1522 printf("Task Management Func 0x%x Complete\n",
1523 scb->hscb->task_management);
1524 lun = CAM_LUN_WILDCARD;
1525 tag = SCB_LIST_NULL;
1526
1527 switch (scb->hscb->task_management) {
1528 case SIU_TASKMGMT_ABORT_TASK:
1529 tag = SCB_GET_TAG(scb);
1530 case SIU_TASKMGMT_ABORT_TASK_SET:
1531 case SIU_TASKMGMT_CLEAR_TASK_SET:
1532 lun = scb->hscb->lun;
1533 error = CAM_REQ_ABORTED;
1534 ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),
1535 'A', lun, tag, ROLE_INITIATOR,
1536 error);
1537 break;
1538 case SIU_TASKMGMT_LUN_RESET:
1539 lun = scb->hscb->lun;
1540 case SIU_TASKMGMT_TARGET_RESET:
1541 {
1542 struct ahd_devinfo devinfo;
1543
1544 ahd_scb_devinfo(ahd, &devinfo, scb);
1545 error = CAM_BDR_SENT;
1546 ahd_handle_devreset(ahd, &devinfo, lun,
1547 CAM_BDR_SENT,
1548 lun != CAM_LUN_WILDCARD
1549 ? "Lun Reset"
1550 : "Target Reset",
1551 0);
1552 break;
1553 }
1554 default:
1555 panic("Unexpected TaskMgmt Func\n");
1556 break;
1557 }
1558 }
1559 break;
1560 }
1561 case TASKMGMT_CMD_CMPLT_OKAY:
1562 {
1563 u_int scbid;
1564 struct scb *scb;
1565
1566
1567
1568
1569
1570 scbid = ahd_get_scbptr(ahd);
1571 scb = ahd_lookup_scb(ahd, scbid);
1572 if (scb != NULL) {
1573
1574
1575
1576
1577 ahd_print_path(ahd, scb);
1578 printf("SCB completes before TMF\n");
1579
1580
1581
1582
1583
1584
1585
1586 while ((ahd_inb(ahd, SCSISEQ0) & ENSELO) != 0
1587 && (ahd_inb(ahd, SSTAT0) & SELDO) == 0
1588 && (ahd_inb(ahd, SSTAT1) & SELTO) == 0)
1589 ;
1590 ahd_outb(ahd, SCB_TASK_MANAGEMENT, 0);
1591 ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),
1592 SCB_GET_CHANNEL(ahd, scb),
1593 SCB_GET_LUN(scb), SCB_GET_TAG(scb),
1594 ROLE_INITIATOR, 0,
1595 SEARCH_REMOVE);
1596 }
1597 break;
1598 }
1599 case TRACEPOINT0:
1600 case TRACEPOINT1:
1601 case TRACEPOINT2:
1602 case TRACEPOINT3:
1603 printf("%s: Tracepoint %d\n", ahd_name(ahd),
1604 seqintcode - TRACEPOINT0);
1605 break;
1606 case NO_SEQINT:
1607 break;
1608 case SAW_HWERR:
1609 ahd_handle_hwerrint(ahd);
1610 break;
1611 default:
1612 printf("%s: Unexpected SEQINTCODE %d\n", ahd_name(ahd),
1613 seqintcode);
1614 break;
1615 }
1616
1617
1618
1619
1620
1621 ahd_unpause(ahd);
1622}
1623
1624void
1625ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
1626{
1627 struct scb *scb;
1628 u_int status0;
1629 u_int status3;
1630 u_int status;
1631 u_int lqistat1;
1632 u_int lqostat0;
1633 u_int scbid;
1634 u_int busfreetime;
1635
1636 ahd_update_modes(ahd);
1637 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
1638
1639 status3 = ahd_inb(ahd, SSTAT3) & (NTRAMPERR|OSRAMPERR);
1640 status0 = ahd_inb(ahd, SSTAT0) & (IOERR|OVERRUN|SELDI|SELDO);
1641 status = ahd_inb(ahd, SSTAT1) & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR);
1642 lqistat1 = ahd_inb(ahd, LQISTAT1);
1643 lqostat0 = ahd_inb(ahd, LQOSTAT0);
1644 busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME;
1645
1646
1647
1648
1649 if (((status & SCSIRSTI) != 0) && (ahd->flags & AHD_BUS_RESET_ACTIVE)) {
1650 ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);
1651 return;
1652 }
1653
1654
1655
1656
1657 ahd->flags &= ~AHD_BUS_RESET_ACTIVE;
1658
1659 if ((status0 & (SELDI|SELDO)) != 0) {
1660 u_int simode0;
1661
1662 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
1663 simode0 = ahd_inb(ahd, SIMODE0);
1664 status0 &= simode0 & (IOERR|OVERRUN|SELDI|SELDO);
1665 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
1666 }
1667 scbid = ahd_get_scbptr(ahd);
1668 scb = ahd_lookup_scb(ahd, scbid);
1669 if (scb != NULL
1670 && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)
1671 scb = NULL;
1672
1673 if ((status0 & IOERR) != 0) {
1674 u_int now_lvd;
1675
1676 now_lvd = ahd_inb(ahd, SBLKCTL) & ENAB40;
1677 printf("%s: Transceiver State Has Changed to %s mode\n",
1678 ahd_name(ahd), now_lvd ? "LVD" : "SE");
1679 ahd_outb(ahd, CLRSINT0, CLRIOERR);
1680
1681
1682
1683 ahd_reset_channel(ahd, 'A', TRUE);
1684 ahd_pause(ahd);
1685 ahd_setup_iocell_workaround(ahd);
1686 ahd_unpause(ahd);
1687 } else if ((status0 & OVERRUN) != 0) {
1688
1689 printf("%s: SCSI offset overrun detected. Resetting bus.\n",
1690 ahd_name(ahd));
1691 ahd_reset_channel(ahd, 'A', TRUE);
1692 } else if ((status & SCSIRSTI) != 0) {
1693
1694 printf("%s: Someone reset channel A\n", ahd_name(ahd));
1695 ahd_reset_channel(ahd, 'A', FALSE);
1696 } else if ((status & SCSIPERR) != 0) {
1697
1698
1699 ahd_clear_critical_section(ahd);
1700
1701 ahd_handle_transmission_error(ahd);
1702 } else if (lqostat0 != 0) {
1703
1704 printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0);
1705 ahd_outb(ahd, CLRLQOINT0, lqostat0);
1706 if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)
1707 ahd_outb(ahd, CLRLQOINT1, 0);
1708 } else if ((status & SELTO) != 0) {
1709 u_int scbid;
1710
1711
1712 ahd_outb(ahd, SCSISEQ0, 0);
1713
1714
1715 ahd_clear_critical_section(ahd);
1716
1717
1718 ahd_clear_msg_state(ahd);
1719
1720
1721 ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR);
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731 ahd_outb(ahd, CLRSINT0, CLRSELINGO);
1732
1733 scbid = ahd_inw(ahd, WAITING_TID_HEAD);
1734 scb = ahd_lookup_scb(ahd, scbid);
1735 if (scb == NULL) {
1736 printf("%s: ahd_intr - referenced scb not "
1737 "valid during SELTO scb(0x%x)\n",
1738 ahd_name(ahd), scbid);
1739 ahd_dump_card_state(ahd);
1740 } else {
1741 struct ahd_devinfo devinfo;
1742#ifdef AHD_DEBUG
1743 if ((ahd_debug & AHD_SHOW_SELTO) != 0) {
1744 ahd_print_path(ahd, scb);
1745 printf("Saw Selection Timeout for SCB 0x%x\n",
1746 scbid);
1747 }
1748#endif
1749 ahd_scb_devinfo(ahd, &devinfo, scb);
1750 ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT);
1751 ahd_freeze_devq(ahd, scb);
1752
1753
1754
1755
1756
1757
1758
1759 ahd_handle_devreset(ahd, &devinfo,
1760 CAM_LUN_WILDCARD,
1761 CAM_SEL_TIMEOUT,
1762 "Selection Timeout",
1763 1);
1764 }
1765 ahd_outb(ahd, CLRINT, CLRSCSIINT);
1766 ahd_iocell_first_selection(ahd);
1767 ahd_unpause(ahd);
1768 } else if ((status0 & (SELDI|SELDO)) != 0) {
1769
1770 ahd_iocell_first_selection(ahd);
1771 ahd_unpause(ahd);
1772 } else if (status3 != 0) {
1773 printf("%s: SCSI Cell parity error SSTAT3 == 0x%x\n",
1774 ahd_name(ahd), status3);
1775 ahd_outb(ahd, CLRSINT3, status3);
1776 } else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) {
1777
1778
1779 ahd_clear_critical_section(ahd);
1780
1781 ahd_handle_lqiphase_error(ahd, lqistat1);
1782 } else if ((lqistat1 & LQICRCI_NLQ) != 0) {
1783
1784
1785
1786
1787
1788
1789 ahd_outb(ahd, CLRLQIINT1, CLRLQICRCI_NLQ);
1790 } else if ((status & BUSFREE) != 0
1791 || (lqistat1 & LQOBUSFREE) != 0) {
1792 u_int lqostat1;
1793 int restart;
1794 int clear_fifo;
1795 int packetized;
1796 u_int mode;
1797
1798
1799
1800
1801
1802
1803
1804 ahd_outb(ahd, SCSISEQ0, 0);
1805
1806
1807 ahd_clear_critical_section(ahd);
1808
1809
1810
1811
1812
1813 mode = AHD_MODE_SCSI;
1814 busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME;
1815 lqostat1 = ahd_inb(ahd, LQOSTAT1);
1816 switch (busfreetime) {
1817 case BUSFREE_DFF0:
1818 case BUSFREE_DFF1:
1819 {
1820 u_int scbid;
1821 struct scb *scb;
1822
1823 mode = busfreetime == BUSFREE_DFF0
1824 ? AHD_MODE_DFF0 : AHD_MODE_DFF1;
1825 ahd_set_modes(ahd, mode, mode);
1826 scbid = ahd_get_scbptr(ahd);
1827 scb = ahd_lookup_scb(ahd, scbid);
1828 if (scb == NULL) {
1829 printf("%s: Invalid SCB %d in DFF%d "
1830 "during unexpected busfree\n",
1831 ahd_name(ahd), scbid, mode);
1832 packetized = 0;
1833 } else
1834 packetized = (scb->flags & SCB_PACKETIZED) != 0;
1835 clear_fifo = 1;
1836 break;
1837 }
1838 case BUSFREE_LQO:
1839 clear_fifo = 0;
1840 packetized = 1;
1841 break;
1842 default:
1843 clear_fifo = 0;
1844 packetized = (lqostat1 & LQOBUSFREE) != 0;
1845 if (!packetized
1846 && ahd_inb(ahd, LASTPHASE) == P_BUSFREE
1847 && (ahd_inb(ahd, SSTAT0) & SELDI) == 0
1848 && ((ahd_inb(ahd, SSTAT0) & SELDO) == 0
1849 || (ahd_inb(ahd, SCSISEQ0) & ENSELO) == 0))
1850
1851
1852
1853
1854
1855
1856 packetized = 1;
1857 break;
1858 }
1859
1860#ifdef AHD_DEBUG
1861 if ((ahd_debug & AHD_SHOW_MISC) != 0)
1862 printf("Saw Busfree. Busfreetime = 0x%x.\n",
1863 busfreetime);
1864#endif
1865
1866
1867
1868
1869 if (packetized && ahd_inb(ahd, LASTPHASE) == P_BUSFREE) {
1870 restart = ahd_handle_pkt_busfree(ahd, busfreetime);
1871 } else {
1872 packetized = 0;
1873 restart = ahd_handle_nonpkt_busfree(ahd);
1874 }
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886 ahd_outb(ahd, CLRSINT1, CLRBUSFREE);
1887 if (packetized == 0
1888 && (ahd->bugs & AHD_BUSFREEREV_BUG) != 0)
1889 ahd_outb(ahd, SIMODE1,
1890 ahd_inb(ahd, SIMODE1) & ~ENBUSFREE);
1891
1892 if (clear_fifo)
1893 ahd_clear_fifo(ahd, mode);
1894
1895 ahd_clear_msg_state(ahd);
1896 ahd_outb(ahd, CLRINT, CLRSCSIINT);
1897 if (restart) {
1898 ahd_restart(ahd);
1899 } else {
1900 ahd_unpause(ahd);
1901 }
1902 } else {
1903 printf("%s: Missing case in ahd_handle_scsiint. status = %x\n",
1904 ahd_name(ahd), status);
1905 ahd_dump_card_state(ahd);
1906 ahd_clear_intstat(ahd);
1907 ahd_unpause(ahd);
1908 }
1909}
1910
1911static void
1912ahd_handle_transmission_error(struct ahd_softc *ahd)
1913{
1914 struct scb *scb;
1915 u_int scbid;
1916 u_int lqistat1;
1917 u_int lqistat2;
1918 u_int msg_out;
1919 u_int curphase;
1920 u_int lastphase;
1921 u_int perrdiag;
1922 u_int cur_col;
1923 int silent;
1924
1925 scb = NULL;
1926 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
1927 lqistat1 = ahd_inb(ahd, LQISTAT1) & ~(LQIPHASE_LQ|LQIPHASE_NLQ);
1928 lqistat2 = ahd_inb(ahd, LQISTAT2);
1929 if ((lqistat1 & (LQICRCI_NLQ|LQICRCI_LQ)) == 0
1930 && (ahd->bugs & AHD_NLQICRC_DELAYED_BUG) != 0) {
1931 u_int lqistate;
1932
1933 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
1934 lqistate = ahd_inb(ahd, LQISTATE);
1935 if ((lqistate >= 0x1E && lqistate <= 0x24)
1936 || (lqistate == 0x29)) {
1937#ifdef AHD_DEBUG
1938 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
1939 printf("%s: NLQCRC found via LQISTATE\n",
1940 ahd_name(ahd));
1941 }
1942#endif
1943 lqistat1 |= LQICRCI_NLQ;
1944 }
1945 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
1946 }
1947
1948 ahd_outb(ahd, CLRLQIINT1, lqistat1);
1949 lastphase = ahd_inb(ahd, LASTPHASE);
1950 curphase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;
1951 perrdiag = ahd_inb(ahd, PERRDIAG);
1952 msg_out = MSG_INITIATOR_DET_ERR;
1953 ahd_outb(ahd, CLRSINT1, CLRSCSIPERR);
1954
1955
1956
1957
1958 silent = FALSE;
1959 if (lqistat1 == 0
1960 || (lqistat1 & LQICRCI_NLQ) != 0) {
1961 if ((lqistat1 & (LQICRCI_NLQ|LQIOVERI_NLQ)) != 0)
1962 ahd_set_active_fifo(ahd);
1963 scbid = ahd_get_scbptr(ahd);
1964 scb = ahd_lookup_scb(ahd, scbid);
1965 if (scb != NULL && SCB_IS_SILENT(scb))
1966 silent = TRUE;
1967 }
1968
1969 cur_col = 0;
1970 if (silent == FALSE) {
1971 printf("%s: Transmission error detected\n", ahd_name(ahd));
1972 ahd_lqistat1_print(lqistat1, &cur_col, 50);
1973 ahd_lastphase_print(lastphase, &cur_col, 50);
1974 ahd_scsisigi_print(curphase, &cur_col, 50);
1975 ahd_perrdiag_print(perrdiag, &cur_col, 50);
1976 printf("\n");
1977 ahd_dump_card_state(ahd);
1978 }
1979
1980 if ((lqistat1 & (LQIOVERI_LQ|LQIOVERI_NLQ)) != 0) {
1981 if (silent == FALSE) {
1982 printf("%s: Gross protocol error during incoming "
1983 "packet. lqistat1 == 0x%x. Resetting bus.\n",
1984 ahd_name(ahd), lqistat1);
1985 }
1986 ahd_reset_channel(ahd, 'A', TRUE);
1987 return;
1988 } else if ((lqistat1 & LQICRCI_LQ) != 0) {
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010 ahd_outb(ahd, LQCTL2, LQIRETRY);
2011 printf("LQIRetry for LQICRCI_LQ to release ACK\n");
2012 } else if ((lqistat1 & LQICRCI_NLQ) != 0) {
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058 if (silent == FALSE)
2059 printf("LQICRC_NLQ\n");
2060 if (scb == NULL) {
2061 printf("%s: No SCB valid for LQICRC_NLQ. "
2062 "Resetting bus\n", ahd_name(ahd));
2063 ahd_reset_channel(ahd, 'A', TRUE);
2064 return;
2065 }
2066 } else if ((lqistat1 & LQIBADLQI) != 0) {
2067 printf("Need to handle BADLQI!\n");
2068 ahd_reset_channel(ahd, 'A', TRUE);
2069 return;
2070 } else if ((perrdiag & (PARITYERR|PREVPHASE)) == PARITYERR) {
2071 if ((curphase & ~P_DATAIN_DT) != 0) {
2072
2073 if (silent == FALSE)
2074 printf("Acking %s to clear perror\n",
2075 ahd_lookup_phase_entry(curphase)->phasemsg);
2076 ahd_inb(ahd, SCSIDAT);
2077 }
2078
2079 if (curphase == P_MESGIN)
2080 msg_out = MSG_PARITY_ERROR;
2081 }
2082
2083
2084
2085
2086
2087
2088
2089
2090 ahd->send_msg_perror = msg_out;
2091 if (scb != NULL && msg_out == MSG_INITIATOR_DET_ERR)
2092 scb->flags |= SCB_TRANSMISSION_ERROR;
2093 ahd_outb(ahd, MSG_OUT, HOST_MSG);
2094 ahd_outb(ahd, CLRINT, CLRSCSIINT);
2095 ahd_unpause(ahd);
2096}
2097
2098static void
2099ahd_handle_lqiphase_error(struct ahd_softc *ahd, u_int lqistat1)
2100{
2101
2102
2103
2104 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
2105 ahd_outb(ahd, CLRLQIINT1, lqistat1);
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115 ahd_set_active_fifo(ahd);
2116 if ((ahd_inb(ahd, SCSISIGO) & ATNO) != 0
2117 && (ahd_inb(ahd, MDFFSTAT) & DLZERO) != 0) {
2118 if ((lqistat1 & LQIPHASE_LQ) != 0) {
2119 printf("LQIRETRY for LQIPHASE_LQ\n");
2120 ahd_outb(ahd, LQCTL2, LQIRETRY);
2121 } else if ((lqistat1 & LQIPHASE_NLQ) != 0) {
2122 printf("LQIRETRY for LQIPHASE_NLQ\n");
2123 ahd_outb(ahd, LQCTL2, LQIRETRY);
2124 } else
2125 panic("ahd_handle_lqiphase_error: No phase errors\n");
2126 ahd_dump_card_state(ahd);
2127 ahd_outb(ahd, CLRINT, CLRSCSIINT);
2128 ahd_unpause(ahd);
2129 } else {
2130 printf("Reseting Channel for LQI Phase error\n");
2131 ahd_dump_card_state(ahd);
2132 ahd_reset_channel(ahd, 'A', TRUE);
2133 }
2134}
2135
2136
2137
2138
2139
2140static int
2141ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
2142{
2143 u_int lqostat1;
2144
2145 AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
2146 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
2147 lqostat1 = ahd_inb(ahd, LQOSTAT1);
2148 if ((lqostat1 & LQOBUSFREE) != 0) {
2149 struct scb *scb;
2150 u_int scbid;
2151 u_int saved_scbptr;
2152 u_int waiting_h;
2153 u_int waiting_t;
2154 u_int next;
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
2172 scbid = ahd_inw(ahd, CURRSCB);
2173 scb = ahd_lookup_scb(ahd, scbid);
2174 if (scb == NULL)
2175 panic("SCB not valid during LQOBUSFREE");
2176
2177
2178
2179 ahd_outb(ahd, CLRLQOINT1, CLRLQOBUSFREE);
2180 if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)
2181 ahd_outb(ahd, CLRLQOINT1, 0);
2182 ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
2183 ahd_flush_device_writes(ahd);
2184 ahd_outb(ahd, CLRSINT0, CLRSELDO);
2185
2186
2187
2188
2189
2190
2191
2192 ahd_outb(ahd, LQCTL2, ahd_inb(ahd, LQCTL2) | LQOTOIDLE);
2193
2194
2195
2196
2197
2198 waiting_h = ahd_inw(ahd, WAITING_TID_HEAD);
2199 saved_scbptr = ahd_get_scbptr(ahd);
2200 if (waiting_h != scbid) {
2201
2202 ahd_outw(ahd, WAITING_TID_HEAD, scbid);
2203 waiting_t = ahd_inw(ahd, WAITING_TID_TAIL);
2204 if (waiting_t == waiting_h) {
2205 ahd_outw(ahd, WAITING_TID_TAIL, scbid);
2206 next = SCB_LIST_NULL;
2207 } else {
2208 ahd_set_scbptr(ahd, waiting_h);
2209 next = ahd_inw_scbram(ahd, SCB_NEXT2);
2210 }
2211 ahd_set_scbptr(ahd, scbid);
2212 ahd_outw(ahd, SCB_NEXT2, next);
2213 }
2214 ahd_set_scbptr(ahd, saved_scbptr);
2215 if (scb->crc_retry_count < AHD_MAX_LQ_CRC_ERRORS) {
2216 if (SCB_IS_SILENT(scb) == FALSE) {
2217 ahd_print_path(ahd, scb);
2218 printf("Probable outgoing LQ CRC error. "
2219 "Retrying command\n");
2220 }
2221 scb->crc_retry_count++;
2222 } else {
2223 ahd_set_transaction_status(scb, CAM_UNCOR_PARITY);
2224 ahd_freeze_scb(scb);
2225 ahd_freeze_devq(ahd, scb);
2226 }
2227
2228 return (0);
2229 } else if ((ahd_inb(ahd, PERRDIAG) & PARITYERR) != 0) {
2230
2231
2232
2233
2234
2235
2236
2237 ahd_outb(ahd, CLRSINT1, CLRSCSIPERR|CLRBUSFREE);
2238#ifdef AHD_DEBUG
2239 if ((ahd_debug & AHD_SHOW_MASKED_ERRORS) != 0)
2240 printf("%s: Parity on last REQ detected "
2241 "during busfree phase.\n",
2242 ahd_name(ahd));
2243#endif
2244
2245 return (0);
2246 }
2247 if (ahd->src_mode != AHD_MODE_SCSI) {
2248 u_int scbid;
2249 struct scb *scb;
2250
2251 scbid = ahd_get_scbptr(ahd);
2252 scb = ahd_lookup_scb(ahd, scbid);
2253 ahd_print_path(ahd, scb);
2254 printf("Unexpected PKT busfree condition\n");
2255 ahd_dump_card_state(ahd);
2256 ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), 'A',
2257 SCB_GET_LUN(scb), SCB_GET_TAG(scb),
2258 ROLE_INITIATOR, CAM_UNEXP_BUSFREE);
2259
2260
2261 return (1);
2262 }
2263 printf("%s: Unexpected PKT busfree condition\n", ahd_name(ahd));
2264 ahd_dump_card_state(ahd);
2265
2266 return (1);
2267}
2268
2269
2270
2271
2272static int
2273ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
2274{
2275 struct ahd_devinfo devinfo;
2276 struct scb *scb;
2277 u_int lastphase;
2278 u_int saved_scsiid;
2279 u_int saved_lun;
2280 u_int target;
2281 u_int initiator_role_id;
2282 u_int scbid;
2283 u_int ppr_busfree;
2284 int printerror;
2285
2286
2287
2288
2289
2290
2291 lastphase = ahd_inb(ahd, LASTPHASE);
2292 saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
2293 saved_lun = ahd_inb(ahd, SAVED_LUN);
2294 target = SCSIID_TARGET(ahd, saved_scsiid);
2295 initiator_role_id = SCSIID_OUR_ID(saved_scsiid);
2296 ahd_compile_devinfo(&devinfo, initiator_role_id,
2297 target, saved_lun, 'A', ROLE_INITIATOR);
2298 printerror = 1;
2299
2300 scbid = ahd_get_scbptr(ahd);
2301 scb = ahd_lookup_scb(ahd, scbid);
2302 if (scb != NULL
2303 && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)
2304 scb = NULL;
2305
2306 ppr_busfree = (ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0;
2307 if (lastphase == P_MESGOUT) {
2308 u_int tag;
2309
2310 tag = SCB_LIST_NULL;
2311 if (ahd_sent_msg(ahd, AHDMSG_1B, MSG_ABORT_TAG, TRUE)
2312 || ahd_sent_msg(ahd, AHDMSG_1B, MSG_ABORT, TRUE)) {
2313 int found;
2314 int sent_msg;
2315
2316 if (scb == NULL) {
2317 ahd_print_devinfo(ahd, &devinfo);
2318 printf("Abort for unidentified "
2319 "connection completed.\n");
2320
2321 return (1);
2322 }
2323 sent_msg = ahd->msgout_buf[ahd->msgout_index - 1];
2324 ahd_print_path(ahd, scb);
2325 printf("SCB %d - Abort%s Completed.\n",
2326 SCB_GET_TAG(scb),
2327 sent_msg == MSG_ABORT_TAG ? "" : " Tag");
2328
2329 if (sent_msg == MSG_ABORT_TAG)
2330 tag = SCB_GET_TAG(scb);
2331
2332 if ((scb->flags & SCB_EXTERNAL_RESET) != 0) {
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345 tag = SCB_GET_TAG(scb);
2346 saved_lun = scb->hscb->lun;
2347 }
2348 found = ahd_abort_scbs(ahd, target, 'A', saved_lun,
2349 tag, ROLE_INITIATOR,
2350 CAM_REQ_ABORTED);
2351 printf("found == 0x%x\n", found);
2352 printerror = 0;
2353 } else if (ahd_sent_msg(ahd, AHDMSG_1B,
2354 MSG_BUS_DEV_RESET, TRUE)) {
2355#ifdef __FreeBSD__
2356
2357
2358
2359
2360
2361 if (scb != NULL
2362 && scb->io_ctx->ccb_h.func_code== XPT_RESET_DEV
2363 && ahd_match_scb(ahd, scb, target, 'A',
2364 CAM_LUN_WILDCARD, SCB_LIST_NULL,
2365 ROLE_INITIATOR))
2366 ahd_set_transaction_status(scb, CAM_REQ_CMP);
2367#endif
2368 ahd_handle_devreset(ahd, &devinfo, CAM_LUN_WILDCARD,
2369 CAM_BDR_SENT, "Bus Device Reset",
2370 0);
2371 printerror = 0;
2372 } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, FALSE)
2373 && ppr_busfree == 0) {
2374 struct ahd_initiator_tinfo *tinfo;
2375 struct ahd_tmode_tstate *tstate;
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387#ifdef AHD_DEBUG
2388 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2389 printf("PPR negotiation rejected busfree.\n");
2390#endif
2391 tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
2392 devinfo.our_scsiid,
2393 devinfo.target, &tstate);
2394 if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)!=0) {
2395 ahd_set_width(ahd, &devinfo,
2396 MSG_EXT_WDTR_BUS_8_BIT,
2397 AHD_TRANS_CUR,
2398 TRUE);
2399 ahd_set_syncrate(ahd, &devinfo,
2400 0, 0,
2401 0,
2402 AHD_TRANS_CUR,
2403 TRUE);
2404
2405
2406
2407
2408
2409 } else {
2410 tinfo->curr.transport_version = 2;
2411 tinfo->goal.transport_version = 2;
2412 tinfo->goal.ppr_options = 0;
2413
2414
2415
2416
2417
2418 ahd_freeze_devq(ahd, scb);
2419 ahd_qinfifo_requeue_tail(ahd, scb);
2420 printerror = 0;
2421 }
2422 } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, FALSE)
2423 && ppr_busfree == 0) {
2424
2425
2426
2427
2428#ifdef AHD_DEBUG
2429 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2430 printf("WDTR negotiation rejected busfree.\n");
2431#endif
2432 ahd_set_width(ahd, &devinfo,
2433 MSG_EXT_WDTR_BUS_8_BIT,
2434 AHD_TRANS_CUR|AHD_TRANS_GOAL,
2435 TRUE);
2436
2437
2438
2439
2440
2441 ahd_freeze_devq(ahd, scb);
2442 ahd_qinfifo_requeue_tail(ahd, scb);
2443 printerror = 0;
2444 } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, FALSE)
2445 && ppr_busfree == 0) {
2446
2447
2448
2449
2450#ifdef AHD_DEBUG
2451 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2452 printf("SDTR negotiation rejected busfree.\n");
2453#endif
2454 ahd_set_syncrate(ahd, &devinfo,
2455 0, 0,
2456 0,
2457 AHD_TRANS_CUR|AHD_TRANS_GOAL,
2458 TRUE);
2459
2460
2461
2462
2463
2464 ahd_freeze_devq(ahd, scb);
2465 ahd_qinfifo_requeue_tail(ahd, scb);
2466 printerror = 0;
2467 } else if ((ahd->msg_flags & MSG_FLAG_EXPECT_IDE_BUSFREE) != 0
2468 && ahd_sent_msg(ahd, AHDMSG_1B,
2469 MSG_INITIATOR_DET_ERR, TRUE)) {
2470
2471#ifdef AHD_DEBUG
2472 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2473 printf("Expected IDE Busfree\n");
2474#endif
2475 printerror = 0;
2476 } else if ((ahd->msg_flags & MSG_FLAG_EXPECT_QASREJ_BUSFREE)
2477 && ahd_sent_msg(ahd, AHDMSG_1B,
2478 MSG_MESSAGE_REJECT, TRUE)) {
2479
2480#ifdef AHD_DEBUG
2481 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2482 printf("Expected QAS Reject Busfree\n");
2483#endif
2484 printerror = 0;
2485 }
2486 }
2487
2488
2489
2490
2491
2492
2493 if (printerror != 0
2494 && (lastphase == P_MESGIN || lastphase == P_MESGOUT)
2495 && ((ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0)) {
2496
2497 ahd_freeze_devq(ahd, scb);
2498 ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
2499 ahd_freeze_scb(scb);
2500 if ((ahd->msg_flags & MSG_FLAG_IU_REQ_CHANGED) != 0) {
2501 ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),
2502 SCB_GET_CHANNEL(ahd, scb),
2503 SCB_GET_LUN(scb), SCB_LIST_NULL,
2504 ROLE_INITIATOR, CAM_REQ_ABORTED);
2505 } else {
2506#ifdef AHD_DEBUG
2507 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2508 printf("PPR Negotiation Busfree.\n");
2509#endif
2510 ahd_done(ahd, scb);
2511 }
2512 printerror = 0;
2513 }
2514 if (printerror != 0) {
2515 int aborted;
2516
2517 aborted = 0;
2518 if (scb != NULL) {
2519 u_int tag;
2520
2521 if ((scb->hscb->control & TAG_ENB) != 0)
2522 tag = SCB_GET_TAG(scb);
2523 else
2524 tag = SCB_LIST_NULL;
2525 ahd_print_path(ahd, scb);
2526 aborted = ahd_abort_scbs(ahd, target, 'A',
2527 SCB_GET_LUN(scb), tag,
2528 ROLE_INITIATOR,
2529 CAM_UNEXP_BUSFREE);
2530 } else {
2531
2532
2533
2534
2535 printf("%s: ", ahd_name(ahd));
2536 }
2537 printf("Unexpected busfree %s, %d SCBs aborted, "
2538 "PRGMCNT == 0x%x\n",
2539 ahd_lookup_phase_entry(lastphase)->phasemsg,
2540 aborted,
2541 ahd_inw(ahd, PRGMCNT));
2542 ahd_dump_card_state(ahd);
2543 if (lastphase != P_BUSFREE)
2544 ahd_force_renegotiation(ahd, &devinfo);
2545 }
2546
2547 return (1);
2548}
2549
2550static void
2551ahd_handle_proto_violation(struct ahd_softc *ahd)
2552{
2553 struct ahd_devinfo devinfo;
2554 struct scb *scb;
2555 u_int scbid;
2556 u_int seq_flags;
2557 u_int curphase;
2558 u_int lastphase;
2559 int found;
2560
2561 ahd_fetch_devinfo(ahd, &devinfo);
2562 scbid = ahd_get_scbptr(ahd);
2563 scb = ahd_lookup_scb(ahd, scbid);
2564 seq_flags = ahd_inb(ahd, SEQ_FLAGS);
2565 curphase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;
2566 lastphase = ahd_inb(ahd, LASTPHASE);
2567 if ((seq_flags & NOT_IDENTIFIED) != 0) {
2568
2569
2570
2571
2572
2573
2574 ahd_print_devinfo(ahd, &devinfo);
2575 printf("Target did not send an IDENTIFY message. "
2576 "LASTPHASE = 0x%x.\n", lastphase);
2577 scb = NULL;
2578 } else if (scb == NULL) {
2579
2580
2581
2582
2583 ahd_print_devinfo(ahd, &devinfo);
2584 printf("No SCB found during protocol violation\n");
2585 goto proto_violation_reset;
2586 } else {
2587 ahd_set_transaction_status(scb, CAM_SEQUENCE_FAIL);
2588 if ((seq_flags & NO_CDB_SENT) != 0) {
2589 ahd_print_path(ahd, scb);
2590 printf("No or incomplete CDB sent to device.\n");
2591 } else if ((ahd_inb_scbram(ahd, SCB_CONTROL)
2592 & STATUS_RCVD) == 0) {
2593
2594
2595
2596
2597
2598
2599
2600 ahd_print_path(ahd, scb);
2601 printf("Completed command without status.\n");
2602 } else {
2603 ahd_print_path(ahd, scb);
2604 printf("Unknown protocol violation.\n");
2605 ahd_dump_card_state(ahd);
2606 }
2607 }
2608 if ((lastphase & ~P_DATAIN_DT) == 0
2609 || lastphase == P_COMMAND) {
2610proto_violation_reset:
2611
2612
2613
2614
2615
2616
2617 found = ahd_reset_channel(ahd, 'A', TRUE);
2618 printf("%s: Issued Channel %c Bus Reset. "
2619 "%d SCBs aborted\n", ahd_name(ahd), 'A', found);
2620 } else {
2621
2622
2623
2624
2625
2626 ahd_outb(ahd, SCSISEQ0,
2627 ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
2628 ahd_assert_atn(ahd);
2629 ahd_outb(ahd, MSG_OUT, HOST_MSG);
2630 if (scb == NULL) {
2631 ahd_print_devinfo(ahd, &devinfo);
2632 ahd->msgout_buf[0] = MSG_ABORT_TASK;
2633 ahd->msgout_len = 1;
2634 ahd->msgout_index = 0;
2635 ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
2636 } else {
2637 ahd_print_path(ahd, scb);
2638 scb->flags |= SCB_ABORT;
2639 }
2640 printf("Protocol violation %s. Attempting to abort.\n",
2641 ahd_lookup_phase_entry(curphase)->phasemsg);
2642 }
2643}
2644
2645
2646
2647
2648
2649static void
2650ahd_force_renegotiation(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
2651{
2652 struct ahd_initiator_tinfo *targ_info;
2653 struct ahd_tmode_tstate *tstate;
2654
2655#ifdef AHD_DEBUG
2656 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
2657 ahd_print_devinfo(ahd, devinfo);
2658 printf("Forcing renegotiation\n");
2659 }
2660#endif
2661 targ_info = ahd_fetch_transinfo(ahd,
2662 devinfo->channel,
2663 devinfo->our_scsiid,
2664 devinfo->target,
2665 &tstate);
2666 ahd_update_neg_request(ahd, devinfo, tstate,
2667 targ_info, AHD_NEG_IF_NON_ASYNC);
2668}
2669
2670#define AHD_MAX_STEPS 2000
2671static void
2672ahd_clear_critical_section(struct ahd_softc *ahd)
2673{
2674 ahd_mode_state saved_modes;
2675 int stepping;
2676 int steps;
2677 int first_instr;
2678 u_int simode0;
2679 u_int simode1;
2680 u_int simode3;
2681 u_int lqimode0;
2682 u_int lqimode1;
2683 u_int lqomode0;
2684 u_int lqomode1;
2685
2686 if (ahd->num_critical_sections == 0)
2687 return;
2688
2689 stepping = FALSE;
2690 steps = 0;
2691 first_instr = 0;
2692 simode0 = 0;
2693 simode1 = 0;
2694 simode3 = 0;
2695 lqimode0 = 0;
2696 lqimode1 = 0;
2697 lqomode0 = 0;
2698 lqomode1 = 0;
2699 saved_modes = ahd_save_modes(ahd);
2700 for (;;) {
2701 struct cs *cs;
2702 u_int seqaddr;
2703 u_int i;
2704
2705 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
2706 seqaddr = ahd_inw(ahd, CURADDR);
2707
2708 cs = ahd->critical_sections;
2709 for (i = 0; i < ahd->num_critical_sections; i++, cs++) {
2710
2711 if (cs->begin < seqaddr && cs->end >= seqaddr)
2712 break;
2713 }
2714
2715 if (i == ahd->num_critical_sections)
2716 break;
2717
2718 if (steps > AHD_MAX_STEPS) {
2719 printf("%s: Infinite loop in critical section\n"
2720 "%s: First Instruction 0x%x now 0x%x\n",
2721 ahd_name(ahd), ahd_name(ahd), first_instr,
2722 seqaddr);
2723 ahd_dump_card_state(ahd);
2724 panic("critical section loop");
2725 }
2726
2727 steps++;
2728#ifdef AHD_DEBUG
2729 if ((ahd_debug & AHD_SHOW_MISC) != 0)
2730 printf("%s: Single stepping at 0x%x\n", ahd_name(ahd),
2731 seqaddr);
2732#endif
2733 if (stepping == FALSE) {
2734
2735 first_instr = seqaddr;
2736 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
2737 simode0 = ahd_inb(ahd, SIMODE0);
2738 simode3 = ahd_inb(ahd, SIMODE3);
2739 lqimode0 = ahd_inb(ahd, LQIMODE0);
2740 lqimode1 = ahd_inb(ahd, LQIMODE1);
2741 lqomode0 = ahd_inb(ahd, LQOMODE0);
2742 lqomode1 = ahd_inb(ahd, LQOMODE1);
2743 ahd_outb(ahd, SIMODE0, 0);
2744 ahd_outb(ahd, SIMODE3, 0);
2745 ahd_outb(ahd, LQIMODE0, 0);
2746 ahd_outb(ahd, LQIMODE1, 0);
2747 ahd_outb(ahd, LQOMODE0, 0);
2748 ahd_outb(ahd, LQOMODE1, 0);
2749 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
2750 simode1 = ahd_inb(ahd, SIMODE1);
2751
2752
2753
2754
2755
2756
2757 ahd_outb(ahd, SIMODE1, simode1 & ENBUSFREE);
2758 ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) | STEP);
2759 stepping = TRUE;
2760 }
2761 ahd_outb(ahd, CLRSINT1, CLRBUSFREE);
2762 ahd_outb(ahd, CLRINT, CLRSCSIINT);
2763 ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
2764 ahd_outb(ahd, HCNTRL, ahd->unpause);
2765 while (!ahd_is_paused(ahd))
2766 ahd_delay(200);
2767 ahd_update_modes(ahd);
2768 }
2769 if (stepping) {
2770 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
2771 ahd_outb(ahd, SIMODE0, simode0);
2772 ahd_outb(ahd, SIMODE3, simode3);
2773 ahd_outb(ahd, LQIMODE0, lqimode0);
2774 ahd_outb(ahd, LQIMODE1, lqimode1);
2775 ahd_outb(ahd, LQOMODE0, lqomode0);
2776 ahd_outb(ahd, LQOMODE1, lqomode1);
2777 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
2778 ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) & ~STEP);
2779 ahd_outb(ahd, SIMODE1, simode1);
2780
2781
2782
2783
2784
2785
2786 ahd_outb(ahd, CLRINT, CLRSCSIINT);
2787 }
2788 ahd_restore_modes(ahd, saved_modes);
2789}
2790
2791
2792
2793
2794static void
2795ahd_clear_intstat(struct ahd_softc *ahd)
2796{
2797 AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
2798 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
2799
2800 ahd_outb(ahd, CLRLQIINT0, CLRLQIATNQAS|CLRLQICRCT1|CLRLQICRCT2
2801 |CLRLQIBADLQT|CLRLQIATNLQ|CLRLQIATNCMD);
2802 ahd_outb(ahd, CLRLQIINT1, CLRLQIPHASE_LQ|CLRLQIPHASE_NLQ|CLRLIQABORT
2803 |CLRLQICRCI_LQ|CLRLQICRCI_NLQ|CLRLQIBADLQI
2804 |CLRLQIOVERI_LQ|CLRLQIOVERI_NLQ|CLRNONPACKREQ);
2805 ahd_outb(ahd, CLRLQOINT0, CLRLQOTARGSCBPERR|CLRLQOSTOPT2|CLRLQOATNLQ
2806 |CLRLQOATNPKT|CLRLQOTCRC);
2807 ahd_outb(ahd, CLRLQOINT1, CLRLQOINITSCBPERR|CLRLQOSTOPI2|CLRLQOBADQAS
2808 |CLRLQOBUSFREE|CLRLQOPHACHGINPKT);
2809 if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {
2810 ahd_outb(ahd, CLRLQOINT0, 0);
2811 ahd_outb(ahd, CLRLQOINT1, 0);
2812 }
2813 ahd_outb(ahd, CLRSINT3, CLRNTRAMPERR|CLROSRAMPERR);
2814 ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI
2815 |CLRBUSFREE|CLRSCSIPERR|CLRREQINIT);
2816 ahd_outb(ahd, CLRSINT0, CLRSELDO|CLRSELDI|CLRSELINGO
2817 |CLRIOERR|CLROVERRUN);
2818 ahd_outb(ahd, CLRINT, CLRSCSIINT);
2819}
2820
2821
2822#ifdef AHD_DEBUG
2823uint32_t ahd_debug = AHD_DEBUG_OPTS;
2824#endif
2825
2826#if 0
2827void
2828ahd_print_scb(struct scb *scb)
2829{
2830 struct hardware_scb *hscb;
2831 int i;
2832
2833 hscb = scb->hscb;
2834 printf("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n",
2835 (void *)scb,
2836 hscb->control,
2837 hscb->scsiid,
2838 hscb->lun,
2839 hscb->cdb_len);
2840 printf("Shared Data: ");
2841 for (i = 0; i < sizeof(hscb->shared_data.idata.cdb); i++)
2842 printf("%#02x", hscb->shared_data.idata.cdb[i]);
2843 printf(" dataptr:%#x%x datacnt:%#x sgptr:%#x tag:%#x\n",
2844 (uint32_t)((ahd_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF),
2845 (uint32_t)(ahd_le64toh(hscb->dataptr) & 0xFFFFFFFF),
2846 ahd_le32toh(hscb->datacnt),
2847 ahd_le32toh(hscb->sgptr),
2848 SCB_GET_TAG(scb));
2849 ahd_dump_sglist(scb);
2850}
2851#endif
2852
2853
2854
2855
2856
2857
2858static struct ahd_tmode_tstate *
2859ahd_alloc_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel)
2860{
2861 struct ahd_tmode_tstate *master_tstate;
2862 struct ahd_tmode_tstate *tstate;
2863 int i;
2864
2865 master_tstate = ahd->enabled_targets[ahd->our_id];
2866 if (ahd->enabled_targets[scsi_id] != NULL
2867 && ahd->enabled_targets[scsi_id] != master_tstate)
2868 panic("%s: ahd_alloc_tstate - Target already allocated",
2869 ahd_name(ahd));
2870 tstate = malloc(sizeof(*tstate), M_DEVBUF, M_NOWAIT);
2871 if (tstate == NULL)
2872 return (NULL);
2873
2874
2875
2876
2877
2878
2879
2880 if (master_tstate != NULL) {
2881 memcpy(tstate, master_tstate, sizeof(*tstate));
2882 memset(tstate->enabled_luns, 0, sizeof(tstate->enabled_luns));
2883 for (i = 0; i < 16; i++) {
2884 memset(&tstate->transinfo[i].curr, 0,
2885 sizeof(tstate->transinfo[i].curr));
2886 memset(&tstate->transinfo[i].goal, 0,
2887 sizeof(tstate->transinfo[i].goal));
2888 }
2889 } else
2890 memset(tstate, 0, sizeof(*tstate));
2891 ahd->enabled_targets[scsi_id] = tstate;
2892 return (tstate);
2893}
2894
2895#ifdef AHD_TARGET_MODE
2896
2897
2898
2899
2900static void
2901ahd_free_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel, int force)
2902{
2903 struct ahd_tmode_tstate *tstate;
2904
2905
2906
2907
2908
2909 if (scsi_id == ahd->our_id
2910 && force == FALSE)
2911 return;
2912
2913 tstate = ahd->enabled_targets[scsi_id];
2914 if (tstate != NULL)
2915 free(tstate, M_DEVBUF);
2916 ahd->enabled_targets[scsi_id] = NULL;
2917}
2918#endif
2919
2920
2921
2922
2923
2924
2925
2926void
2927ahd_devlimited_syncrate(struct ahd_softc *ahd,
2928 struct ahd_initiator_tinfo *tinfo,
2929 u_int *period, u_int *ppr_options, role_t role)
2930{
2931 struct ahd_transinfo *transinfo;
2932 u_int maxsync;
2933
2934 if ((ahd_inb(ahd, SBLKCTL) & ENAB40) != 0
2935 && (ahd_inb(ahd, SSTAT2) & EXP_ACTIVE) == 0) {
2936 maxsync = AHD_SYNCRATE_PACED;
2937 } else {
2938 maxsync = AHD_SYNCRATE_ULTRA;
2939
2940 *ppr_options &= MSG_EXT_PPR_QAS_REQ;
2941 }
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952 if (role == ROLE_TARGET)
2953 transinfo = &tinfo->user;
2954 else
2955 transinfo = &tinfo->goal;
2956 *ppr_options &= (transinfo->ppr_options|MSG_EXT_PPR_PCOMP_EN);
2957 if (transinfo->width == MSG_EXT_WDTR_BUS_8_BIT) {
2958 maxsync = max(maxsync, (u_int)AHD_SYNCRATE_ULTRA2);
2959 *ppr_options &= ~MSG_EXT_PPR_DT_REQ;
2960 }
2961 if (transinfo->period == 0) {
2962 *period = 0;
2963 *ppr_options = 0;
2964 } else {
2965 *period = max(*period, (u_int)transinfo->period);
2966 ahd_find_syncrate(ahd, period, ppr_options, maxsync);
2967 }
2968}
2969
2970
2971
2972
2973
2974
2975void
2976ahd_find_syncrate(struct ahd_softc *ahd, u_int *period,
2977 u_int *ppr_options, u_int maxsync)
2978{
2979 if (*period < maxsync)
2980 *period = maxsync;
2981
2982 if ((*ppr_options & MSG_EXT_PPR_DT_REQ) != 0
2983 && *period > AHD_SYNCRATE_MIN_DT)
2984 *ppr_options &= ~MSG_EXT_PPR_DT_REQ;
2985
2986 if (*period > AHD_SYNCRATE_MIN)
2987 *period = 0;
2988
2989
2990 if (*period > AHD_SYNCRATE_PACED)
2991 *ppr_options &= ~MSG_EXT_PPR_RTI;
2992
2993 if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 0)
2994 *ppr_options &= (MSG_EXT_PPR_DT_REQ|MSG_EXT_PPR_QAS_REQ);
2995
2996 if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0)
2997 *ppr_options &= MSG_EXT_PPR_QAS_REQ;
2998
2999
3000 if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 0
3001 && *period < AHD_SYNCRATE_DT)
3002 *period = AHD_SYNCRATE_DT;
3003
3004
3005 if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0
3006 && *period < AHD_SYNCRATE_ULTRA2)
3007 *period = AHD_SYNCRATE_ULTRA2;
3008}
3009
3010
3011
3012
3013
3014static void
3015ahd_validate_offset(struct ahd_softc *ahd,
3016 struct ahd_initiator_tinfo *tinfo,
3017 u_int period, u_int *offset, int wide,
3018 role_t role)
3019{
3020 u_int maxoffset;
3021
3022
3023 if (period == 0)
3024 maxoffset = 0;
3025 else if (period <= AHD_SYNCRATE_PACED) {
3026 if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0)
3027 maxoffset = MAX_OFFSET_PACED_BUG;
3028 else
3029 maxoffset = MAX_OFFSET_PACED;
3030 } else
3031 maxoffset = MAX_OFFSET_NON_PACED;
3032 *offset = min(*offset, maxoffset);
3033 if (tinfo != NULL) {
3034 if (role == ROLE_TARGET)
3035 *offset = min(*offset, (u_int)tinfo->user.offset);
3036 else
3037 *offset = min(*offset, (u_int)tinfo->goal.offset);
3038 }
3039}
3040
3041
3042
3043
3044
3045static void
3046ahd_validate_width(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo,
3047 u_int *bus_width, role_t role)
3048{
3049 switch (*bus_width) {
3050 default:
3051 if (ahd->features & AHD_WIDE) {
3052
3053 *bus_width = MSG_EXT_WDTR_BUS_16_BIT;
3054 break;
3055 }
3056
3057 case MSG_EXT_WDTR_BUS_8_BIT:
3058 *bus_width = MSG_EXT_WDTR_BUS_8_BIT;
3059 break;
3060 }
3061 if (tinfo != NULL) {
3062 if (role == ROLE_TARGET)
3063 *bus_width = min((u_int)tinfo->user.width, *bus_width);
3064 else
3065 *bus_width = min((u_int)tinfo->goal.width, *bus_width);
3066 }
3067}
3068
3069
3070
3071
3072
3073
3074
3075int
3076ahd_update_neg_request(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
3077 struct ahd_tmode_tstate *tstate,
3078 struct ahd_initiator_tinfo *tinfo, ahd_neg_type neg_type)
3079{
3080 u_int auto_negotiate_orig;
3081
3082 auto_negotiate_orig = tstate->auto_negotiate;
3083 if (neg_type == AHD_NEG_ALWAYS) {
3084
3085
3086
3087
3088
3089
3090 if ((ahd->features & AHD_WIDE) != 0)
3091 tinfo->curr.width = AHD_WIDTH_UNKNOWN;
3092 tinfo->curr.period = AHD_PERIOD_UNKNOWN;
3093 tinfo->curr.offset = AHD_OFFSET_UNKNOWN;
3094 }
3095 if (tinfo->curr.period != tinfo->goal.period
3096 || tinfo->curr.width != tinfo->goal.width
3097 || tinfo->curr.offset != tinfo->goal.offset
3098 || tinfo->curr.ppr_options != tinfo->goal.ppr_options
3099 || (neg_type == AHD_NEG_IF_NON_ASYNC
3100 && (tinfo->goal.offset != 0
3101 || tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT
3102 || tinfo->goal.ppr_options != 0)))
3103 tstate->auto_negotiate |= devinfo->target_mask;
3104 else
3105 tstate->auto_negotiate &= ~devinfo->target_mask;
3106
3107 return (auto_negotiate_orig != tstate->auto_negotiate);
3108}
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118void
3119ahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
3120 u_int period, u_int offset, u_int ppr_options,
3121 u_int type, int paused)
3122{
3123 struct ahd_initiator_tinfo *tinfo;
3124 struct ahd_tmode_tstate *tstate;
3125 u_int old_period;
3126 u_int old_offset;
3127 u_int old_ppr;
3128 int active;
3129 int update_needed;
3130
3131 active = (type & AHD_TRANS_ACTIVE) == AHD_TRANS_ACTIVE;
3132 update_needed = 0;
3133
3134 if (period == 0 || offset == 0) {
3135 period = 0;
3136 offset = 0;
3137 }
3138
3139 tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
3140 devinfo->target, &tstate);
3141
3142 if ((type & AHD_TRANS_USER) != 0) {
3143 tinfo->user.period = period;
3144 tinfo->user.offset = offset;
3145 tinfo->user.ppr_options = ppr_options;
3146 }
3147
3148 if ((type & AHD_TRANS_GOAL) != 0) {
3149 tinfo->goal.period = period;
3150 tinfo->goal.offset = offset;
3151 tinfo->goal.ppr_options = ppr_options;
3152 }
3153
3154 old_period = tinfo->curr.period;
3155 old_offset = tinfo->curr.offset;
3156 old_ppr = tinfo->curr.ppr_options;
3157
3158 if ((type & AHD_TRANS_CUR) != 0
3159 && (old_period != period
3160 || old_offset != offset
3161 || old_ppr != ppr_options)) {
3162
3163 update_needed++;
3164
3165 tinfo->curr.period = period;
3166 tinfo->curr.offset = offset;
3167 tinfo->curr.ppr_options = ppr_options;
3168
3169 ahd_send_async(ahd, devinfo->channel, devinfo->target,
3170 CAM_LUN_WILDCARD, AC_TRANSFER_NEG);
3171 if (bootverbose) {
3172 if (offset != 0) {
3173 int options;
3174
3175 printf("%s: target %d synchronous with "
3176 "period = 0x%x, offset = 0x%x",
3177 ahd_name(ahd), devinfo->target,
3178 period, offset);
3179 options = 0;
3180 if ((ppr_options & MSG_EXT_PPR_RD_STRM) != 0) {
3181 printf("(RDSTRM");
3182 options++;
3183 }
3184 if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {
3185 printf("%s", options ? "|DT" : "(DT");
3186 options++;
3187 }
3188 if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
3189 printf("%s", options ? "|IU" : "(IU");
3190 options++;
3191 }
3192 if ((ppr_options & MSG_EXT_PPR_RTI) != 0) {
3193 printf("%s", options ? "|RTI" : "(RTI");
3194 options++;
3195 }
3196 if ((ppr_options & MSG_EXT_PPR_QAS_REQ) != 0) {
3197 printf("%s", options ? "|QAS" : "(QAS");
3198 options++;
3199 }
3200 if (options != 0)
3201 printf(")\n");
3202 else
3203 printf("\n");
3204 } else {
3205 printf("%s: target %d using "
3206 "asynchronous transfers%s\n",
3207 ahd_name(ahd), devinfo->target,
3208 (ppr_options & MSG_EXT_PPR_QAS_REQ) != 0
3209 ? "(QAS)" : "");
3210 }
3211 }
3212 }
3213
3214
3215
3216
3217
3218
3219
3220
3221 if ((type & AHD_TRANS_CUR) != 0) {
3222 if (!paused)
3223 ahd_pause(ahd);
3224 ahd_update_neg_table(ahd, devinfo, &tinfo->curr);
3225 if (!paused)
3226 ahd_unpause(ahd);
3227 if (ahd->msg_type != MSG_TYPE_NONE) {
3228 if ((old_ppr & MSG_EXT_PPR_IU_REQ)
3229 != (ppr_options & MSG_EXT_PPR_IU_REQ)) {
3230#ifdef AHD_DEBUG
3231 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
3232 ahd_print_devinfo(ahd, devinfo);
3233 printf("Expecting IU Change busfree\n");
3234 }
3235#endif
3236 ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE
3237 | MSG_FLAG_IU_REQ_CHANGED;
3238 }
3239 if ((old_ppr & MSG_EXT_PPR_IU_REQ) != 0) {
3240#ifdef AHD_DEBUG
3241 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
3242 printf("PPR with IU_REQ outstanding\n");
3243#endif
3244 ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE;
3245 }
3246 }
3247 }
3248
3249 update_needed += ahd_update_neg_request(ahd, devinfo, tstate,
3250 tinfo, AHD_NEG_TO_GOAL);
3251
3252 if (update_needed && active)
3253 ahd_update_pending_scbs(ahd);
3254}
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264void
3265ahd_set_width(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
3266 u_int width, u_int type, int paused)
3267{
3268 struct ahd_initiator_tinfo *tinfo;
3269 struct ahd_tmode_tstate *tstate;
3270 u_int oldwidth;
3271 int active;
3272 int update_needed;
3273
3274 active = (type & AHD_TRANS_ACTIVE) == AHD_TRANS_ACTIVE;
3275 update_needed = 0;
3276 tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
3277 devinfo->target, &tstate);
3278
3279 if ((type & AHD_TRANS_USER) != 0)
3280 tinfo->user.width = width;
3281
3282 if ((type & AHD_TRANS_GOAL) != 0)
3283 tinfo->goal.width = width;
3284
3285 oldwidth = tinfo->curr.width;
3286 if ((type & AHD_TRANS_CUR) != 0 && oldwidth != width) {
3287
3288 update_needed++;
3289
3290 tinfo->curr.width = width;
3291 ahd_send_async(ahd, devinfo->channel, devinfo->target,
3292 CAM_LUN_WILDCARD, AC_TRANSFER_NEG);
3293 if (bootverbose) {
3294 printf("%s: target %d using %dbit transfers\n",
3295 ahd_name(ahd), devinfo->target,
3296 8 * (0x01 << width));
3297 }
3298 }
3299
3300 if ((type & AHD_TRANS_CUR) != 0) {
3301 if (!paused)
3302 ahd_pause(ahd);
3303 ahd_update_neg_table(ahd, devinfo, &tinfo->curr);
3304 if (!paused)
3305 ahd_unpause(ahd);
3306 }
3307
3308 update_needed += ahd_update_neg_request(ahd, devinfo, tstate,
3309 tinfo, AHD_NEG_TO_GOAL);
3310 if (update_needed && active)
3311 ahd_update_pending_scbs(ahd);
3312
3313}
3314
3315
3316
3317
3318static void
3319ahd_set_tags(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
3320 struct ahd_devinfo *devinfo, ahd_queue_alg alg)
3321{
3322 struct scsi_device *sdev = cmd->device;
3323
3324 ahd_platform_set_tags(ahd, sdev, devinfo, alg);
3325 ahd_send_async(ahd, devinfo->channel, devinfo->target,
3326 devinfo->lun, AC_TRANSFER_NEG);
3327}
3328
3329static void
3330ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
3331 struct ahd_transinfo *tinfo)
3332{
3333 ahd_mode_state saved_modes;
3334 u_int period;
3335 u_int ppr_opts;
3336 u_int con_opts;
3337 u_int offset;
3338 u_int saved_negoaddr;
3339 uint8_t iocell_opts[sizeof(ahd->iocell_opts)];
3340
3341 saved_modes = ahd_save_modes(ahd);
3342 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
3343
3344 saved_negoaddr = ahd_inb(ahd, NEGOADDR);
3345 ahd_outb(ahd, NEGOADDR, devinfo->target);
3346 period = tinfo->period;
3347 offset = tinfo->offset;
3348 memcpy(iocell_opts, ahd->iocell_opts, sizeof(ahd->iocell_opts));
3349 ppr_opts = tinfo->ppr_options & (MSG_EXT_PPR_QAS_REQ|MSG_EXT_PPR_DT_REQ
3350 |MSG_EXT_PPR_IU_REQ|MSG_EXT_PPR_RTI);
3351 con_opts = 0;
3352 if (period == 0)
3353 period = AHD_SYNCRATE_ASYNC;
3354 if (period == AHD_SYNCRATE_160) {
3355
3356 if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368 ppr_opts |= PPROPT_PACE;
3369 offset *= 2;
3370
3371
3372
3373
3374
3375
3376
3377 period = AHD_SYNCRATE_REVA_160;
3378 }
3379 if ((tinfo->ppr_options & MSG_EXT_PPR_PCOMP_EN) == 0)
3380 iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=
3381 ~AHD_PRECOMP_MASK;
3382 } else {
3383
3384
3385
3386 iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK;
3387
3388 if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0
3389 && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0
3390 && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) {
3391
3392
3393
3394
3395
3396
3397 con_opts |= ENSLOWCRC;
3398 }
3399
3400 if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {
3401
3402
3403
3404
3405 iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=
3406 ~AHD_SLEWRATE_MASK;
3407 }
3408 }
3409
3410 ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW);
3411 ahd_outb(ahd, ANNEXDAT, iocell_opts[AHD_PRECOMP_SLEW_INDEX]);
3412 ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_AMPLITUDE);
3413 ahd_outb(ahd, ANNEXDAT, iocell_opts[AHD_AMPLITUDE_INDEX]);
3414
3415 ahd_outb(ahd, NEGPERIOD, period);
3416 ahd_outb(ahd, NEGPPROPTS, ppr_opts);
3417 ahd_outb(ahd, NEGOFFSET, offset);
3418
3419 if (tinfo->width == MSG_EXT_WDTR_BUS_16_BIT)
3420 con_opts |= WIDEXFER;
3421
3422
3423
3424
3425
3426
3427 if (ahd->features & AHD_AIC79XXB_SLOWCRC) {
3428 con_opts |= ENSLOWCRC;
3429 }
3430
3431
3432
3433
3434
3435
3436 if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) == 0)
3437 con_opts |= ENAUTOATNO;
3438 ahd_outb(ahd, NEGCONOPTS, con_opts);
3439 ahd_outb(ahd, NEGOADDR, saved_negoaddr);
3440 ahd_restore_modes(ahd, saved_modes);
3441}
3442
3443
3444
3445
3446
3447
3448
3449static void
3450ahd_update_pending_scbs(struct ahd_softc *ahd)
3451{
3452 struct scb *pending_scb;
3453 int pending_scb_count;
3454 int paused;
3455 u_int saved_scbptr;
3456 ahd_mode_state saved_modes;
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468 pending_scb_count = 0;
3469 LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
3470 struct ahd_devinfo devinfo;
3471 struct ahd_initiator_tinfo *tinfo;
3472 struct ahd_tmode_tstate *tstate;
3473
3474 ahd_scb_devinfo(ahd, &devinfo, pending_scb);
3475 tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
3476 devinfo.our_scsiid,
3477 devinfo.target, &tstate);
3478 if ((tstate->auto_negotiate & devinfo.target_mask) == 0
3479 && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) {
3480 pending_scb->flags &= ~SCB_AUTO_NEGOTIATE;
3481 pending_scb->hscb->control &= ~MK_MESSAGE;
3482 }
3483 ahd_sync_scb(ahd, pending_scb,
3484 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
3485 pending_scb_count++;
3486 }
3487
3488 if (pending_scb_count == 0)
3489 return;
3490
3491 if (ahd_is_paused(ahd)) {
3492 paused = 1;
3493 } else {
3494 paused = 0;
3495 ahd_pause(ahd);
3496 }
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506 saved_modes = ahd_save_modes(ahd);
3507 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
3508 if ((ahd_inb(ahd, SCSISIGI) & BSYI) != 0
3509 && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)
3510 ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
3511 saved_scbptr = ahd_get_scbptr(ahd);
3512
3513 LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
3514 u_int scb_tag;
3515 u_int control;
3516
3517 scb_tag = SCB_GET_TAG(pending_scb);
3518 ahd_set_scbptr(ahd, scb_tag);
3519 control = ahd_inb_scbram(ahd, SCB_CONTROL);
3520 control &= ~MK_MESSAGE;
3521 control |= pending_scb->hscb->control & MK_MESSAGE;
3522 ahd_outb(ahd, SCB_CONTROL, control);
3523 }
3524 ahd_set_scbptr(ahd, saved_scbptr);
3525 ahd_restore_modes(ahd, saved_modes);
3526
3527 if (paused == 0)
3528 ahd_unpause(ahd);
3529}
3530
3531
3532static void
3533ahd_fetch_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
3534{
3535 ahd_mode_state saved_modes;
3536 u_int saved_scsiid;
3537 role_t role;
3538 int our_id;
3539
3540 saved_modes = ahd_save_modes(ahd);
3541 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
3542
3543 if (ahd_inb(ahd, SSTAT0) & TARGET)
3544 role = ROLE_TARGET;
3545 else
3546 role = ROLE_INITIATOR;
3547
3548 if (role == ROLE_TARGET
3549 && (ahd_inb(ahd, SEQ_FLAGS) & CMDPHASE_PENDING) != 0) {
3550
3551 our_id = ahd_inb(ahd, TARGIDIN) & OID;
3552 } else if (role == ROLE_TARGET)
3553 our_id = ahd_inb(ahd, TOWNID);
3554 else
3555 our_id = ahd_inb(ahd, IOWNID);
3556
3557 saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
3558 ahd_compile_devinfo(devinfo,
3559 our_id,
3560 SCSIID_TARGET(ahd, saved_scsiid),
3561 ahd_inb(ahd, SAVED_LUN),
3562 SCSIID_CHANNEL(ahd, saved_scsiid),
3563 role);
3564 ahd_restore_modes(ahd, saved_modes);
3565}
3566
3567void
3568ahd_print_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
3569{
3570 printf("%s:%c:%d:%d: ", ahd_name(ahd), 'A',
3571 devinfo->target, devinfo->lun);
3572}
3573
3574static struct ahd_phase_table_entry*
3575ahd_lookup_phase_entry(int phase)
3576{
3577 struct ahd_phase_table_entry *entry;
3578 struct ahd_phase_table_entry *last_entry;
3579
3580
3581
3582
3583
3584 last_entry = &ahd_phase_table[num_phases];
3585 for (entry = ahd_phase_table; entry < last_entry; entry++) {
3586 if (phase == entry->phase)
3587 break;
3588 }
3589 return (entry);
3590}
3591
3592void
3593ahd_compile_devinfo(struct ahd_devinfo *devinfo, u_int our_id, u_int target,
3594 u_int lun, char channel, role_t role)
3595{
3596 devinfo->our_scsiid = our_id;
3597 devinfo->target = target;
3598 devinfo->lun = lun;
3599 devinfo->target_offset = target;
3600 devinfo->channel = channel;
3601 devinfo->role = role;
3602 if (channel == 'B')
3603 devinfo->target_offset += 8;
3604 devinfo->target_mask = (0x01 << devinfo->target_offset);
3605}
3606
3607static void
3608ahd_scb_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
3609 struct scb *scb)
3610{
3611 role_t role;
3612 int our_id;
3613
3614 our_id = SCSIID_OUR_ID(scb->hscb->scsiid);
3615 role = ROLE_INITIATOR;
3616 if ((scb->hscb->control & TARGET_SCB) != 0)
3617 role = ROLE_TARGET;
3618 ahd_compile_devinfo(devinfo, our_id, SCB_GET_TARGET(ahd, scb),
3619 SCB_GET_LUN(scb), SCB_GET_CHANNEL(ahd, scb), role);
3620}
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630static void
3631ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
3632 struct scb *scb)
3633{
3634
3635
3636
3637
3638
3639 ahd->msgout_index = 0;
3640 ahd->msgout_len = 0;
3641
3642 if (ahd_currently_packetized(ahd))
3643 ahd->msg_flags |= MSG_FLAG_PACKETIZED;
3644
3645 if (ahd->send_msg_perror
3646 && ahd_inb(ahd, MSG_OUT) == HOST_MSG) {
3647 ahd->msgout_buf[ahd->msgout_index++] = ahd->send_msg_perror;
3648 ahd->msgout_len++;
3649 ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
3650#ifdef AHD_DEBUG
3651 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
3652 printf("Setting up for Parity Error delivery\n");
3653#endif
3654 return;
3655 } else if (scb == NULL) {
3656 printf("%s: WARNING. No pending message for "
3657 "I_T msgin. Issuing NO-OP\n", ahd_name(ahd));
3658 ahd->msgout_buf[ahd->msgout_index++] = MSG_NOOP;
3659 ahd->msgout_len++;
3660 ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
3661 return;
3662 }
3663
3664 if ((scb->flags & SCB_DEVICE_RESET) == 0
3665 && (scb->flags & SCB_PACKETIZED) == 0
3666 && ahd_inb(ahd, MSG_OUT) == MSG_IDENTIFYFLAG) {
3667 u_int identify_msg;
3668
3669 identify_msg = MSG_IDENTIFYFLAG | SCB_GET_LUN(scb);
3670 if ((scb->hscb->control & DISCENB) != 0)
3671 identify_msg |= MSG_IDENTIFY_DISCFLAG;
3672 ahd->msgout_buf[ahd->msgout_index++] = identify_msg;
3673 ahd->msgout_len++;
3674
3675 if ((scb->hscb->control & TAG_ENB) != 0) {
3676 ahd->msgout_buf[ahd->msgout_index++] =
3677 scb->hscb->control & (TAG_ENB|SCB_TAG_TYPE);
3678 ahd->msgout_buf[ahd->msgout_index++] = SCB_GET_TAG(scb);
3679 ahd->msgout_len += 2;
3680 }
3681 }
3682
3683 if (scb->flags & SCB_DEVICE_RESET) {
3684 ahd->msgout_buf[ahd->msgout_index++] = MSG_BUS_DEV_RESET;
3685 ahd->msgout_len++;
3686 ahd_print_path(ahd, scb);
3687 printf("Bus Device Reset Message Sent\n");
3688
3689
3690
3691
3692
3693
3694
3695 ahd_outb(ahd, SCSISEQ0, 0);
3696 } else if ((scb->flags & SCB_ABORT) != 0) {
3697
3698 if ((scb->hscb->control & TAG_ENB) != 0) {
3699 ahd->msgout_buf[ahd->msgout_index++] = MSG_ABORT_TAG;
3700 } else {
3701 ahd->msgout_buf[ahd->msgout_index++] = MSG_ABORT;
3702 }
3703 ahd->msgout_len++;
3704 ahd_print_path(ahd, scb);
3705 printf("Abort%s Message Sent\n",
3706 (scb->hscb->control & TAG_ENB) != 0 ? " Tag" : "");
3707
3708
3709
3710
3711
3712
3713
3714 ahd_outb(ahd, SCSISEQ0, 0);
3715 } else if ((scb->flags & (SCB_AUTO_NEGOTIATE|SCB_NEGOTIATE)) != 0) {
3716 ahd_build_transfer_msg(ahd, devinfo);
3717
3718
3719
3720
3721
3722
3723
3724 ahd_outb(ahd, SCSISEQ0, 0);
3725 } else {
3726 printf("ahd_intr: AWAITING_MSG for an SCB that "
3727 "does not have a waiting message\n");
3728 printf("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid,
3729 devinfo->target_mask);
3730 panic("SCB = %d, SCB Control = %x:%x, MSG_OUT = %x "
3731 "SCB flags = %x", SCB_GET_TAG(scb), scb->hscb->control,
3732 ahd_inb_scbram(ahd, SCB_CONTROL), ahd_inb(ahd, MSG_OUT),
3733 scb->flags);
3734 }
3735
3736
3737
3738
3739
3740 ahd_outb(ahd, SCB_CONTROL,
3741 ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE);
3742 scb->hscb->control &= ~MK_MESSAGE;
3743 ahd->msgout_index = 0;
3744 ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
3745}
3746
3747
3748
3749
3750
3751static void
3752ahd_build_transfer_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
3753{
3754
3755
3756
3757
3758
3759 struct ahd_initiator_tinfo *tinfo;
3760 struct ahd_tmode_tstate *tstate;
3761 int dowide;
3762 int dosync;
3763 int doppr;
3764 u_int period;
3765 u_int ppr_options;
3766 u_int offset;
3767
3768 tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
3769 devinfo->target, &tstate);
3770
3771
3772
3773
3774
3775
3776 period = tinfo->goal.period;
3777 offset = tinfo->goal.offset;
3778 ppr_options = tinfo->goal.ppr_options;
3779
3780 if (devinfo->role == ROLE_TARGET)
3781 ppr_options = 0;
3782 ahd_devlimited_syncrate(ahd, tinfo, &period,
3783 &ppr_options, devinfo->role);
3784 dowide = tinfo->curr.width != tinfo->goal.width;
3785 dosync = tinfo->curr.offset != offset || tinfo->curr.period != period;
3786
3787
3788
3789
3790
3791 doppr = ppr_options != 0;
3792
3793 if (!dowide && !dosync && !doppr) {
3794 dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT;
3795 dosync = tinfo->goal.offset != 0;
3796 }
3797
3798 if (!dowide && !dosync && !doppr) {
3799
3800
3801
3802
3803 if ((ahd->features & AHD_WIDE) != 0)
3804 dowide = 1;
3805 else
3806 dosync = 1;
3807
3808 if (bootverbose) {
3809 ahd_print_devinfo(ahd, devinfo);
3810 printf("Ensuring async\n");
3811 }
3812 }
3813
3814 if (devinfo->role == ROLE_TARGET)
3815 doppr = 0;
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825 if (doppr || (dosync && !dowide)) {
3826
3827 offset = tinfo->goal.offset;
3828 ahd_validate_offset(ahd, tinfo, period, &offset,
3829 doppr ? tinfo->goal.width
3830 : tinfo->curr.width,
3831 devinfo->role);
3832 if (doppr) {
3833 ahd_construct_ppr(ahd, devinfo, period, offset,
3834 tinfo->goal.width, ppr_options);
3835 } else {
3836 ahd_construct_sdtr(ahd, devinfo, period, offset);
3837 }
3838 } else {
3839 ahd_construct_wdtr(ahd, devinfo, tinfo->goal.width);
3840 }
3841}
3842
3843
3844
3845
3846
3847static void
3848ahd_construct_sdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
3849 u_int period, u_int offset)
3850{
3851 if (offset == 0)
3852 period = AHD_ASYNC_XFER_PERIOD;
3853 ahd->msgout_index += spi_populate_sync_msg(
3854 ahd->msgout_buf + ahd->msgout_index, period, offset);
3855 ahd->msgout_len += 5;
3856 if (bootverbose) {
3857 printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n",
3858 ahd_name(ahd), devinfo->channel, devinfo->target,
3859 devinfo->lun, period, offset);
3860 }
3861}
3862
3863
3864
3865
3866
3867static void
3868ahd_construct_wdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
3869 u_int bus_width)
3870{
3871 ahd->msgout_index += spi_populate_width_msg(
3872 ahd->msgout_buf + ahd->msgout_index, bus_width);
3873 ahd->msgout_len += 4;
3874 if (bootverbose) {
3875 printf("(%s:%c:%d:%d): Sending WDTR %x\n",
3876 ahd_name(ahd), devinfo->channel, devinfo->target,
3877 devinfo->lun, bus_width);
3878 }
3879}
3880
3881
3882
3883
3884
3885static void
3886ahd_construct_ppr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
3887 u_int period, u_int offset, u_int bus_width,
3888 u_int ppr_options)
3889{
3890
3891
3892
3893
3894
3895 if (period <= AHD_SYNCRATE_PACED)
3896 ppr_options |= MSG_EXT_PPR_PCOMP_EN;
3897 if (offset == 0)
3898 period = AHD_ASYNC_XFER_PERIOD;
3899 ahd->msgout_index += spi_populate_ppr_msg(
3900 ahd->msgout_buf + ahd->msgout_index, period, offset,
3901 bus_width, ppr_options);
3902 ahd->msgout_len += 8;
3903 if (bootverbose) {
3904 printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, "
3905 "offset %x, ppr_options %x\n", ahd_name(ahd),
3906 devinfo->channel, devinfo->target, devinfo->lun,
3907 bus_width, period, offset, ppr_options);
3908 }
3909}
3910
3911
3912
3913
3914static void
3915ahd_clear_msg_state(struct ahd_softc *ahd)
3916{
3917 ahd_mode_state saved_modes;
3918
3919 saved_modes = ahd_save_modes(ahd);
3920 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
3921 ahd->send_msg_perror = 0;
3922 ahd->msg_flags = MSG_FLAG_NONE;
3923 ahd->msgout_len = 0;
3924 ahd->msgin_index = 0;
3925 ahd->msg_type = MSG_TYPE_NONE;
3926 if ((ahd_inb(ahd, SCSISIGO) & ATNO) != 0) {
3927
3928
3929
3930
3931 ahd_outb(ahd, CLRSINT1, CLRATNO);
3932 }
3933 ahd_outb(ahd, MSG_OUT, MSG_NOOP);
3934 ahd_outb(ahd, SEQ_FLAGS2,
3935 ahd_inb(ahd, SEQ_FLAGS2) & ~TARGET_MSG_PENDING);
3936 ahd_restore_modes(ahd, saved_modes);
3937}
3938
3939
3940
3941
3942static void
3943ahd_handle_message_phase(struct ahd_softc *ahd)
3944{
3945 struct ahd_devinfo devinfo;
3946 u_int bus_phase;
3947 int end_session;
3948
3949 ahd_fetch_devinfo(ahd, &devinfo);
3950 end_session = FALSE;
3951 bus_phase = ahd_inb(ahd, LASTPHASE);
3952
3953 if ((ahd_inb(ahd, LQISTAT2) & LQIPHASE_OUTPKT) != 0) {
3954 printf("LQIRETRY for LQIPHASE_OUTPKT\n");
3955 ahd_outb(ahd, LQCTL2, LQIRETRY);
3956 }
3957reswitch:
3958 switch (ahd->msg_type) {
3959 case MSG_TYPE_INITIATOR_MSGOUT:
3960 {
3961 int lastbyte;
3962 int phasemis;
3963 int msgdone;
3964
3965 if (ahd->msgout_len == 0 && ahd->send_msg_perror == 0)
3966 panic("HOST_MSG_LOOP interrupt with no active message");
3967
3968#ifdef AHD_DEBUG
3969 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
3970 ahd_print_devinfo(ahd, &devinfo);
3971 printf("INITIATOR_MSG_OUT");
3972 }
3973#endif
3974 phasemis = bus_phase != P_MESGOUT;
3975 if (phasemis) {
3976#ifdef AHD_DEBUG
3977 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
3978 printf(" PHASEMIS %s\n",
3979 ahd_lookup_phase_entry(bus_phase)
3980 ->phasemsg);
3981 }
3982#endif
3983 if (bus_phase == P_MESGIN) {
3984
3985
3986
3987
3988
3989
3990 ahd_outb(ahd, CLRSINT1, CLRATNO);
3991 ahd->send_msg_perror = 0;
3992 ahd->msg_type = MSG_TYPE_INITIATOR_MSGIN;
3993 ahd->msgin_index = 0;
3994 goto reswitch;
3995 }
3996 end_session = TRUE;
3997 break;
3998 }
3999
4000 if (ahd->send_msg_perror) {
4001 ahd_outb(ahd, CLRSINT1, CLRATNO);
4002 ahd_outb(ahd, CLRSINT1, CLRREQINIT);
4003#ifdef AHD_DEBUG
4004 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
4005 printf(" byte 0x%x\n", ahd->send_msg_perror);
4006#endif
4007
4008
4009
4010
4011
4012
4013 if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0
4014 && ahd->send_msg_perror == MSG_INITIATOR_DET_ERR)
4015 ahd->msg_flags |= MSG_FLAG_EXPECT_IDE_BUSFREE;
4016
4017 ahd_outb(ahd, RETURN_2, ahd->send_msg_perror);
4018 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_WRITE);
4019 break;
4020 }
4021
4022 msgdone = ahd->msgout_index == ahd->msgout_len;
4023 if (msgdone) {
4024
4025
4026
4027
4028
4029 ahd->msgout_index = 0;
4030 ahd_assert_atn(ahd);
4031 }
4032
4033 lastbyte = ahd->msgout_index == (ahd->msgout_len - 1);
4034 if (lastbyte) {
4035
4036 ahd_outb(ahd, CLRSINT1, CLRATNO);
4037 }
4038
4039
4040
4041
4042
4043 ahd_outb(ahd, CLRSINT1, CLRREQINIT);
4044#ifdef AHD_DEBUG
4045 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
4046 printf(" byte 0x%x\n",
4047 ahd->msgout_buf[ahd->msgout_index]);
4048#endif
4049 ahd_outb(ahd, RETURN_2, ahd->msgout_buf[ahd->msgout_index++]);
4050 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_WRITE);
4051 break;
4052 }
4053 case MSG_TYPE_INITIATOR_MSGIN:
4054 {
4055 int phasemis;
4056 int message_done;
4057
4058#ifdef AHD_DEBUG
4059 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
4060 ahd_print_devinfo(ahd, &devinfo);
4061 printf("INITIATOR_MSG_IN");
4062 }
4063#endif
4064 phasemis = bus_phase != P_MESGIN;
4065 if (phasemis) {
4066#ifdef AHD_DEBUG
4067 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
4068 printf(" PHASEMIS %s\n",
4069 ahd_lookup_phase_entry(bus_phase)
4070 ->phasemsg);
4071 }
4072#endif
4073 ahd->msgin_index = 0;
4074 if (bus_phase == P_MESGOUT
4075 && (ahd->send_msg_perror != 0
4076 || (ahd->msgout_len != 0
4077 && ahd->msgout_index == 0))) {
4078 ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
4079 goto reswitch;
4080 }
4081 end_session = TRUE;
4082 break;
4083 }
4084
4085
4086 ahd->msgin_buf[ahd->msgin_index] = ahd_inb(ahd, SCSIBUS);
4087#ifdef AHD_DEBUG
4088 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
4089 printf(" byte 0x%x\n",
4090 ahd->msgin_buf[ahd->msgin_index]);
4091#endif
4092
4093 message_done = ahd_parse_msg(ahd, &devinfo);
4094
4095 if (message_done) {
4096
4097
4098
4099
4100 ahd->msgin_index = 0;
4101
4102
4103
4104
4105
4106
4107 if (ahd->msgout_len != 0) {
4108#ifdef AHD_DEBUG
4109 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
4110 ahd_print_devinfo(ahd, &devinfo);
4111 printf("Asserting ATN for response\n");
4112 }
4113#endif
4114 ahd_assert_atn(ahd);
4115 }
4116 } else
4117 ahd->msgin_index++;
4118
4119 if (message_done == MSGLOOP_TERMINATED) {
4120 end_session = TRUE;
4121 } else {
4122
4123 ahd_outb(ahd, CLRSINT1, CLRREQINIT);
4124 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_READ);
4125 }
4126 break;
4127 }
4128 case MSG_TYPE_TARGET_MSGIN:
4129 {
4130 int msgdone;
4131 int msgout_request;
4132
4133
4134
4135
4136 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
4137
4138 if (ahd->msgout_len == 0)
4139 panic("Target MSGIN with no active message");
4140
4141
4142
4143
4144
4145
4146
4147 if ((ahd_inb(ahd, SCSISIGI) & ATNI) != 0
4148 && ahd->msgout_index > 0)
4149 msgout_request = TRUE;
4150 else
4151 msgout_request = FALSE;
4152
4153 if (msgout_request) {
4154
4155
4156
4157
4158
4159
4160
4161 ahd->msg_type = MSG_TYPE_TARGET_MSGOUT;
4162 ahd_outb(ahd, SCSISIGO, P_MESGOUT | BSYO);
4163 ahd->msgin_index = 0;
4164
4165 ahd_inb(ahd, SCSIDAT);
4166 ahd_outb(ahd, SXFRCTL0,
4167 ahd_inb(ahd, SXFRCTL0) | SPIOEN);
4168 break;
4169 }
4170
4171 msgdone = ahd->msgout_index == ahd->msgout_len;
4172 if (msgdone) {
4173 ahd_outb(ahd, SXFRCTL0,
4174 ahd_inb(ahd, SXFRCTL0) & ~SPIOEN);
4175 end_session = TRUE;
4176 break;
4177 }
4178
4179
4180
4181
4182 ahd_outb(ahd, SXFRCTL0, ahd_inb(ahd, SXFRCTL0) | SPIOEN);
4183 ahd_outb(ahd, SCSIDAT, ahd->msgout_buf[ahd->msgout_index++]);
4184 break;
4185 }
4186 case MSG_TYPE_TARGET_MSGOUT:
4187 {
4188 int lastbyte;
4189 int msgdone;
4190
4191
4192
4193
4194 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
4195
4196
4197
4198
4199
4200 lastbyte = (ahd_inb(ahd, SCSISIGI) & ATNI) == 0;
4201
4202
4203
4204
4205
4206
4207 ahd_outb(ahd, SXFRCTL0, ahd_inb(ahd, SXFRCTL0) & ~SPIOEN);
4208 ahd->msgin_buf[ahd->msgin_index] = ahd_inb(ahd, SCSIDAT);
4209 msgdone = ahd_parse_msg(ahd, &devinfo);
4210 if (msgdone == MSGLOOP_TERMINATED) {
4211
4212
4213
4214
4215
4216
4217 return;
4218 }
4219
4220 ahd->msgin_index++;
4221
4222
4223
4224
4225
4226 if (msgdone == MSGLOOP_MSGCOMPLETE) {
4227 ahd->msgin_index = 0;
4228
4229
4230
4231
4232
4233 if (ahd->msgout_len != 0) {
4234 ahd_outb(ahd, SCSISIGO, P_MESGIN | BSYO);
4235 ahd_outb(ahd, SXFRCTL0,
4236 ahd_inb(ahd, SXFRCTL0) | SPIOEN);
4237 ahd->msg_type = MSG_TYPE_TARGET_MSGIN;
4238 ahd->msgin_index = 0;
4239 break;
4240 }
4241 }
4242
4243 if (lastbyte)
4244 end_session = TRUE;
4245 else {
4246
4247 ahd_outb(ahd, SXFRCTL0,
4248 ahd_inb(ahd, SXFRCTL0) | SPIOEN);
4249 }
4250
4251 break;
4252 }
4253 default:
4254 panic("Unknown REQINIT message type");
4255 }
4256
4257 if (end_session) {
4258 if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0) {
4259 printf("%s: Returning to Idle Loop\n",
4260 ahd_name(ahd));
4261 ahd_clear_msg_state(ahd);
4262
4263
4264
4265
4266 ahd_outb(ahd, LASTPHASE, P_BUSFREE);
4267 ahd_outb(ahd, SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT);
4268 ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
4269 } else {
4270 ahd_clear_msg_state(ahd);
4271 ahd_outb(ahd, RETURN_1, EXIT_MSG_LOOP);
4272 }
4273 }
4274}
4275
4276
4277
4278
4279
4280
4281
4282static int
4283ahd_sent_msg(struct ahd_softc *ahd, ahd_msgtype type, u_int msgval, int full)
4284{
4285 int found;
4286 u_int index;
4287
4288 found = FALSE;
4289 index = 0;
4290
4291 while (index < ahd->msgout_len) {
4292 if (ahd->msgout_buf[index] == MSG_EXTENDED) {
4293 u_int end_index;
4294
4295 end_index = index + 1 + ahd->msgout_buf[index + 1];
4296 if (ahd->msgout_buf[index+2] == msgval
4297 && type == AHDMSG_EXT) {
4298
4299 if (full) {
4300 if (ahd->msgout_index > end_index)
4301 found = TRUE;
4302 } else if (ahd->msgout_index > index)
4303 found = TRUE;
4304 }
4305 index = end_index;
4306 } else if (ahd->msgout_buf[index] >= MSG_SIMPLE_TASK
4307 && ahd->msgout_buf[index] <= MSG_IGN_WIDE_RESIDUE) {
4308
4309
4310 index += 2;
4311 } else {
4312
4313 if (type == AHDMSG_1B
4314 && ahd->msgout_index > index
4315 && (ahd->msgout_buf[index] == msgval
4316 || ((ahd->msgout_buf[index] & MSG_IDENTIFYFLAG) != 0
4317 && msgval == MSG_IDENTIFYFLAG)))
4318 found = TRUE;
4319 index++;
4320 }
4321
4322 if (found)
4323 break;
4324 }
4325 return (found);
4326}
4327
4328
4329
4330
4331static int
4332ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
4333{
4334 struct ahd_initiator_tinfo *tinfo;
4335 struct ahd_tmode_tstate *tstate;
4336 int reject;
4337 int done;
4338 int response;
4339
4340 done = MSGLOOP_IN_PROG;
4341 response = FALSE;
4342 reject = FALSE;
4343 tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
4344 devinfo->target, &tstate);
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357 switch (ahd->msgin_buf[0]) {
4358 case MSG_DISCONNECT:
4359 case MSG_SAVEDATAPOINTER:
4360 case MSG_CMDCOMPLETE:
4361 case MSG_RESTOREPOINTERS:
4362 case MSG_IGN_WIDE_RESIDUE:
4363
4364
4365
4366
4367 done = MSGLOOP_TERMINATED;
4368 break;
4369 case MSG_MESSAGE_REJECT:
4370 response = ahd_handle_msg_reject(ahd, devinfo);
4371
4372 case MSG_NOOP:
4373 done = MSGLOOP_MSGCOMPLETE;
4374 break;
4375 case MSG_EXTENDED:
4376 {
4377
4378 if (ahd->msgin_index < 2)
4379 break;
4380 switch (ahd->msgin_buf[2]) {
4381 case MSG_EXT_SDTR:
4382 {
4383 u_int period;
4384 u_int ppr_options;
4385 u_int offset;
4386 u_int saved_offset;
4387
4388 if (ahd->msgin_buf[1] != MSG_EXT_SDTR_LEN) {
4389 reject = TRUE;
4390 break;
4391 }
4392
4393
4394
4395
4396
4397
4398
4399
4400 if (ahd->msgin_index < (MSG_EXT_SDTR_LEN + 1))
4401 break;
4402
4403 period = ahd->msgin_buf[3];
4404 ppr_options = 0;
4405 saved_offset = offset = ahd->msgin_buf[4];
4406 ahd_devlimited_syncrate(ahd, tinfo, &period,
4407 &ppr_options, devinfo->role);
4408 ahd_validate_offset(ahd, tinfo, period, &offset,
4409 tinfo->curr.width, devinfo->role);
4410 if (bootverbose) {
4411 printf("(%s:%c:%d:%d): Received "
4412 "SDTR period %x, offset %x\n\t"
4413 "Filtered to period %x, offset %x\n",
4414 ahd_name(ahd), devinfo->channel,
4415 devinfo->target, devinfo->lun,
4416 ahd->msgin_buf[3], saved_offset,
4417 period, offset);
4418 }
4419 ahd_set_syncrate(ahd, devinfo, period,
4420 offset, ppr_options,
4421 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
4422 TRUE);
4423
4424
4425
4426
4427
4428
4429 if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, TRUE)) {
4430
4431 if (saved_offset != offset) {
4432
4433 reject = TRUE;
4434 }
4435 } else {
4436
4437
4438
4439 if (bootverbose
4440 && devinfo->role == ROLE_INITIATOR) {
4441 printf("(%s:%c:%d:%d): Target "
4442 "Initiated SDTR\n",
4443 ahd_name(ahd), devinfo->channel,
4444 devinfo->target, devinfo->lun);
4445 }
4446 ahd->msgout_index = 0;
4447 ahd->msgout_len = 0;
4448 ahd_construct_sdtr(ahd, devinfo,
4449 period, offset);
4450 ahd->msgout_index = 0;
4451 response = TRUE;
4452 }
4453 done = MSGLOOP_MSGCOMPLETE;
4454 break;
4455 }
4456 case MSG_EXT_WDTR:
4457 {
4458 u_int bus_width;
4459 u_int saved_width;
4460 u_int sending_reply;
4461
4462 sending_reply = FALSE;
4463 if (ahd->msgin_buf[1] != MSG_EXT_WDTR_LEN) {
4464 reject = TRUE;
4465 break;
4466 }
4467
4468
4469
4470
4471
4472
4473
4474
4475 if (ahd->msgin_index < (MSG_EXT_WDTR_LEN + 1))
4476 break;
4477
4478 bus_width = ahd->msgin_buf[3];
4479 saved_width = bus_width;
4480 ahd_validate_width(ahd, tinfo, &bus_width,
4481 devinfo->role);
4482 if (bootverbose) {
4483 printf("(%s:%c:%d:%d): Received WDTR "
4484 "%x filtered to %x\n",
4485 ahd_name(ahd), devinfo->channel,
4486 devinfo->target, devinfo->lun,
4487 saved_width, bus_width);
4488 }
4489
4490 if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, TRUE)) {
4491
4492
4493
4494
4495
4496
4497 if (saved_width > bus_width) {
4498 reject = TRUE;
4499 printf("(%s:%c:%d:%d): requested %dBit "
4500 "transfers. Rejecting...\n",
4501 ahd_name(ahd), devinfo->channel,
4502 devinfo->target, devinfo->lun,
4503 8 * (0x01 << bus_width));
4504 bus_width = 0;
4505 }
4506 } else {
4507
4508
4509
4510 if (bootverbose
4511 && devinfo->role == ROLE_INITIATOR) {
4512 printf("(%s:%c:%d:%d): Target "
4513 "Initiated WDTR\n",
4514 ahd_name(ahd), devinfo->channel,
4515 devinfo->target, devinfo->lun);
4516 }
4517 ahd->msgout_index = 0;
4518 ahd->msgout_len = 0;
4519 ahd_construct_wdtr(ahd, devinfo, bus_width);
4520 ahd->msgout_index = 0;
4521 response = TRUE;
4522 sending_reply = TRUE;
4523 }
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533 ahd_update_neg_request(ahd, devinfo, tstate,
4534 tinfo, AHD_NEG_ALWAYS);
4535 ahd_set_width(ahd, devinfo, bus_width,
4536 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
4537 TRUE);
4538 if (sending_reply == FALSE && reject == FALSE) {
4539
4540
4541
4542
4543 ahd->msgout_index = 0;
4544 ahd->msgout_len = 0;
4545 ahd_build_transfer_msg(ahd, devinfo);
4546 ahd->msgout_index = 0;
4547 response = TRUE;
4548 }
4549 done = MSGLOOP_MSGCOMPLETE;
4550 break;
4551 }
4552 case MSG_EXT_PPR:
4553 {
4554 u_int period;
4555 u_int offset;
4556 u_int bus_width;
4557 u_int ppr_options;
4558 u_int saved_width;
4559 u_int saved_offset;
4560 u_int saved_ppr_options;
4561
4562 if (ahd->msgin_buf[1] != MSG_EXT_PPR_LEN) {
4563 reject = TRUE;
4564 break;
4565 }
4566
4567
4568
4569
4570
4571
4572
4573
4574 if (ahd->msgin_index < (MSG_EXT_PPR_LEN + 1))
4575 break;
4576
4577 period = ahd->msgin_buf[3];
4578 offset = ahd->msgin_buf[5];
4579 bus_width = ahd->msgin_buf[6];
4580 saved_width = bus_width;
4581 ppr_options = ahd->msgin_buf[7];
4582
4583
4584
4585
4586
4587 if ((ppr_options & MSG_EXT_PPR_DT_REQ) == 0
4588 && period <= 9)
4589 offset = 0;
4590 saved_ppr_options = ppr_options;
4591 saved_offset = offset;
4592
4593
4594
4595
4596
4597 if (bus_width == 0)
4598 ppr_options &= MSG_EXT_PPR_QAS_REQ;
4599
4600 ahd_validate_width(ahd, tinfo, &bus_width,
4601 devinfo->role);
4602 ahd_devlimited_syncrate(ahd, tinfo, &period,
4603 &ppr_options, devinfo->role);
4604 ahd_validate_offset(ahd, tinfo, period, &offset,
4605 bus_width, devinfo->role);
4606
4607 if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, TRUE)) {
4608
4609
4610
4611
4612
4613 if (saved_width > bus_width
4614 || saved_offset != offset
4615 || saved_ppr_options != ppr_options) {
4616 reject = TRUE;
4617 period = 0;
4618 offset = 0;
4619 bus_width = 0;
4620 ppr_options = 0;
4621 }
4622 } else {
4623 if (devinfo->role != ROLE_TARGET)
4624 printf("(%s:%c:%d:%d): Target "
4625 "Initiated PPR\n",
4626 ahd_name(ahd), devinfo->channel,
4627 devinfo->target, devinfo->lun);
4628 else
4629 printf("(%s:%c:%d:%d): Initiator "
4630 "Initiated PPR\n",
4631 ahd_name(ahd), devinfo->channel,
4632 devinfo->target, devinfo->lun);
4633 ahd->msgout_index = 0;
4634 ahd->msgout_len = 0;
4635 ahd_construct_ppr(ahd, devinfo, period, offset,
4636 bus_width, ppr_options);
4637 ahd->msgout_index = 0;
4638 response = TRUE;
4639 }
4640 if (bootverbose) {
4641 printf("(%s:%c:%d:%d): Received PPR width %x, "
4642 "period %x, offset %x,options %x\n"
4643 "\tFiltered to width %x, period %x, "
4644 "offset %x, options %x\n",
4645 ahd_name(ahd), devinfo->channel,
4646 devinfo->target, devinfo->lun,
4647 saved_width, ahd->msgin_buf[3],
4648 saved_offset, saved_ppr_options,
4649 bus_width, period, offset, ppr_options);
4650 }
4651 ahd_set_width(ahd, devinfo, bus_width,
4652 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
4653 TRUE);
4654 ahd_set_syncrate(ahd, devinfo, period,
4655 offset, ppr_options,
4656 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
4657 TRUE);
4658
4659 done = MSGLOOP_MSGCOMPLETE;
4660 break;
4661 }
4662 default:
4663
4664 reject = TRUE;
4665 break;
4666 }
4667 break;
4668 }
4669#ifdef AHD_TARGET_MODE
4670 case MSG_BUS_DEV_RESET:
4671 ahd_handle_devreset(ahd, devinfo, CAM_LUN_WILDCARD,
4672 CAM_BDR_SENT,
4673 "Bus Device Reset Received",
4674 0);
4675 ahd_restart(ahd);
4676 done = MSGLOOP_TERMINATED;
4677 break;
4678 case MSG_ABORT_TAG:
4679 case MSG_ABORT:
4680 case MSG_CLEAR_QUEUE:
4681 {
4682 int tag;
4683
4684
4685 if (devinfo->role != ROLE_TARGET) {
4686 reject = TRUE;
4687 break;
4688 }
4689 tag = SCB_LIST_NULL;
4690 if (ahd->msgin_buf[0] == MSG_ABORT_TAG)
4691 tag = ahd_inb(ahd, INITIATOR_TAG);
4692 ahd_abort_scbs(ahd, devinfo->target, devinfo->channel,
4693 devinfo->lun, tag, ROLE_TARGET,
4694 CAM_REQ_ABORTED);
4695
4696 tstate = ahd->enabled_targets[devinfo->our_scsiid];
4697 if (tstate != NULL) {
4698 struct ahd_tmode_lstate* lstate;
4699
4700 lstate = tstate->enabled_luns[devinfo->lun];
4701 if (lstate != NULL) {
4702 ahd_queue_lstate_event(ahd, lstate,
4703 devinfo->our_scsiid,
4704 ahd->msgin_buf[0],
4705 tag);
4706 ahd_send_lstate_events(ahd, lstate);
4707 }
4708 }
4709 ahd_restart(ahd);
4710 done = MSGLOOP_TERMINATED;
4711 break;
4712 }
4713#endif
4714 case MSG_QAS_REQUEST:
4715#ifdef AHD_DEBUG
4716 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
4717 printf("%s: QAS request. SCSISIGI == 0x%x\n",
4718 ahd_name(ahd), ahd_inb(ahd, SCSISIGI));
4719#endif
4720 ahd->msg_flags |= MSG_FLAG_EXPECT_QASREJ_BUSFREE;
4721
4722 case MSG_TERM_IO_PROC:
4723 default:
4724 reject = TRUE;
4725 break;
4726 }
4727
4728 if (reject) {
4729
4730
4731
4732 ahd->msgout_index = 0;
4733 ahd->msgout_len = 1;
4734 ahd->msgout_buf[0] = MSG_MESSAGE_REJECT;
4735 done = MSGLOOP_MSGCOMPLETE;
4736 response = TRUE;
4737 }
4738
4739 if (done != MSGLOOP_IN_PROG && !response)
4740
4741 ahd->msgout_len = 0;
4742
4743 return (done);
4744}
4745
4746
4747
4748
4749static int
4750ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
4751{
4752
4753
4754
4755
4756
4757
4758 struct scb *scb;
4759 struct ahd_initiator_tinfo *tinfo;
4760 struct ahd_tmode_tstate *tstate;
4761 u_int scb_index;
4762 u_int last_msg;
4763 int response = 0;
4764
4765 scb_index = ahd_get_scbptr(ahd);
4766 scb = ahd_lookup_scb(ahd, scb_index);
4767 tinfo = ahd_fetch_transinfo(ahd, devinfo->channel,
4768 devinfo->our_scsiid,
4769 devinfo->target, &tstate);
4770
4771 last_msg = ahd_inb(ahd, LAST_MSG);
4772
4773 if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, FALSE)) {
4774 if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, TRUE)
4775 && tinfo->goal.period <= AHD_SYNCRATE_PACED) {
4776
4777
4778
4779
4780
4781 if (bootverbose) {
4782 printf("(%s:%c:%d:%d): PPR Rejected. "
4783 "Trying simple U160 PPR\n",
4784 ahd_name(ahd), devinfo->channel,
4785 devinfo->target, devinfo->lun);
4786 }
4787 tinfo->goal.period = AHD_SYNCRATE_DT;
4788 tinfo->goal.ppr_options &= MSG_EXT_PPR_IU_REQ
4789 | MSG_EXT_PPR_QAS_REQ
4790 | MSG_EXT_PPR_DT_REQ;
4791 } else {
4792
4793
4794
4795
4796 if (bootverbose) {
4797 printf("(%s:%c:%d:%d): PPR Rejected. "
4798 "Trying WDTR/SDTR\n",
4799 ahd_name(ahd), devinfo->channel,
4800 devinfo->target, devinfo->lun);
4801 }
4802 tinfo->goal.ppr_options = 0;
4803 tinfo->curr.transport_version = 2;
4804 tinfo->goal.transport_version = 2;
4805 }
4806 ahd->msgout_index = 0;
4807 ahd->msgout_len = 0;
4808 ahd_build_transfer_msg(ahd, devinfo);
4809 ahd->msgout_index = 0;
4810 response = 1;
4811 } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, FALSE)) {
4812
4813
4814 printf("(%s:%c:%d:%d): refuses WIDE negotiation. Using "
4815 "8bit transfers\n", ahd_name(ahd),
4816 devinfo->channel, devinfo->target, devinfo->lun);
4817 ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,
4818 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
4819 TRUE);
4820
4821
4822
4823
4824
4825
4826
4827 if (tinfo->goal.offset != tinfo->curr.offset) {
4828
4829
4830 ahd->msgout_index = 0;
4831 ahd->msgout_len = 0;
4832 ahd_build_transfer_msg(ahd, devinfo);
4833 ahd->msgout_index = 0;
4834 response = 1;
4835 }
4836 } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, FALSE)) {
4837
4838 ahd_set_syncrate(ahd, devinfo, 0,
4839 0, 0,
4840 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
4841 TRUE);
4842 printf("(%s:%c:%d:%d): refuses synchronous negotiation. "
4843 "Using asynchronous transfers\n",
4844 ahd_name(ahd), devinfo->channel,
4845 devinfo->target, devinfo->lun);
4846 } else if ((scb->hscb->control & MSG_SIMPLE_TASK) != 0) {
4847 int tag_type;
4848 int mask;
4849
4850 tag_type = (scb->hscb->control & MSG_SIMPLE_TASK);
4851
4852 if (tag_type == MSG_SIMPLE_TASK) {
4853 printf("(%s:%c:%d:%d): refuses tagged commands. "
4854 "Performing non-tagged I/O\n", ahd_name(ahd),
4855 devinfo->channel, devinfo->target, devinfo->lun);
4856 ahd_set_tags(ahd, scb->io_ctx, devinfo, AHD_QUEUE_NONE);
4857 mask = ~0x23;
4858 } else {
4859 printf("(%s:%c:%d:%d): refuses %s tagged commands. "
4860 "Performing simple queue tagged I/O only\n",
4861 ahd_name(ahd), devinfo->channel, devinfo->target,
4862 devinfo->lun, tag_type == MSG_ORDERED_TASK
4863 ? "ordered" : "head of queue");
4864 ahd_set_tags(ahd, scb->io_ctx, devinfo, AHD_QUEUE_BASIC);
4865 mask = ~0x03;
4866 }
4867
4868
4869
4870
4871
4872 ahd_outb(ahd, SCB_CONTROL,
4873 ahd_inb_scbram(ahd, SCB_CONTROL) & mask);
4874 scb->hscb->control &= mask;
4875 ahd_set_transaction_tag(scb, FALSE,
4876 MSG_SIMPLE_TASK);
4877 ahd_outb(ahd, MSG_OUT, MSG_IDENTIFYFLAG);
4878 ahd_assert_atn(ahd);
4879 ahd_busy_tcl(ahd, BUILD_TCL(scb->hscb->scsiid, devinfo->lun),
4880 SCB_GET_TAG(scb));
4881
4882
4883
4884
4885
4886
4887 ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),
4888 SCB_GET_CHANNEL(ahd, scb),
4889 SCB_GET_LUN(scb), SCB_LIST_NULL,
4890 ROLE_INITIATOR, CAM_REQUEUE_REQ,
4891 SEARCH_COMPLETE);
4892 } else if (ahd_sent_msg(ahd, AHDMSG_1B, MSG_IDENTIFYFLAG, TRUE)) {
4893
4894
4895
4896
4897 ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE
4898 | MSG_FLAG_IU_REQ_CHANGED;
4899
4900 ahd_force_renegotiation(ahd, devinfo);
4901 ahd->msgout_index = 0;
4902 ahd->msgout_len = 0;
4903 ahd_build_transfer_msg(ahd, devinfo);
4904 ahd->msgout_index = 0;
4905 response = 1;
4906 } else {
4907
4908
4909
4910 printf("%s:%c:%d: Message reject for %x -- ignored\n",
4911 ahd_name(ahd), devinfo->channel, devinfo->target,
4912 last_msg);
4913 }
4914 return (response);
4915}
4916
4917
4918
4919
4920static void
4921ahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
4922{
4923 u_int scb_index;
4924 struct scb *scb;
4925
4926 scb_index = ahd_get_scbptr(ahd);
4927 scb = ahd_lookup_scb(ahd, scb_index);
4928
4929
4930
4931
4932 if ((ahd_inb(ahd, SEQ_FLAGS) & DPHASE) == 0
4933 || ahd_get_transfer_dir(scb) != CAM_DIR_IN) {
4934
4935
4936
4937
4938 } else {
4939
4940
4941
4942
4943
4944
4945
4946 uint32_t sgptr;
4947
4948 sgptr = ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR);
4949 if ((sgptr & SG_LIST_NULL) != 0
4950 && (ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)
4951 & SCB_XFERLEN_ODD) != 0) {
4952
4953
4954
4955
4956
4957
4958 } else {
4959 uint32_t data_cnt;
4960 uint64_t data_addr;
4961 uint32_t sglen;
4962
4963
4964 sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
4965 data_cnt = ahd_inl_scbram(ahd, SCB_RESIDUAL_DATACNT);
4966 if ((sgptr & SG_LIST_NULL) != 0) {
4967
4968
4969
4970
4971
4972 data_cnt &= ~AHD_SG_LEN_MASK;
4973 }
4974 data_addr = ahd_inq(ahd, SHADDR);
4975 data_cnt += 1;
4976 data_addr -= 1;
4977 sgptr &= SG_PTR_MASK;
4978 if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
4979 struct ahd_dma64_seg *sg;
4980
4981 sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
4982
4983
4984
4985
4986
4987 sg--;
4988 sglen = ahd_le32toh(sg->len) & AHD_SG_LEN_MASK;
4989 if (sg != scb->sg_list
4990 && sglen < (data_cnt & AHD_SG_LEN_MASK)) {
4991
4992 sg--;
4993 sglen = ahd_le32toh(sg->len);
4994
4995
4996
4997
4998 data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK));
4999 data_addr = ahd_le64toh(sg->addr)
5000 + (sglen & AHD_SG_LEN_MASK)
5001 - 1;
5002
5003
5004
5005
5006
5007 sg++;
5008 sgptr = ahd_sg_virt_to_bus(ahd, scb,
5009 sg);
5010 }
5011 } else {
5012 struct ahd_dma_seg *sg;
5013
5014 sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
5015
5016
5017
5018
5019
5020 sg--;
5021 sglen = ahd_le32toh(sg->len) & AHD_SG_LEN_MASK;
5022 if (sg != scb->sg_list
5023 && sglen < (data_cnt & AHD_SG_LEN_MASK)) {
5024
5025 sg--;
5026 sglen = ahd_le32toh(sg->len);
5027
5028
5029
5030
5031 data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK));
5032 data_addr = ahd_le32toh(sg->addr)
5033 + (sglen & AHD_SG_LEN_MASK)
5034 - 1;
5035
5036
5037
5038
5039
5040 sg++;
5041 sgptr = ahd_sg_virt_to_bus(ahd, scb,
5042 sg);
5043 }
5044 }
5045
5046
5047
5048
5049
5050
5051 ahd_outb(ahd, SCB_TASK_ATTRIBUTE,
5052 ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)
5053 ^ SCB_XFERLEN_ODD);
5054
5055 ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
5056 ahd_outl(ahd, SCB_RESIDUAL_DATACNT, data_cnt);
5057
5058
5059
5060
5061 }
5062 }
5063}
5064
5065
5066
5067
5068
5069
5070static void
5071ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
5072{
5073 struct scb *scb;
5074 ahd_mode_state saved_modes;
5075 u_int scb_index;
5076 u_int wait;
5077 uint32_t sgptr;
5078 uint32_t resid;
5079 uint64_t dataptr;
5080
5081 AHD_ASSERT_MODES(ahd, AHD_MODE_DFF0_MSK|AHD_MODE_DFF1_MSK,
5082 AHD_MODE_DFF0_MSK|AHD_MODE_DFF1_MSK);
5083
5084 scb_index = ahd_get_scbptr(ahd);
5085 scb = ahd_lookup_scb(ahd, scb_index);
5086
5087
5088
5089
5090
5091 ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
5092 wait = 1000;
5093 while (--wait && !(ahd_inb(ahd, MDFFSTAT) & FIFOFREE))
5094 ahd_delay(100);
5095 if (wait == 0) {
5096 ahd_print_path(ahd, scb);
5097 printf("ahd_reinitialize_dataptrs: Forcing FIFO free.\n");
5098 ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT);
5099 }
5100 saved_modes = ahd_save_modes(ahd);
5101 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
5102 ahd_outb(ahd, DFFSTAT,
5103 ahd_inb(ahd, DFFSTAT)
5104 | (saved_modes == 0x11 ? CURRFIFO_1 : CURRFIFO_0));
5105
5106
5107
5108
5109
5110 sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
5111 sgptr &= SG_PTR_MASK;
5112
5113 resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16)
5114 | (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 1) << 8)
5115 | ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT);
5116
5117 if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
5118 struct ahd_dma64_seg *sg;
5119
5120 sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
5121
5122
5123 sg--;
5124
5125 dataptr = ahd_le64toh(sg->addr)
5126 + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK)
5127 - resid;
5128 ahd_outl(ahd, HADDR + 4, dataptr >> 32);
5129 } else {
5130 struct ahd_dma_seg *sg;
5131
5132 sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
5133
5134
5135 sg--;
5136
5137 dataptr = ahd_le32toh(sg->addr)
5138 + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK)
5139 - resid;
5140 ahd_outb(ahd, HADDR + 4,
5141 (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24);
5142 }
5143 ahd_outl(ahd, HADDR, dataptr);
5144 ahd_outb(ahd, HCNT + 2, resid >> 16);
5145 ahd_outb(ahd, HCNT + 1, resid >> 8);
5146 ahd_outb(ahd, HCNT, resid);
5147}
5148
5149
5150
5151
5152static void
5153ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
5154 u_int lun, cam_status status, char *message,
5155 int verbose_level)
5156{
5157#ifdef AHD_TARGET_MODE
5158 struct ahd_tmode_tstate* tstate;
5159#endif
5160 int found;
5161
5162 found = ahd_abort_scbs(ahd, devinfo->target, devinfo->channel,
5163 lun, SCB_LIST_NULL, devinfo->role,
5164 status);
5165
5166#ifdef AHD_TARGET_MODE
5167
5168
5169
5170
5171 tstate = ahd->enabled_targets[devinfo->our_scsiid];
5172 if (tstate != NULL) {
5173 u_int cur_lun;
5174 u_int max_lun;
5175
5176 if (lun != CAM_LUN_WILDCARD) {
5177 cur_lun = 0;
5178 max_lun = AHD_NUM_LUNS - 1;
5179 } else {
5180 cur_lun = lun;
5181 max_lun = lun;
5182 }
5183 for (;cur_lun <= max_lun; cur_lun++) {
5184 struct ahd_tmode_lstate* lstate;
5185
5186 lstate = tstate->enabled_luns[cur_lun];
5187 if (lstate == NULL)
5188 continue;
5189
5190 ahd_queue_lstate_event(ahd, lstate, devinfo->our_scsiid,
5191 MSG_BUS_DEV_RESET, 0);
5192 ahd_send_lstate_events(ahd, lstate);
5193 }
5194 }
5195#endif
5196
5197
5198
5199
5200 ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,
5201 AHD_TRANS_CUR, TRUE);
5202 ahd_set_syncrate(ahd, devinfo, 0, 0,
5203 0, AHD_TRANS_CUR,
5204 TRUE);
5205
5206 if (status != CAM_SEL_TIMEOUT)
5207 ahd_send_async(ahd, devinfo->channel, devinfo->target,
5208 CAM_LUN_WILDCARD, AC_SENT_BDR);
5209
5210 if (message != NULL && bootverbose)
5211 printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd),
5212 message, devinfo->channel, devinfo->target, found);
5213}
5214
5215#ifdef AHD_TARGET_MODE
5216static void
5217ahd_setup_target_msgin(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
5218 struct scb *scb)
5219{
5220
5221
5222
5223
5224
5225
5226 ahd->msgout_index = 0;
5227 ahd->msgout_len = 0;
5228
5229 if (scb != NULL && (scb->flags & SCB_AUTO_NEGOTIATE) != 0)
5230 ahd_build_transfer_msg(ahd, devinfo);
5231 else
5232 panic("ahd_intr: AWAITING target message with no message");
5233
5234 ahd->msgout_index = 0;
5235 ahd->msg_type = MSG_TYPE_TARGET_MSGIN;
5236}
5237#endif
5238
5239static u_int
5240ahd_sglist_size(struct ahd_softc *ahd)
5241{
5242 bus_size_t list_size;
5243
5244 list_size = sizeof(struct ahd_dma_seg) * AHD_NSEG;
5245 if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
5246 list_size = sizeof(struct ahd_dma64_seg) * AHD_NSEG;
5247 return (list_size);
5248}
5249
5250
5251
5252
5253
5254
5255
5256static u_int
5257ahd_sglist_allocsize(struct ahd_softc *ahd)
5258{
5259 bus_size_t sg_list_increment;
5260 bus_size_t sg_list_size;
5261 bus_size_t max_list_size;
5262 bus_size_t best_list_size;
5263
5264
5265 sg_list_increment = ahd_sglist_size(ahd);
5266 sg_list_size = sg_list_increment;
5267
5268
5269 while ((sg_list_size + sg_list_increment) <= PAGE_SIZE)
5270 sg_list_size += sg_list_increment;
5271
5272
5273
5274
5275
5276 best_list_size = sg_list_size;
5277 max_list_size = roundup(sg_list_increment, PAGE_SIZE);
5278 if (max_list_size < 4 * PAGE_SIZE)
5279 max_list_size = 4 * PAGE_SIZE;
5280 if (max_list_size > (AHD_SCB_MAX_ALLOC * sg_list_increment))
5281 max_list_size = (AHD_SCB_MAX_ALLOC * sg_list_increment);
5282 while ((sg_list_size + sg_list_increment) <= max_list_size
5283 && (sg_list_size % PAGE_SIZE) != 0) {
5284 bus_size_t new_mod;
5285 bus_size_t best_mod;
5286
5287 sg_list_size += sg_list_increment;
5288 new_mod = sg_list_size % PAGE_SIZE;
5289 best_mod = best_list_size % PAGE_SIZE;
5290 if (new_mod > best_mod || new_mod == 0) {
5291 best_list_size = sg_list_size;
5292 }
5293 }
5294 return (best_list_size);
5295}
5296
5297
5298
5299
5300
5301struct ahd_softc *
5302ahd_alloc(void *platform_arg, char *name)
5303{
5304 struct ahd_softc *ahd;
5305
5306#ifndef __FreeBSD__
5307 ahd = malloc(sizeof(*ahd), M_DEVBUF, M_NOWAIT);
5308 if (!ahd) {
5309 printf("aic7xxx: cannot malloc softc!\n");
5310 free(name, M_DEVBUF);
5311 return NULL;
5312 }
5313#else
5314 ahd = device_get_softc((device_t)platform_arg);
5315#endif
5316 memset(ahd, 0, sizeof(*ahd));
5317 ahd->seep_config = malloc(sizeof(*ahd->seep_config),
5318 M_DEVBUF, M_NOWAIT);
5319 if (ahd->seep_config == NULL) {
5320#ifndef __FreeBSD__
5321 free(ahd, M_DEVBUF);
5322#endif
5323 free(name, M_DEVBUF);
5324 return (NULL);
5325 }
5326 LIST_INIT(&ahd->pending_scbs);
5327
5328 ahd->name = name;
5329 ahd->unit = -1;
5330 ahd->description = NULL;
5331 ahd->bus_description = NULL;
5332 ahd->channel = 'A';
5333 ahd->chip = AHD_NONE;
5334 ahd->features = AHD_FENONE;
5335 ahd->bugs = AHD_BUGNONE;
5336 ahd->flags = AHD_SPCHK_ENB_A|AHD_RESET_BUS_A|AHD_TERM_ENB_A
5337 | AHD_EXTENDED_TRANS_A|AHD_STPWLEVEL_A;
5338 ahd_timer_init(&ahd->reset_timer);
5339 ahd_timer_init(&ahd->stat_timer);
5340 ahd->int_coalescing_timer = AHD_INT_COALESCING_TIMER_DEFAULT;
5341 ahd->int_coalescing_maxcmds = AHD_INT_COALESCING_MAXCMDS_DEFAULT;
5342 ahd->int_coalescing_mincmds = AHD_INT_COALESCING_MINCMDS_DEFAULT;
5343 ahd->int_coalescing_threshold = AHD_INT_COALESCING_THRESHOLD_DEFAULT;
5344 ahd->int_coalescing_stop_threshold =
5345 AHD_INT_COALESCING_STOP_THRESHOLD_DEFAULT;
5346
5347 if (ahd_platform_alloc(ahd, platform_arg) != 0) {
5348 ahd_free(ahd);
5349 ahd = NULL;
5350 }
5351#ifdef AHD_DEBUG
5352 if ((ahd_debug & AHD_SHOW_MEMORY) != 0) {
5353 printf("%s: scb size = 0x%x, hscb size = 0x%x\n",
5354 ahd_name(ahd), (u_int)sizeof(struct scb),
5355 (u_int)sizeof(struct hardware_scb));
5356 }
5357#endif
5358 return (ahd);
5359}
5360
5361int
5362ahd_softc_init(struct ahd_softc *ahd)
5363{
5364
5365 ahd->unpause = 0;
5366 ahd->pause = PAUSE;
5367 return (0);
5368}
5369
5370void
5371ahd_set_unit(struct ahd_softc *ahd, int unit)
5372{
5373 ahd->unit = unit;
5374}
5375
5376void
5377ahd_set_name(struct ahd_softc *ahd, char *name)
5378{
5379 if (ahd->name != NULL)
5380 free(ahd->name, M_DEVBUF);
5381 ahd->name = name;
5382}
5383
5384void
5385ahd_free(struct ahd_softc *ahd)
5386{
5387 int i;
5388
5389 switch (ahd->init_level) {
5390 default:
5391 case 5:
5392 ahd_shutdown(ahd);
5393
5394 case 4:
5395 ahd_dmamap_unload(ahd, ahd->shared_data_dmat,
5396 ahd->shared_data_map.dmamap);
5397
5398 case 3:
5399 ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo,
5400 ahd->shared_data_map.dmamap);
5401 ahd_dmamap_destroy(ahd, ahd->shared_data_dmat,
5402 ahd->shared_data_map.dmamap);
5403
5404 case 2:
5405 ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat);
5406 case 1:
5407#ifndef __linux__
5408 ahd_dma_tag_destroy(ahd, ahd->buffer_dmat);
5409#endif
5410 break;
5411 case 0:
5412 break;
5413 }
5414
5415#ifndef __linux__
5416 ahd_dma_tag_destroy(ahd, ahd->parent_dmat);
5417#endif
5418 ahd_platform_free(ahd);
5419 ahd_fini_scbdata(ahd);
5420 for (i = 0; i < AHD_NUM_TARGETS; i++) {
5421 struct ahd_tmode_tstate *tstate;
5422
5423 tstate = ahd->enabled_targets[i];
5424 if (tstate != NULL) {
5425#ifdef AHD_TARGET_MODE
5426 int j;
5427
5428 for (j = 0; j < AHD_NUM_LUNS; j++) {
5429 struct ahd_tmode_lstate *lstate;
5430
5431 lstate = tstate->enabled_luns[j];
5432 if (lstate != NULL) {
5433 xpt_free_path(lstate->path);
5434 free(lstate, M_DEVBUF);
5435 }
5436 }
5437#endif
5438 free(tstate, M_DEVBUF);
5439 }
5440 }
5441#ifdef AHD_TARGET_MODE
5442 if (ahd->black_hole != NULL) {
5443 xpt_free_path(ahd->black_hole->path);
5444 free(ahd->black_hole, M_DEVBUF);
5445 }
5446#endif
5447 if (ahd->name != NULL)
5448 free(ahd->name, M_DEVBUF);
5449 if (ahd->seep_config != NULL)
5450 free(ahd->seep_config, M_DEVBUF);
5451 if (ahd->saved_stack != NULL)
5452 free(ahd->saved_stack, M_DEVBUF);
5453#ifndef __FreeBSD__
5454 free(ahd, M_DEVBUF);
5455#endif
5456 return;
5457}
5458
5459static void
5460ahd_shutdown(void *arg)
5461{
5462 struct ahd_softc *ahd;
5463
5464 ahd = (struct ahd_softc *)arg;
5465
5466
5467
5468
5469 ahd_timer_stop(&ahd->reset_timer);
5470 ahd_timer_stop(&ahd->stat_timer);
5471
5472
5473 ahd_reset(ahd, FALSE);
5474}
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485int
5486ahd_reset(struct ahd_softc *ahd, int reinit)
5487{
5488 u_int sxfrctl1;
5489 int wait;
5490 uint32_t cmd;
5491
5492
5493
5494
5495
5496
5497 ahd_pause(ahd);
5498 ahd_update_modes(ahd);
5499 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
5500 sxfrctl1 = ahd_inb(ahd, SXFRCTL1);
5501
5502 cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, 2);
5503 if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) {
5504 uint32_t mod_cmd;
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515 mod_cmd = cmd & ~(PCIM_CMD_PERRESPEN|PCIM_CMD_SERRESPEN);
5516 ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
5517 mod_cmd, 2);
5518 }
5519 ahd_outb(ahd, HCNTRL, CHIPRST | ahd->pause);
5520
5521
5522
5523
5524
5525
5526
5527 wait = 1000;
5528 do {
5529 ahd_delay(1000);
5530 } while (--wait && !(ahd_inb(ahd, HCNTRL) & CHIPRSTACK));
5531
5532 if (wait == 0) {
5533 printf("%s: WARNING - Failed chip reset! "
5534 "Trying to initialize anyway.\n", ahd_name(ahd));
5535 }
5536 ahd_outb(ahd, HCNTRL, ahd->pause);
5537
5538 if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) {
5539
5540
5541
5542
5543 ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
5544 0xFF, 1);
5545 ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
5546 cmd, 2);
5547 }
5548
5549
5550
5551
5552
5553
5554
5555 ahd_known_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
5556 ahd_outb(ahd, MODE_PTR,
5557 ahd_build_mode_state(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI));
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567 ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN);
5568 ahd_outb(ahd, SXFRCTL1, sxfrctl1);
5569
5570
5571 ahd->features &= ~AHD_WIDE;
5572 if ((ahd_inb(ahd, SBLKCTL) & SELWIDE) != 0)
5573 ahd->features |= AHD_WIDE;
5574
5575
5576
5577
5578
5579 if (reinit != 0)
5580 ahd_chip_init(ahd);
5581
5582 return (0);
5583}
5584
5585
5586
5587
5588static int
5589ahd_probe_scbs(struct ahd_softc *ahd) {
5590 int i;
5591
5592 AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
5593 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
5594 for (i = 0; i < AHD_SCB_MAX; i++) {
5595 int j;
5596
5597 ahd_set_scbptr(ahd, i);
5598 ahd_outw(ahd, SCB_BASE, i);
5599 for (j = 2; j < 64; j++)
5600 ahd_outb(ahd, SCB_BASE+j, 0);
5601
5602 ahd_outb(ahd, SCB_CONTROL, MK_MESSAGE);
5603 if (ahd_inw_scbram(ahd, SCB_BASE) != i)
5604 break;
5605 ahd_set_scbptr(ahd, 0);
5606 if (ahd_inw_scbram(ahd, SCB_BASE) != 0)
5607 break;
5608 }
5609 return (i);
5610}
5611
5612static void
5613ahd_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
5614{
5615 dma_addr_t *baddr;
5616
5617 baddr = (dma_addr_t *)arg;
5618 *baddr = segs->ds_addr;
5619}
5620
5621static void
5622ahd_initialize_hscbs(struct ahd_softc *ahd)
5623{
5624 int i;
5625
5626 for (i = 0; i < ahd->scb_data.maxhscbs; i++) {
5627 ahd_set_scbptr(ahd, i);
5628
5629
5630 ahd_outb(ahd, SCB_CONTROL, 0);
5631
5632
5633 ahd_outw(ahd, SCB_NEXT, SCB_LIST_NULL);
5634 }
5635}
5636
5637static int
5638ahd_init_scbdata(struct ahd_softc *ahd)
5639{
5640 struct scb_data *scb_data;
5641 int i;
5642
5643 scb_data = &ahd->scb_data;
5644 TAILQ_INIT(&scb_data->free_scbs);
5645 for (i = 0; i < AHD_NUM_TARGETS * AHD_NUM_LUNS_NONPKT; i++)
5646 LIST_INIT(&scb_data->free_scb_lists[i]);
5647 LIST_INIT(&scb_data->any_dev_free_scb_list);
5648 SLIST_INIT(&scb_data->hscb_maps);
5649 SLIST_INIT(&scb_data->sg_maps);
5650 SLIST_INIT(&scb_data->sense_maps);
5651
5652
5653 scb_data->maxhscbs = ahd_probe_scbs(ahd);
5654 if (scb_data->maxhscbs == 0) {
5655 printf("%s: No SCB space found\n", ahd_name(ahd));
5656 return (ENXIO);
5657 }
5658
5659 ahd_initialize_hscbs(ahd);
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672 if (ahd_dma_tag_create(ahd, ahd->parent_dmat, 1,
5673 BUS_SPACE_MAXADDR_32BIT + 1,
5674 BUS_SPACE_MAXADDR_32BIT,
5675 BUS_SPACE_MAXADDR,
5676 NULL, NULL,
5677 PAGE_SIZE, 1,
5678 BUS_SPACE_MAXSIZE_32BIT,
5679 0, &scb_data->hscb_dmat) != 0) {
5680 goto error_exit;
5681 }
5682
5683 scb_data->init_level++;
5684
5685
5686 if (ahd_dma_tag_create(ahd, ahd->parent_dmat, 8,
5687 BUS_SPACE_MAXADDR_32BIT + 1,
5688 BUS_SPACE_MAXADDR_32BIT,
5689 BUS_SPACE_MAXADDR,
5690 NULL, NULL,
5691 ahd_sglist_allocsize(ahd), 1,
5692 BUS_SPACE_MAXSIZE_32BIT,
5693 0, &scb_data->sg_dmat) != 0) {
5694 goto error_exit;
5695 }
5696#ifdef AHD_DEBUG
5697 if ((ahd_debug & AHD_SHOW_MEMORY) != 0)
5698 printf("%s: ahd_sglist_allocsize = 0x%x\n", ahd_name(ahd),
5699 ahd_sglist_allocsize(ahd));
5700#endif
5701
5702 scb_data->init_level++;
5703
5704
5705 if (ahd_dma_tag_create(ahd, ahd->parent_dmat, 1,
5706 BUS_SPACE_MAXADDR_32BIT + 1,
5707 BUS_SPACE_MAXADDR_32BIT,
5708 BUS_SPACE_MAXADDR,
5709 NULL, NULL,
5710 PAGE_SIZE, 1,
5711 BUS_SPACE_MAXSIZE_32BIT,
5712 0, &scb_data->sense_dmat) != 0) {
5713 goto error_exit;
5714 }
5715
5716 scb_data->init_level++;
5717
5718
5719 ahd_alloc_scbs(ahd);
5720
5721 if (scb_data->numscbs == 0) {
5722 printf("%s: ahd_init_scbdata - "
5723 "Unable to allocate initial scbs\n",
5724 ahd_name(ahd));
5725 goto error_exit;
5726 }
5727
5728
5729
5730
5731 return (0);
5732
5733error_exit:
5734
5735 return (ENOMEM);
5736}
5737
5738static struct scb *
5739ahd_find_scb_by_tag(struct ahd_softc *ahd, u_int tag)
5740{
5741 struct scb *scb;
5742
5743
5744
5745
5746 LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
5747 if (SCB_GET_TAG(scb) == tag)
5748 return (scb);
5749 }
5750
5751
5752
5753
5754 TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) {
5755 struct scb *list_scb;
5756
5757 list_scb = scb;
5758 do {
5759 if (SCB_GET_TAG(list_scb) == tag)
5760 return (list_scb);
5761 list_scb = LIST_NEXT(list_scb, collision_links);
5762 } while (list_scb);
5763 }
5764
5765
5766
5767
5768 LIST_FOREACH(scb, &ahd->scb_data.any_dev_free_scb_list, links.le) {
5769 if (SCB_GET_TAG(scb) == tag)
5770 return (scb);
5771 }
5772
5773 return (NULL);
5774}
5775
5776static void
5777ahd_fini_scbdata(struct ahd_softc *ahd)
5778{
5779 struct scb_data *scb_data;
5780
5781 scb_data = &ahd->scb_data;
5782 if (scb_data == NULL)
5783 return;
5784
5785 switch (scb_data->init_level) {
5786 default:
5787 case 7:
5788 {
5789 struct map_node *sns_map;
5790
5791 while ((sns_map = SLIST_FIRST(&scb_data->sense_maps)) != NULL) {
5792 SLIST_REMOVE_HEAD(&scb_data->sense_maps, links);
5793 ahd_dmamap_unload(ahd, scb_data->sense_dmat,
5794 sns_map->dmamap);
5795 ahd_dmamem_free(ahd, scb_data->sense_dmat,
5796 sns_map->vaddr, sns_map->dmamap);
5797 free(sns_map, M_DEVBUF);
5798 }
5799 ahd_dma_tag_destroy(ahd, scb_data->sense_dmat);
5800
5801 }
5802 case 6:
5803 {
5804 struct map_node *sg_map;
5805
5806 while ((sg_map = SLIST_FIRST(&scb_data->sg_maps)) != NULL) {
5807 SLIST_REMOVE_HEAD(&scb_data->sg_maps, links);
5808 ahd_dmamap_unload(ahd, scb_data->sg_dmat,
5809 sg_map->dmamap);
5810 ahd_dmamem_free(ahd, scb_data->sg_dmat,
5811 sg_map->vaddr, sg_map->dmamap);
5812 free(sg_map, M_DEVBUF);
5813 }
5814 ahd_dma_tag_destroy(ahd, scb_data->sg_dmat);
5815
5816 }
5817 case 5:
5818 {
5819 struct map_node *hscb_map;
5820
5821 while ((hscb_map = SLIST_FIRST(&scb_data->hscb_maps)) != NULL) {
5822 SLIST_REMOVE_HEAD(&scb_data->hscb_maps, links);
5823 ahd_dmamap_unload(ahd, scb_data->hscb_dmat,
5824 hscb_map->dmamap);
5825 ahd_dmamem_free(ahd, scb_data->hscb_dmat,
5826 hscb_map->vaddr, hscb_map->dmamap);
5827 free(hscb_map, M_DEVBUF);
5828 }
5829 ahd_dma_tag_destroy(ahd, scb_data->hscb_dmat);
5830
5831 }
5832 case 4:
5833 case 3:
5834 case 2:
5835 case 1:
5836 case 0:
5837 break;
5838 }
5839}
5840
5841
5842
5843
5844
5845static void
5846ahd_setup_iocell_workaround(struct ahd_softc *ahd)
5847{
5848 ahd_mode_state saved_modes;
5849
5850 saved_modes = ahd_save_modes(ahd);
5851 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
5852 ahd_outb(ahd, DSPDATACTL, ahd_inb(ahd, DSPDATACTL)
5853 | BYPASSENAB | RCVROFFSTDIS | XMITOFFSTDIS);
5854 ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) | (ENSELDO|ENSELDI));
5855#ifdef AHD_DEBUG
5856 if ((ahd_debug & AHD_SHOW_MISC) != 0)
5857 printf("%s: Setting up iocell workaround\n", ahd_name(ahd));
5858#endif
5859 ahd_restore_modes(ahd, saved_modes);
5860 ahd->flags &= ~AHD_HAD_FIRST_SEL;
5861}
5862
5863static void
5864ahd_iocell_first_selection(struct ahd_softc *ahd)
5865{
5866 ahd_mode_state saved_modes;
5867 u_int sblkctl;
5868
5869 if ((ahd->flags & AHD_HAD_FIRST_SEL) != 0)
5870 return;
5871 saved_modes = ahd_save_modes(ahd);
5872 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
5873 sblkctl = ahd_inb(ahd, SBLKCTL);
5874 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
5875#ifdef AHD_DEBUG
5876 if ((ahd_debug & AHD_SHOW_MISC) != 0)
5877 printf("%s: iocell first selection\n", ahd_name(ahd));
5878#endif
5879 if ((sblkctl & ENAB40) != 0) {
5880 ahd_outb(ahd, DSPDATACTL,
5881 ahd_inb(ahd, DSPDATACTL) & ~BYPASSENAB);
5882#ifdef AHD_DEBUG
5883 if ((ahd_debug & AHD_SHOW_MISC) != 0)
5884 printf("%s: BYPASS now disabled\n", ahd_name(ahd));
5885#endif
5886 }
5887 ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) & ~(ENSELDO|ENSELDI));
5888 ahd_outb(ahd, CLRINT, CLRSCSIINT);
5889 ahd_restore_modes(ahd, saved_modes);
5890 ahd->flags |= AHD_HAD_FIRST_SEL;
5891}
5892
5893
5894static void
5895ahd_add_col_list(struct ahd_softc *ahd, struct scb *scb, u_int col_idx)
5896{
5897 struct scb_list *free_list;
5898 struct scb_tailq *free_tailq;
5899 struct scb *first_scb;
5900
5901 scb->flags |= SCB_ON_COL_LIST;
5902 AHD_SET_SCB_COL_IDX(scb, col_idx);
5903 free_list = &ahd->scb_data.free_scb_lists[col_idx];
5904 free_tailq = &ahd->scb_data.free_scbs;
5905 first_scb = LIST_FIRST(free_list);
5906 if (first_scb != NULL) {
5907 LIST_INSERT_AFTER(first_scb, scb, collision_links);
5908 } else {
5909 LIST_INSERT_HEAD(free_list, scb, collision_links);
5910 TAILQ_INSERT_TAIL(free_tailq, scb, links.tqe);
5911 }
5912}
5913
5914static void
5915ahd_rem_col_list(struct ahd_softc *ahd, struct scb *scb)
5916{
5917 struct scb_list *free_list;
5918 struct scb_tailq *free_tailq;
5919 struct scb *first_scb;
5920 u_int col_idx;
5921
5922 scb->flags &= ~SCB_ON_COL_LIST;
5923 col_idx = AHD_GET_SCB_COL_IDX(ahd, scb);
5924 free_list = &ahd->scb_data.free_scb_lists[col_idx];
5925 free_tailq = &ahd->scb_data.free_scbs;
5926 first_scb = LIST_FIRST(free_list);
5927 if (first_scb == scb) {
5928 struct scb *next_scb;
5929
5930
5931
5932
5933
5934
5935 next_scb = LIST_NEXT(scb, collision_links);
5936 if (next_scb != NULL) {
5937 TAILQ_INSERT_AFTER(free_tailq, scb,
5938 next_scb, links.tqe);
5939 }
5940 TAILQ_REMOVE(free_tailq, scb, links.tqe);
5941 }
5942 LIST_REMOVE(scb, collision_links);
5943}
5944
5945
5946
5947
5948struct scb *
5949ahd_get_scb(struct ahd_softc *ahd, u_int col_idx)
5950{
5951 struct scb *scb;
5952 int tries;
5953
5954 tries = 0;
5955look_again:
5956 TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) {
5957 if (AHD_GET_SCB_COL_IDX(ahd, scb) != col_idx) {
5958 ahd_rem_col_list(ahd, scb);
5959 goto found;
5960 }
5961 }
5962 if ((scb = LIST_FIRST(&ahd->scb_data.any_dev_free_scb_list)) == NULL) {
5963
5964 if (tries++ != 0)
5965 return (NULL);
5966 ahd_alloc_scbs(ahd);
5967 goto look_again;
5968 }
5969 LIST_REMOVE(scb, links.le);
5970 if (col_idx != AHD_NEVER_COL_IDX
5971 && (scb->col_scb != NULL)
5972 && (scb->col_scb->flags & SCB_ACTIVE) == 0) {
5973 LIST_REMOVE(scb->col_scb, links.le);
5974 ahd_add_col_list(ahd, scb->col_scb, col_idx);
5975 }
5976found:
5977 scb->flags |= SCB_ACTIVE;
5978 return (scb);
5979}
5980
5981
5982
5983
5984void
5985ahd_free_scb(struct ahd_softc *ahd, struct scb *scb)
5986{
5987
5988
5989 scb->flags = SCB_FLAG_NONE;
5990 scb->hscb->control = 0;
5991 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = NULL;
5992
5993 if (scb->col_scb == NULL) {
5994
5995
5996
5997
5998 LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,
5999 scb, links.le);
6000 } else if ((scb->col_scb->flags & SCB_ON_COL_LIST) != 0) {
6001
6002
6003
6004
6005
6006
6007 ahd_rem_col_list(ahd, scb->col_scb);
6008 LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,
6009 scb, links.le);
6010 LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,
6011 scb->col_scb, links.le);
6012 } else if ((scb->col_scb->flags
6013 & (SCB_PACKETIZED|SCB_ACTIVE)) == SCB_ACTIVE
6014 && (scb->col_scb->hscb->control & TAG_ENB) != 0) {
6015
6016
6017
6018
6019
6020
6021 ahd_add_col_list(ahd, scb,
6022 AHD_GET_SCB_COL_IDX(ahd, scb->col_scb));
6023 } else {
6024
6025
6026
6027
6028
6029
6030 LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,
6031 scb, links.le);
6032 }
6033
6034 ahd_platform_scb_free(ahd, scb);
6035}
6036
6037static void
6038ahd_alloc_scbs(struct ahd_softc *ahd)
6039{
6040 struct scb_data *scb_data;
6041 struct scb *next_scb;
6042 struct hardware_scb *hscb;
6043 struct map_node *hscb_map;
6044 struct map_node *sg_map;
6045 struct map_node *sense_map;
6046 uint8_t *segs;
6047 uint8_t *sense_data;
6048 dma_addr_t hscb_busaddr;
6049 dma_addr_t sg_busaddr;
6050 dma_addr_t sense_busaddr;
6051 int newcount;
6052 int i;
6053
6054 scb_data = &ahd->scb_data;
6055 if (scb_data->numscbs >= AHD_SCB_MAX_ALLOC)
6056
6057 return;
6058
6059 if (scb_data->scbs_left != 0) {
6060 int offset;
6061
6062 offset = (PAGE_SIZE / sizeof(*hscb)) - scb_data->scbs_left;
6063 hscb_map = SLIST_FIRST(&scb_data->hscb_maps);
6064 hscb = &((struct hardware_scb *)hscb_map->vaddr)[offset];
6065 hscb_busaddr = hscb_map->physaddr + (offset * sizeof(*hscb));
6066 } else {
6067 hscb_map = malloc(sizeof(*hscb_map), M_DEVBUF, M_NOWAIT);
6068
6069 if (hscb_map == NULL)
6070 return;
6071
6072
6073 if (ahd_dmamem_alloc(ahd, scb_data->hscb_dmat,
6074 (void **)&hscb_map->vaddr,
6075 BUS_DMA_NOWAIT, &hscb_map->dmamap) != 0) {
6076 free(hscb_map, M_DEVBUF);
6077 return;
6078 }
6079
6080 SLIST_INSERT_HEAD(&scb_data->hscb_maps, hscb_map, links);
6081
6082 ahd_dmamap_load(ahd, scb_data->hscb_dmat, hscb_map->dmamap,
6083 hscb_map->vaddr, PAGE_SIZE, ahd_dmamap_cb,
6084 &hscb_map->physaddr, 0);
6085
6086 hscb = (struct hardware_scb *)hscb_map->vaddr;
6087 hscb_busaddr = hscb_map->physaddr;
6088 scb_data->scbs_left = PAGE_SIZE / sizeof(*hscb);
6089 }
6090
6091 if (scb_data->sgs_left != 0) {
6092 int offset;
6093
6094 offset = ((ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd))
6095 - scb_data->sgs_left) * ahd_sglist_size(ahd);
6096 sg_map = SLIST_FIRST(&scb_data->sg_maps);
6097 segs = sg_map->vaddr + offset;
6098 sg_busaddr = sg_map->physaddr + offset;
6099 } else {
6100 sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);
6101
6102 if (sg_map == NULL)
6103 return;
6104
6105
6106 if (ahd_dmamem_alloc(ahd, scb_data->sg_dmat,
6107 (void **)&sg_map->vaddr,
6108 BUS_DMA_NOWAIT, &sg_map->dmamap) != 0) {
6109 free(sg_map, M_DEVBUF);
6110 return;
6111 }
6112
6113 SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links);
6114
6115 ahd_dmamap_load(ahd, scb_data->sg_dmat, sg_map->dmamap,
6116 sg_map->vaddr, ahd_sglist_allocsize(ahd),
6117 ahd_dmamap_cb, &sg_map->physaddr, 0);
6118
6119 segs = sg_map->vaddr;
6120 sg_busaddr = sg_map->physaddr;
6121 scb_data->sgs_left =
6122 ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd);
6123#ifdef AHD_DEBUG
6124 if (ahd_debug & AHD_SHOW_MEMORY)
6125 printf("Mapped SG data\n");
6126#endif
6127 }
6128
6129 if (scb_data->sense_left != 0) {
6130 int offset;
6131
6132 offset = PAGE_SIZE - (AHD_SENSE_BUFSIZE * scb_data->sense_left);
6133 sense_map = SLIST_FIRST(&scb_data->sense_maps);
6134 sense_data = sense_map->vaddr + offset;
6135 sense_busaddr = sense_map->physaddr + offset;
6136 } else {
6137 sense_map = malloc(sizeof(*sense_map), M_DEVBUF, M_NOWAIT);
6138
6139 if (sense_map == NULL)
6140 return;
6141
6142
6143 if (ahd_dmamem_alloc(ahd, scb_data->sense_dmat,
6144 (void **)&sense_map->vaddr,
6145 BUS_DMA_NOWAIT, &sense_map->dmamap) != 0) {
6146 free(sense_map, M_DEVBUF);
6147 return;
6148 }
6149
6150 SLIST_INSERT_HEAD(&scb_data->sense_maps, sense_map, links);
6151
6152 ahd_dmamap_load(ahd, scb_data->sense_dmat, sense_map->dmamap,
6153 sense_map->vaddr, PAGE_SIZE, ahd_dmamap_cb,
6154 &sense_map->physaddr, 0);
6155
6156 sense_data = sense_map->vaddr;
6157 sense_busaddr = sense_map->physaddr;
6158 scb_data->sense_left = PAGE_SIZE / AHD_SENSE_BUFSIZE;
6159#ifdef AHD_DEBUG
6160 if (ahd_debug & AHD_SHOW_MEMORY)
6161 printf("Mapped sense data\n");
6162#endif
6163 }
6164
6165 newcount = min(scb_data->sense_left, scb_data->scbs_left);
6166 newcount = min(newcount, scb_data->sgs_left);
6167 newcount = min(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs));
6168 for (i = 0; i < newcount; i++) {
6169 struct scb_platform_data *pdata;
6170 u_int col_tag;
6171#ifndef __linux__
6172 int error;
6173#endif
6174
6175 next_scb = (struct scb *)malloc(sizeof(*next_scb),
6176 M_DEVBUF, M_NOWAIT);
6177 if (next_scb == NULL)
6178 break;
6179
6180 pdata = (struct scb_platform_data *)malloc(sizeof(*pdata),
6181 M_DEVBUF, M_NOWAIT);
6182 if (pdata == NULL) {
6183 free(next_scb, M_DEVBUF);
6184 break;
6185 }
6186 next_scb->platform_data = pdata;
6187 next_scb->hscb_map = hscb_map;
6188 next_scb->sg_map = sg_map;
6189 next_scb->sense_map = sense_map;
6190 next_scb->sg_list = segs;
6191 next_scb->sense_data = sense_data;
6192 next_scb->sense_busaddr = sense_busaddr;
6193 memset(hscb, 0, sizeof(*hscb));
6194 next_scb->hscb = hscb;
6195 hscb->hscb_busaddr = ahd_htole32(hscb_busaddr);
6196
6197
6198
6199
6200
6201 next_scb->sg_list_busaddr = sg_busaddr;
6202 if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
6203 next_scb->sg_list_busaddr
6204 += sizeof(struct ahd_dma64_seg);
6205 else
6206 next_scb->sg_list_busaddr += sizeof(struct ahd_dma_seg);
6207 next_scb->ahd_softc = ahd;
6208 next_scb->flags = SCB_FLAG_NONE;
6209#ifndef __linux__
6210 error = ahd_dmamap_create(ahd, ahd->buffer_dmat, 0,
6211 &next_scb->dmamap);
6212 if (error != 0) {
6213 free(next_scb, M_DEVBUF);
6214 free(pdata, M_DEVBUF);
6215 break;
6216 }
6217#endif
6218 next_scb->hscb->tag = ahd_htole16(scb_data->numscbs);
6219 col_tag = scb_data->numscbs ^ 0x100;
6220 next_scb->col_scb = ahd_find_scb_by_tag(ahd, col_tag);
6221 if (next_scb->col_scb != NULL)
6222 next_scb->col_scb->col_scb = next_scb;
6223 ahd_free_scb(ahd, next_scb);
6224 hscb++;
6225 hscb_busaddr += sizeof(*hscb);
6226 segs += ahd_sglist_size(ahd);
6227 sg_busaddr += ahd_sglist_size(ahd);
6228 sense_data += AHD_SENSE_BUFSIZE;
6229 sense_busaddr += AHD_SENSE_BUFSIZE;
6230 scb_data->numscbs++;
6231 scb_data->sense_left--;
6232 scb_data->scbs_left--;
6233 scb_data->sgs_left--;
6234 }
6235}
6236
6237void
6238ahd_controller_info(struct ahd_softc *ahd, char *buf)
6239{
6240 const char *speed;
6241 const char *type;
6242 int len;
6243
6244 len = sprintf(buf, "%s: ", ahd_chip_names[ahd->chip & AHD_CHIPID_MASK]);
6245 buf += len;
6246
6247 speed = "Ultra320 ";
6248 if ((ahd->features & AHD_WIDE) != 0) {
6249 type = "Wide ";
6250 } else {
6251 type = "Single ";
6252 }
6253 len = sprintf(buf, "%s%sChannel %c, SCSI Id=%d, ",
6254 speed, type, ahd->channel, ahd->our_id);
6255 buf += len;
6256
6257 sprintf(buf, "%s, %d SCBs", ahd->bus_description,
6258 ahd->scb_data.maxhscbs);
6259}
6260
6261static const char *channel_strings[] = {
6262 "Primary Low",
6263 "Primary High",
6264 "Secondary Low",
6265 "Secondary High"
6266};
6267
6268static const char *termstat_strings[] = {
6269 "Terminated Correctly",
6270 "Over Terminated",
6271 "Under Terminated",
6272 "Not Configured"
6273};
6274
6275
6276
6277
6278int
6279ahd_init(struct ahd_softc *ahd)
6280{
6281 uint8_t *next_vaddr;
6282 dma_addr_t next_baddr;
6283 size_t driver_data_size;
6284 int i;
6285 int error;
6286 u_int warn_user;
6287 uint8_t current_sensing;
6288 uint8_t fstat;
6289
6290 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
6291
6292 ahd->stack_size = ahd_probe_stack_size(ahd);
6293 ahd->saved_stack = malloc(ahd->stack_size * sizeof(uint16_t),
6294 M_DEVBUF, M_NOWAIT);
6295 if (ahd->saved_stack == NULL)
6296 return (ENOMEM);
6297
6298
6299
6300
6301
6302 if (sizeof(struct hardware_scb) != 64)
6303 panic("Hardware SCB size is incorrect");
6304
6305#ifdef AHD_DEBUG
6306 if ((ahd_debug & AHD_DEBUG_SEQUENCER) != 0)
6307 ahd->flags |= AHD_SEQUENCER_DEBUG;
6308#endif
6309
6310
6311
6312
6313 ahd->flags |= AHD_INITIATORROLE;
6314
6315
6316
6317
6318 if ((AHD_TMODE_ENABLE & (0x1 << ahd->unit)) == 0)
6319 ahd->features &= ~AHD_TARGETMODE;
6320
6321#ifndef __linux__
6322
6323 if (ahd_dma_tag_create(ahd, ahd->parent_dmat, 1,
6324 BUS_SPACE_MAXADDR_32BIT + 1,
6325 ahd->flags & AHD_39BIT_ADDRESSING
6326 ? (dma_addr_t)0x7FFFFFFFFFULL
6327 : BUS_SPACE_MAXADDR_32BIT,
6328 BUS_SPACE_MAXADDR,
6329 NULL, NULL,
6330 (AHD_NSEG - 1) * PAGE_SIZE,
6331 AHD_NSEG,
6332 AHD_MAXTRANSFER_SIZE,
6333 BUS_DMA_ALLOCNOW,
6334 &ahd->buffer_dmat) != 0) {
6335 return (ENOMEM);
6336 }
6337#endif
6338
6339 ahd->init_level++;
6340
6341
6342
6343
6344
6345
6346
6347
6348 driver_data_size = AHD_SCB_MAX * sizeof(*ahd->qoutfifo)
6349 + sizeof(struct hardware_scb);
6350 if ((ahd->features & AHD_TARGETMODE) != 0)
6351 driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd);
6352 if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0)
6353 driver_data_size += PKT_OVERRUN_BUFSIZE;
6354 if (ahd_dma_tag_create(ahd, ahd->parent_dmat, 1,
6355 BUS_SPACE_MAXADDR_32BIT + 1,
6356 BUS_SPACE_MAXADDR_32BIT,
6357 BUS_SPACE_MAXADDR,
6358 NULL, NULL,
6359 driver_data_size,
6360 1,
6361 BUS_SPACE_MAXSIZE_32BIT,
6362 0, &ahd->shared_data_dmat) != 0) {
6363 return (ENOMEM);
6364 }
6365
6366 ahd->init_level++;
6367
6368
6369 if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat,
6370 (void **)&ahd->shared_data_map.vaddr,
6371 BUS_DMA_NOWAIT,
6372 &ahd->shared_data_map.dmamap) != 0) {
6373 return (ENOMEM);
6374 }
6375
6376 ahd->init_level++;
6377
6378
6379 ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
6380 ahd->shared_data_map.vaddr, driver_data_size,
6381 ahd_dmamap_cb, &ahd->shared_data_map.physaddr,
6382 0);
6383 ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr;
6384 next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE];
6385 next_baddr = ahd->shared_data_map.physaddr
6386 + AHD_QOUT_SIZE*sizeof(struct ahd_completion);
6387 if ((ahd->features & AHD_TARGETMODE) != 0) {
6388 ahd->targetcmds = (struct target_cmd *)next_vaddr;
6389 next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);
6390 next_baddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);
6391 }
6392
6393 if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) {
6394 ahd->overrun_buf = next_vaddr;
6395 next_vaddr += PKT_OVERRUN_BUFSIZE;
6396 next_baddr += PKT_OVERRUN_BUFSIZE;
6397 }
6398
6399
6400
6401
6402
6403
6404
6405
6406 ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr;
6407 ahd->next_queued_hscb_map = &ahd->shared_data_map;
6408 ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr);
6409
6410 ahd->init_level++;
6411
6412
6413 if (ahd_init_scbdata(ahd) != 0)
6414 return (ENOMEM);
6415
6416 if ((ahd->flags & AHD_INITIATORROLE) == 0)
6417 ahd->flags &= ~AHD_RESET_BUS_A;
6418
6419
6420
6421
6422
6423 ahd_platform_init(ahd);
6424
6425
6426 ahd_chip_init(ahd);
6427
6428 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
6429
6430 if ((ahd->flags & AHD_CURRENT_SENSING) == 0)
6431 goto init_done;
6432
6433
6434
6435
6436
6437 error = ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL,
6438 CURSENSE_ENB);
6439 if (error != 0) {
6440 printf("%s: current sensing timeout 1\n", ahd_name(ahd));
6441 goto init_done;
6442 }
6443 for (i = 20, fstat = FLX_FSTAT_BUSY;
6444 (fstat & FLX_FSTAT_BUSY) != 0 && i; i--) {
6445 error = ahd_read_flexport(ahd, FLXADDR_FLEXSTAT, &fstat);
6446 if (error != 0) {
6447 printf("%s: current sensing timeout 2\n",
6448 ahd_name(ahd));
6449 goto init_done;
6450 }
6451 }
6452 if (i == 0) {
6453 printf("%s: Timedout during current-sensing test\n",
6454 ahd_name(ahd));
6455 goto init_done;
6456 }
6457
6458
6459 error = ahd_read_flexport(ahd, FLXADDR_CURRENT_STAT, ¤t_sensing);
6460 if (error != 0) {
6461 printf("%s: current sensing timeout 3\n", ahd_name(ahd));
6462 goto init_done;
6463 }
6464
6465
6466 ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0);
6467
6468#ifdef AHD_DEBUG
6469 if ((ahd_debug & AHD_SHOW_TERMCTL) != 0) {
6470 printf("%s: current_sensing == 0x%x\n",
6471 ahd_name(ahd), current_sensing);
6472 }
6473#endif
6474 warn_user = 0;
6475 for (i = 0; i < 4; i++, current_sensing >>= FLX_CSTAT_SHIFT) {
6476 u_int term_stat;
6477
6478 term_stat = (current_sensing & FLX_CSTAT_MASK);
6479 switch (term_stat) {
6480 case FLX_CSTAT_OVER:
6481 case FLX_CSTAT_UNDER:
6482 warn_user++;
6483 case FLX_CSTAT_INVALID:
6484 case FLX_CSTAT_OKAY:
6485 if (warn_user == 0 && bootverbose == 0)
6486 break;
6487 printf("%s: %s Channel %s\n", ahd_name(ahd),
6488 channel_strings[i], termstat_strings[term_stat]);
6489 break;
6490 }
6491 }
6492 if (warn_user) {
6493 printf("%s: WARNING. Termination is not configured correctly.\n"
6494 "%s: WARNING. SCSI bus operations may FAIL.\n",
6495 ahd_name(ahd), ahd_name(ahd));
6496 }
6497init_done:
6498 ahd_restart(ahd);
6499 ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US,
6500 ahd_stat_timer, ahd);
6501 return (0);
6502}
6503
6504
6505
6506
6507static void
6508ahd_chip_init(struct ahd_softc *ahd)
6509{
6510 uint32_t busaddr;
6511 u_int sxfrctl1;
6512 u_int scsiseq_template;
6513 u_int wait;
6514 u_int i;
6515 u_int target;
6516
6517 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
6518
6519
6520
6521 ahd_outb(ahd, SBLKCTL, ahd_inb(ahd, SBLKCTL) & ~(DIAGLEDEN|DIAGLEDON));
6522
6523
6524
6525
6526 ahd->hs_mailbox = 0;
6527 ahd_outb(ahd, HS_MAILBOX, 0);
6528
6529
6530 ahd_outb(ahd, IOWNID, ahd->our_id);
6531 ahd_outb(ahd, TOWNID, ahd->our_id);
6532 sxfrctl1 = (ahd->flags & AHD_TERM_ENB_A) != 0 ? STPWEN : 0;
6533 sxfrctl1 |= (ahd->flags & AHD_SPCHK_ENB_A) != 0 ? ENSPCHK : 0;
6534 if ((ahd->bugs & AHD_LONG_SETIMO_BUG)
6535 && (ahd->seltime != STIMESEL_MIN)) {
6536
6537
6538
6539
6540
6541 sxfrctl1 |= ahd->seltime + STIMESEL_BUG_ADJ;
6542 } else {
6543 sxfrctl1 |= ahd->seltime;
6544 }
6545
6546 ahd_outb(ahd, SXFRCTL0, DFON);
6547 ahd_outb(ahd, SXFRCTL1, sxfrctl1|ahd->seltime|ENSTIMER|ACTNEGEN);
6548 ahd_outb(ahd, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
6549
6550
6551
6552
6553
6554
6555
6556
6557 for (wait = 10000;
6558 (ahd_inb(ahd, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait;
6559 wait--)
6560 ahd_delay(100);
6561
6562
6563 ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);
6564 ahd_outb(ahd, CLRINT, CLRSCSIINT);
6565
6566
6567 for (i = 0; i < 2; i++) {
6568 ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);
6569 ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
6570 ahd_outb(ahd, SG_STATE, 0);
6571 ahd_outb(ahd, CLRSEQINTSRC, 0xFF);
6572 ahd_outb(ahd, SEQIMODE,
6573 ENSAVEPTRS|ENCFG4DATA|ENCFG4ISTAT
6574 |ENCFG4TSTAT|ENCFG4ICMD|ENCFG4TCMD);
6575 }
6576
6577 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
6578 ahd_outb(ahd, DSCOMMAND0, ahd_inb(ahd, DSCOMMAND0)|MPARCKEN|CACHETHEN);
6579 ahd_outb(ahd, DFF_THRSH, RD_DFTHRSH_75|WR_DFTHRSH_75);
6580 ahd_outb(ahd, SIMODE0, ENIOERR|ENOVERRUN);
6581 ahd_outb(ahd, SIMODE3, ENNTRAMPERR|ENOSRAMPERR);
6582 if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
6583 ahd_outb(ahd, OPTIONMODE, AUTOACKEN|AUTO_MSGOUT_DE);
6584 } else {
6585 ahd_outb(ahd, OPTIONMODE, AUTOACKEN|BUSFREEREV|AUTO_MSGOUT_DE);
6586 }
6587 ahd_outb(ahd, SCSCHKN, CURRFIFODEF|WIDERESEN|SHVALIDSTDIS);
6588 if ((ahd->chip & AHD_BUS_MASK) == AHD_PCIX)
6589
6590
6591
6592
6593
6594 ahd_outb(ahd, PCIXCTL, ahd_inb(ahd, PCIXCTL) | SPLTSTADIS);
6595
6596 if ((ahd->bugs & AHD_LQOOVERRUN_BUG) != 0)
6597 ahd_outb(ahd, LQOSCSCTL, LQONOCHKOVER);
6598
6599
6600
6601
6602 if ((ahd->flags & AHD_HP_BOARD) != 0) {
6603 for (i = 0; i < NUMDSPS; i++) {
6604 ahd_outb(ahd, DSPSELECT, i);
6605 ahd_outb(ahd, WRTBIASCTL, WRTBIASCTL_HP_DEFAULT);
6606 }
6607#ifdef AHD_DEBUG
6608 if ((ahd_debug & AHD_SHOW_MISC) != 0)
6609 printf("%s: WRTBIASCTL now 0x%x\n", ahd_name(ahd),
6610 WRTBIASCTL_HP_DEFAULT);
6611#endif
6612 }
6613 ahd_setup_iocell_workaround(ahd);
6614
6615
6616
6617
6618 ahd_outb(ahd, LQIMODE1, ENLQIPHASE_LQ|ENLQIPHASE_NLQ|ENLIQABORT
6619 | ENLQICRCI_LQ|ENLQICRCI_NLQ|ENLQIBADLQI
6620 | ENLQIOVERI_LQ|ENLQIOVERI_NLQ);
6621 ahd_outb(ahd, LQOMODE0, ENLQOATNLQ|ENLQOATNPKT|ENLQOTCRC);
6622
6623
6624
6625
6626
6627
6628
6629
6630 ahd_outb(ahd, LQOMODE1, ENLQOBUSFREE);
6631
6632
6633
6634
6635 ahd_outw(ahd, INTVEC1_ADDR, ahd_resolve_seqaddr(ahd, LABEL_seq_isr));
6636 ahd_outw(ahd, INTVEC2_ADDR, ahd_resolve_seqaddr(ahd, LABEL_timer_isr));
6637
6638
6639
6640
6641 if ((ahd->bugs & AHD_PKT_LUN_BUG) != 0) {
6642 ahd_outb(ahd, LUNPTR, offsetof(struct hardware_scb,
6643 pkt_long_lun));
6644 } else {
6645 ahd_outb(ahd, LUNPTR, offsetof(struct hardware_scb, lun));
6646 }
6647 ahd_outb(ahd, CMDLENPTR, offsetof(struct hardware_scb, cdb_len));
6648 ahd_outb(ahd, ATTRPTR, offsetof(struct hardware_scb, task_attribute));
6649 ahd_outb(ahd, FLAGPTR, offsetof(struct hardware_scb, task_management));
6650 ahd_outb(ahd, CMDPTR, offsetof(struct hardware_scb,
6651 shared_data.idata.cdb));
6652 ahd_outb(ahd, QNEXTPTR,
6653 offsetof(struct hardware_scb, next_hscb_busaddr));
6654 ahd_outb(ahd, ABRTBITPTR, MK_MESSAGE_BIT_OFFSET);
6655 ahd_outb(ahd, ABRTBYTEPTR, offsetof(struct hardware_scb, control));
6656 if ((ahd->bugs & AHD_PKT_LUN_BUG) != 0) {
6657 ahd_outb(ahd, LUNLEN,
6658 sizeof(ahd->next_queued_hscb->pkt_long_lun) - 1);
6659 } else {
6660 ahd_outb(ahd, LUNLEN, LUNLEN_SINGLE_LEVEL_LUN);
6661 }
6662 ahd_outb(ahd, CDBLIMIT, SCB_CDB_LEN_PTR - 1);
6663 ahd_outb(ahd, MAXCMD, 0xFF);
6664 ahd_outb(ahd, SCBAUTOPTR,
6665 AUSCBPTR_EN | offsetof(struct hardware_scb, tag));
6666
6667
6668 ahd_outb(ahd, MULTARGID, 0);
6669 ahd_outb(ahd, MULTARGID + 1, 0);
6670
6671 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
6672
6673 if ((ahd->features & AHD_NEW_IOCELL_OPTS) == 0) {
6674
6675
6676
6677
6678 for (target = 0; target < AHD_NUM_TARGETS; target++) {
6679 ahd_outb(ahd, NEGOADDR, target);
6680 ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PER_DEV0);
6681 for (i = 0; i < AHD_NUM_PER_DEV_ANNEXCOLS; i++)
6682 ahd_outb(ahd, ANNEXDAT, 0);
6683 }
6684 }
6685 for (target = 0; target < AHD_NUM_TARGETS; target++) {
6686 struct ahd_devinfo devinfo;
6687 struct ahd_initiator_tinfo *tinfo;
6688 struct ahd_tmode_tstate *tstate;
6689
6690 tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
6691 target, &tstate);
6692 ahd_compile_devinfo(&devinfo, ahd->our_id,
6693 target, CAM_LUN_WILDCARD,
6694 'A', ROLE_INITIATOR);
6695 ahd_update_neg_table(ahd, &devinfo, &tinfo->curr);
6696 }
6697
6698 ahd_outb(ahd, CLRSINT3, NTRAMPERR|OSRAMPERR);
6699 ahd_outb(ahd, CLRINT, CLRSCSIINT);
6700
6701#ifdef NEEDS_MORE_TESTING
6702
6703
6704
6705
6706 if ((ahd->bugs & AHD_ABORT_LQI_BUG) == 0)
6707 ahd_outb(ahd, LQCTL1, ABORTPENDING);
6708 else
6709#endif
6710 ahd_outb(ahd, LQCTL1, 0);
6711
6712
6713 ahd->qoutfifonext = 0;
6714 ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID;
6715 ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID);
6716 for (i = 0; i < AHD_QOUT_SIZE; i++)
6717 ahd->qoutfifo[i].valid_tag = 0;
6718 ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD);
6719
6720 ahd->qinfifonext = 0;
6721 for (i = 0; i < AHD_QIN_SIZE; i++)
6722 ahd->qinfifo[i] = SCB_LIST_NULL;
6723
6724 if ((ahd->features & AHD_TARGETMODE) != 0) {
6725
6726 for (i = 0; i < AHD_TMODE_CMDS; i++)
6727 ahd->targetcmds[i].cmd_valid = 0;
6728 ahd_sync_tqinfifo(ahd, BUS_DMASYNC_PREREAD);
6729 ahd->tqinfifonext = 1;
6730 ahd_outb(ahd, KERNEL_TQINPOS, ahd->tqinfifonext - 1);
6731 ahd_outb(ahd, TQINPOS, ahd->tqinfifonext);
6732 }
6733
6734
6735 ahd_outb(ahd, SEQ_FLAGS, 0);
6736 ahd_outb(ahd, SEQ_FLAGS2, 0);
6737
6738
6739 ahd_outw(ahd, WAITING_TID_HEAD, SCB_LIST_NULL);
6740 ahd_outw(ahd, WAITING_TID_TAIL, SCB_LIST_NULL);
6741 ahd_outw(ahd, MK_MESSAGE_SCB, SCB_LIST_NULL);
6742 ahd_outw(ahd, MK_MESSAGE_SCSIID, 0xFF);
6743 for (i = 0; i < AHD_NUM_TARGETS; i++)
6744 ahd_outw(ahd, WAITING_SCB_TAILS + (2 * i), SCB_LIST_NULL);
6745
6746
6747
6748
6749 ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);
6750 ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL);
6751 ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
6752 ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
6753 ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
6754
6755
6756
6757
6758 ahd->qfreeze_cnt = 0;
6759 ahd_outw(ahd, QFREEZE_COUNT, 0);
6760 ahd_outw(ahd, KERNEL_QFREEZE_COUNT, 0);
6761
6762
6763
6764
6765 busaddr = ahd->shared_data_map.physaddr;
6766 ahd_outl(ahd, SHARED_DATA_ADDR, busaddr);
6767 ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr);
6768
6769
6770
6771
6772
6773
6774 scsiseq_template = ENAUTOATNP;
6775 if ((ahd->flags & AHD_INITIATORROLE) != 0)
6776 scsiseq_template |= ENRSELI;
6777 ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq_template);
6778
6779
6780 for (target = 0; target < AHD_NUM_TARGETS; target++) {
6781 int lun;
6782
6783 for (lun = 0; lun < AHD_NUM_LUNS_NONPKT; lun++)
6784 ahd_unbusy_tcl(ahd, BUILD_TCL_RAW(target, 'A', lun));
6785 }
6786
6787
6788
6789
6790
6791
6792
6793 ahd_outb(ahd, CMDSIZE_TABLE, 5);
6794 ahd_outb(ahd, CMDSIZE_TABLE + 1, 9);
6795 ahd_outb(ahd, CMDSIZE_TABLE + 2, 9);
6796 ahd_outb(ahd, CMDSIZE_TABLE + 3, 0);
6797 ahd_outb(ahd, CMDSIZE_TABLE + 4, 15);
6798 ahd_outb(ahd, CMDSIZE_TABLE + 5, 11);
6799 ahd_outb(ahd, CMDSIZE_TABLE + 6, 0);
6800 ahd_outb(ahd, CMDSIZE_TABLE + 7, 0);
6801
6802
6803 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
6804 ahd_outb(ahd, QOFF_CTLSTA, SCB_QSIZE_512);
6805 ahd->qinfifonext = 0;
6806 ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
6807 ahd_set_hescb_qoff(ahd, 0);
6808 ahd_set_snscb_qoff(ahd, 0);
6809 ahd_set_sescb_qoff(ahd, 0);
6810 ahd_set_sdscb_qoff(ahd, 0);
6811
6812
6813
6814
6815 busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);
6816 ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
6817
6818
6819
6820
6821 ahd_outw(ahd, INT_COALESCING_CMDCOUNT, 0);
6822 ahd_outw(ahd, CMDS_PENDING, 0);
6823 ahd_update_coalescing_values(ahd, ahd->int_coalescing_timer,
6824 ahd->int_coalescing_maxcmds,
6825 ahd->int_coalescing_mincmds);
6826 ahd_enable_coalescing(ahd, FALSE);
6827
6828 ahd_loadseq(ahd);
6829 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
6830
6831 if (ahd->features & AHD_AIC79XXB_SLOWCRC) {
6832 u_int negodat3 = ahd_inb(ahd, NEGCONOPTS);
6833
6834 negodat3 |= ENSLOWCRC;
6835 ahd_outb(ahd, NEGCONOPTS, negodat3);
6836 negodat3 = ahd_inb(ahd, NEGCONOPTS);
6837 if (!(negodat3 & ENSLOWCRC))
6838 printf("aic79xx: failed to set the SLOWCRC bit\n");
6839 else
6840 printf("aic79xx: SLOWCRC bit set\n");
6841 }
6842}
6843
6844
6845
6846
6847
6848
6849int
6850ahd_default_config(struct ahd_softc *ahd)
6851{
6852 int targ;
6853
6854 ahd->our_id = 7;
6855
6856
6857
6858
6859
6860
6861 if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) {
6862 printf("%s: unable to allocate ahd_tmode_tstate. "
6863 "Failing attach\n", ahd_name(ahd));
6864 return (ENOMEM);
6865 }
6866
6867 for (targ = 0; targ < AHD_NUM_TARGETS; targ++) {
6868 struct ahd_devinfo devinfo;
6869 struct ahd_initiator_tinfo *tinfo;
6870 struct ahd_tmode_tstate *tstate;
6871 uint16_t target_mask;
6872
6873 tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
6874 targ, &tstate);
6875
6876
6877
6878 tinfo->user.protocol_version = 4;
6879 tinfo->user.transport_version = 4;
6880
6881 target_mask = 0x01 << targ;
6882 ahd->user_discenable |= target_mask;
6883 tstate->discenable |= target_mask;
6884 ahd->user_tagenable |= target_mask;
6885#ifdef AHD_FORCE_160
6886 tinfo->user.period = AHD_SYNCRATE_DT;
6887#else
6888 tinfo->user.period = AHD_SYNCRATE_160;
6889#endif
6890 tinfo->user.offset = MAX_OFFSET;
6891 tinfo->user.ppr_options = MSG_EXT_PPR_RD_STRM
6892 | MSG_EXT_PPR_WR_FLOW
6893 | MSG_EXT_PPR_HOLD_MCS
6894 | MSG_EXT_PPR_IU_REQ
6895 | MSG_EXT_PPR_QAS_REQ
6896 | MSG_EXT_PPR_DT_REQ;
6897 if ((ahd->features & AHD_RTI) != 0)
6898 tinfo->user.ppr_options |= MSG_EXT_PPR_RTI;
6899
6900 tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT;
6901
6902
6903
6904
6905
6906 tinfo->goal.protocol_version = 2;
6907 tinfo->goal.transport_version = 2;
6908 tinfo->curr.protocol_version = 2;
6909 tinfo->curr.transport_version = 2;
6910 ahd_compile_devinfo(&devinfo, ahd->our_id,
6911 targ, CAM_LUN_WILDCARD,
6912 'A', ROLE_INITIATOR);
6913 tstate->tagenable &= ~target_mask;
6914 ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
6915 AHD_TRANS_CUR|AHD_TRANS_GOAL, TRUE);
6916 ahd_set_syncrate(ahd, &devinfo, 0, 0,
6917 0, AHD_TRANS_CUR|AHD_TRANS_GOAL,
6918 TRUE);
6919 }
6920 return (0);
6921}
6922
6923
6924
6925
6926int
6927ahd_parse_cfgdata(struct ahd_softc *ahd, struct seeprom_config *sc)
6928{
6929 int targ;
6930 int max_targ;
6931
6932 max_targ = sc->max_targets & CFMAXTARG;
6933 ahd->our_id = sc->brtime_id & CFSCSIID;
6934
6935
6936
6937
6938
6939
6940 if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) {
6941 printf("%s: unable to allocate ahd_tmode_tstate. "
6942 "Failing attach\n", ahd_name(ahd));
6943 return (ENOMEM);
6944 }
6945
6946 for (targ = 0; targ < max_targ; targ++) {
6947 struct ahd_devinfo devinfo;
6948 struct ahd_initiator_tinfo *tinfo;
6949 struct ahd_transinfo *user_tinfo;
6950 struct ahd_tmode_tstate *tstate;
6951 uint16_t target_mask;
6952
6953 tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
6954 targ, &tstate);
6955 user_tinfo = &tinfo->user;
6956
6957
6958
6959
6960 tinfo->user.protocol_version = 4;
6961 tinfo->user.transport_version = 4;
6962
6963 target_mask = 0x01 << targ;
6964 ahd->user_discenable &= ~target_mask;
6965 tstate->discenable &= ~target_mask;
6966 ahd->user_tagenable &= ~target_mask;
6967 if (sc->device_flags[targ] & CFDISC) {
6968 tstate->discenable |= target_mask;
6969 ahd->user_discenable |= target_mask;
6970 ahd->user_tagenable |= target_mask;
6971 } else {
6972
6973
6974
6975 sc->device_flags[targ] &= ~CFPACKETIZED;
6976 }
6977
6978 user_tinfo->ppr_options = 0;
6979 user_tinfo->period = (sc->device_flags[targ] & CFXFER);
6980 if (user_tinfo->period < CFXFER_ASYNC) {
6981 if (user_tinfo->period <= AHD_PERIOD_10MHz)
6982 user_tinfo->ppr_options |= MSG_EXT_PPR_DT_REQ;
6983 user_tinfo->offset = MAX_OFFSET;
6984 } else {
6985 user_tinfo->offset = 0;
6986 user_tinfo->period = AHD_ASYNC_XFER_PERIOD;
6987 }
6988#ifdef AHD_FORCE_160
6989 if (user_tinfo->period <= AHD_SYNCRATE_160)
6990 user_tinfo->period = AHD_SYNCRATE_DT;
6991#endif
6992
6993 if ((sc->device_flags[targ] & CFPACKETIZED) != 0) {
6994 user_tinfo->ppr_options |= MSG_EXT_PPR_RD_STRM
6995 | MSG_EXT_PPR_WR_FLOW
6996 | MSG_EXT_PPR_HOLD_MCS
6997 | MSG_EXT_PPR_IU_REQ;
6998 if ((ahd->features & AHD_RTI) != 0)
6999 user_tinfo->ppr_options |= MSG_EXT_PPR_RTI;
7000 }
7001
7002 if ((sc->device_flags[targ] & CFQAS) != 0)
7003 user_tinfo->ppr_options |= MSG_EXT_PPR_QAS_REQ;
7004
7005 if ((sc->device_flags[targ] & CFWIDEB) != 0)
7006 user_tinfo->width = MSG_EXT_WDTR_BUS_16_BIT;
7007 else
7008 user_tinfo->width = MSG_EXT_WDTR_BUS_8_BIT;
7009#ifdef AHD_DEBUG
7010 if ((ahd_debug & AHD_SHOW_MISC) != 0)
7011 printf("(%d): %x:%x:%x:%x\n", targ, user_tinfo->width,
7012 user_tinfo->period, user_tinfo->offset,
7013 user_tinfo->ppr_options);
7014#endif
7015
7016
7017
7018
7019 tstate->tagenable &= ~target_mask;
7020 tinfo->goal.protocol_version = 2;
7021 tinfo->goal.transport_version = 2;
7022 tinfo->curr.protocol_version = 2;
7023 tinfo->curr.transport_version = 2;
7024 ahd_compile_devinfo(&devinfo, ahd->our_id,
7025 targ, CAM_LUN_WILDCARD,
7026 'A', ROLE_INITIATOR);
7027 ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
7028 AHD_TRANS_CUR|AHD_TRANS_GOAL, TRUE);
7029 ahd_set_syncrate(ahd, &devinfo, 0, 0,
7030 0, AHD_TRANS_CUR|AHD_TRANS_GOAL,
7031 TRUE);
7032 }
7033
7034 ahd->flags &= ~AHD_SPCHK_ENB_A;
7035 if (sc->bios_control & CFSPARITY)
7036 ahd->flags |= AHD_SPCHK_ENB_A;
7037
7038 ahd->flags &= ~AHD_RESET_BUS_A;
7039 if (sc->bios_control & CFRESETB)
7040 ahd->flags |= AHD_RESET_BUS_A;
7041
7042 ahd->flags &= ~AHD_EXTENDED_TRANS_A;
7043 if (sc->bios_control & CFEXTEND)
7044 ahd->flags |= AHD_EXTENDED_TRANS_A;
7045
7046 ahd->flags &= ~AHD_BIOS_ENABLED;
7047 if ((sc->bios_control & CFBIOSSTATE) == CFBS_ENABLED)
7048 ahd->flags |= AHD_BIOS_ENABLED;
7049
7050 ahd->flags &= ~AHD_STPWLEVEL_A;
7051 if ((sc->adapter_control & CFSTPWLEVEL) != 0)
7052 ahd->flags |= AHD_STPWLEVEL_A;
7053
7054 return (0);
7055}
7056
7057
7058
7059
7060int
7061ahd_parse_vpddata(struct ahd_softc *ahd, struct vpd_config *vpd)
7062{
7063 int error;
7064
7065 error = ahd_verify_vpd_cksum(vpd);
7066 if (error == 0)
7067 return (EINVAL);
7068 if ((vpd->bios_flags & VPDBOOTHOST) != 0)
7069 ahd->flags |= AHD_BOOT_CHANNEL;
7070 return (0);
7071}
7072
7073void
7074ahd_intr_enable(struct ahd_softc *ahd, int enable)
7075{
7076 u_int hcntrl;
7077
7078 hcntrl = ahd_inb(ahd, HCNTRL);
7079 hcntrl &= ~INTEN;
7080 ahd->pause &= ~INTEN;
7081 ahd->unpause &= ~INTEN;
7082 if (enable) {
7083 hcntrl |= INTEN;
7084 ahd->pause |= INTEN;
7085 ahd->unpause |= INTEN;
7086 }
7087 ahd_outb(ahd, HCNTRL, hcntrl);
7088}
7089
7090static void
7091ahd_update_coalescing_values(struct ahd_softc *ahd, u_int timer, u_int maxcmds,
7092 u_int mincmds)
7093{
7094 if (timer > AHD_TIMER_MAX_US)
7095 timer = AHD_TIMER_MAX_US;
7096 ahd->int_coalescing_timer = timer;
7097
7098 if (maxcmds > AHD_INT_COALESCING_MAXCMDS_MAX)
7099 maxcmds = AHD_INT_COALESCING_MAXCMDS_MAX;
7100 if (mincmds > AHD_INT_COALESCING_MINCMDS_MAX)
7101 mincmds = AHD_INT_COALESCING_MINCMDS_MAX;
7102 ahd->int_coalescing_maxcmds = maxcmds;
7103 ahd_outw(ahd, INT_COALESCING_TIMER, timer / AHD_TIMER_US_PER_TICK);
7104 ahd_outb(ahd, INT_COALESCING_MAXCMDS, -maxcmds);
7105 ahd_outb(ahd, INT_COALESCING_MINCMDS, -mincmds);
7106}
7107
7108static void
7109ahd_enable_coalescing(struct ahd_softc *ahd, int enable)
7110{
7111
7112 ahd->hs_mailbox &= ~ENINT_COALESCE;
7113 if (enable)
7114 ahd->hs_mailbox |= ENINT_COALESCE;
7115 ahd_outb(ahd, HS_MAILBOX, ahd->hs_mailbox);
7116 ahd_flush_device_writes(ahd);
7117 ahd_run_qoutfifo(ahd);
7118}
7119
7120
7121
7122
7123
7124
7125
7126
7127void
7128ahd_pause_and_flushwork(struct ahd_softc *ahd)
7129{
7130 u_int intstat;
7131 u_int maxloops;
7132
7133 maxloops = 1000;
7134 ahd->flags |= AHD_ALL_INTERRUPTS;
7135 ahd_pause(ahd);
7136
7137
7138
7139
7140
7141 ahd->qfreeze_cnt--;
7142 ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
7143 ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN);
7144 do {
7145
7146 ahd_unpause(ahd);
7147
7148
7149
7150
7151 ahd_delay(500);
7152
7153 ahd_intr(ahd);
7154 ahd_pause(ahd);
7155 intstat = ahd_inb(ahd, INTSTAT);
7156 if ((intstat & INT_PEND) == 0) {
7157 ahd_clear_critical_section(ahd);
7158 intstat = ahd_inb(ahd, INTSTAT);
7159 }
7160 } while (--maxloops
7161 && (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0)
7162 && ((intstat & INT_PEND) != 0
7163 || (ahd_inb(ahd, SCSISEQ0) & ENSELO) != 0
7164 || (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0));
7165
7166 if (maxloops == 0) {
7167 printf("Infinite interrupt loop, INTSTAT = %x",
7168 ahd_inb(ahd, INTSTAT));
7169 }
7170 ahd->qfreeze_cnt++;
7171 ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
7172
7173 ahd_flush_qoutfifo(ahd);
7174
7175 ahd->flags &= ~AHD_ALL_INTERRUPTS;
7176}
7177
7178int
7179ahd_suspend(struct ahd_softc *ahd)
7180{
7181
7182 ahd_pause_and_flushwork(ahd);
7183
7184 if (LIST_FIRST(&ahd->pending_scbs) != NULL) {
7185 ahd_unpause(ahd);
7186 return (EBUSY);
7187 }
7188 ahd_shutdown(ahd);
7189 return (0);
7190}
7191
7192void
7193ahd_resume(struct ahd_softc *ahd)
7194{
7195
7196 ahd_reset(ahd, TRUE);
7197 ahd_intr_enable(ahd, TRUE);
7198 ahd_restart(ahd);
7199}
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210static __inline u_int
7211ahd_index_busy_tcl(struct ahd_softc *ahd, u_int *saved_scbid, u_int tcl)
7212{
7213
7214
7215
7216 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
7217 *saved_scbid = ahd_get_scbptr(ahd);
7218 ahd_set_scbptr(ahd, TCL_LUN(tcl)
7219 | ((TCL_TARGET_OFFSET(tcl) & 0xC) << 4));
7220
7221
7222
7223
7224
7225
7226 return (((TCL_TARGET_OFFSET(tcl) & 0x3) << 1) + SCB_DISCONNECTED_LISTS);
7227}
7228
7229
7230
7231
7232static u_int
7233ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl)
7234{
7235 u_int scbid;
7236 u_int scb_offset;
7237 u_int saved_scbptr;
7238
7239 scb_offset = ahd_index_busy_tcl(ahd, &saved_scbptr, tcl);
7240 scbid = ahd_inw_scbram(ahd, scb_offset);
7241 ahd_set_scbptr(ahd, saved_scbptr);
7242 return (scbid);
7243}
7244
7245static void
7246ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, u_int scbid)
7247{
7248 u_int scb_offset;
7249 u_int saved_scbptr;
7250
7251 scb_offset = ahd_index_busy_tcl(ahd, &saved_scbptr, tcl);
7252 ahd_outw(ahd, scb_offset, scbid);
7253 ahd_set_scbptr(ahd, saved_scbptr);
7254}
7255
7256
7257static int
7258ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, int target,
7259 char channel, int lun, u_int tag, role_t role)
7260{
7261 int targ = SCB_GET_TARGET(ahd, scb);
7262 char chan = SCB_GET_CHANNEL(ahd, scb);
7263 int slun = SCB_GET_LUN(scb);
7264 int match;
7265
7266 match = ((chan == channel) || (channel == ALL_CHANNELS));
7267 if (match != 0)
7268 match = ((targ == target) || (target == CAM_TARGET_WILDCARD));
7269 if (match != 0)
7270 match = ((lun == slun) || (lun == CAM_LUN_WILDCARD));
7271 if (match != 0) {
7272#ifdef AHD_TARGET_MODE
7273 int group;
7274
7275 group = XPT_FC_GROUP(scb->io_ctx->ccb_h.func_code);
7276 if (role == ROLE_INITIATOR) {
7277 match = (group != XPT_FC_GROUP_TMODE)
7278 && ((tag == SCB_GET_TAG(scb))
7279 || (tag == SCB_LIST_NULL));
7280 } else if (role == ROLE_TARGET) {
7281 match = (group == XPT_FC_GROUP_TMODE)
7282 && ((tag == scb->io_ctx->csio.tag_id)
7283 || (tag == SCB_LIST_NULL));
7284 }
7285#else
7286 match = ((tag == SCB_GET_TAG(scb)) || (tag == SCB_LIST_NULL));
7287#endif
7288 }
7289
7290 return match;
7291}
7292
7293static void
7294ahd_freeze_devq(struct ahd_softc *ahd, struct scb *scb)
7295{
7296 int target;
7297 char channel;
7298 int lun;
7299
7300 target = SCB_GET_TARGET(ahd, scb);
7301 lun = SCB_GET_LUN(scb);
7302 channel = SCB_GET_CHANNEL(ahd, scb);
7303
7304 ahd_search_qinfifo(ahd, target, channel, lun,
7305 SCB_LIST_NULL, ROLE_UNKNOWN,
7306 CAM_REQUEUE_REQ, SEARCH_COMPLETE);
7307
7308 ahd_platform_freeze_devq(ahd, scb);
7309}
7310
7311void
7312ahd_qinfifo_requeue_tail(struct ahd_softc *ahd, struct scb *scb)
7313{
7314 struct scb *prev_scb;
7315 ahd_mode_state saved_modes;
7316
7317 saved_modes = ahd_save_modes(ahd);
7318 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
7319 prev_scb = NULL;
7320 if (ahd_qinfifo_count(ahd) != 0) {
7321 u_int prev_tag;
7322 u_int prev_pos;
7323
7324 prev_pos = AHD_QIN_WRAP(ahd->qinfifonext - 1);
7325 prev_tag = ahd->qinfifo[prev_pos];
7326 prev_scb = ahd_lookup_scb(ahd, prev_tag);
7327 }
7328 ahd_qinfifo_requeue(ahd, prev_scb, scb);
7329 ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
7330 ahd_restore_modes(ahd, saved_modes);
7331}
7332
7333static void
7334ahd_qinfifo_requeue(struct ahd_softc *ahd, struct scb *prev_scb,
7335 struct scb *scb)
7336{
7337 if (prev_scb == NULL) {
7338 uint32_t busaddr;
7339
7340 busaddr = ahd_le32toh(scb->hscb->hscb_busaddr);
7341 ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
7342 } else {
7343 prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
7344 ahd_sync_scb(ahd, prev_scb,
7345 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
7346 }
7347 ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);
7348 ahd->qinfifonext++;
7349 scb->hscb->next_hscb_busaddr = ahd->next_queued_hscb->hscb_busaddr;
7350 ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
7351}
7352
7353static int
7354ahd_qinfifo_count(struct ahd_softc *ahd)
7355{
7356 u_int qinpos;
7357 u_int wrap_qinpos;
7358 u_int wrap_qinfifonext;
7359
7360 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
7361 qinpos = ahd_get_snscb_qoff(ahd);
7362 wrap_qinpos = AHD_QIN_WRAP(qinpos);
7363 wrap_qinfifonext = AHD_QIN_WRAP(ahd->qinfifonext);
7364 if (wrap_qinfifonext >= wrap_qinpos)
7365 return (wrap_qinfifonext - wrap_qinpos);
7366 else
7367 return (wrap_qinfifonext
7368 + ARRAY_SIZE(ahd->qinfifo) - wrap_qinpos);
7369}
7370
7371void
7372ahd_reset_cmds_pending(struct ahd_softc *ahd)
7373{
7374 struct scb *scb;
7375 ahd_mode_state saved_modes;
7376 u_int pending_cmds;
7377
7378 saved_modes = ahd_save_modes(ahd);
7379 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
7380
7381
7382
7383
7384
7385 ahd_flush_qoutfifo(ahd);
7386
7387 pending_cmds = 0;
7388 LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
7389 pending_cmds++;
7390 }
7391 ahd_outw(ahd, CMDS_PENDING, pending_cmds - ahd_qinfifo_count(ahd));
7392 ahd_restore_modes(ahd, saved_modes);
7393 ahd->flags &= ~AHD_UPDATE_PEND_CMDS;
7394}
7395
7396static void
7397ahd_done_with_status(struct ahd_softc *ahd, struct scb *scb, uint32_t status)
7398{
7399 cam_status ostat;
7400 cam_status cstat;
7401
7402 ostat = ahd_get_transaction_status(scb);
7403 if (ostat == CAM_REQ_INPROG)
7404 ahd_set_transaction_status(scb, status);
7405 cstat = ahd_get_transaction_status(scb);
7406 if (cstat != CAM_REQ_CMP)
7407 ahd_freeze_scb(scb);
7408 ahd_done(ahd, scb);
7409}
7410
7411int
7412ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
7413 int lun, u_int tag, role_t role, uint32_t status,
7414 ahd_search_action action)
7415{
7416 struct scb *scb;
7417 struct scb *mk_msg_scb;
7418 struct scb *prev_scb;
7419 ahd_mode_state saved_modes;
7420 u_int qinstart;
7421 u_int qinpos;
7422 u_int qintail;
7423 u_int tid_next;
7424 u_int tid_prev;
7425 u_int scbid;
7426 u_int seq_flags2;
7427 u_int savedscbptr;
7428 uint32_t busaddr;
7429 int found;
7430 int targets;
7431
7432
7433 saved_modes = ahd_save_modes(ahd);
7434 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
7435
7436
7437
7438
7439
7440 if ((ahd_inb(ahd, CCSCBCTL) & (CCARREN|CCSCBEN|CCSCBDIR))
7441 == (CCARREN|CCSCBEN|CCSCBDIR)) {
7442 ahd_outb(ahd, CCSCBCTL,
7443 ahd_inb(ahd, CCSCBCTL) & ~(CCARREN|CCSCBEN));
7444 while ((ahd_inb(ahd, CCSCBCTL) & (CCARREN|CCSCBEN)) != 0)
7445 ;
7446 }
7447
7448 qintail = AHD_QIN_WRAP(ahd->qinfifonext);
7449 qinstart = ahd_get_snscb_qoff(ahd);
7450 qinpos = AHD_QIN_WRAP(qinstart);
7451 found = 0;
7452 prev_scb = NULL;
7453
7454 if (action == SEARCH_PRINT) {
7455 printf("qinstart = %d qinfifonext = %d\nQINFIFO:",
7456 qinstart, ahd->qinfifonext);
7457 }
7458
7459
7460
7461
7462
7463 ahd->qinfifonext = qinstart;
7464 busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);
7465 ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
7466
7467 while (qinpos != qintail) {
7468 scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]);
7469 if (scb == NULL) {
7470 printf("qinpos = %d, SCB index = %d\n",
7471 qinpos, ahd->qinfifo[qinpos]);
7472 panic("Loop 1\n");
7473 }
7474
7475 if (ahd_match_scb(ahd, scb, target, channel, lun, tag, role)) {
7476
7477
7478
7479 found++;
7480 switch (action) {
7481 case SEARCH_COMPLETE:
7482 if ((scb->flags & SCB_ACTIVE) == 0)
7483 printf("Inactive SCB in qinfifo\n");
7484 ahd_done_with_status(ahd, scb, status);
7485
7486 case SEARCH_REMOVE:
7487 break;
7488 case SEARCH_PRINT:
7489 printf(" 0x%x", ahd->qinfifo[qinpos]);
7490
7491 case SEARCH_COUNT:
7492 ahd_qinfifo_requeue(ahd, prev_scb, scb);
7493 prev_scb = scb;
7494 break;
7495 }
7496 } else {
7497 ahd_qinfifo_requeue(ahd, prev_scb, scb);
7498 prev_scb = scb;
7499 }
7500 qinpos = AHD_QIN_WRAP(qinpos+1);
7501 }
7502
7503 ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
7504
7505 if (action == SEARCH_PRINT)
7506 printf("\nWAITING_TID_QUEUES:\n");
7507
7508
7509
7510
7511
7512
7513
7514 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
7515 seq_flags2 = ahd_inb(ahd, SEQ_FLAGS2);
7516 if ((seq_flags2 & PENDING_MK_MESSAGE) != 0) {
7517 scbid = ahd_inw(ahd, MK_MESSAGE_SCB);
7518 mk_msg_scb = ahd_lookup_scb(ahd, scbid);
7519 } else
7520 mk_msg_scb = NULL;
7521 savedscbptr = ahd_get_scbptr(ahd);
7522 tid_next = ahd_inw(ahd, WAITING_TID_HEAD);
7523 tid_prev = SCB_LIST_NULL;
7524 targets = 0;
7525 for (scbid = tid_next; !SCBID_IS_NULL(scbid); scbid = tid_next) {
7526 u_int tid_head;
7527 u_int tid_tail;
7528
7529 targets++;
7530 if (targets > AHD_NUM_TARGETS)
7531 panic("TID LIST LOOP");
7532
7533 if (scbid >= ahd->scb_data.numscbs) {
7534 printf("%s: Waiting TID List inconsistency. "
7535 "SCB index == 0x%x, yet numscbs == 0x%x.",
7536 ahd_name(ahd), scbid, ahd->scb_data.numscbs);
7537 ahd_dump_card_state(ahd);
7538 panic("for safety");
7539 }
7540 scb = ahd_lookup_scb(ahd, scbid);
7541 if (scb == NULL) {
7542 printf("%s: SCB = 0x%x Not Active!\n",
7543 ahd_name(ahd), scbid);
7544 panic("Waiting TID List traversal\n");
7545 }
7546 ahd_set_scbptr(ahd, scbid);
7547 tid_next = ahd_inw_scbram(ahd, SCB_NEXT2);
7548 if (ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD,
7549 SCB_LIST_NULL, ROLE_UNKNOWN) == 0) {
7550 tid_prev = scbid;
7551 continue;
7552 }
7553
7554
7555
7556
7557 if (action == SEARCH_PRINT)
7558 printf(" %d ( ", SCB_GET_TARGET(ahd, scb));
7559 tid_head = scbid;
7560 found += ahd_search_scb_list(ahd, target, channel,
7561 lun, tag, role, status,
7562 action, &tid_head, &tid_tail,
7563 SCB_GET_TARGET(ahd, scb));
7564
7565
7566
7567
7568 if (mk_msg_scb != NULL
7569 && ahd_match_scb(ahd, mk_msg_scb, target, channel,
7570 lun, tag, role)) {
7571
7572
7573
7574
7575 found++;
7576 switch (action) {
7577 case SEARCH_COMPLETE:
7578 if ((mk_msg_scb->flags & SCB_ACTIVE) == 0)
7579 printf("Inactive SCB pending MK_MSG\n");
7580 ahd_done_with_status(ahd, mk_msg_scb, status);
7581
7582 case SEARCH_REMOVE:
7583 {
7584 u_int tail_offset;
7585
7586 printf("Removing MK_MSG scb\n");
7587
7588
7589
7590
7591
7592 tail_offset = WAITING_SCB_TAILS
7593 + (2 * SCB_GET_TARGET(ahd, mk_msg_scb));
7594 ahd_outw(ahd, tail_offset, tid_tail);
7595
7596 seq_flags2 &= ~PENDING_MK_MESSAGE;
7597 ahd_outb(ahd, SEQ_FLAGS2, seq_flags2);
7598 ahd_outw(ahd, CMDS_PENDING,
7599 ahd_inw(ahd, CMDS_PENDING)-1);
7600 mk_msg_scb = NULL;
7601 break;
7602 }
7603 case SEARCH_PRINT:
7604 printf(" 0x%x", SCB_GET_TAG(scb));
7605
7606 case SEARCH_COUNT:
7607 break;
7608 }
7609 }
7610
7611 if (mk_msg_scb != NULL
7612 && SCBID_IS_NULL(tid_head)
7613 && ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD,
7614 SCB_LIST_NULL, ROLE_UNKNOWN)) {
7615
7616
7617
7618
7619
7620
7621 printf("Queueing mk_msg_scb\n");
7622 tid_head = ahd_inw(ahd, MK_MESSAGE_SCB);
7623 seq_flags2 &= ~PENDING_MK_MESSAGE;
7624 ahd_outb(ahd, SEQ_FLAGS2, seq_flags2);
7625 mk_msg_scb = NULL;
7626 }
7627 if (tid_head != scbid)
7628 ahd_stitch_tid_list(ahd, tid_prev, tid_head, tid_next);
7629 if (!SCBID_IS_NULL(tid_head))
7630 tid_prev = tid_head;
7631 if (action == SEARCH_PRINT)
7632 printf(")\n");
7633 }
7634
7635
7636 ahd_set_scbptr(ahd, savedscbptr);
7637 ahd_restore_modes(ahd, saved_modes);
7638 return (found);
7639}
7640
7641static int
7642ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel,
7643 int lun, u_int tag, role_t role, uint32_t status,
7644 ahd_search_action action, u_int *list_head,
7645 u_int *list_tail, u_int tid)
7646{
7647 struct scb *scb;
7648 u_int scbid;
7649 u_int next;
7650 u_int prev;
7651 int found;
7652
7653 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
7654 found = 0;
7655 prev = SCB_LIST_NULL;
7656 next = *list_head;
7657 *list_tail = SCB_LIST_NULL;
7658 for (scbid = next; !SCBID_IS_NULL(scbid); scbid = next) {
7659 if (scbid >= ahd->scb_data.numscbs) {
7660 printf("%s:SCB List inconsistency. "
7661 "SCB == 0x%x, yet numscbs == 0x%x.",
7662 ahd_name(ahd), scbid, ahd->scb_data.numscbs);
7663 ahd_dump_card_state(ahd);
7664 panic("for safety");
7665 }
7666 scb = ahd_lookup_scb(ahd, scbid);
7667 if (scb == NULL) {
7668 printf("%s: SCB = %d Not Active!\n",
7669 ahd_name(ahd), scbid);
7670 panic("Waiting List traversal\n");
7671 }
7672 ahd_set_scbptr(ahd, scbid);
7673 *list_tail = scbid;
7674 next = ahd_inw_scbram(ahd, SCB_NEXT);
7675 if (ahd_match_scb(ahd, scb, target, channel,
7676 lun, SCB_LIST_NULL, role) == 0) {
7677 prev = scbid;
7678 continue;
7679 }
7680 found++;
7681 switch (action) {
7682 case SEARCH_COMPLETE:
7683 if ((scb->flags & SCB_ACTIVE) == 0)
7684 printf("Inactive SCB in Waiting List\n");
7685 ahd_done_with_status(ahd, scb, status);
7686
7687 case SEARCH_REMOVE:
7688 ahd_rem_wscb(ahd, scbid, prev, next, tid);
7689 *list_tail = prev;
7690 if (SCBID_IS_NULL(prev))
7691 *list_head = next;
7692 break;
7693 case SEARCH_PRINT:
7694 printf("0x%x ", scbid);
7695 case SEARCH_COUNT:
7696 prev = scbid;
7697 break;
7698 }
7699 if (found > AHD_SCB_MAX)
7700 panic("SCB LIST LOOP");
7701 }
7702 if (action == SEARCH_COMPLETE
7703 || action == SEARCH_REMOVE)
7704 ahd_outw(ahd, CMDS_PENDING, ahd_inw(ahd, CMDS_PENDING) - found);
7705 return (found);
7706}
7707
7708static void
7709ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev,
7710 u_int tid_cur, u_int tid_next)
7711{
7712 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
7713
7714 if (SCBID_IS_NULL(tid_cur)) {
7715
7716
7717 if (SCBID_IS_NULL(tid_prev)) {
7718 ahd_outw(ahd, WAITING_TID_HEAD, tid_next);
7719 } else {
7720 ahd_set_scbptr(ahd, tid_prev);
7721 ahd_outw(ahd, SCB_NEXT2, tid_next);
7722 }
7723 if (SCBID_IS_NULL(tid_next))
7724 ahd_outw(ahd, WAITING_TID_TAIL, tid_prev);
7725 } else {
7726
7727
7728 if (SCBID_IS_NULL(tid_prev)) {
7729 ahd_outw(ahd, WAITING_TID_HEAD, tid_cur);
7730 } else {
7731 ahd_set_scbptr(ahd, tid_prev);
7732 ahd_outw(ahd, SCB_NEXT2, tid_cur);
7733 }
7734 ahd_set_scbptr(ahd, tid_cur);
7735 ahd_outw(ahd, SCB_NEXT2, tid_next);
7736
7737 if (SCBID_IS_NULL(tid_next))
7738 ahd_outw(ahd, WAITING_TID_TAIL, tid_cur);
7739 }
7740}
7741
7742
7743
7744
7745
7746static u_int
7747ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,
7748 u_int prev, u_int next, u_int tid)
7749{
7750 u_int tail_offset;
7751
7752 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
7753 if (!SCBID_IS_NULL(prev)) {
7754 ahd_set_scbptr(ahd, prev);
7755 ahd_outw(ahd, SCB_NEXT, next);
7756 }
7757
7758
7759
7760
7761
7762
7763
7764
7765 tail_offset = WAITING_SCB_TAILS + (2 * tid);
7766 if (SCBID_IS_NULL(next)
7767 && ahd_inw(ahd, tail_offset) == scbid)
7768 ahd_outw(ahd, tail_offset, prev);
7769
7770 ahd_add_scb_to_free_list(ahd, scbid);
7771 return (next);
7772}
7773
7774
7775
7776
7777
7778
7779static void
7780ahd_add_scb_to_free_list(struct ahd_softc *ahd, u_int scbid)
7781{
7782
7783
7784
7785
7786
7787
7788}
7789
7790
7791
7792
7793
7794
7795
7796
7797static int
7798ahd_abort_scbs(struct ahd_softc *ahd, int target, char channel,
7799 int lun, u_int tag, role_t role, uint32_t status)
7800{
7801 struct scb *scbp;
7802 struct scb *scbp_next;
7803 u_int i, j;
7804 u_int maxtarget;
7805 u_int minlun;
7806 u_int maxlun;
7807 int found;
7808 ahd_mode_state saved_modes;
7809
7810
7811 saved_modes = ahd_save_modes(ahd);
7812 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
7813
7814 found = ahd_search_qinfifo(ahd, target, channel, lun, SCB_LIST_NULL,
7815 role, CAM_REQUEUE_REQ, SEARCH_COMPLETE);
7816
7817
7818
7819
7820 i = 0;
7821 maxtarget = 16;
7822 if (target != CAM_TARGET_WILDCARD) {
7823 i = target;
7824 if (channel == 'B')
7825 i += 8;
7826 maxtarget = i + 1;
7827 }
7828
7829 if (lun == CAM_LUN_WILDCARD) {
7830 minlun = 0;
7831 maxlun = AHD_NUM_LUNS_NONPKT;
7832 } else if (lun >= AHD_NUM_LUNS_NONPKT) {
7833 minlun = maxlun = 0;
7834 } else {
7835 minlun = lun;
7836 maxlun = lun + 1;
7837 }
7838
7839 if (role != ROLE_TARGET) {
7840 for (;i < maxtarget; i++) {
7841 for (j = minlun;j < maxlun; j++) {
7842 u_int scbid;
7843 u_int tcl;
7844
7845 tcl = BUILD_TCL_RAW(i, 'A', j);
7846 scbid = ahd_find_busy_tcl(ahd, tcl);
7847 scbp = ahd_lookup_scb(ahd, scbid);
7848 if (scbp == NULL
7849 || ahd_match_scb(ahd, scbp, target, channel,
7850 lun, tag, role) == 0)
7851 continue;
7852 ahd_unbusy_tcl(ahd, BUILD_TCL_RAW(i, 'A', j));
7853 }
7854 }
7855 }
7856
7857
7858
7859
7860
7861 ahd_flush_qoutfifo(ahd);
7862
7863
7864
7865
7866
7867
7868
7869 scbp_next = LIST_FIRST(&ahd->pending_scbs);
7870 while (scbp_next != NULL) {
7871 scbp = scbp_next;
7872 scbp_next = LIST_NEXT(scbp, pending_links);
7873 if (ahd_match_scb(ahd, scbp, target, channel, lun, tag, role)) {
7874 cam_status ostat;
7875
7876 ostat = ahd_get_transaction_status(scbp);
7877 if (ostat == CAM_REQ_INPROG)
7878 ahd_set_transaction_status(scbp, status);
7879 if (ahd_get_transaction_status(scbp) != CAM_REQ_CMP)
7880 ahd_freeze_scb(scbp);
7881 if ((scbp->flags & SCB_ACTIVE) == 0)
7882 printf("Inactive SCB on pending list\n");
7883 ahd_done(ahd, scbp);
7884 found++;
7885 }
7886 }
7887 ahd_restore_modes(ahd, saved_modes);
7888 ahd_platform_abort_scbs(ahd, target, channel, lun, tag, role, status);
7889 ahd->flags |= AHD_UPDATE_PEND_CMDS;
7890 return found;
7891}
7892
7893static void
7894ahd_reset_current_bus(struct ahd_softc *ahd)
7895{
7896 uint8_t scsiseq;
7897
7898 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
7899 ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) & ~ENSCSIRST);
7900 scsiseq = ahd_inb(ahd, SCSISEQ0) & ~(ENSELO|ENARBO|SCSIRSTO);
7901 ahd_outb(ahd, SCSISEQ0, scsiseq | SCSIRSTO);
7902 ahd_flush_device_writes(ahd);
7903 ahd_delay(AHD_BUSRESET_DELAY);
7904
7905 ahd_outb(ahd, SCSISEQ0, scsiseq);
7906 ahd_flush_device_writes(ahd);
7907 ahd_delay(AHD_BUSRESET_DELAY);
7908 if ((ahd->bugs & AHD_SCSIRST_BUG) != 0) {
7909
7910
7911
7912
7913
7914
7915 ahd_reset(ahd, TRUE);
7916 ahd_intr_enable(ahd, TRUE);
7917 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
7918 }
7919
7920 ahd_clear_intstat(ahd);
7921}
7922
7923int
7924ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
7925{
7926 struct ahd_devinfo devinfo;
7927 u_int initiator;
7928 u_int target;
7929 u_int max_scsiid;
7930 int found;
7931 u_int fifo;
7932 u_int next_fifo;
7933 uint8_t scsiseq;
7934
7935
7936
7937
7938 if (ahd->flags & AHD_BUS_RESET_ACTIVE) {
7939 printf("%s: bus reset still active\n",
7940 ahd_name(ahd));
7941 return 0;
7942 }
7943 ahd->flags |= AHD_BUS_RESET_ACTIVE;
7944
7945 ahd->pending_device = NULL;
7946
7947 ahd_compile_devinfo(&devinfo,
7948 CAM_TARGET_WILDCARD,
7949 CAM_TARGET_WILDCARD,
7950 CAM_LUN_WILDCARD,
7951 channel, ROLE_UNKNOWN);
7952 ahd_pause(ahd);
7953
7954
7955 ahd_clear_critical_section(ahd);
7956
7957
7958
7959
7960
7961
7962 ahd_run_qoutfifo(ahd);
7963#ifdef AHD_TARGET_MODE
7964 if ((ahd->flags & AHD_TARGETROLE) != 0) {
7965 ahd_run_tqinfifo(ahd, TRUE);
7966 }
7967#endif
7968 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
7969
7970
7971
7972
7973
7974 ahd_outb(ahd, SCSISEQ0, 0);
7975 ahd_outb(ahd, SCSISEQ1, 0);
7976
7977
7978
7979
7980
7981
7982 next_fifo = fifo = ahd_inb(ahd, DFFSTAT) & CURRFIFO;
7983 if (next_fifo > CURRFIFO_1)
7984
7985 next_fifo = fifo = 0;
7986 do {
7987 next_fifo ^= CURRFIFO_1;
7988 ahd_set_modes(ahd, next_fifo, next_fifo);
7989 ahd_outb(ahd, DFCNTRL,
7990 ahd_inb(ahd, DFCNTRL) & ~(SCSIEN|HDMAEN));
7991 while ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0)
7992 ahd_delay(10);
7993
7994
7995
7996 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
7997 ahd_outb(ahd, DFFSTAT, next_fifo);
7998 } while (next_fifo != fifo);
7999
8000
8001
8002
8003 ahd_clear_msg_state(ahd);
8004 ahd_outb(ahd, SIMODE1,
8005 ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST));
8006
8007 if (initiate_reset)
8008 ahd_reset_current_bus(ahd);
8009
8010 ahd_clear_intstat(ahd);
8011
8012
8013
8014
8015
8016 found = ahd_abort_scbs(ahd, CAM_TARGET_WILDCARD, channel,
8017 CAM_LUN_WILDCARD, SCB_LIST_NULL,
8018 ROLE_UNKNOWN, CAM_SCSI_BUS_RESET);
8019
8020
8021
8022
8023 ahd_clear_fifo(ahd, 0);
8024 ahd_clear_fifo(ahd, 1);
8025
8026
8027
8028
8029 ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);
8030
8031
8032
8033
8034 ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST);
8035 scsiseq = ahd_inb(ahd, SCSISEQ_TEMPLATE);
8036 ahd_outb(ahd, SCSISEQ1, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP));
8037
8038 max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7;
8039#ifdef AHD_TARGET_MODE
8040
8041
8042
8043
8044 for (target = 0; target <= max_scsiid; target++) {
8045 struct ahd_tmode_tstate* tstate;
8046 u_int lun;
8047
8048 tstate = ahd->enabled_targets[target];
8049 if (tstate == NULL)
8050 continue;
8051 for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
8052 struct ahd_tmode_lstate* lstate;
8053
8054 lstate = tstate->enabled_luns[lun];
8055 if (lstate == NULL)
8056 continue;
8057
8058 ahd_queue_lstate_event(ahd, lstate, CAM_TARGET_WILDCARD,
8059 EVENT_TYPE_BUS_RESET, 0);
8060 ahd_send_lstate_events(ahd, lstate);
8061 }
8062 }
8063#endif
8064
8065
8066
8067 for (target = 0; target <= max_scsiid; target++) {
8068
8069 if (ahd->enabled_targets[target] == NULL)
8070 continue;
8071 for (initiator = 0; initiator <= max_scsiid; initiator++) {
8072 struct ahd_devinfo devinfo;
8073
8074 ahd_compile_devinfo(&devinfo, target, initiator,
8075 CAM_LUN_WILDCARD,
8076 'A', ROLE_UNKNOWN);
8077 ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
8078 AHD_TRANS_CUR, TRUE);
8079 ahd_set_syncrate(ahd, &devinfo, 0,
8080 0, 0,
8081 AHD_TRANS_CUR, TRUE);
8082 }
8083 }
8084
8085
8086 ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD,
8087 CAM_LUN_WILDCARD, AC_BUS_RESET);
8088
8089 ahd_restart(ahd);
8090
8091 return (found);
8092}
8093
8094
8095static void
8096ahd_stat_timer(void *arg)
8097{
8098 struct ahd_softc *ahd = arg;
8099 u_long s;
8100 int enint_coal;
8101
8102 ahd_lock(ahd, &s);
8103
8104 enint_coal = ahd->hs_mailbox & ENINT_COALESCE;
8105 if (ahd->cmdcmplt_total > ahd->int_coalescing_threshold)
8106 enint_coal |= ENINT_COALESCE;
8107 else if (ahd->cmdcmplt_total < ahd->int_coalescing_stop_threshold)
8108 enint_coal &= ~ENINT_COALESCE;
8109
8110 if (enint_coal != (ahd->hs_mailbox & ENINT_COALESCE)) {
8111 ahd_enable_coalescing(ahd, enint_coal);
8112#ifdef AHD_DEBUG
8113 if ((ahd_debug & AHD_SHOW_INT_COALESCING) != 0)
8114 printf("%s: Interrupt coalescing "
8115 "now %sabled. Cmds %d\n",
8116 ahd_name(ahd),
8117 (enint_coal & ENINT_COALESCE) ? "en" : "dis",
8118 ahd->cmdcmplt_total);
8119#endif
8120 }
8121
8122 ahd->cmdcmplt_bucket = (ahd->cmdcmplt_bucket+1) & (AHD_STAT_BUCKETS-1);
8123 ahd->cmdcmplt_total -= ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket];
8124 ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket] = 0;
8125 ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US,
8126 ahd_stat_timer, ahd);
8127 ahd_unlock(ahd, &s);
8128}
8129
8130
8131
8132static void
8133ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
8134{
8135 struct hardware_scb *hscb;
8136 int paused;
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147 hscb = scb->hscb;
8148
8149 if (ahd_is_paused(ahd)) {
8150 paused = 1;
8151 } else {
8152 paused = 0;
8153 ahd_pause(ahd);
8154 }
8155
8156
8157 ahd_freeze_devq(ahd, scb);
8158 ahd_freeze_scb(scb);
8159 ahd->qfreeze_cnt++;
8160 ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
8161
8162 if (paused == 0)
8163 ahd_unpause(ahd);
8164
8165
8166 if ((scb->flags & SCB_SENSE) != 0) {
8167
8168
8169
8170
8171 scb->flags &= ~SCB_SENSE;
8172 ahd_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
8173 ahd_done(ahd, scb);
8174 return;
8175 }
8176 ahd_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR);
8177 ahd_set_scsi_status(scb, hscb->shared_data.istatus.scsi_status);
8178 switch (hscb->shared_data.istatus.scsi_status) {
8179 case STATUS_PKT_SENSE:
8180 {
8181 struct scsi_status_iu_header *siu;
8182
8183 ahd_sync_sense(ahd, scb, BUS_DMASYNC_POSTREAD);
8184 siu = (struct scsi_status_iu_header *)scb->sense_data;
8185 ahd_set_scsi_status(scb, siu->status);
8186#ifdef AHD_DEBUG
8187 if ((ahd_debug & AHD_SHOW_SENSE) != 0) {
8188 ahd_print_path(ahd, scb);
8189 printf("SCB 0x%x Received PKT Status of 0x%x\n",
8190 SCB_GET_TAG(scb), siu->status);
8191 printf("\tflags = 0x%x, sense len = 0x%x, "
8192 "pktfail = 0x%x\n",
8193 siu->flags, scsi_4btoul(siu->sense_length),
8194 scsi_4btoul(siu->pkt_failures_length));
8195 }
8196#endif
8197 if ((siu->flags & SIU_RSPVALID) != 0) {
8198 ahd_print_path(ahd, scb);
8199 if (scsi_4btoul(siu->pkt_failures_length) < 4) {
8200 printf("Unable to parse pkt_failures\n");
8201 } else {
8202
8203 switch (SIU_PKTFAIL_CODE(siu)) {
8204 case SIU_PFC_NONE:
8205 printf("No packet failure found\n");
8206 break;
8207 case SIU_PFC_CIU_FIELDS_INVALID:
8208 printf("Invalid Command IU Field\n");
8209 break;
8210 case SIU_PFC_TMF_NOT_SUPPORTED:
8211 printf("TMF not supportd\n");
8212 break;
8213 case SIU_PFC_TMF_FAILED:
8214 printf("TMF failed\n");
8215 break;
8216 case SIU_PFC_INVALID_TYPE_CODE:
8217 printf("Invalid L_Q Type code\n");
8218 break;
8219 case SIU_PFC_ILLEGAL_REQUEST:
8220 printf("Illegal request\n");
8221 default:
8222 break;
8223 }
8224 }
8225 if (siu->status == SCSI_STATUS_OK)
8226 ahd_set_transaction_status(scb,
8227 CAM_REQ_CMP_ERR);
8228 }
8229 if ((siu->flags & SIU_SNSVALID) != 0) {
8230 scb->flags |= SCB_PKT_SENSE;
8231#ifdef AHD_DEBUG
8232 if ((ahd_debug & AHD_SHOW_SENSE) != 0)
8233 printf("Sense data available\n");
8234#endif
8235 }
8236 ahd_done(ahd, scb);
8237 break;
8238 }
8239 case SCSI_STATUS_CMD_TERMINATED:
8240 case SCSI_STATUS_CHECK_COND:
8241 {
8242 struct ahd_devinfo devinfo;
8243 struct ahd_dma_seg *sg;
8244 struct scsi_sense *sc;
8245 struct ahd_initiator_tinfo *targ_info;
8246 struct ahd_tmode_tstate *tstate;
8247 struct ahd_transinfo *tinfo;
8248#ifdef AHD_DEBUG
8249 if (ahd_debug & AHD_SHOW_SENSE) {
8250 ahd_print_path(ahd, scb);
8251 printf("SCB %d: requests Check Status\n",
8252 SCB_GET_TAG(scb));
8253 }
8254#endif
8255
8256 if (ahd_perform_autosense(scb) == 0)
8257 break;
8258
8259 ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb),
8260 SCB_GET_TARGET(ahd, scb),
8261 SCB_GET_LUN(scb),
8262 SCB_GET_CHANNEL(ahd, scb),
8263 ROLE_INITIATOR);
8264 targ_info = ahd_fetch_transinfo(ahd,
8265 devinfo.channel,
8266 devinfo.our_scsiid,
8267 devinfo.target,
8268 &tstate);
8269 tinfo = &targ_info->curr;
8270 sg = scb->sg_list;
8271 sc = (struct scsi_sense *)hscb->shared_data.idata.cdb;
8272
8273
8274
8275 ahd_update_residual(ahd, scb);
8276#ifdef AHD_DEBUG
8277 if (ahd_debug & AHD_SHOW_SENSE) {
8278 ahd_print_path(ahd, scb);
8279 printf("Sending Sense\n");
8280 }
8281#endif
8282 scb->sg_count = 0;
8283 sg = ahd_sg_setup(ahd, scb, sg, ahd_get_sense_bufaddr(ahd, scb),
8284 ahd_get_sense_bufsize(ahd, scb),
8285 TRUE);
8286 sc->opcode = REQUEST_SENSE;
8287 sc->byte2 = 0;
8288 if (tinfo->protocol_version <= SCSI_REV_2
8289 && SCB_GET_LUN(scb) < 8)
8290 sc->byte2 = SCB_GET_LUN(scb) << 5;
8291 sc->unused[0] = 0;
8292 sc->unused[1] = 0;
8293 sc->length = ahd_get_sense_bufsize(ahd, scb);
8294 sc->control = 0;
8295
8296
8297
8298
8299
8300
8301
8302
8303 hscb->control = 0;
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313 if (ahd_get_residual(scb) == ahd_get_transfer_length(scb)) {
8314 ahd_update_neg_request(ahd, &devinfo,
8315 tstate, targ_info,
8316 AHD_NEG_IF_NON_ASYNC);
8317 }
8318 if (tstate->auto_negotiate & devinfo.target_mask) {
8319 hscb->control |= MK_MESSAGE;
8320 scb->flags &=
8321 ~(SCB_NEGOTIATE|SCB_ABORT|SCB_DEVICE_RESET);
8322 scb->flags |= SCB_AUTO_NEGOTIATE;
8323 }
8324 hscb->cdb_len = sizeof(*sc);
8325 ahd_setup_data_scb(ahd, scb);
8326 scb->flags |= SCB_SENSE;
8327 ahd_queue_scb(ahd, scb);
8328 break;
8329 }
8330 case SCSI_STATUS_OK:
8331 printf("%s: Interrupted for staus of 0???\n",
8332 ahd_name(ahd));
8333
8334 default:
8335 ahd_done(ahd, scb);
8336 break;
8337 }
8338}
8339
8340static void
8341ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb)
8342{
8343 if (scb->hscb->shared_data.istatus.scsi_status != 0) {
8344 ahd_handle_scsi_status(ahd, scb);
8345 } else {
8346 ahd_calc_residual(ahd, scb);
8347 ahd_done(ahd, scb);
8348 }
8349}
8350
8351
8352
8353
8354static void
8355ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb)
8356{
8357 struct hardware_scb *hscb;
8358 struct initiator_status *spkt;
8359 uint32_t sgptr;
8360 uint32_t resid_sgptr;
8361 uint32_t resid;
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373
8374
8375
8376
8377
8378
8379 hscb = scb->hscb;
8380 sgptr = ahd_le32toh(hscb->sgptr);
8381 if ((sgptr & SG_STATUS_VALID) == 0)
8382
8383 return;
8384 sgptr &= ~SG_STATUS_VALID;
8385
8386 if ((sgptr & SG_LIST_NULL) != 0)
8387
8388 return;
8389
8390
8391
8392
8393
8394
8395
8396 spkt = &hscb->shared_data.istatus;
8397 resid_sgptr = ahd_le32toh(spkt->residual_sgptr);
8398 if ((sgptr & SG_FULL_RESID) != 0) {
8399
8400 resid = ahd_get_transfer_length(scb);
8401 } else if ((resid_sgptr & SG_LIST_NULL) != 0) {
8402
8403 return;
8404 } else if ((resid_sgptr & SG_OVERRUN_RESID) != 0) {
8405 ahd_print_path(ahd, scb);
8406 printf("data overrun detected Tag == 0x%x.\n",
8407 SCB_GET_TAG(scb));
8408 ahd_freeze_devq(ahd, scb);
8409 ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR);
8410 ahd_freeze_scb(scb);
8411 return;
8412 } else if ((resid_sgptr & ~SG_PTR_MASK) != 0) {
8413 panic("Bogus resid sgptr value 0x%x\n", resid_sgptr);
8414
8415 } else {
8416 struct ahd_dma_seg *sg;
8417
8418
8419
8420
8421
8422 resid = ahd_le32toh(spkt->residual_datacnt) & AHD_SG_LEN_MASK;
8423 sg = ahd_sg_bus_to_virt(ahd, scb, resid_sgptr & SG_PTR_MASK);
8424
8425
8426 sg--;
8427
8428
8429
8430
8431
8432
8433 while ((ahd_le32toh(sg->len) & AHD_DMA_LAST_SEG) == 0) {
8434 sg++;
8435 resid += ahd_le32toh(sg->len) & AHD_SG_LEN_MASK;
8436 }
8437 }
8438 if ((scb->flags & SCB_SENSE) == 0)
8439 ahd_set_residual(scb, resid);
8440 else
8441 ahd_set_sense_residual(scb, resid);
8442
8443#ifdef AHD_DEBUG
8444 if ((ahd_debug & AHD_SHOW_MISC) != 0) {
8445 ahd_print_path(ahd, scb);
8446 printf("Handled %sResidual of %d bytes\n",
8447 (scb->flags & SCB_SENSE) ? "Sense " : "", resid);
8448 }
8449#endif
8450}
8451
8452
8453#ifdef AHD_TARGET_MODE
8454
8455
8456
8457static void
8458ahd_queue_lstate_event(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate,
8459 u_int initiator_id, u_int event_type, u_int event_arg)
8460{
8461 struct ahd_tmode_event *event;
8462 int pending;
8463
8464 xpt_freeze_devq(lstate->path, 1);
8465 if (lstate->event_w_idx >= lstate->event_r_idx)
8466 pending = lstate->event_w_idx - lstate->event_r_idx;
8467 else
8468 pending = AHD_TMODE_EVENT_BUFFER_SIZE + 1
8469 - (lstate->event_r_idx - lstate->event_w_idx);
8470
8471 if (event_type == EVENT_TYPE_BUS_RESET
8472 || event_type == MSG_BUS_DEV_RESET) {
8473
8474
8475
8476
8477
8478
8479 lstate->event_r_idx = 0;
8480 lstate->event_w_idx = 0;
8481 xpt_release_devq(lstate->path, pending, FALSE);
8482 }
8483
8484 if (pending == AHD_TMODE_EVENT_BUFFER_SIZE) {
8485 xpt_print_path(lstate->path);
8486 printf("immediate event %x:%x lost\n",
8487 lstate->event_buffer[lstate->event_r_idx].event_type,
8488 lstate->event_buffer[lstate->event_r_idx].event_arg);
8489 lstate->event_r_idx++;
8490 if (lstate->event_r_idx == AHD_TMODE_EVENT_BUFFER_SIZE)
8491 lstate->event_r_idx = 0;
8492 xpt_release_devq(lstate->path, 1, FALSE);
8493 }
8494
8495 event = &lstate->event_buffer[lstate->event_w_idx];
8496 event->initiator_id = initiator_id;
8497 event->event_type = event_type;
8498 event->event_arg = event_arg;
8499 lstate->event_w_idx++;
8500 if (lstate->event_w_idx == AHD_TMODE_EVENT_BUFFER_SIZE)
8501 lstate->event_w_idx = 0;
8502}
8503
8504
8505
8506
8507
8508void
8509ahd_send_lstate_events(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate)
8510{
8511 struct ccb_hdr *ccbh;
8512 struct ccb_immed_notify *inot;
8513
8514 while (lstate->event_r_idx != lstate->event_w_idx
8515 && (ccbh = SLIST_FIRST(&lstate->immed_notifies)) != NULL) {
8516 struct ahd_tmode_event *event;
8517
8518 event = &lstate->event_buffer[lstate->event_r_idx];
8519 SLIST_REMOVE_HEAD(&lstate->immed_notifies, sim_links.sle);
8520 inot = (struct ccb_immed_notify *)ccbh;
8521 switch (event->event_type) {
8522 case EVENT_TYPE_BUS_RESET:
8523 ccbh->status = CAM_SCSI_BUS_RESET|CAM_DEV_QFRZN;
8524 break;
8525 default:
8526 ccbh->status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN;
8527 inot->message_args[0] = event->event_type;
8528 inot->message_args[1] = event->event_arg;
8529 break;
8530 }
8531 inot->initiator_id = event->initiator_id;
8532 inot->sense_len = 0;
8533 xpt_done((union ccb *)inot);
8534 lstate->event_r_idx++;
8535 if (lstate->event_r_idx == AHD_TMODE_EVENT_BUFFER_SIZE)
8536 lstate->event_r_idx = 0;
8537 }
8538}
8539#endif
8540
8541
8542
8543#ifdef AHD_DUMP_SEQ
8544void
8545ahd_dumpseq(struct ahd_softc* ahd)
8546{
8547 int i;
8548 int max_prog;
8549
8550 max_prog = 2048;
8551
8552 ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
8553 ahd_outw(ahd, PRGMCNT, 0);
8554 for (i = 0; i < max_prog; i++) {
8555 uint8_t ins_bytes[4];
8556
8557 ahd_insb(ahd, SEQRAM, ins_bytes, 4);
8558 printf("0x%08x\n", ins_bytes[0] << 24
8559 | ins_bytes[1] << 16
8560 | ins_bytes[2] << 8
8561 | ins_bytes[3]);
8562 }
8563}
8564#endif
8565
8566static void
8567ahd_loadseq(struct ahd_softc *ahd)
8568{
8569 struct cs cs_table[num_critical_sections];
8570 u_int begin_set[num_critical_sections];
8571 u_int end_set[num_critical_sections];
8572 struct patch *cur_patch;
8573 u_int cs_count;
8574 u_int cur_cs;
8575 u_int i;
8576 int downloaded;
8577 u_int skip_addr;
8578 u_int sg_prefetch_cnt;
8579 u_int sg_prefetch_cnt_limit;
8580 u_int sg_prefetch_align;
8581 u_int sg_size;
8582 u_int cacheline_mask;
8583 uint8_t download_consts[DOWNLOAD_CONST_COUNT];
8584
8585 if (bootverbose)
8586 printf("%s: Downloading Sequencer Program...",
8587 ahd_name(ahd));
8588
8589#if DOWNLOAD_CONST_COUNT != 8
8590#error "Download Const Mismatch"
8591#endif
8592
8593
8594
8595
8596 cs_count = 0;
8597 cur_cs = 0;
8598 memset(begin_set, 0, sizeof(begin_set));
8599 memset(end_set, 0, sizeof(end_set));
8600
8601
8602
8603
8604
8605
8606
8607
8608
8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619 sg_prefetch_align = ahd->pci_cachesize;
8620 if (sg_prefetch_align == 0)
8621 sg_prefetch_align = 8;
8622
8623 while (powerof2(sg_prefetch_align) == 0)
8624 sg_prefetch_align--;
8625
8626 cacheline_mask = sg_prefetch_align - 1;
8627
8628
8629
8630
8631
8632
8633 if (sg_prefetch_align > CCSGADDR_MAX/2)
8634 sg_prefetch_align = CCSGADDR_MAX/2;
8635
8636 sg_prefetch_cnt = sg_prefetch_align;
8637
8638
8639
8640
8641 sg_size = sizeof(struct ahd_dma_seg);
8642 if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
8643 sg_size = sizeof(struct ahd_dma64_seg);
8644 while (sg_prefetch_cnt < sg_size)
8645 sg_prefetch_cnt += sg_prefetch_align;
8646
8647
8648
8649
8650
8651 if ((sg_prefetch_align % sg_size) != 0
8652 && (sg_prefetch_cnt < CCSGADDR_MAX))
8653 sg_prefetch_cnt += sg_prefetch_align;
8654
8655
8656
8657
8658
8659 sg_prefetch_cnt_limit = -(sg_prefetch_cnt - sg_size + 1);
8660 download_consts[SG_PREFETCH_CNT] = sg_prefetch_cnt;
8661 download_consts[SG_PREFETCH_CNT_LIMIT] = sg_prefetch_cnt_limit;
8662 download_consts[SG_PREFETCH_ALIGN_MASK] = ~(sg_prefetch_align - 1);
8663 download_consts[SG_PREFETCH_ADDR_MASK] = (sg_prefetch_align - 1);
8664 download_consts[SG_SIZEOF] = sg_size;
8665 download_consts[PKT_OVERRUN_BUFOFFSET] =
8666 (ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256;
8667 download_consts[SCB_TRANSFER_SIZE] = SCB_TRANSFER_SIZE_1BYTE_LUN;
8668 download_consts[CACHELINE_MASK] = cacheline_mask;
8669 cur_patch = patches;
8670 downloaded = 0;
8671 skip_addr = 0;
8672 ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
8673 ahd_outw(ahd, PRGMCNT, 0);
8674
8675 for (i = 0; i < sizeof(seqprog)/4; i++) {
8676 if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) {
8677
8678
8679
8680
8681 continue;
8682 }
8683
8684
8685
8686
8687 for (; cur_cs < num_critical_sections; cur_cs++) {
8688 if (critical_sections[cur_cs].end <= i) {
8689 if (begin_set[cs_count] == TRUE
8690 && end_set[cs_count] == FALSE) {
8691 cs_table[cs_count].end = downloaded;
8692 end_set[cs_count] = TRUE;
8693 cs_count++;
8694 }
8695 continue;
8696 }
8697 if (critical_sections[cur_cs].begin <= i
8698 && begin_set[cs_count] == FALSE) {
8699 cs_table[cs_count].begin = downloaded;
8700 begin_set[cs_count] = TRUE;
8701 }
8702 break;
8703 }
8704 ahd_download_instr(ahd, i, download_consts);
8705 downloaded++;
8706 }
8707
8708 ahd->num_critical_sections = cs_count;
8709 if (cs_count != 0) {
8710
8711 cs_count *= sizeof(struct cs);
8712 ahd->critical_sections = malloc(cs_count, M_DEVBUF, M_NOWAIT);
8713 if (ahd->critical_sections == NULL)
8714 panic("ahd_loadseq: Could not malloc");
8715 memcpy(ahd->critical_sections, cs_table, cs_count);
8716 }
8717 ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE);
8718
8719 if (bootverbose) {
8720 printf(" %d instructions downloaded\n", downloaded);
8721 printf("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n",
8722 ahd_name(ahd), ahd->features, ahd->bugs, ahd->flags);
8723 }
8724}
8725
8726static int
8727ahd_check_patch(struct ahd_softc *ahd, struct patch **start_patch,
8728 u_int start_instr, u_int *skip_addr)
8729{
8730 struct patch *cur_patch;
8731 struct patch *last_patch;
8732 u_int num_patches;
8733
8734 num_patches = ARRAY_SIZE(patches);
8735 last_patch = &patches[num_patches];
8736 cur_patch = *start_patch;
8737
8738 while (cur_patch < last_patch && start_instr == cur_patch->begin) {
8739
8740 if (cur_patch->patch_func(ahd) == 0) {
8741
8742
8743 *skip_addr = start_instr + cur_patch->skip_instr;
8744 cur_patch += cur_patch->skip_patch;
8745 } else {
8746
8747
8748
8749
8750 cur_patch++;
8751 }
8752 }
8753
8754 *start_patch = cur_patch;
8755 if (start_instr < *skip_addr)
8756
8757 return (0);
8758
8759 return (1);
8760}
8761
8762static u_int
8763ahd_resolve_seqaddr(struct ahd_softc *ahd, u_int address)
8764{
8765 struct patch *cur_patch;
8766 int address_offset;
8767 u_int skip_addr;
8768 u_int i;
8769
8770 address_offset = 0;
8771 cur_patch = patches;
8772 skip_addr = 0;
8773
8774 for (i = 0; i < address;) {
8775
8776 ahd_check_patch(ahd, &cur_patch, i, &skip_addr);
8777
8778 if (skip_addr > i) {
8779 int end_addr;
8780
8781 end_addr = min(address, skip_addr);
8782 address_offset += end_addr - i;
8783 i = skip_addr;
8784 } else {
8785 i++;
8786 }
8787 }
8788 return (address - address_offset);
8789}
8790
8791static void
8792ahd_download_instr(struct ahd_softc *ahd, u_int instrptr, uint8_t *dconsts)
8793{
8794 union ins_formats instr;
8795 struct ins_format1 *fmt1_ins;
8796 struct ins_format3 *fmt3_ins;
8797 u_int opcode;
8798
8799
8800
8801
8802 instr.integer = ahd_le32toh(*(uint32_t*)&seqprog[instrptr * 4]);
8803
8804 fmt1_ins = &instr.format1;
8805 fmt3_ins = NULL;
8806
8807
8808 opcode = instr.format1.opcode;
8809 switch (opcode) {
8810 case AIC_OP_JMP:
8811 case AIC_OP_JC:
8812 case AIC_OP_JNC:
8813 case AIC_OP_CALL:
8814 case AIC_OP_JNE:
8815 case AIC_OP_JNZ:
8816 case AIC_OP_JE:
8817 case AIC_OP_JZ:
8818 {
8819 fmt3_ins = &instr.format3;
8820 fmt3_ins->address = ahd_resolve_seqaddr(ahd, fmt3_ins->address);
8821
8822 }
8823 case AIC_OP_OR:
8824 case AIC_OP_AND:
8825 case AIC_OP_XOR:
8826 case AIC_OP_ADD:
8827 case AIC_OP_ADC:
8828 case AIC_OP_BMOV:
8829 if (fmt1_ins->parity != 0) {
8830 fmt1_ins->immediate = dconsts[fmt1_ins->immediate];
8831 }
8832 fmt1_ins->parity = 0;
8833
8834 case AIC_OP_ROL:
8835 {
8836 int i, count;
8837
8838
8839 for (i = 0, count = 0; i < 31; i++) {
8840 uint32_t mask;
8841
8842 mask = 0x01 << i;
8843 if ((instr.integer & mask) != 0)
8844 count++;
8845 }
8846 if ((count & 0x01) == 0)
8847 instr.format1.parity = 1;
8848
8849
8850 instr.integer = ahd_htole32(instr.integer);
8851 ahd_outsb(ahd, SEQRAM, instr.bytes, 4);
8852 break;
8853 }
8854 default:
8855 panic("Unknown opcode encountered in seq program");
8856 break;
8857 }
8858}
8859
8860static int
8861ahd_probe_stack_size(struct ahd_softc *ahd)
8862{
8863 int last_probe;
8864
8865 last_probe = 0;
8866 while (1) {
8867 int i;
8868
8869
8870
8871
8872
8873
8874
8875 for (i = 1; i <= last_probe+1; i++) {
8876 ahd_outb(ahd, STACK, i & 0xFF);
8877 ahd_outb(ahd, STACK, (i >> 8) & 0xFF);
8878 }
8879
8880
8881 for (i = last_probe+1; i > 0; i--) {
8882 u_int stack_entry;
8883
8884 stack_entry = ahd_inb(ahd, STACK)
8885 |(ahd_inb(ahd, STACK) << 8);
8886 if (stack_entry != i)
8887 goto sized;
8888 }
8889 last_probe++;
8890 }
8891sized:
8892 return (last_probe);
8893}
8894
8895int
8896ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries,
8897 const char *name, u_int address, u_int value,
8898 u_int *cur_column, u_int wrap_point)
8899{
8900 int printed;
8901 u_int printed_mask;
8902
8903 if (cur_column != NULL && *cur_column >= wrap_point) {
8904 printf("\n");
8905 *cur_column = 0;
8906 }
8907 printed = printf("%s[0x%x]", name, value);
8908 if (table == NULL) {
8909 printed += printf(" ");
8910 *cur_column += printed;
8911 return (printed);
8912 }
8913 printed_mask = 0;
8914 while (printed_mask != 0xFF) {
8915 int entry;
8916
8917 for (entry = 0; entry < num_entries; entry++) {
8918 if (((value & table[entry].mask)
8919 != table[entry].value)
8920 || ((printed_mask & table[entry].mask)
8921 == table[entry].mask))
8922 continue;
8923
8924 printed += printf("%s%s",
8925 printed_mask == 0 ? ":(" : "|",
8926 table[entry].name);
8927 printed_mask |= table[entry].mask;
8928
8929 break;
8930 }
8931 if (entry >= num_entries)
8932 break;
8933 }
8934 if (printed_mask != 0)
8935 printed += printf(") ");
8936 else
8937 printed += printf(" ");
8938 if (cur_column != NULL)
8939 *cur_column += printed;
8940 return (printed);
8941}
8942
8943void
8944ahd_dump_card_state(struct ahd_softc *ahd)
8945{
8946 struct scb *scb;
8947 ahd_mode_state saved_modes;
8948 u_int dffstat;
8949 int paused;
8950 u_int scb_index;
8951 u_int saved_scb_index;
8952 u_int cur_col;
8953 int i;
8954
8955 if (ahd_is_paused(ahd)) {
8956 paused = 1;
8957 } else {
8958 paused = 0;
8959 ahd_pause(ahd);
8960 }
8961 saved_modes = ahd_save_modes(ahd);
8962 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
8963 printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n"
8964 "%s: Dumping Card State at program address 0x%x Mode 0x%x\n",
8965 ahd_name(ahd),
8966 ahd_inw(ahd, CURADDR),
8967 ahd_build_mode_state(ahd, ahd->saved_src_mode,
8968 ahd->saved_dst_mode));
8969 if (paused)
8970 printf("Card was paused\n");
8971
8972 if (ahd_check_cmdcmpltqueues(ahd))
8973 printf("Completions are pending\n");
8974
8975
8976
8977
8978 cur_col = 0;
8979 ahd_intstat_print(ahd_inb(ahd, INTSTAT), &cur_col, 50);
8980 ahd_seloid_print(ahd_inb(ahd, SELOID), &cur_col, 50);
8981 ahd_selid_print(ahd_inb(ahd, SELID), &cur_col, 50);
8982 ahd_hs_mailbox_print(ahd_inb(ahd, LOCAL_HS_MAILBOX), &cur_col, 50);
8983 ahd_intctl_print(ahd_inb(ahd, INTCTL), &cur_col, 50);
8984 ahd_seqintstat_print(ahd_inb(ahd, SEQINTSTAT), &cur_col, 50);
8985 ahd_saved_mode_print(ahd_inb(ahd, SAVED_MODE), &cur_col, 50);
8986 ahd_dffstat_print(ahd_inb(ahd, DFFSTAT), &cur_col, 50);
8987 ahd_scsisigi_print(ahd_inb(ahd, SCSISIGI), &cur_col, 50);
8988 ahd_scsiphase_print(ahd_inb(ahd, SCSIPHASE), &cur_col, 50);
8989 ahd_scsibus_print(ahd_inb(ahd, SCSIBUS), &cur_col, 50);
8990 ahd_lastphase_print(ahd_inb(ahd, LASTPHASE), &cur_col, 50);
8991 ahd_scsiseq0_print(ahd_inb(ahd, SCSISEQ0), &cur_col, 50);
8992 ahd_scsiseq1_print(ahd_inb(ahd, SCSISEQ1), &cur_col, 50);
8993 ahd_seqctl0_print(ahd_inb(ahd, SEQCTL0), &cur_col, 50);
8994 ahd_seqintctl_print(ahd_inb(ahd, SEQINTCTL), &cur_col, 50);
8995 ahd_seq_flags_print(ahd_inb(ahd, SEQ_FLAGS), &cur_col, 50);
8996 ahd_seq_flags2_print(ahd_inb(ahd, SEQ_FLAGS2), &cur_col, 50);
8997 ahd_qfreeze_count_print(ahd_inw(ahd, QFREEZE_COUNT), &cur_col, 50);
8998 ahd_kernel_qfreeze_count_print(ahd_inw(ahd, KERNEL_QFREEZE_COUNT),
8999 &cur_col, 50);
9000 ahd_mk_message_scb_print(ahd_inw(ahd, MK_MESSAGE_SCB), &cur_col, 50);
9001 ahd_mk_message_scsiid_print(ahd_inb(ahd, MK_MESSAGE_SCSIID),
9002 &cur_col, 50);
9003 ahd_sstat0_print(ahd_inb(ahd, SSTAT0), &cur_col, 50);
9004 ahd_sstat1_print(ahd_inb(ahd, SSTAT1), &cur_col, 50);
9005 ahd_sstat2_print(ahd_inb(ahd, SSTAT2), &cur_col, 50);
9006 ahd_sstat3_print(ahd_inb(ahd, SSTAT3), &cur_col, 50);
9007 ahd_perrdiag_print(ahd_inb(ahd, PERRDIAG), &cur_col, 50);
9008 ahd_simode1_print(ahd_inb(ahd, SIMODE1), &cur_col, 50);
9009 ahd_lqistat0_print(ahd_inb(ahd, LQISTAT0), &cur_col, 50);
9010 ahd_lqistat1_print(ahd_inb(ahd, LQISTAT1), &cur_col, 50);
9011 ahd_lqistat2_print(ahd_inb(ahd, LQISTAT2), &cur_col, 50);
9012 ahd_lqostat0_print(ahd_inb(ahd, LQOSTAT0), &cur_col, 50);
9013 ahd_lqostat1_print(ahd_inb(ahd, LQOSTAT1), &cur_col, 50);
9014 ahd_lqostat2_print(ahd_inb(ahd, LQOSTAT2), &cur_col, 50);
9015 printf("\n");
9016 printf("\nSCB Count = %d CMDS_PENDING = %d LASTSCB 0x%x "
9017 "CURRSCB 0x%x NEXTSCB 0x%x\n",
9018 ahd->scb_data.numscbs, ahd_inw(ahd, CMDS_PENDING),
9019 ahd_inw(ahd, LASTSCB), ahd_inw(ahd, CURRSCB),
9020 ahd_inw(ahd, NEXTSCB));
9021 cur_col = 0;
9022
9023 ahd_search_qinfifo(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,
9024 CAM_LUN_WILDCARD, SCB_LIST_NULL,
9025 ROLE_UNKNOWN, 0, SEARCH_PRINT);
9026 saved_scb_index = ahd_get_scbptr(ahd);
9027 printf("Pending list:");
9028 i = 0;
9029 LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
9030 if (i++ > AHD_SCB_MAX)
9031 break;
9032 cur_col = printf("\n%3d FIFO_USE[0x%x] ", SCB_GET_TAG(scb),
9033 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT));
9034 ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
9035 ahd_scb_control_print(ahd_inb_scbram(ahd, SCB_CONTROL),
9036 &cur_col, 60);
9037 ahd_scb_scsiid_print(ahd_inb_scbram(ahd, SCB_SCSIID),
9038 &cur_col, 60);
9039 }
9040 printf("\nTotal %d\n", i);
9041
9042 printf("Kernel Free SCB list: ");
9043 i = 0;
9044 TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) {
9045 struct scb *list_scb;
9046
9047 list_scb = scb;
9048 do {
9049 printf("%d ", SCB_GET_TAG(list_scb));
9050 list_scb = LIST_NEXT(list_scb, collision_links);
9051 } while (list_scb && i++ < AHD_SCB_MAX);
9052 }
9053
9054 LIST_FOREACH(scb, &ahd->scb_data.any_dev_free_scb_list, links.le) {
9055 if (i++ > AHD_SCB_MAX)
9056 break;
9057 printf("%d ", SCB_GET_TAG(scb));
9058 }
9059 printf("\n");
9060
9061 printf("Sequencer Complete DMA-inprog list: ");
9062 scb_index = ahd_inw(ahd, COMPLETE_SCB_DMAINPROG_HEAD);
9063 i = 0;
9064 while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
9065 ahd_set_scbptr(ahd, scb_index);
9066 printf("%d ", scb_index);
9067 scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
9068 }
9069 printf("\n");
9070
9071 printf("Sequencer Complete list: ");
9072 scb_index = ahd_inw(ahd, COMPLETE_SCB_HEAD);
9073 i = 0;
9074 while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
9075 ahd_set_scbptr(ahd, scb_index);
9076 printf("%d ", scb_index);
9077 scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
9078 }
9079 printf("\n");
9080
9081
9082 printf("Sequencer DMA-Up and Complete list: ");
9083 scb_index = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
9084 i = 0;
9085 while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
9086 ahd_set_scbptr(ahd, scb_index);
9087 printf("%d ", scb_index);
9088 scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
9089 }
9090 printf("\n");
9091 printf("Sequencer On QFreeze and Complete list: ");
9092 scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
9093 i = 0;
9094 while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
9095 ahd_set_scbptr(ahd, scb_index);
9096 printf("%d ", scb_index);
9097 scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
9098 }
9099 printf("\n");
9100 ahd_set_scbptr(ahd, saved_scb_index);
9101 dffstat = ahd_inb(ahd, DFFSTAT);
9102 for (i = 0; i < 2; i++) {
9103#ifdef AHD_DEBUG
9104 struct scb *fifo_scb;
9105#endif
9106 u_int fifo_scbptr;
9107
9108 ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);
9109 fifo_scbptr = ahd_get_scbptr(ahd);
9110 printf("\n\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n",
9111 ahd_name(ahd), i,
9112 (dffstat & (FIFO0FREE << i)) ? "Free" : "Active",
9113 ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr);
9114 cur_col = 0;
9115 ahd_seqimode_print(ahd_inb(ahd, SEQIMODE), &cur_col, 50);
9116 ahd_seqintsrc_print(ahd_inb(ahd, SEQINTSRC), &cur_col, 50);
9117 ahd_dfcntrl_print(ahd_inb(ahd, DFCNTRL), &cur_col, 50);
9118 ahd_dfstatus_print(ahd_inb(ahd, DFSTATUS), &cur_col, 50);
9119 ahd_sg_cache_shadow_print(ahd_inb(ahd, SG_CACHE_SHADOW),
9120 &cur_col, 50);
9121 ahd_sg_state_print(ahd_inb(ahd, SG_STATE), &cur_col, 50);
9122 ahd_dffsxfrctl_print(ahd_inb(ahd, DFFSXFRCTL), &cur_col, 50);
9123 ahd_soffcnt_print(ahd_inb(ahd, SOFFCNT), &cur_col, 50);
9124 ahd_mdffstat_print(ahd_inb(ahd, MDFFSTAT), &cur_col, 50);
9125 if (cur_col > 50) {
9126 printf("\n");
9127 cur_col = 0;
9128 }
9129 cur_col += printf("SHADDR = 0x%x%x, SHCNT = 0x%x ",
9130 ahd_inl(ahd, SHADDR+4),
9131 ahd_inl(ahd, SHADDR),
9132 (ahd_inb(ahd, SHCNT)
9133 | (ahd_inb(ahd, SHCNT + 1) << 8)
9134 | (ahd_inb(ahd, SHCNT + 2) << 16)));
9135 if (cur_col > 50) {
9136 printf("\n");
9137 cur_col = 0;
9138 }
9139 cur_col += printf("HADDR = 0x%x%x, HCNT = 0x%x ",
9140 ahd_inl(ahd, HADDR+4),
9141 ahd_inl(ahd, HADDR),
9142 (ahd_inb(ahd, HCNT)
9143 | (ahd_inb(ahd, HCNT + 1) << 8)
9144 | (ahd_inb(ahd, HCNT + 2) << 16)));
9145 ahd_ccsgctl_print(ahd_inb(ahd, CCSGCTL), &cur_col, 50);
9146#ifdef AHD_DEBUG
9147 if ((ahd_debug & AHD_SHOW_SG) != 0) {
9148 fifo_scb = ahd_lookup_scb(ahd, fifo_scbptr);
9149 if (fifo_scb != NULL)
9150 ahd_dump_sglist(fifo_scb);
9151 }
9152#endif
9153 }
9154 printf("\nLQIN: ");
9155 for (i = 0; i < 20; i++)
9156 printf("0x%x ", ahd_inb(ahd, LQIN + i));
9157 printf("\n");
9158 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
9159 printf("%s: LQISTATE = 0x%x, LQOSTATE = 0x%x, OPTIONMODE = 0x%x\n",
9160 ahd_name(ahd), ahd_inb(ahd, LQISTATE), ahd_inb(ahd, LQOSTATE),
9161 ahd_inb(ahd, OPTIONMODE));
9162 printf("%s: OS_SPACE_CNT = 0x%x MAXCMDCNT = 0x%x\n",
9163 ahd_name(ahd), ahd_inb(ahd, OS_SPACE_CNT),
9164 ahd_inb(ahd, MAXCMDCNT));
9165 printf("%s: SAVED_SCSIID = 0x%x SAVED_LUN = 0x%x\n",
9166 ahd_name(ahd), ahd_inb(ahd, SAVED_SCSIID),
9167 ahd_inb(ahd, SAVED_LUN));
9168 ahd_simode0_print(ahd_inb(ahd, SIMODE0), &cur_col, 50);
9169 printf("\n");
9170 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
9171 cur_col = 0;
9172 ahd_ccscbctl_print(ahd_inb(ahd, CCSCBCTL), &cur_col, 50);
9173 printf("\n");
9174 ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
9175 printf("%s: REG0 == 0x%x, SINDEX = 0x%x, DINDEX = 0x%x\n",
9176 ahd_name(ahd), ahd_inw(ahd, REG0), ahd_inw(ahd, SINDEX),
9177 ahd_inw(ahd, DINDEX));
9178 printf("%s: SCBPTR == 0x%x, SCB_NEXT == 0x%x, SCB_NEXT2 == 0x%x\n",
9179 ahd_name(ahd), ahd_get_scbptr(ahd),
9180 ahd_inw_scbram(ahd, SCB_NEXT),
9181 ahd_inw_scbram(ahd, SCB_NEXT2));
9182 printf("CDB %x %x %x %x %x %x\n",
9183 ahd_inb_scbram(ahd, SCB_CDB_STORE),
9184 ahd_inb_scbram(ahd, SCB_CDB_STORE+1),
9185 ahd_inb_scbram(ahd, SCB_CDB_STORE+2),
9186 ahd_inb_scbram(ahd, SCB_CDB_STORE+3),
9187 ahd_inb_scbram(ahd, SCB_CDB_STORE+4),
9188 ahd_inb_scbram(ahd, SCB_CDB_STORE+5));
9189 printf("STACK:");
9190 for (i = 0; i < ahd->stack_size; i++) {
9191 ahd->saved_stack[i] =
9192 ahd_inb(ahd, STACK)|(ahd_inb(ahd, STACK) << 8);
9193 printf(" 0x%x", ahd->saved_stack[i]);
9194 }
9195 for (i = ahd->stack_size-1; i >= 0; i--) {
9196 ahd_outb(ahd, STACK, ahd->saved_stack[i] & 0xFF);
9197 ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF);
9198 }
9199 printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n");
9200 ahd_restore_modes(ahd, saved_modes);
9201 if (paused == 0)
9202 ahd_unpause(ahd);
9203}
9204
9205#if 0
9206void
9207ahd_dump_scbs(struct ahd_softc *ahd)
9208{
9209 ahd_mode_state saved_modes;
9210 u_int saved_scb_index;
9211 int i;
9212
9213 saved_modes = ahd_save_modes(ahd);
9214 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
9215 saved_scb_index = ahd_get_scbptr(ahd);
9216 for (i = 0; i < AHD_SCB_MAX; i++) {
9217 ahd_set_scbptr(ahd, i);
9218 printf("%3d", i);
9219 printf("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x, RSG 0x%x)\n",
9220 ahd_inb_scbram(ahd, SCB_CONTROL),
9221 ahd_inb_scbram(ahd, SCB_SCSIID),
9222 ahd_inw_scbram(ahd, SCB_NEXT),
9223 ahd_inw_scbram(ahd, SCB_NEXT2),
9224 ahd_inl_scbram(ahd, SCB_SGPTR),
9225 ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR));
9226 }
9227 printf("\n");
9228 ahd_set_scbptr(ahd, saved_scb_index);
9229 ahd_restore_modes(ahd, saved_modes);
9230}
9231#endif
9232
9233
9234
9235
9236
9237
9238
9239
9240int
9241ahd_read_seeprom(struct ahd_softc *ahd, uint16_t *buf,
9242 u_int start_addr, u_int count, int bytestream)
9243{
9244 u_int cur_addr;
9245 u_int end_addr;
9246 int error;
9247
9248
9249
9250
9251
9252 error = EINVAL;
9253 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
9254 end_addr = start_addr + count;
9255 for (cur_addr = start_addr; cur_addr < end_addr; cur_addr++) {
9256
9257 ahd_outb(ahd, SEEADR, cur_addr);
9258 ahd_outb(ahd, SEECTL, SEEOP_READ | SEESTART);
9259
9260 error = ahd_wait_seeprom(ahd);
9261 if (error)
9262 break;
9263 if (bytestream != 0) {
9264 uint8_t *bytestream_ptr;
9265
9266 bytestream_ptr = (uint8_t *)buf;
9267 *bytestream_ptr++ = ahd_inb(ahd, SEEDAT);
9268 *bytestream_ptr = ahd_inb(ahd, SEEDAT+1);
9269 } else {
9270
9271
9272
9273 *buf = ahd_inw(ahd, SEEDAT);
9274 }
9275 buf++;
9276 }
9277 return (error);
9278}
9279
9280
9281
9282
9283
9284
9285int
9286ahd_write_seeprom(struct ahd_softc *ahd, uint16_t *buf,
9287 u_int start_addr, u_int count)
9288{
9289 u_int cur_addr;
9290 u_int end_addr;
9291 int error;
9292 int retval;
9293
9294 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
9295 error = ENOENT;
9296
9297
9298 ahd_outb(ahd, SEEADR, SEEOP_EWEN_ADDR);
9299 ahd_outb(ahd, SEECTL, SEEOP_EWEN | SEESTART);
9300 error = ahd_wait_seeprom(ahd);
9301 if (error)
9302 return (error);
9303
9304
9305
9306
9307
9308 retval = EINVAL;
9309 end_addr = start_addr + count;
9310 for (cur_addr = start_addr; cur_addr < end_addr; cur_addr++) {
9311 ahd_outw(ahd, SEEDAT, *buf++);
9312 ahd_outb(ahd, SEEADR, cur_addr);
9313 ahd_outb(ahd, SEECTL, SEEOP_WRITE | SEESTART);
9314
9315 retval = ahd_wait_seeprom(ahd);
9316 if (retval)
9317 break;
9318 }
9319
9320
9321
9322
9323 ahd_outb(ahd, SEEADR, SEEOP_EWDS_ADDR);
9324 ahd_outb(ahd, SEECTL, SEEOP_EWDS | SEESTART);
9325 error = ahd_wait_seeprom(ahd);
9326 if (error)
9327 return (error);
9328 return (retval);
9329}
9330
9331
9332
9333
9334static int
9335ahd_wait_seeprom(struct ahd_softc *ahd)
9336{
9337 int cnt;
9338
9339 cnt = 5000;
9340 while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt)
9341 ahd_delay(5);
9342
9343 if (cnt == 0)
9344 return (ETIMEDOUT);
9345 return (0);
9346}
9347
9348
9349
9350
9351
9352static int
9353ahd_verify_vpd_cksum(struct vpd_config *vpd)
9354{
9355 int i;
9356 int maxaddr;
9357 uint32_t checksum;
9358 uint8_t *vpdarray;
9359
9360 vpdarray = (uint8_t *)vpd;
9361 maxaddr = offsetof(struct vpd_config, vpd_checksum);
9362 checksum = 0;
9363 for (i = offsetof(struct vpd_config, resource_type); i < maxaddr; i++)
9364 checksum = checksum + vpdarray[i];
9365 if (checksum == 0
9366 || (-checksum & 0xFF) != vpd->vpd_checksum)
9367 return (0);
9368
9369 checksum = 0;
9370 maxaddr = offsetof(struct vpd_config, checksum);
9371 for (i = offsetof(struct vpd_config, default_target_flags);
9372 i < maxaddr; i++)
9373 checksum = checksum + vpdarray[i];
9374 if (checksum == 0
9375 || (-checksum & 0xFF) != vpd->checksum)
9376 return (0);
9377 return (1);
9378}
9379
9380int
9381ahd_verify_cksum(struct seeprom_config *sc)
9382{
9383 int i;
9384 int maxaddr;
9385 uint32_t checksum;
9386 uint16_t *scarray;
9387
9388 maxaddr = (sizeof(*sc)/2) - 1;
9389 checksum = 0;
9390 scarray = (uint16_t *)sc;
9391
9392 for (i = 0; i < maxaddr; i++)
9393 checksum = checksum + scarray[i];
9394 if (checksum == 0
9395 || (checksum & 0xFFFF) != sc->checksum) {
9396 return (0);
9397 } else {
9398 return (1);
9399 }
9400}
9401
9402int
9403ahd_acquire_seeprom(struct ahd_softc *ahd)
9404{
9405
9406
9407
9408
9409
9410
9411
9412 return (1);
9413#if 0
9414 uint8_t seetype;
9415 int error;
9416
9417 error = ahd_read_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, &seetype);
9418 if (error != 0
9419 || ((seetype & FLX_ROMSTAT_SEECFG) == FLX_ROMSTAT_SEE_NONE))
9420 return (0);
9421 return (1);
9422#endif
9423}
9424
9425void
9426ahd_release_seeprom(struct ahd_softc *ahd)
9427{
9428
9429}
9430
9431
9432
9433
9434static int
9435ahd_wait_flexport(struct ahd_softc *ahd)
9436{
9437 int cnt;
9438
9439 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
9440 cnt = 1000000 * 2 / 5;
9441 while ((ahd_inb(ahd, BRDCTL) & FLXARBACK) == 0 && --cnt)
9442 ahd_delay(5);
9443
9444 if (cnt == 0)
9445 return (ETIMEDOUT);
9446 return (0);
9447}
9448
9449int
9450ahd_write_flexport(struct ahd_softc *ahd, u_int addr, u_int value)
9451{
9452 int error;
9453
9454 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
9455 if (addr > 7)
9456 panic("ahd_write_flexport: address out of range");
9457 ahd_outb(ahd, BRDCTL, BRDEN|(addr << 3));
9458 error = ahd_wait_flexport(ahd);
9459 if (error != 0)
9460 return (error);
9461 ahd_outb(ahd, BRDDAT, value);
9462 ahd_flush_device_writes(ahd);
9463 ahd_outb(ahd, BRDCTL, BRDSTB|BRDEN|(addr << 3));
9464 ahd_flush_device_writes(ahd);
9465 ahd_outb(ahd, BRDCTL, BRDEN|(addr << 3));
9466 ahd_flush_device_writes(ahd);
9467 ahd_outb(ahd, BRDCTL, 0);
9468 ahd_flush_device_writes(ahd);
9469 return (0);
9470}
9471
9472int
9473ahd_read_flexport(struct ahd_softc *ahd, u_int addr, uint8_t *value)
9474{
9475 int error;
9476
9477 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
9478 if (addr > 7)
9479 panic("ahd_read_flexport: address out of range");
9480 ahd_outb(ahd, BRDCTL, BRDRW|BRDEN|(addr << 3));
9481 error = ahd_wait_flexport(ahd);
9482 if (error != 0)
9483 return (error);
9484 *value = ahd_inb(ahd, BRDDAT);
9485 ahd_outb(ahd, BRDCTL, 0);
9486 ahd_flush_device_writes(ahd);
9487 return (0);
9488}
9489
9490
9491#ifdef AHD_TARGET_MODE
9492cam_status
9493ahd_find_tmode_devs(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb,
9494 struct ahd_tmode_tstate **tstate,
9495 struct ahd_tmode_lstate **lstate,
9496 int notfound_failure)
9497{
9498
9499 if ((ahd->features & AHD_TARGETMODE) == 0)
9500 return (CAM_REQ_INVALID);
9501
9502
9503
9504
9505
9506 if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD
9507 && ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) {
9508 *tstate = NULL;
9509 *lstate = ahd->black_hole;
9510 } else {
9511 u_int max_id;
9512
9513 max_id = (ahd->features & AHD_WIDE) ? 16 : 8;
9514 if (ccb->ccb_h.target_id >= max_id)
9515 return (CAM_TID_INVALID);
9516
9517 if (ccb->ccb_h.target_lun >= AHD_NUM_LUNS)
9518 return (CAM_LUN_INVALID);
9519
9520 *tstate = ahd->enabled_targets[ccb->ccb_h.target_id];
9521 *lstate = NULL;
9522 if (*tstate != NULL)
9523 *lstate =
9524 (*tstate)->enabled_luns[ccb->ccb_h.target_lun];
9525 }
9526
9527 if (notfound_failure != 0 && *lstate == NULL)
9528 return (CAM_PATH_INVALID);
9529
9530 return (CAM_REQ_CMP);
9531}
9532
9533void
9534ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
9535{
9536#if NOT_YET
9537 struct ahd_tmode_tstate *tstate;
9538 struct ahd_tmode_lstate *lstate;
9539 struct ccb_en_lun *cel;
9540 cam_status status;
9541 u_int target;
9542 u_int lun;
9543 u_int target_mask;
9544 u_long s;
9545 char channel;
9546
9547 status = ahd_find_tmode_devs(ahd, sim, ccb, &tstate, &lstate,
9548 FALSE);
9549
9550 if (status != CAM_REQ_CMP) {
9551 ccb->ccb_h.status = status;
9552 return;
9553 }
9554
9555 if ((ahd->features & AHD_MULTIROLE) != 0) {
9556 u_int our_id;
9557
9558 our_id = ahd->our_id;
9559 if (ccb->ccb_h.target_id != our_id) {
9560 if ((ahd->features & AHD_MULTI_TID) != 0
9561 && (ahd->flags & AHD_INITIATORROLE) != 0) {
9562
9563
9564
9565
9566
9567
9568
9569 status = CAM_TID_INVALID;
9570 } else if ((ahd->flags & AHD_INITIATORROLE) != 0
9571 || ahd->enabled_luns > 0) {
9572
9573
9574
9575
9576
9577
9578
9579 status = CAM_TID_INVALID;
9580 }
9581 }
9582 }
9583
9584 if (status != CAM_REQ_CMP) {
9585 ccb->ccb_h.status = status;
9586 return;
9587 }
9588
9589
9590
9591
9592
9593 if ((ahd->flags & AHD_TARGETROLE) == 0
9594 && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
9595 u_long s;
9596
9597 printf("Configuring Target Mode\n");
9598 ahd_lock(ahd, &s);
9599 if (LIST_FIRST(&ahd->pending_scbs) != NULL) {
9600 ccb->ccb_h.status = CAM_BUSY;
9601 ahd_unlock(ahd, &s);
9602 return;
9603 }
9604 ahd->flags |= AHD_TARGETROLE;
9605 if ((ahd->features & AHD_MULTIROLE) == 0)
9606 ahd->flags &= ~AHD_INITIATORROLE;
9607 ahd_pause(ahd);
9608 ahd_loadseq(ahd);
9609 ahd_restart(ahd);
9610 ahd_unlock(ahd, &s);
9611 }
9612 cel = &ccb->cel;
9613 target = ccb->ccb_h.target_id;
9614 lun = ccb->ccb_h.target_lun;
9615 channel = SIM_CHANNEL(ahd, sim);
9616 target_mask = 0x01 << target;
9617 if (channel == 'B')
9618 target_mask <<= 8;
9619
9620 if (cel->enable != 0) {
9621 u_int scsiseq1;
9622
9623
9624 if (lstate != NULL) {
9625 xpt_print_path(ccb->ccb_h.path);
9626 printf("Lun already enabled\n");
9627 ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
9628 return;
9629 }
9630
9631 if (cel->grp6_len != 0
9632 || cel->grp7_len != 0) {
9633
9634
9635
9636
9637 ccb->ccb_h.status = CAM_REQ_INVALID;
9638 printf("Non-zero Group Codes\n");
9639 return;
9640 }
9641
9642
9643
9644
9645
9646 if (target != CAM_TARGET_WILDCARD && tstate == NULL) {
9647 tstate = ahd_alloc_tstate(ahd, target, channel);
9648 if (tstate == NULL) {
9649 xpt_print_path(ccb->ccb_h.path);
9650 printf("Couldn't allocate tstate\n");
9651 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
9652 return;
9653 }
9654 }
9655 lstate = malloc(sizeof(*lstate), M_DEVBUF, M_NOWAIT);
9656 if (lstate == NULL) {
9657 xpt_print_path(ccb->ccb_h.path);
9658 printf("Couldn't allocate lstate\n");
9659 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
9660 return;
9661 }
9662 memset(lstate, 0, sizeof(*lstate));
9663 status = xpt_create_path(&lstate->path, NULL,
9664 xpt_path_path_id(ccb->ccb_h.path),
9665 xpt_path_target_id(ccb->ccb_h.path),
9666 xpt_path_lun_id(ccb->ccb_h.path));
9667 if (status != CAM_REQ_CMP) {
9668 free(lstate, M_DEVBUF);
9669 xpt_print_path(ccb->ccb_h.path);
9670 printf("Couldn't allocate path\n");
9671 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
9672 return;
9673 }
9674 SLIST_INIT(&lstate->accept_tios);
9675 SLIST_INIT(&lstate->immed_notifies);
9676 ahd_lock(ahd, &s);
9677 ahd_pause(ahd);
9678 if (target != CAM_TARGET_WILDCARD) {
9679 tstate->enabled_luns[lun] = lstate;
9680 ahd->enabled_luns++;
9681
9682 if ((ahd->features & AHD_MULTI_TID) != 0) {
9683 u_int targid_mask;
9684
9685 targid_mask = ahd_inw(ahd, TARGID);
9686 targid_mask |= target_mask;
9687 ahd_outw(ahd, TARGID, targid_mask);
9688 ahd_update_scsiid(ahd, targid_mask);
9689 } else {
9690 u_int our_id;
9691 char channel;
9692
9693 channel = SIM_CHANNEL(ahd, sim);
9694 our_id = SIM_SCSI_ID(ahd, sim);
9695
9696
9697
9698
9699
9700 if (target != our_id) {
9701 u_int sblkctl;
9702 char cur_channel;
9703 int swap;
9704
9705 sblkctl = ahd_inb(ahd, SBLKCTL);
9706 cur_channel = (sblkctl & SELBUSB)
9707 ? 'B' : 'A';
9708 if ((ahd->features & AHD_TWIN) == 0)
9709 cur_channel = 'A';
9710 swap = cur_channel != channel;
9711 ahd->our_id = target;
9712
9713 if (swap)
9714 ahd_outb(ahd, SBLKCTL,
9715 sblkctl ^ SELBUSB);
9716
9717 ahd_outb(ahd, SCSIID, target);
9718
9719 if (swap)
9720 ahd_outb(ahd, SBLKCTL, sblkctl);
9721 }
9722 }
9723 } else
9724 ahd->black_hole = lstate;
9725
9726 if (ahd->black_hole != NULL && ahd->enabled_luns > 0) {
9727 scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE);
9728 scsiseq1 |= ENSELI;
9729 ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq1);
9730 scsiseq1 = ahd_inb(ahd, SCSISEQ1);
9731 scsiseq1 |= ENSELI;
9732 ahd_outb(ahd, SCSISEQ1, scsiseq1);
9733 }
9734 ahd_unpause(ahd);
9735 ahd_unlock(ahd, &s);
9736 ccb->ccb_h.status = CAM_REQ_CMP;
9737 xpt_print_path(ccb->ccb_h.path);
9738 printf("Lun now enabled for target mode\n");
9739 } else {
9740 struct scb *scb;
9741 int i, empty;
9742
9743 if (lstate == NULL) {
9744 ccb->ccb_h.status = CAM_LUN_INVALID;
9745 return;
9746 }
9747
9748 ahd_lock(ahd, &s);
9749
9750 ccb->ccb_h.status = CAM_REQ_CMP;
9751 LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
9752 struct ccb_hdr *ccbh;
9753
9754 ccbh = &scb->io_ctx->ccb_h;
9755 if (ccbh->func_code == XPT_CONT_TARGET_IO
9756 && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){
9757 printf("CTIO pending\n");
9758 ccb->ccb_h.status = CAM_REQ_INVALID;
9759 ahd_unlock(ahd, &s);
9760 return;
9761 }
9762 }
9763
9764 if (SLIST_FIRST(&lstate->accept_tios) != NULL) {
9765 printf("ATIOs pending\n");
9766 ccb->ccb_h.status = CAM_REQ_INVALID;
9767 }
9768
9769 if (SLIST_FIRST(&lstate->immed_notifies) != NULL) {
9770 printf("INOTs pending\n");
9771 ccb->ccb_h.status = CAM_REQ_INVALID;
9772 }
9773
9774 if (ccb->ccb_h.status != CAM_REQ_CMP) {
9775 ahd_unlock(ahd, &s);
9776 return;
9777 }
9778
9779 xpt_print_path(ccb->ccb_h.path);
9780 printf("Target mode disabled\n");
9781 xpt_free_path(lstate->path);
9782 free(lstate, M_DEVBUF);
9783
9784 ahd_pause(ahd);
9785
9786 if (target != CAM_TARGET_WILDCARD) {
9787 tstate->enabled_luns[lun] = NULL;
9788 ahd->enabled_luns--;
9789 for (empty = 1, i = 0; i < 8; i++)
9790 if (tstate->enabled_luns[i] != NULL) {
9791 empty = 0;
9792 break;
9793 }
9794
9795 if (empty) {
9796 ahd_free_tstate(ahd, target, channel,
9797 FALSE);
9798 if (ahd->features & AHD_MULTI_TID) {
9799 u_int targid_mask;
9800
9801 targid_mask = ahd_inw(ahd, TARGID);
9802 targid_mask &= ~target_mask;
9803 ahd_outw(ahd, TARGID, targid_mask);
9804 ahd_update_scsiid(ahd, targid_mask);
9805 }
9806 }
9807 } else {
9808
9809 ahd->black_hole = NULL;
9810
9811
9812
9813
9814
9815 empty = TRUE;
9816 }
9817 if (ahd->enabled_luns == 0) {
9818
9819 u_int scsiseq1;
9820
9821 scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE);
9822 scsiseq1 &= ~ENSELI;
9823 ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq1);
9824 scsiseq1 = ahd_inb(ahd, SCSISEQ1);
9825 scsiseq1 &= ~ENSELI;
9826 ahd_outb(ahd, SCSISEQ1, scsiseq1);
9827
9828 if ((ahd->features & AHD_MULTIROLE) == 0) {
9829 printf("Configuring Initiator Mode\n");
9830 ahd->flags &= ~AHD_TARGETROLE;
9831 ahd->flags |= AHD_INITIATORROLE;
9832 ahd_pause(ahd);
9833 ahd_loadseq(ahd);
9834 ahd_restart(ahd);
9835
9836
9837
9838
9839 }
9840 }
9841 ahd_unpause(ahd);
9842 ahd_unlock(ahd, &s);
9843 }
9844#endif
9845}
9846
9847static void
9848ahd_update_scsiid(struct ahd_softc *ahd, u_int targid_mask)
9849{
9850#if NOT_YET
9851 u_int scsiid_mask;
9852 u_int scsiid;
9853
9854 if ((ahd->features & AHD_MULTI_TID) == 0)
9855 panic("ahd_update_scsiid called on non-multitid unit\n");
9856
9857
9858
9859
9860
9861
9862
9863 if ((ahd->features & AHD_ULTRA2) != 0)
9864 scsiid = ahd_inb(ahd, SCSIID_ULTRA2);
9865 else
9866 scsiid = ahd_inb(ahd, SCSIID);
9867 scsiid_mask = 0x1 << (scsiid & OID);
9868 if ((targid_mask & scsiid_mask) == 0) {
9869 u_int our_id;
9870
9871
9872 our_id = ffs(targid_mask);
9873 if (our_id == 0)
9874 our_id = ahd->our_id;
9875 else
9876 our_id--;
9877 scsiid &= TID;
9878 scsiid |= our_id;
9879 }
9880 if ((ahd->features & AHD_ULTRA2) != 0)
9881 ahd_outb(ahd, SCSIID_ULTRA2, scsiid);
9882 else
9883 ahd_outb(ahd, SCSIID, scsiid);
9884#endif
9885}
9886
9887void
9888ahd_run_tqinfifo(struct ahd_softc *ahd, int paused)
9889{
9890 struct target_cmd *cmd;
9891
9892 ahd_sync_tqinfifo(ahd, BUS_DMASYNC_POSTREAD);
9893 while ((cmd = &ahd->targetcmds[ahd->tqinfifonext])->cmd_valid != 0) {
9894
9895
9896
9897
9898
9899 if (ahd_handle_target_cmd(ahd, cmd) != 0)
9900 break;
9901
9902 cmd->cmd_valid = 0;
9903 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
9904 ahd->shared_data_map.dmamap,
9905 ahd_targetcmd_offset(ahd, ahd->tqinfifonext),
9906 sizeof(struct target_cmd),
9907 BUS_DMASYNC_PREREAD);
9908 ahd->tqinfifonext++;
9909
9910
9911
9912
9913
9914 if ((ahd->tqinfifonext & (HOST_TQINPOS - 1)) == 1) {
9915 u_int hs_mailbox;
9916
9917 hs_mailbox = ahd_inb(ahd, HS_MAILBOX);
9918 hs_mailbox &= ~HOST_TQINPOS;
9919 hs_mailbox |= ahd->tqinfifonext & HOST_TQINPOS;
9920 ahd_outb(ahd, HS_MAILBOX, hs_mailbox);
9921 }
9922 }
9923}
9924
9925static int
9926ahd_handle_target_cmd(struct ahd_softc *ahd, struct target_cmd *cmd)
9927{
9928 struct ahd_tmode_tstate *tstate;
9929 struct ahd_tmode_lstate *lstate;
9930 struct ccb_accept_tio *atio;
9931 uint8_t *byte;
9932 int initiator;
9933 int target;
9934 int lun;
9935
9936 initiator = SCSIID_TARGET(ahd, cmd->scsiid);
9937 target = SCSIID_OUR_ID(cmd->scsiid);
9938 lun = (cmd->identify & MSG_IDENTIFY_LUNMASK);
9939
9940 byte = cmd->bytes;
9941 tstate = ahd->enabled_targets[target];
9942 lstate = NULL;
9943 if (tstate != NULL)
9944 lstate = tstate->enabled_luns[lun];
9945
9946
9947
9948
9949 if (lstate == NULL)
9950 lstate = ahd->black_hole;
9951
9952 atio = (struct ccb_accept_tio*)SLIST_FIRST(&lstate->accept_tios);
9953 if (atio == NULL) {
9954 ahd->flags |= AHD_TQINFIFO_BLOCKED;
9955
9956
9957
9958 return (1);
9959 } else
9960 ahd->flags &= ~AHD_TQINFIFO_BLOCKED;
9961#ifdef AHD_DEBUG
9962 if ((ahd_debug & AHD_SHOW_TQIN) != 0)
9963 printf("Incoming command from %d for %d:%d%s\n",
9964 initiator, target, lun,
9965 lstate == ahd->black_hole ? "(Black Holed)" : "");
9966#endif
9967 SLIST_REMOVE_HEAD(&lstate->accept_tios, sim_links.sle);
9968
9969 if (lstate == ahd->black_hole) {
9970
9971 atio->ccb_h.target_id = target;
9972 atio->ccb_h.target_lun = lun;
9973 }
9974
9975
9976
9977
9978
9979 atio->sense_len = 0;
9980 atio->init_id = initiator;
9981 if (byte[0] != 0xFF) {
9982
9983 atio->tag_action = *byte++;
9984 atio->tag_id = *byte++;
9985 atio->ccb_h.flags = CAM_TAG_ACTION_VALID;
9986 } else {
9987 atio->ccb_h.flags = 0;
9988 }
9989 byte++;
9990
9991
9992 switch (*byte >> CMD_GROUP_CODE_SHIFT) {
9993 case 0:
9994 atio->cdb_len = 6;
9995 break;
9996 case 1:
9997 case 2:
9998 atio->cdb_len = 10;
9999 break;
10000 case 4:
10001 atio->cdb_len = 16;
10002 break;
10003 case 5:
10004 atio->cdb_len = 12;
10005 break;
10006 case 3:
10007 default:
10008
10009 atio->cdb_len = 1;
10010 printf("Reserved or VU command code type encountered\n");
10011 break;
10012 }
10013
10014 memcpy(atio->cdb_io.cdb_bytes, byte, atio->cdb_len);
10015
10016 atio->ccb_h.status |= CAM_CDB_RECVD;
10017
10018 if ((cmd->identify & MSG_IDENTIFY_DISCFLAG) == 0) {
10019
10020
10021
10022
10023
10024
10025#ifdef AHD_DEBUG
10026 if ((ahd_debug & AHD_SHOW_TQIN) != 0)
10027 printf("Received Immediate Command %d:%d:%d - %p\n",
10028 initiator, target, lun, ahd->pending_device);
10029#endif
10030 ahd->pending_device = lstate;
10031 ahd_freeze_ccb((union ccb *)atio);
10032 atio->ccb_h.flags |= CAM_DIS_DISCONNECT;
10033 }
10034 xpt_done((union ccb*)atio);
10035 return (0);
10036}
10037
10038#endif
10039