This source file includes following definitions.
- LIST_HEAD
- ahc_isa_idstring
- ahc_isa_match
- ahc_isa_probe
- ahc_isa_attach
- aha2840_load_seeprom
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
56
57
58
59
60
61
62
63
64
65
66 #include <sys/param.h>
67 #include <sys/systm.h>
68 #include <sys/kernel.h>
69 #include <sys/device.h>
70 #include <sys/queue.h>
71 #include <sys/malloc.h>
72
73 #include <machine/bus.h>
74 #include <machine/intr.h>
75
76 #include <scsi/scsi_all.h>
77 #include <scsi/scsiconf.h>
78
79 #include <dev/isa/isavar.h>
80
81 #include <dev/eisa/eisareg.h>
82 #include <dev/eisa/eisavar.h>
83 #include <dev/eisa/eisadevs.h>
84
85 #include <dev/ic/aic7xxx_openbsd.h>
86 #include <dev/ic/aic7xxx_inline.h>
87 #include <dev/ic/smc93cx6var.h>
88
89 #ifdef DEBUG
90 #define bootverbose 1
91 #else
92 #define bootverbose 0
93 #endif
94
95
96 #define AHC_ISA_MIN_SLOT 0x1
97 #define AHC_ISA_MAX_SLOT 0xe
98
99 #define AHC_ISA_SLOT_OFFSET 0xc00
100 #define AHC_ISA_IOSIZE 0x100
101
102
103
104
105 #define AHC_ISA_VID (EISA_SLOTOFF_VID - AHC_ISA_SLOT_OFFSET)
106 #define AHC_ISA_PID (EISA_SLOTOFF_PID - AHC_ISA_SLOT_OFFSET)
107 #define AHC_ISA_PRIMING AHC_ISA_VID
108
109
110
111
112 #define AHC_ISA_PRIMING_VID(index) (AHC_ISA_VID + (index))
113 #define AHC_ISA_PRIMING_PID(index) (AHC_ISA_PID + (index))
114
115 int ahc_isa_irq(bus_space_tag_t, bus_space_handle_t);
116 int ahc_isa_idstring(bus_space_tag_t, bus_space_handle_t, char *);
117 int ahc_isa_match(struct isa_attach_args *, bus_addr_t);
118
119 int ahc_isa_probe(struct device *, void *, void *);
120 void ahc_isa_attach(struct device *, struct device *, void *);
121 void aha2840_load_seeprom(struct ahc_softc *ahc);
122
123 struct cfattach ahc_isa_ca = {
124 sizeof(struct ahc_softc), ahc_isa_probe, ahc_isa_attach
125 };
126
127
128
129
130
131
132
133
134
135
136 struct ahc_isa_slot {
137 LIST_ENTRY(ahc_isa_slot) link;
138 int bus;
139 int slot;
140 };
141 static LIST_HEAD(, ahc_isa_slot) ahc_isa_all_slots;
142 static int ahc_isa_slot_initialized;
143
144
145
146
147 int
148 ahc_isa_irq(bus_space_tag_t iot, bus_space_handle_t ioh)
149 {
150 int irq;
151 u_char intdef;
152 u_char hcntrl;
153
154
155 hcntrl = bus_space_read_1(iot, ioh, HCNTRL) & IRQMS;
156 bus_space_write_1(iot, ioh, HCNTRL, hcntrl | PAUSE);
157
158 intdef = bus_space_read_1(iot, ioh, INTDEF);
159 switch (irq = (intdef & VECTOR)) {
160 case 9:
161 case 10:
162 case 11:
163 case 12:
164 case 14:
165 case 15:
166 break;
167 default:
168 printf("ahc_isa_irq: illegal irq setting %d\n", intdef);
169 return -1;
170 }
171
172
173 return irq;
174 }
175
176 int
177 ahc_isa_idstring(bus_space_tag_t iot, bus_space_handle_t ioh, char *idstring)
178 {
179 u_int8_t vid[EISA_NVIDREGS], pid[EISA_NPIDREGS];
180 int i;
181
182
183 for (i = 0; i < EISA_NVIDREGS; i++) {
184 bus_space_write_1(iot, ioh, AHC_ISA_PRIMING,
185 AHC_ISA_PRIMING_VID(i));
186 vid[i] = bus_space_read_1(iot, ioh, AHC_ISA_VID + i);
187 }
188
189
190 if (EISA_VENDID_NODEV(vid)) {
191 #if 0
192 printf("ahc_isa_idstring: no device at 0x%lx\n",
193 ioh);
194 printf("\t(0x%x, 0x%x)\n", vid[0], vid[1]);
195 #endif
196 return (0);
197 }
198
199
200 if (EISA_VENDID_IDDELAY(vid)) {
201 printf("ahc_isa_idstring: BIOS biffed it at 0x%lx\n",
202 ioh);
203 return (0);
204 }
205
206
207 for (i = 0; i < EISA_NPIDREGS; i++) {
208 bus_space_write_1(iot, ioh, AHC_ISA_PRIMING,
209 AHC_ISA_PRIMING_PID(i));
210 pid[i] = bus_space_read_1(iot, ioh, AHC_ISA_PID + i);
211 }
212
213
214 idstring[0] = EISA_VENDID_0(vid);
215 idstring[1] = EISA_VENDID_1(vid);
216 idstring[2] = EISA_VENDID_2(vid);
217 idstring[3] = EISA_PRODID_0(pid);
218 idstring[4] = EISA_PRODID_1(pid);
219 idstring[5] = EISA_PRODID_2(pid);
220 idstring[6] = EISA_PRODID_3(pid);
221 idstring[7] = '\0';
222
223 return (1);
224 }
225
226 int
227 ahc_isa_match(struct isa_attach_args *ia, bus_addr_t iobase)
228 {
229 bus_space_tag_t iot = ia->ia_iot;
230 bus_space_handle_t ioh;
231 int irq;
232 char idstring[EISA_IDSTRINGLEN];
233
234
235
236
237
238
239 if (bus_space_map(iot, iobase, AHC_ISA_IOSIZE, 0, &ioh)) {
240 #if 0
241
242
243
244
245
246 printf("ahc_isa_match: can't map I/O space for 0x%x\n",
247 iobase);
248 #endif
249 return (0);
250 }
251
252 if (!ahc_isa_idstring(iot, ioh, idstring))
253 irq = -1;
254 else if (strcmp(idstring, "ADP7756") &&
255 strcmp(idstring, "ADP7757"))
256 irq = -1;
257 else
258 irq = ahc_isa_irq(iot, ioh);
259
260 bus_space_unmap(iot, ioh, AHC_ISA_IOSIZE);
261
262 if (irq < 0)
263 return (0);
264
265 if (ia->ia_irq != IRQUNK &&
266 ia->ia_irq != irq) {
267 printf("ahc_isa_match: irq mismatch (kernel %d, card %d)\n",
268 ia->ia_irq, irq);
269 return (0);
270 }
271
272
273 ia->ia_iobase = iobase;
274 ia->ia_irq = irq;
275 ia->ia_iosize = AHC_ISA_IOSIZE;
276 ia->ia_msize = 0;
277 return (1);
278 }
279
280
281
282
283
284
285 int
286 ahc_isa_probe(struct device *parent, void *match, void *aux)
287 {
288 struct isa_attach_args *ia = aux;
289 struct ahc_isa_slot *as;
290
291 if (ahc_isa_slot_initialized == 0) {
292 LIST_INIT(&ahc_isa_all_slots);
293 ahc_isa_slot_initialized = 1;
294 }
295
296 if (ia->ia_iobase != IOBASEUNK)
297 return (ahc_isa_match(ia, ia->ia_iobase));
298
299
300
301
302
303 LIST_FOREACH(as, &ahc_isa_all_slots, link)
304 if (as->bus == parent->dv_unit)
305 goto found_slot_marker;
306
307
308
309
310 as = (struct ahc_isa_slot *)
311 malloc(sizeof(struct ahc_isa_slot), M_DEVBUF, M_NOWAIT);
312 if (as == NULL)
313 panic("ahc_isa_probe: can't allocate slot marker");
314
315 as->bus = parent->dv_unit;
316 as->slot = AHC_ISA_MIN_SLOT;
317 LIST_INSERT_HEAD(&ahc_isa_all_slots, as, link);
318
319 found_slot_marker:
320
321 for (; as->slot <= AHC_ISA_MAX_SLOT; as->slot++) {
322 if (ahc_isa_match(ia, EISA_SLOT_ADDR(as->slot) +
323 AHC_ISA_SLOT_OFFSET)) {
324 as->slot++;
325 return (1);
326 }
327 }
328
329
330 return (0);
331 }
332
333 void
334 ahc_isa_attach(struct device *parent, struct device *self, void *aux)
335 {
336 struct ahc_softc *ahc = (void *)self;
337 struct isa_attach_args *ia = aux;
338 bus_space_tag_t iot = ia->ia_iot;
339 bus_space_handle_t ioh;
340 int irq;
341 char idstring[EISA_IDSTRINGLEN];
342 const char *model;
343 u_int intdef;
344
345 ahc_set_name(ahc, ahc->sc_dev.dv_xname);
346 ahc_set_unit(ahc, ahc->sc_dev.dv_unit);
347
348
349 ahc->parent_dmat = ia->ia_dmat;
350
351 ahc->chip = AHC_VL;
352
353 if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh))
354 panic("ahc_isa_attach: could not map slot I/O addresses");
355 if (!ahc_isa_idstring(iot, ioh, idstring))
356 panic("ahc_isa_attach: could not read ID string");
357 if ((irq = ahc_isa_irq(iot, ioh)) < 0)
358 panic("ahc_isa_attach: ahc_isa_irq failed!");
359
360 if (strcmp(idstring, "ADP7756") == 0) {
361 model = EISA_PRODUCT_ADP7756;
362 } else if (strcmp(idstring, "ADP7757") == 0) {
363 model = EISA_PRODUCT_ADP7757;
364 } else {
365 panic("ahc_isa_attach: Unknown device type %s", idstring);
366 }
367 printf(": %s\n", model);
368
369 ahc->channel = 'A';
370 ahc->chip = AHC_AIC7770;
371 ahc->features = AHC_AIC7770_FE;
372 ahc->bugs |= AHC_TMODE_WIDEODD_BUG;
373 ahc->flags |= AHC_PAGESCBS;
374
375
376 ahc->tag = iot;
377 ahc->bsh = ioh;
378
379 #ifdef DEBUG
380
381
382
383
384 printf( "%s: Using %s Interrupts\n", ahc_name(ahc),
385 ahc->pause & IRQMS ? "Level Sensitive" : "Edge Triggered");
386 #endif
387
388 if (ahc_reset(ahc, FALSE) != 0)
389 return;
390
391
392 intdef = ahc_inb(ahc, INTDEF);
393 if ((intdef & EDGE_TRIG) != 0)
394 ahc->flags |= AHC_EDGE_INTERRUPT;
395
396
397
398
399
400 aha2840_load_seeprom(ahc);
401
402
403
404
405
406
407
408
409
410 {
411 char *id_string;
412 u_char sblkctl;
413 u_char sblkctl_orig;
414
415 sblkctl_orig = ahc_inb(ahc, SBLKCTL);
416 sblkctl = sblkctl_orig ^ AUTOFLUSHDIS;
417 ahc_outb(ahc, SBLKCTL, sblkctl);
418 sblkctl = ahc_inb(ahc, SBLKCTL);
419 if(sblkctl != sblkctl_orig)
420 {
421 id_string = "aic7770 >= Rev E, ";
422
423
424
425 sblkctl &= ~AUTOFLUSHDIS;
426 ahc_outb(ahc, SBLKCTL, sblkctl);
427
428
429 ahc->flags |= AHC_PAGESCBS;
430 }
431 else
432 id_string = "aic7770 <= Rev C, ";
433
434 printf("%s: %s", ahc_name(ahc), id_string);
435 }
436
437
438 {
439 u_char hostconf = ahc_inb(ahc, HOSTCONF);
440 ahc_outb(ahc, BUSSPD, hostconf & DFTHRSH);
441 ahc_outb(ahc, BUSTIME, (hostconf << 2) & BOFF);
442 }
443
444
445
446
447 if(ahc_init(ahc)){
448 ahc_free(ahc);
449 return;
450 }
451
452
453
454
455 ahc_softc_insert(ahc);
456
457
458
459
460 ahc_outb(ahc, BCTL, ENABLE);
461
462
463
464
465
466 ahc->ih = isa_intr_establish(ia->ia_ic, irq,
467 ahc->pause & IRQMS ? IST_LEVEL : IST_EDGE, IPL_BIO, ahc_platform_intr,
468 ahc, ahc->sc_dev.dv_xname);
469 if (ahc->ih == NULL) {
470 printf("%s: couldn't establish interrupt\n",
471 ahc->sc_dev.dv_xname);
472 ahc_free(ahc);
473 return;
474 }
475
476 ahc_intr_enable(ahc, TRUE);
477
478
479 ahc_attach(ahc);
480 }
481
482
483
484
485 void
486 aha2840_load_seeprom(struct ahc_softc *ahc)
487 {
488 struct seeprom_descriptor sd;
489 struct seeprom_config sc;
490 u_int16_t checksum = 0;
491 u_int8_t scsi_conf;
492 int have_seeprom;
493
494 sd.sd_tag = ahc->tag;
495 sd.sd_bsh = ahc->bsh;
496 sd.sd_regsize = 1;
497 sd.sd_control_offset = SEECTL_2840;
498 sd.sd_status_offset = STATUS_2840;
499 sd.sd_dataout_offset = STATUS_2840;
500 sd.sd_chip = C46;
501 sd.sd_MS = 0;
502 sd.sd_RDY = EEPROM_TF;
503 sd.sd_CS = CS_2840;
504 sd.sd_CK = CK_2840;
505 sd.sd_DO = DO_2840;
506 sd.sd_DI = DI_2840;
507
508 if (bootverbose)
509 printf("%s: Reading SEEPROM...", ahc_name(ahc));
510 have_seeprom = read_seeprom(&sd,
511 (u_int16_t *)&sc,
512 0,
513 sizeof(sc)/2);
514
515 if (have_seeprom) {
516
517 int i;
518 int maxaddr = (sizeof(sc)/2) - 1;
519 u_int16_t *scarray = (u_int16_t *)≻
520
521 for (i = 0; i < maxaddr; i++)
522 checksum = checksum + scarray[i];
523 if (checksum != sc.checksum) {
524 if(bootverbose)
525 printf ("checksum error\n");
526 have_seeprom = 0;
527 } else if (bootverbose) {
528 printf("done.\n");
529 }
530 }
531
532 if (!have_seeprom) {
533 if (bootverbose)
534 printf("%s: No SEEPROM available\n", ahc_name(ahc));
535 ahc->flags |= AHC_USEDEFAULTS;
536 } else {
537
538
539
540
541 int i;
542 int max_targ = (ahc->features & AHC_WIDE) != 0 ? 16 : 8;
543 u_int16_t discenable;
544
545 discenable = 0;
546 for (i = 0; i < max_targ; i++){
547 u_int8_t target_settings;
548 target_settings = (sc.device_flags[i] & CFXFER) << 4;
549 if (sc.device_flags[i] & CFSYNCH)
550 target_settings |= SOFS;
551 if (sc.device_flags[i] & CFWIDEB)
552 target_settings |= WIDEXFER;
553 if (sc.device_flags[i] & CFDISC)
554 discenable |= (0x01 << i);
555 ahc_outb(ahc, TARG_SCSIRATE + i, target_settings);
556 }
557 ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff));
558 ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff));
559
560 ahc->our_id = sc.brtime_id & CFSCSIID;
561
562 scsi_conf = (ahc->our_id & 0x7);
563 if (sc.adapter_control & CFSPARITY)
564 scsi_conf |= ENSPCHK;
565 if (sc.adapter_control & CFRESETB)
566 scsi_conf |= RESET_SCSI;
567
568 if (sc.bios_control & CF284XEXTEND)
569 ahc->flags |= AHC_EXTENDED_TRANS_A;
570
571 ahc_outb(ahc, SCSICONF, scsi_conf);
572
573 if (sc.adapter_control & CF284XSTERM)
574 ahc->flags |= AHC_TERM_ENB_A;
575 }
576 }