This source file includes following definitions.
- ahc_check_extport
- ahc_parse_pci_eeprom
- configure_termination
- ahc_new_term_detect
- aic787X_cable_detect
- aic785X_cable_detect
- ahc_acquire_seeprom
- ahc_release_seeprom
- write_brdctl
- read_brdctl
- verify_seeprom_cksum
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 #include <sys/cdefs.h>
56
57
58 #include <sys/param.h>
59 #include <sys/systm.h>
60 #include <sys/malloc.h>
61 #include <sys/kernel.h>
62 #include <sys/queue.h>
63 #include <sys/device.h>
64 #include <sys/reboot.h>
65
66 #include <machine/bus.h>
67 #include <machine/intr.h>
68
69 #include <scsi/scsi_all.h>
70 #include <scsi/scsiconf.h>
71
72 #include <dev/ic/aic7xxx_openbsd.h>
73 #include <dev/ic/aic7xxx_inline.h>
74
75 #include <dev/ic/smc93cx6var.h>
76
77 #define DEVCONFIG 0x40
78 #define STPWLEVEL 0x00000002
79
80 static void configure_termination(struct ahc_softc *,
81 struct seeprom_descriptor *, u_int, u_int *);
82 static int verify_seeprom_cksum(struct seeprom_config *sc);
83
84 static void ahc_new_term_detect(struct ahc_softc *, int *, int *, int *,
85 int *, int *);
86 static void aic787X_cable_detect(struct ahc_softc *, int *, int *, int *,
87 int *);
88 static void aic785X_cable_detect(struct ahc_softc *, int *, int *, int *);
89 static void write_brdctl(struct ahc_softc *, u_int8_t);
90 static u_int8_t read_brdctl(struct ahc_softc *);
91 static void ahc_parse_pci_eeprom(struct ahc_softc *, struct seeprom_config *);
92
93
94
95
96
97 void
98 ahc_check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
99 {
100 struct seeprom_descriptor sd;
101 struct seeprom_config *sc;
102 int have_seeprom;
103 int have_autoterm;
104
105 sd.sd_tag = ahc->tag;
106 sd.sd_bsh = ahc->bsh;
107 sd.sd_regsize = 1;
108 sd.sd_control_offset = SEECTL;
109 sd.sd_status_offset = SEECTL;
110 sd.sd_dataout_offset = SEECTL;
111 sc = ahc->seep_config;
112
113
114
115
116
117
118
119 if (ahc->flags & AHC_LARGE_SEEPROM)
120 sd.sd_chip = C56_66;
121 else
122 sd.sd_chip = C46;
123
124 sd.sd_MS = SEEMS;
125 sd.sd_RDY = SEERDY;
126 sd.sd_CS = SEECS;
127 sd.sd_CK = SEECK;
128 sd.sd_DO = SEEDO;
129 sd.sd_DI = SEEDI;
130
131 have_seeprom = ahc_acquire_seeprom(ahc, &sd);
132 if (have_seeprom) {
133
134 if (bootverbose)
135 printf("%s: Reading SEEPROM...", ahc_name(ahc));
136
137 for (;;) {
138 u_int start_addr;
139
140 start_addr = 32 * (ahc->channel - 'A');
141 have_seeprom = read_seeprom(&sd, (uint16_t *)sc,
142 start_addr,
143 sizeof(*sc)/2);
144
145 if (have_seeprom)
146 have_seeprom = verify_seeprom_cksum(sc);
147
148 if (have_seeprom != 0 || sd.sd_chip == C56_66) {
149 if (bootverbose) {
150 if (have_seeprom == 0)
151 printf ("checksum error\n");
152 else
153 printf ("done.\n");
154 }
155 break;
156 }
157 sd.sd_chip = C56_66;
158 }
159 ahc_release_seeprom(&sd);
160 }
161
162 if (!have_seeprom) {
163
164
165
166
167
168
169
170 ahc_outb(ahc, SCBPTR, 2);
171 if (ahc_inb(ahc, SCB_BASE) == 'A'
172 && ahc_inb(ahc, SCB_BASE + 1) == 'D'
173 && ahc_inb(ahc, SCB_BASE + 2) == 'P'
174 && ahc_inb(ahc, SCB_BASE + 3) == 'T') {
175 uint16_t *sc_data;
176 int i;
177
178 sc_data = (uint16_t *)sc;
179 for (i = 0; i < 32; i++, sc_data++) {
180 int j;
181
182 j = i * 2;
183 *sc_data = ahc_inb(ahc, SRAM_BASE + j)
184 | ahc_inb(ahc, SRAM_BASE + j + 1) << 8;
185 }
186 have_seeprom = verify_seeprom_cksum(sc);
187 if (have_seeprom)
188 ahc->flags |= AHC_SCB_CONFIG_USED;
189 }
190
191
192
193
194 ahc_outb(ahc, CLRINT, CLRPARERR);
195 ahc_outb(ahc, CLRINT, CLRBRKADRINT);
196 }
197
198 if (!have_seeprom) {
199 if (bootverbose)
200 printf("%s: No SEEPROM available.\n", ahc_name(ahc));
201 ahc->flags |= AHC_USEDEFAULTS | AHC_NO_BIOS_INIT;
202 free(ahc->seep_config, M_DEVBUF);
203 ahc->seep_config = NULL;
204 sc = NULL;
205 } else {
206 ahc_parse_pci_eeprom(ahc, sc);
207 }
208
209
210
211
212
213
214
215 have_autoterm = have_seeprom;
216
217
218
219
220
221
222 if ((ahc->features & AHC_SPIOCAP) != 0) {
223 if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0)
224 have_autoterm = FALSE;
225 }
226
227 if (have_autoterm) {
228 ahc_acquire_seeprom(ahc, &sd);
229 configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1);
230 ahc_release_seeprom(&sd);
231 } else if (have_seeprom) {
232 *sxfrctl1 &= ~STPWEN;
233 if ((sc->adapter_control & CFSTERM) != 0)
234 *sxfrctl1 |= STPWEN;
235 if (bootverbose)
236 printf("%s: Low byte termination %sabled\n",
237 ahc_name(ahc),
238 (*sxfrctl1 & STPWEN) ? "en" : "dis");
239 }
240 }
241
242 static void
243 ahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc)
244 {
245
246
247
248
249 int i;
250 int max_targ = sc->max_targets & CFMAXTARG;
251 u_int scsi_conf;
252 uint16_t discenable;
253 uint16_t ultraenb;
254
255 discenable = 0;
256 ultraenb = 0;
257 if ((sc->adapter_control & CFULTRAEN) != 0) {
258
259
260
261
262 for (i = 0; i < max_targ; i++) {
263 if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) {
264 ahc->flags |= AHC_NEWEEPROM_FMT;
265 break;
266 }
267 }
268 }
269
270 for (i = 0; i < max_targ; i++) {
271 u_int scsirate;
272 uint16_t target_mask;
273
274 target_mask = 0x01 << i;
275 if (sc->device_flags[i] & CFDISC)
276 discenable |= target_mask;
277 if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) {
278 if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0)
279 ultraenb |= target_mask;
280 } else if ((sc->adapter_control & CFULTRAEN) != 0) {
281 ultraenb |= target_mask;
282 }
283 if ((sc->device_flags[i] & CFXFER) == 0x04
284 && (ultraenb & target_mask) != 0) {
285
286 sc->device_flags[i] &= ~CFXFER;
287 ultraenb &= ~target_mask;
288 }
289 if ((ahc->features & AHC_ULTRA2) != 0) {
290 u_int offset;
291
292 if (sc->device_flags[i] & CFSYNCH)
293 offset = MAX_OFFSET_ULTRA2;
294 else
295 offset = 0;
296 ahc_outb(ahc, TARG_OFFSET + i, offset);
297
298
299
300
301
302
303 scsirate = (sc->device_flags[i] & CFXFER)
304 | ((ultraenb & target_mask) ? 0x8 : 0x0);
305 if (sc->device_flags[i] & CFWIDEB)
306 scsirate |= WIDEXFER;
307 } else {
308 scsirate = (sc->device_flags[i] & CFXFER) << 4;
309 if (sc->device_flags[i] & CFSYNCH)
310 scsirate |= SOFS;
311 if (sc->device_flags[i] & CFWIDEB)
312 scsirate |= WIDEXFER;
313 }
314 ahc_outb(ahc, TARG_SCSIRATE + i, scsirate);
315 }
316 ahc->our_id = sc->brtime_id & CFSCSIID;
317
318 scsi_conf = (ahc->our_id & 0x7);
319 if (sc->adapter_control & CFSPARITY)
320 scsi_conf |= ENSPCHK;
321 if (sc->adapter_control & CFRESETB)
322 scsi_conf |= RESET_SCSI;
323
324 ahc->flags |= (sc->adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT;
325
326 if (sc->bios_control & CFEXTEND)
327 ahc->flags |= AHC_EXTENDED_TRANS_A;
328
329 if (sc->bios_control & CFBIOSEN)
330 ahc->flags |= AHC_BIOS_ENABLED;
331 if (ahc->features & AHC_ULTRA
332 && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) {
333
334 if (!(sc->adapter_control & CFULTRAEN))
335
336 ultraenb = 0;
337 }
338
339 if (sc->signature == CFSIGNATURE
340 || sc->signature == CFSIGNATURE2) {
341 uint32_t devconfig;
342
343
344 devconfig = pci_conf_read(ahc->bd->pc, ahc->bd->tag, DEVCONFIG);
345 devconfig &= ~STPWLEVEL;
346 if ((sc->bios_control & CFSTPWLEVEL) != 0)
347 devconfig |= STPWLEVEL;
348 pci_conf_write(ahc->bd->pc, ahc->bd->tag, DEVCONFIG, devconfig);
349 }
350
351 ahc_outb(ahc, SCSICONF, scsi_conf);
352 ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff));
353 ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff));
354 ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff);
355 ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff);
356 }
357
358 static void
359 configure_termination(struct ahc_softc *ahc,
360 struct seeprom_descriptor *sd,
361 u_int adapter_control,
362 u_int *sxfrctl1)
363 {
364 uint8_t brddat;
365
366 brddat = 0;
367
368
369
370
371
372 *sxfrctl1 = 0;
373
374
375
376
377
378
379 SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS);
380 if ((adapter_control & CFAUTOTERM) != 0
381 || (ahc->features & AHC_NEW_TERMCTL) != 0) {
382 int internal50_present;
383 int internal68_present;
384 int externalcable_present;
385 int eeprom_present;
386 int enableSEC_low;
387 int enableSEC_high;
388 int enablePRI_low;
389 int enablePRI_high;
390 int sum;
391
392 enableSEC_low = 0;
393 enableSEC_high = 0;
394 enablePRI_low = 0;
395 enablePRI_high = 0;
396 if ((ahc->features & AHC_NEW_TERMCTL) != 0) {
397 ahc_new_term_detect(ahc, &enableSEC_low,
398 &enableSEC_high,
399 &enablePRI_low,
400 &enablePRI_high,
401 &eeprom_present);
402 if ((adapter_control & CFSEAUTOTERM) == 0) {
403 if (bootverbose)
404 printf("%s: Manual SE Termination\n",
405 ahc_name(ahc));
406 enableSEC_low = (adapter_control & CFSELOWTERM);
407 enableSEC_high =
408 (adapter_control & CFSEHIGHTERM);
409 }
410 if ((adapter_control & CFAUTOTERM) == 0) {
411 if (bootverbose)
412 printf("%s: Manual LVD Termination\n",
413 ahc_name(ahc));
414 enablePRI_low = (adapter_control & CFSTERM);
415 enablePRI_high = (adapter_control & CFWSTERM);
416 }
417
418 internal50_present = 0;
419 internal68_present = 1;
420 externalcable_present = 1;
421 } else if ((ahc->features & AHC_SPIOCAP) != 0) {
422 aic785X_cable_detect(ahc, &internal50_present,
423 &externalcable_present,
424 &eeprom_present);
425
426 internal68_present = 0;
427 } else {
428 aic787X_cable_detect(ahc, &internal50_present,
429 &internal68_present,
430 &externalcable_present,
431 &eeprom_present);
432 }
433
434 if ((ahc->features & AHC_WIDE) == 0)
435 internal68_present = 0;
436
437 if (bootverbose
438 && (ahc->features & AHC_ULTRA2) == 0) {
439 printf("%s: internal 50 cable %s present",
440 ahc_name(ahc),
441 internal50_present ? "is":"not");
442
443 if ((ahc->features & AHC_WIDE) != 0)
444 printf(", internal 68 cable %s present",
445 internal68_present ? "is":"not");
446 printf("\n%s: external cable %s present\n",
447 ahc_name(ahc),
448 externalcable_present ? "is":"not");
449 }
450 if (bootverbose)
451 printf("%s: BIOS eeprom %s present\n",
452 ahc_name(ahc), eeprom_present ? "is" : "not");
453
454 if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) {
455
456
457
458
459
460
461
462 internal50_present = 0;
463 }
464
465
466
467
468
469
470
471
472
473 if ((ahc->features & AHC_ULTRA2) == 0
474 && (internal50_present != 0)
475 && (internal68_present != 0)
476 && (externalcable_present != 0)) {
477 printf("%s: Illegal cable configuration!!. "
478 "Only two connectors on the "
479 "adapter may be used at a "
480 "time!\n", ahc_name(ahc));
481
482
483
484
485
486
487 internal50_present = 0;
488 internal68_present = 0;
489 externalcable_present = 0;
490 }
491
492 if ((ahc->features & AHC_WIDE) != 0
493 && ((externalcable_present == 0)
494 || (internal68_present == 0)
495 || (enableSEC_high != 0))) {
496 brddat |= BRDDAT6;
497 if (bootverbose) {
498 if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)
499 printf("%s: 68 pin termination "
500 "Enabled\n", ahc_name(ahc));
501 else
502 printf("%s: %sHigh byte termination "
503 "Enabled\n", ahc_name(ahc),
504 enableSEC_high ? "Secondary "
505 : "");
506 }
507 }
508
509 sum = internal50_present + internal68_present
510 + externalcable_present;
511 if (sum < 2 || (enableSEC_low != 0)) {
512 if ((ahc->features & AHC_ULTRA2) != 0)
513 brddat |= BRDDAT5;
514 else
515 *sxfrctl1 |= STPWEN;
516 if (bootverbose) {
517 if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)
518 printf("%s: 50 pin termination "
519 "Enabled\n", ahc_name(ahc));
520 else
521 printf("%s: %sLow byte termination "
522 "Enabled\n", ahc_name(ahc),
523 enableSEC_low ? "Secondary "
524 : "");
525 }
526 }
527
528 if (enablePRI_low != 0) {
529 *sxfrctl1 |= STPWEN;
530 if (bootverbose)
531 printf("%s: Primary Low Byte termination "
532 "Enabled\n", ahc_name(ahc));
533 }
534
535
536
537
538
539 ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
540
541 if (enablePRI_high != 0) {
542 brddat |= BRDDAT4;
543 if (bootverbose)
544 printf("%s: Primary High Byte "
545 "termination Enabled\n",
546 ahc_name(ahc));
547 }
548
549 write_brdctl(ahc, brddat);
550
551 } else {
552 if ((adapter_control & CFSTERM) != 0) {
553 *sxfrctl1 |= STPWEN;
554
555 if (bootverbose)
556 printf("%s: %sLow byte termination Enabled\n",
557 ahc_name(ahc),
558 (ahc->features & AHC_ULTRA2) ? "Primary "
559 : "");
560 }
561
562 if ((adapter_control & CFWSTERM) != 0
563 && (ahc->features & AHC_WIDE) != 0) {
564 brddat |= BRDDAT6;
565 if (bootverbose)
566 printf("%s: %sHigh byte termination Enabled\n",
567 ahc_name(ahc),
568 (ahc->features & AHC_ULTRA2)
569 ? "Secondary " : "");
570 }
571
572
573
574
575
576 ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
577
578 if ((ahc->features & AHC_WIDE) != 0)
579 write_brdctl(ahc, brddat);
580 }
581 SEEPROM_OUTB(sd, sd->sd_MS);
582 }
583
584 static void
585 ahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low,
586 int *enableSEC_high, int *enablePRI_low,
587 int *enablePRI_high, int *eeprom_present)
588 {
589 uint8_t brdctl;
590
591
592
593
594
595
596
597
598 brdctl = read_brdctl(ahc);
599 *eeprom_present = brdctl & BRDDAT7;
600 *enableSEC_high = (brdctl & BRDDAT6);
601 *enableSEC_low = (brdctl & BRDDAT5);
602 *enablePRI_high = (brdctl & BRDDAT4);
603 *enablePRI_low = (brdctl & BRDDAT3);
604 }
605
606 static void
607 aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
608 int *internal68_present, int *externalcable_present,
609 int *eeprom_present)
610 {
611 uint8_t brdctl;
612
613
614
615
616
617
618
619
620 write_brdctl(ahc, 0);
621
622
623
624
625
626
627 brdctl = read_brdctl(ahc);
628 *internal50_present = (brdctl & BRDDAT6) ? 0 : 1;
629 *internal68_present = (brdctl & BRDDAT7) ? 0 : 1;
630
631
632
633
634
635 write_brdctl(ahc, BRDDAT5);
636
637
638
639
640
641
642 brdctl = read_brdctl(ahc);
643 *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
644 *eeprom_present = (brdctl & BRDDAT7) ? 1 : 0;
645 }
646
647 static void
648 aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
649 int *externalcable_present, int *eeprom_present)
650 {
651 uint8_t brdctl;
652 uint8_t spiocap;
653
654 spiocap = ahc_inb(ahc, SPIOCAP);
655 spiocap &= ~SOFTCMDEN;
656 spiocap |= EXT_BRDCTL;
657 ahc_outb(ahc, SPIOCAP, spiocap);
658 ahc_outb(ahc, BRDCTL, BRDRW|BRDCS);
659 ahc_outb(ahc, BRDCTL, 0);
660 brdctl = ahc_inb(ahc, BRDCTL);
661 *internal50_present = (brdctl & BRDDAT5) ? 0 : 1;
662 *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
663
664 *eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0;
665 }
666
667 int
668 ahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd)
669 {
670 int wait;
671
672 if ((ahc->features & AHC_SPIOCAP) != 0
673 && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0)
674 return (0);
675
676
677
678
679
680
681
682
683 SEEPROM_OUTB(sd, sd->sd_MS);
684 wait = 1000;
685 while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) {
686 aic_delay(1000);
687 }
688 if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) {
689 SEEPROM_OUTB(sd, 0);
690 return (0);
691 }
692 return(1);
693 }
694
695 void
696 ahc_release_seeprom(struct seeprom_descriptor *sd)
697 {
698
699 SEEPROM_OUTB(sd, 0);
700 }
701
702 static void
703 write_brdctl(struct ahc_softc *ahc, uint8_t value)
704 {
705 uint8_t brdctl;
706
707 if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
708 brdctl = BRDSTB;
709 if (ahc->channel == 'B')
710 brdctl |= BRDCS;
711 } else if ((ahc->features & AHC_ULTRA2) != 0) {
712 brdctl = 0;
713 } else {
714 brdctl = BRDSTB|BRDCS;
715 }
716 ahc_outb(ahc, BRDCTL, brdctl);
717 ahc_flush_device_writes(ahc);
718 brdctl |= value;
719 ahc_outb(ahc, BRDCTL, brdctl);
720 ahc_flush_device_writes(ahc);
721 if ((ahc->features & AHC_ULTRA2) != 0)
722 brdctl |= BRDSTB_ULTRA2;
723 else
724 brdctl &= ~BRDSTB;
725 ahc_outb(ahc, BRDCTL, brdctl);
726 ahc_flush_device_writes(ahc);
727 if ((ahc->features & AHC_ULTRA2) != 0)
728 brdctl = 0;
729 else
730 brdctl &= ~BRDCS;
731 ahc_outb(ahc, BRDCTL, brdctl);
732 }
733
734 static uint8_t
735 read_brdctl(ahc)
736 struct ahc_softc *ahc;
737 {
738 uint8_t brdctl;
739 uint8_t value;
740
741 if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
742 brdctl = BRDRW;
743 if (ahc->channel == 'B')
744 brdctl |= BRDCS;
745 } else if ((ahc->features & AHC_ULTRA2) != 0) {
746 brdctl = BRDRW_ULTRA2;
747 } else {
748 brdctl = BRDRW|BRDCS;
749 }
750 ahc_outb(ahc, BRDCTL, brdctl);
751 ahc_flush_device_writes(ahc);
752 value = ahc_inb(ahc, BRDCTL);
753 ahc_outb(ahc, BRDCTL, 0);
754 return (value);
755 }
756
757 static int
758 verify_seeprom_cksum(struct seeprom_config *sc)
759 {
760 int i;
761 int maxaddr;
762 uint32_t checksum;
763 uint16_t *scarray;
764
765 maxaddr = (sizeof(*sc)/2) - 1;
766 checksum = 0;
767 scarray = (uint16_t *)sc;
768
769 for (i = 0; i < maxaddr; i++)
770 checksum = checksum + scarray[i];
771 if (checksum == 0
772 || (checksum & 0xFFFF) != sc->checksum) {
773 return (0);
774 } else {
775 return(1);
776 }
777 }