ahc_pci.c revision 1.20 1 /* $NetBSD: ahc_pci.c,v 1.20 2000/01/26 06:04:41 thorpej Exp $ */
2
3 /*
4 * Product specific probe and attach routines for:
5 * 3940, 2940, aic7880, aic7870, aic7860 and aic7850 SCSI controllers
6 *
7 * Copyright (c) 1995, 1996 Justin T. Gibbs.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice immediately at the beginning of the file, without modification,
15 * this list of conditions, and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
26 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * from Id: aic7870.c,v 1.37 1996/06/08 06:55:55 gibbs Exp
35 */
36
37 #if defined(__FreeBSD__)
38 #include <pci.h>
39 #endif
40 #if NPCI > 0 || defined(__NetBSD__)
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/malloc.h>
44 #include <sys/kernel.h>
45 #include <sys/queue.h>
46 #if defined(__NetBSD__)
47 #include <sys/device.h>
48 #include <machine/bus.h>
49 #include <machine/intr.h>
50 #endif /* defined(__NetBSD__) */
51
52 #include <dev/scsipi/scsi_all.h>
53 #include <dev/scsipi/scsipi_all.h>
54 #if defined (__NetBSD__)
55 #endif
56 #include <dev/scsipi/scsiconf.h>
57
58 #if defined(__FreeBSD__)
59
60 #include <pci/pcireg.h>
61 #include <pci/pcivar.h>
62
63 #include <machine/clock.h>
64
65 #include <i386/scsi/aic7xxx.h>
66 #include <i386/scsi/93cx6.h>
67
68 #include <dev/aic7xxx/aic7xxx_reg.h>
69
70 #define PCI_BASEADR0 PCI_MAP_REG_START
71
72 #elif defined(__NetBSD__)
73
74 #include <dev/pci/pcireg.h>
75 #include <dev/pci/pcivar.h>
76
77 #include <dev/ic/aic7xxxreg.h>
78 #include <dev/ic/aic7xxxvar.h>
79
80 /*
81 * Under normal circumstances, these messages are unnecessary
82 * and not terribly cosmetic.
83 */
84 #ifdef DEBUG
85 #define bootverbose 1
86 #else
87 #define bootverbose 0
88 #endif
89
90 #define PCI_BASEADR_IO 0x10
91 #define PCI_BASEADR_MEM 0x14
92
93 #endif /* defined(__NetBSD__) */
94
95 #define PCI_DEVICE_ID_ADAPTEC_3940U 0x82789004ul
96 #define PCI_DEVICE_ID_ADAPTEC_2944U 0x84789004ul
97 #define PCI_DEVICE_ID_ADAPTEC_2940U 0x81789004ul
98 #define PCI_DEVICE_ID_ADAPTEC_2940UP 0x87789004ul
99 #define PCI_DEVICE_ID_ADAPTEC_2940AU 0x61789004ul
100 #define PCI_DEVICE_ID_ADAPTEC_3940 0x72789004ul
101 #define PCI_DEVICE_ID_ADAPTEC_2944 0x74789004ul
102 #define PCI_DEVICE_ID_ADAPTEC_2940 0x71789004ul
103 #define PCI_DEVICE_ID_ADAPTEC_AIC7880 0x80789004ul
104 #define PCI_DEVICE_ID_ADAPTEC_AIC7870 0x70789004ul
105 #define PCI_DEVICE_ID_ADAPTEC_AIC7860 0x60789004ul
106 #define PCI_DEVICE_ID_ADAPTEC_AIC7855 0x55789004ul
107 #define PCI_DEVICE_ID_ADAPTEC_AIC7850 0x50789004ul
108
109 #define DEVCONFIG 0x40
110 #define MPORTMODE 0x00000400ul /* aic7870 only */
111 #define RAMPSM 0x00000200ul /* aic7870 only */
112 #define VOLSENSE 0x00000100ul
113 #define SCBRAMSEL 0x00000080ul
114 #define MRDCEN 0x00000040ul
115 #define EXTSCBTIME 0x00000020ul /* aic7870 only */
116 #define EXTSCBPEN 0x00000010ul /* aic7870 only */
117 #define BERREN 0x00000008ul
118 #define DACEN 0x00000004ul
119 #define STPWLEVEL 0x00000002ul
120 #define DIFACTNEGEN 0x00000001ul /* aic7870 only */
121
122 #define CSIZE_LATTIME 0x0c
123 #define CACHESIZE 0x0000003ful /* only 5 bits */
124 #define LATTIME 0x0000ff00ul
125
126 static u_char aic3940_count;
127
128 #if defined(__FreeBSD__)
129
130 static char* aic7870_probe __P((pcici_t tag, pcidi_t type));
131 static void aic7870_attach __P((pcici_t config_id, int unit));
132
133 static struct pci_device ahc_pci_driver = {
134 "ahc",
135 aic7870_probe,
136 aic7870_attach,
137 &ahc_unit,
138 NULL
139 };
140
141 DATA_SET (pcidevice_set, ahc_pci_driver);
142
143 static char*
144 aic7870_probe (pcici_t tag, pcidi_t type)
145 {
146 switch(type) {
147 case PCI_DEVICE_ID_ADAPTEC_3940U:
148 return ("Adaptec 3940 Ultra SCSI host adapter");
149 break;
150 case PCI_DEVICE_ID_ADAPTEC_3940:
151 return ("Adaptec 3940 SCSI host adapter");
152 break;
153 case PCI_DEVICE_ID_ADAPTEC_2944U:
154 return ("Adaptec 2944 Ultra SCSI host adapter");
155 break;
156 case PCI_DEVICE_ID_ADAPTEC_2940U:
157 return ("Adaptec 2940 Ultra SCSI host adapter");
158 break;
159 case PCI_DEVICE_ID_ADAPTEC_2940UP:
160 return ("Adaptec 2940 Ultra SCSI Pro host adapter");
161 break;
162 case PCI_DEVICE_ID_ADAPTEC_2944:
163 return ("Adaptec 2944 SCSI host adapter");
164 break;
165 case PCI_DEVICE_ID_ADAPTEC_2940:
166 return ("Adaptec 2940 SCSI host adapter");
167 break;
168 case PCI_DEVICE_ID_ADAPTEC_2940AU:
169 return ("Adaptec 2940A Ultra SCSI host adapter");
170 break;
171 case PCI_DEVICE_ID_ADAPTEC_AIC7880:
172 return ("Adaptec aic7880 Ultra SCSI host adapter");
173 break;
174 case PCI_DEVICE_ID_ADAPTEC_AIC7870:
175 return ("Adaptec aic7870 SCSI host adapter");
176 break;
177 case PCI_DEVICE_ID_ADAPTEC_AIC7860:
178 return ("Adaptec aic7860 SCSI host adapter");
179 break;
180 case PCI_DEVICE_ID_ADAPTEC_AIC7855:
181 return ("Adaptec aic7855 SCSI host adapter");
182 break;
183 case PCI_DEVICE_ID_ADAPTEC_AIC7850:
184 return ("Adaptec aic7850 SCSI host adapter");
185 break;
186 default:
187 break;
188 }
189 return (0);
190
191 }
192
193 #elif defined(__NetBSD__)
194
195 int ahc_pci_probe __P((struct device *, struct cfdata *, void *));
196 void ahc_pci_attach __P((struct device *, struct device *, void *));
197
198 struct cfattach ahc_pci_ca = {
199 sizeof(struct ahc_data), ahc_pci_probe, ahc_pci_attach
200 };
201
202 int
203 ahc_pci_probe(parent, match, aux)
204 struct device *parent;
205 struct cfdata *match;
206 void *aux;
207 {
208 struct pci_attach_args *pa = aux;
209
210 switch (pa->pa_id) {
211 case PCI_DEVICE_ID_ADAPTEC_3940U:
212 case PCI_DEVICE_ID_ADAPTEC_2944U:
213 case PCI_DEVICE_ID_ADAPTEC_2940U:
214 case PCI_DEVICE_ID_ADAPTEC_2940UP:
215 case PCI_DEVICE_ID_ADAPTEC_2940AU:
216 case PCI_DEVICE_ID_ADAPTEC_3940:
217 case PCI_DEVICE_ID_ADAPTEC_2944:
218 case PCI_DEVICE_ID_ADAPTEC_2940:
219 case PCI_DEVICE_ID_ADAPTEC_AIC7880:
220 case PCI_DEVICE_ID_ADAPTEC_AIC7870:
221 case PCI_DEVICE_ID_ADAPTEC_AIC7860:
222 case PCI_DEVICE_ID_ADAPTEC_AIC7855:
223 case PCI_DEVICE_ID_ADAPTEC_AIC7850:
224 return 1;
225 }
226 return 0;
227 }
228 #endif /* defined(__NetBSD__) */
229
230 #if defined(__FreeBSD__)
231 static void
232 aic7870_attach(config_id, unit)
233 pcici_t config_id;
234 int unit;
235 #elif defined(__NetBSD__)
236 void
237 ahc_pci_attach(parent, self, aux)
238 struct device *parent, *self;
239 void *aux;
240 #endif
241 {
242 #if defined(__FreeBSD__)
243 u_long io_port;
244 int unit = ahc->sc_dev.dv_unit;
245 #elif defined(__NetBSD__)
246 struct pci_attach_args *pa = aux;
247 struct ahc_data *ahc = (void *)self;
248 bus_space_tag_t st, iot, memt;
249 bus_space_handle_t sh, ioh, memh;
250 int ioh_valid, memh_valid;
251 pci_intr_handle_t ih;
252 const char *intrstr;
253 #endif
254 u_long id;
255 unsigned opri = 0;
256 ahc_type ahc_t = AHC_NONE;
257 ahc_flag ahc_f = AHC_FNONE;
258 #if defined(__FreeBSD__)
259 struct ahc_data *ahc;
260 #endif
261 u_char ultra_enb = 0;
262 u_char our_id = 0;
263
264 #if defined(__FreeBSD__)
265 if(!(io_port = pci_conf_read(config_id, PCI_BASEADR0)))
266 return;
267 /*
268 * The first bit of PCI_BASEADR0 is always
269 * set hence we mask it off.
270 */
271 io_port &= 0xfffffffe;
272 #elif defined(__NetBSD__)
273 ioh_valid = (pci_mapreg_map(pa, PCI_BASEADR_IO,
274 PCI_MAPREG_TYPE_IO, 0,
275 &iot, &ioh, NULL, NULL) == 0);
276 memh_valid = (pci_mapreg_map(pa, PCI_BASEADR_MEM,
277 PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
278 &memt, &memh, NULL, NULL) == 0);
279
280 if (memh_valid) {
281 st = memt;
282 sh = memh;
283 } else if (ioh_valid) {
284 st = iot;
285 sh = ioh;
286 } else {
287 printf(": unable to map registers\n");
288 return;
289 }
290 printf("\n");
291 #endif
292
293 #if defined(__FreeBSD__)
294 switch ((id = pci_conf_read(config_id, PCI_ID_REG))) {
295 #elif defined(__NetBSD__)
296 switch (id = pa->pa_id) {
297 #endif
298 case PCI_DEVICE_ID_ADAPTEC_3940U:
299 case PCI_DEVICE_ID_ADAPTEC_3940:
300 if (id == PCI_DEVICE_ID_ADAPTEC_3940U)
301 ahc_t = AHC_394U;
302 else
303 ahc_t = AHC_394;
304 aic3940_count++;
305 if(!(aic3940_count & 0x01))
306 /* Even count implies second channel */
307 ahc_f |= AHC_CHNLB;
308 break;
309 case PCI_DEVICE_ID_ADAPTEC_2944U:
310 case PCI_DEVICE_ID_ADAPTEC_2940U:
311 case PCI_DEVICE_ID_ADAPTEC_2940UP:
312 ahc_t = AHC_294U;
313 break;
314 case PCI_DEVICE_ID_ADAPTEC_2944:
315 case PCI_DEVICE_ID_ADAPTEC_2940:
316 ahc_t = AHC_294;
317 break;
318 case PCI_DEVICE_ID_ADAPTEC_2940AU:
319 ahc_t = AHC_294AU;
320 break;
321 case PCI_DEVICE_ID_ADAPTEC_AIC7880:
322 ahc_t = AHC_AIC7880;
323 break;
324 case PCI_DEVICE_ID_ADAPTEC_AIC7870:
325 ahc_t = AHC_AIC7870;
326 break;
327 case PCI_DEVICE_ID_ADAPTEC_AIC7860:
328 ahc_t = AHC_AIC7860;
329 break;
330 case PCI_DEVICE_ID_ADAPTEC_AIC7855:
331 case PCI_DEVICE_ID_ADAPTEC_AIC7850:
332 ahc_t = AHC_AIC7850;
333 break;
334 default:
335 break;
336 }
337
338 /* On all PCI adapters, we allow SCB paging */
339 ahc_f |= AHC_PAGESCBS;
340
341 /* Remeber how the card was setup in case there is no SEEPROM */
342 #if defined(__FreeBSD__)
343 our_id = inb(SCSIID + io_port) & OID;
344 if(ahc_t & AHC_ULTRA)
345 ultra_enb = inb(SXFRCTL0 + io_port) & ULTRAEN;
346 #else
347 our_id = bus_space_read_1(st, sh, SCSIID) & OID;
348 if(ahc_t & AHC_ULTRA)
349 ultra_enb = bus_space_read_1(st, sh, SXFRCTL0) & ULTRAEN;
350 #endif
351
352 #if defined(__FreeBSD__)
353 ahc_reset(io_port);
354 #elif defined(__NetBSD__)
355 ahc_reset(ahc->sc_dev.dv_xname, st, sh);
356 #endif
357
358 if(ahc_t & AHC_AIC7870){
359 #if defined(__FreeBSD__)
360 u_long devconfig = pci_conf_read(config_id, DEVCONFIG);
361 #elif defined(__NetBSD__)
362 u_long devconfig =
363 pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG);
364 #endif
365
366 if(devconfig & (RAMPSM)) {
367 /*
368 * External SRAM present. Have the probe walk
369 * the SCBs to see how much SRAM we have and set
370 * the number of SCBs accordingly. We have to
371 * turn off SCBRAMSEL to access the external
372 * SCB SRAM.
373 *
374 * It seems that early versions of the aic7870
375 * didn't use these bits, hence the hack for the
376 * 3940 above. I would guess that recent 3940s
377 * using later aic7870 or aic7880 chips do
378 * actually set RAMPSM.
379 *
380 * The documentation isn't clear, but it sounds
381 * like the value written to devconfig must not
382 * have RAMPSM set. The second sixteen bits of
383 * the register are R/O anyway, so it shouldn't
384 * affect RAMPSM either way.
385 */
386 devconfig &= ~(RAMPSM|SCBRAMSEL);
387 #if defined(__FreeBSD__)
388 pci_conf_write(config_id, DEVCONFIG, devconfig);
389 #elif defined(__NetBSD__)
390 pci_conf_write(pa->pa_pc, pa->pa_tag,
391 DEVCONFIG, devconfig);
392 #endif
393 }
394 }
395
396 #if defined(__FreeBSD__)
397 if(!(ahc = ahc_alloc(unit, io_port, ahc_t, ahc_f)))
398 return; /* XXX PCI code should take return status */
399
400 if(!(pci_map_int(config_id, ahc_intr, (void *)ahc, &bio_imask))) {
401 ahc_free(ahc);
402 return;
403 }
404 #elif defined(__NetBSD__)
405 ahc_construct(ahc, st, sh, pa->pa_dmat, ahc_t, ahc_f);
406
407 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
408 pa->pa_intrline, &ih)) {
409 printf("%s: couldn't map interrupt\n", ahc->sc_dev.dv_xname);
410 ahc_free(ahc);
411 return;
412 }
413 intrstr = pci_intr_string(pa->pa_pc, ih);
414 ahc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, ahc_intr, ahc);
415 if (ahc->sc_ih == NULL) {
416 printf("%s: couldn't establish interrupt",
417 ahc->sc_dev.dv_xname);
418 if (intrstr != NULL)
419 printf(" at %s", intrstr);
420 printf("\n");
421 ahc_free(ahc);
422 return;
423 }
424 if (intrstr != NULL)
425 printf("%s: interrupting at %s\n", ahc->sc_dev.dv_xname,
426 intrstr);
427 #endif
428 /*
429 * Protect ourself from spurrious interrupts during
430 * intialization.
431 */
432 opri = splbio();
433
434 /*
435 * Do aic7870/aic7880/aic7850 specific initialization
436 */
437 {
438 u_char sblkctl;
439 char *id_string;
440
441 switch(ahc->type) {
442 case AHC_394U:
443 case AHC_294U:
444 case AHC_AIC7880:
445 {
446 id_string = "aic7880 ";
447 ahc_load_seeprom(ahc);
448 break;
449 }
450 case AHC_394:
451 case AHC_294:
452 case AHC_AIC7870:
453 {
454 id_string = "aic7870 ";
455 ahc_load_seeprom(ahc);
456 break;
457 }
458 case AHC_294AU:
459 case AHC_AIC7860:
460 {
461 id_string = "aic7860 ";
462 ahc_load_seeprom(ahc);
463 break;
464 }
465 case AHC_AIC7850:
466 {
467 id_string = "aic7850 ";
468 /*
469 * Use defaults, if the chip wasn't initialized by
470 * a BIOS.
471 */
472 ahc->flags |= AHC_USEDEFAULTS;
473 break;
474 }
475 default:
476 {
477 printf("ahc: Unknown controller type. Ignoring.\n");
478 ahc_free(ahc);
479 splx(opri);
480 return;
481 }
482 }
483
484 /*
485 * Take the LED out of diagnostic mode
486 */
487 sblkctl = AHC_INB(ahc, SBLKCTL);
488 AHC_OUTB(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON)));
489
490 /*
491 * I don't know where this is set in the SEEPROM or by the
492 * BIOS, so we default to 100%.
493 */
494 AHC_OUTB(ahc, DSPCISTATUS, DFTHRSH_100);
495
496 if(ahc->flags & AHC_USEDEFAULTS) {
497 /*
498 * PCI Adapter default setup
499 * Should only be used if the adapter does not have
500 * an SEEPROM.
501 */
502 /* See if someone else set us up already */
503 u_long i;
504 for(i = TARG_SCRATCH; i < 0x60; i++) {
505 if(AHC_INB(ahc, i) != 0x00)
506 break;
507 }
508 if(i == TARG_SCRATCH) {
509 /*
510 * Try looking for all ones. You can get
511 * either.
512 */
513 for (i = TARG_SCRATCH; i < 0x60; i++) {
514 if(AHC_INB(ahc, i) != 0xff)
515 break;
516 }
517 }
518 if((i != 0x60) && (our_id != 0)) {
519 printf("%s: Using left over BIOS settings\n",
520 ahc_name(ahc));
521 ahc->flags &= ~AHC_USEDEFAULTS;
522 }
523 else
524 our_id = 0x07;
525 AHC_OUTB(ahc, SCSICONF,
526 (our_id & 0x07)|ENSPCHK|RESET_SCSI);
527 /* In case we are a wide card */
528 AHC_OUTB(ahc, SCSICONF + 1, our_id);
529
530 if(!ultra_enb || (ahc->flags & AHC_USEDEFAULTS)) {
531 /*
532 * If there wasn't a BIOS or the board
533 * wasn't in this mode to begin with,
534 * turn off ultra.
535 */
536 ahc->type &= ~AHC_ULTRA;
537 }
538 }
539
540 printf("%s: %s", ahc_name(ahc), id_string);
541 }
542
543 if(ahc_init(ahc)){
544 ahc_free(ahc);
545 splx(opri);
546 return; /* XXX PCI code should take return status */
547 }
548 splx(opri);
549
550 ahc_attach(ahc);
551 }
552 #endif /* NPCI > 0 */
553