No empty .Rs/.Re
[netbsd-mini2440.git] / sys / dev / ic / aic7xxx_seeprom.c
blob8605f7f05eeb6bc78ade36fc071136effa48de09
1 /* $NetBSD: aic7xxx_seeprom.c,v 1.12 2007/10/19 11:59:46 ad Exp $ */
3 /*
4 * Product specific probe and attach routines for:
5 * 3940, 2940, aic7895, aic7890, aic7880,
6 * aic7870, aic7860 and aic7850 SCSI controllers
8 * Copyright (c) 1994-2001 Justin T. Gibbs.
9 * Copyright (c) 2000-2001 Adaptec Inc.
10 * All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
44 * This file was originally split off from the PCI code by
45 * Jason Thorpe <thorpej@NetBSD.org>. This version was split off
46 * from the FreeBSD source file aic7xxx_pci.c by Frank van der Linden
47 * <fvdl@NetBSD.org>
49 * $Id: aic7xxx_seeprom.c,v 1.13 2009/03/14 15:36:17 dsl Exp $
51 * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx_pci.c,v 1.22 2003/01/20 20:44:55 gibbs Exp $
54 #include <sys/cdefs.h>
55 __KERNEL_RCSID(0, "$NetBSD: aic7xxx_seeprom.c,v 1.12 2007/10/19 11:59:46 ad Exp $");
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/malloc.h>
60 #include <sys/kernel.h>
61 #include <sys/queue.h>
62 #include <sys/device.h>
63 #include <sys/reboot.h> /* for AB_* needed by bootverbose */
65 #include <sys/bus.h>
66 #include <sys/intr.h>
68 #include <dev/scsipi/scsi_all.h>
69 #include <dev/scsipi/scsipi_all.h>
70 #include <dev/scsipi/scsiconf.h>
72 #include <dev/ic/aic7xxx_osm.h>
73 #include <dev/ic/aic7xxx_inline.h>
75 #include <dev/ic/smc93cx6var.h>
77 #define DEVCONFIG 0x40
78 #define STPWLEVEL 0x00000002
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);
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 *);
94 * Check the external port logic for a serial eeprom
95 * and termination/cable detection contrls.
97 void
98 ahc_check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
100 struct seeprom_descriptor sd;
101 struct seeprom_config *sc;
102 int have_seeprom;
103 int have_autoterm;
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;
114 * For some multi-channel devices, the c46 is simply too
115 * small to work. For the other controller types, we can
116 * get our information from either SEEPROM type. Set the
117 * type to start our probe with accordingly.
119 if (ahc->flags & AHC_LARGE_SEEPROM)
120 sd.sd_chip = C56_66;
121 else
122 sd.sd_chip = C46;
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;
131 have_seeprom = ahc_acquire_seeprom(ahc, &sd);
132 if (have_seeprom) {
134 if (bootverbose)
135 printf("%s: Reading SEEPROM...", ahc_name(ahc));
137 for (;;) {
138 u_int start_addr;
140 start_addr = 32 * (ahc->channel - 'A');
141 have_seeprom = read_seeprom(&sd, (uint16_t *)sc,
142 start_addr,
143 sizeof(*sc)/2);
145 if (have_seeprom)
146 have_seeprom = verify_seeprom_cksum(sc);
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");
155 break;
157 sd.sd_chip = C56_66;
159 ahc_release_seeprom(&sd);
162 if (!have_seeprom) {
164 * Pull scratch ram settings and treat them as
165 * if they are the contents of an seeprom if
166 * the 'ADPT' signature is found in SCB2.
167 * We manually compose the data as 16bit values
168 * to avoid endian issues.
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;
178 sc_data = (uint16_t *)sc;
179 for (i = 0; i < 32; i++, sc_data++) {
180 int j;
182 j = i * 2;
183 *sc_data = ahc_inb(ahc, SRAM_BASE + j)
184 | ahc_inb(ahc, SRAM_BASE + j + 1) << 8;
186 have_seeprom = verify_seeprom_cksum(sc);
187 if (have_seeprom)
188 ahc->flags |= AHC_SCB_CONFIG_USED;
191 * Clear any SCB parity errors in case this data and
192 * its associated parity was not initialized by the BIOS
194 ahc_outb(ahc, CLRINT, CLRPARERR);
195 ahc_outb(ahc, CLRINT, CLRBRKADRINT);
198 if (!have_seeprom) {
199 if (bootverbose)
200 printf("%s: No SEEPROM available.\n", ahc_name(ahc));
201 ahc->flags |= AHC_USEDEFAULTS;
202 free(ahc->seep_config, M_DEVBUF);
203 ahc->seep_config = NULL;
204 sc = NULL;
205 } else {
206 ahc_parse_pci_eeprom(ahc, sc);
210 * Cards that have the external logic necessary to talk to
211 * a SEEPROM, are almost certain to have the remaining logic
212 * necessary for auto-termination control. This assumption
213 * hasn't failed yet...
215 have_autoterm = have_seeprom;
218 * Some low-cost chips have SEEPROM and auto-term control built
219 * in, instead of using a GAL. They can tell us directly
220 * if the termination logic is enabled.
222 if ((ahc->features & AHC_SPIOCAP) != 0) {
223 if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0)
224 have_autoterm = FALSE;
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");
242 static void
243 ahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc)
246 * Put the data we've collected down into SRAM
247 * where ahc_init will find it.
249 int i;
250 int max_targ = sc->max_targets & CFMAXTARG;
251 u_int scsi_conf;
252 uint16_t discenable;
253 uint16_t ultraenb;
255 discenable = 0;
256 ultraenb = 0;
257 if ((sc->adapter_control & CFULTRAEN) != 0) {
259 * Determine if this adapter has a "newstyle"
260 * SEEPROM format.
262 for (i = 0; i < max_targ; i++) {
263 if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) {
264 ahc->flags |= AHC_NEWEEPROM_FMT;
265 break;
270 for (i = 0; i < max_targ; i++) {
271 u_int scsirate;
272 uint16_t target_mask;
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;
283 if ((sc->device_flags[i] & CFXFER) == 0x04
284 && (ultraenb & target_mask) != 0) {
285 /* Treat 10MHz as a non-ultra speed */
286 sc->device_flags[i] &= ~CFXFER;
287 ultraenb &= ~target_mask;
289 if ((ahc->features & AHC_ULTRA2) != 0) {
290 u_int offset;
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);
299 * The ultra enable bits contain the
300 * high bit of the ultra2 sync rate
301 * field.
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;
314 ahc_outb(ahc, TARG_SCSIRATE + i, scsirate);
316 ahc->our_id = sc->brtime_id & CFSCSIID;
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;
324 ahc->flags |= (sc->adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT;
326 if (sc->bios_control & CFEXTEND)
327 ahc->flags |= AHC_EXTENDED_TRANS_A;
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 /* Should we enable Ultra mode? */
334 if (!(sc->adapter_control & CFULTRAEN))
335 /* Treat us as a non-ultra card */
336 ultraenb = 0;
339 if (sc->signature == CFSIGNATURE
340 || sc->signature == CFSIGNATURE2) {
341 uint32_t devconfig;
343 /* Honor the STPWLEVEL settings */
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);
350 /* Set SCSICONF info */
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);
358 static void
359 configure_termination(struct ahc_softc *ahc,
360 struct seeprom_descriptor *sd,
361 u_int adapter_control,
362 u_int *sxfrctl1)
364 uint8_t brddat;
366 brddat = 0;
369 * Update the settings in sxfrctl1 to match the
370 * termination settings
372 *sxfrctl1 = 0;
375 * SEECS must be on for the GALS to latch
376 * the data properly. Be sure to leave MS
377 * on or we will release the seeprom.
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;
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);
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);
417 /* Make the table calculations below happy */
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 /* Can never support a wide connector. */
426 internal68_present = 0;
427 } else {
428 aic787X_cable_detect(ahc, &internal50_present,
429 &internal68_present,
430 &externalcable_present,
431 &eeprom_present);
434 if ((ahc->features & AHC_WIDE) == 0)
435 internal68_present = 0;
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");
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");
450 if (bootverbose)
451 printf("%s: BIOS eeprom %s present\n",
452 ahc_name(ahc), eeprom_present ? "is" : "not");
454 if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) {
456 * The 50 pin connector is a separate bus,
457 * so force it to always be terminated.
458 * In the future, perform current sensing
459 * to determine if we are in the middle of
460 * a properly terminated bus.
462 internal50_present = 0;
466 * Now set the termination based on what
467 * we found.
468 * Flash Enable = BRDDAT7
469 * Secondary High Term Enable = BRDDAT6
470 * Secondary Low Term Enable = BRDDAT5 (7890)
471 * Primary High Term Enable = BRDDAT4 (7890)
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));
483 * Pretend there are no cables in the hope
484 * that having all of the termination on
485 * gives us a more stable bus.
487 internal50_present = 0;
488 internal68_present = 0;
489 externalcable_present = 0;
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 : "");
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 : "");
528 if (enablePRI_low != 0) {
529 *sxfrctl1 |= STPWEN;
530 if (bootverbose)
531 printf("%s: Primary Low Byte termination "
532 "Enabled\n", ahc_name(ahc));
536 * Setup STPWEN before setting up the rest of
537 * the termination per the tech note on the U160 cards.
539 ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
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));
549 write_brdctl(ahc, brddat);
551 } else {
552 if ((adapter_control & CFSTERM) != 0) {
553 *sxfrctl1 |= STPWEN;
555 if (bootverbose)
556 printf("%s: %sLow byte termination Enabled\n",
557 ahc_name(ahc),
558 (ahc->features & AHC_ULTRA2) ? "Primary "
559 : "");
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 " : "");
573 * Setup STPWEN before setting up the rest of
574 * the termination per the tech note on the U160 cards.
576 ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
578 if ((ahc->features & AHC_WIDE) != 0)
579 write_brdctl(ahc, brddat);
581 SEEPROM_OUTB(sd, sd->sd_MS); /* Clear CS */
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)
589 uint8_t brdctl;
592 * BRDDAT7 = Eeprom
593 * BRDDAT6 = Enable Secondary High Byte termination
594 * BRDDAT5 = Enable Secondary Low Byte termination
595 * BRDDAT4 = Enable Primary high byte termination
596 * BRDDAT3 = Enable Primary low byte termination
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);
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)
611 uint8_t brdctl;
614 * First read the status of our cables.
615 * Set the rom bank to 0 since the
616 * bank setting serves as a multiplexor
617 * for the cable detection logic.
618 * BRDDAT5 controls the bank switch.
620 write_brdctl(ahc, 0);
623 * Now read the state of the internal
624 * connectors. BRDDAT6 is INT50 and
625 * BRDDAT7 is INT68.
627 brdctl = read_brdctl(ahc);
628 *internal50_present = (brdctl & BRDDAT6) ? 0 : 1;
629 *internal68_present = (brdctl & BRDDAT7) ? 0 : 1;
632 * Set the rom bank to 1 and determine
633 * the other signals.
635 write_brdctl(ahc, BRDDAT5);
638 * Now read the state of the external
639 * connectors. BRDDAT6 is EXT68 and
640 * BRDDAT7 is EPROMPS.
642 brdctl = read_brdctl(ahc);
643 *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
644 *eeprom_present = (brdctl & BRDDAT7) ? 1 : 0;
647 static void
648 aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
649 int *externalcable_present, int *eeprom_present)
651 uint8_t brdctl;
652 uint8_t spiocap;
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;
664 *eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0;
668 ahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd)
670 int wait;
672 if ((ahc->features & AHC_SPIOCAP) != 0
673 && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0)
674 return (0);
677 * Request access of the memory port. When access is
678 * granted, SEERDY will go high. We use a 1 second
679 * timeout which should be near 1 second more than
680 * is needed. Reason: after the chip reset, there
681 * should be no contention.
683 SEEPROM_OUTB(sd, sd->sd_MS);
684 wait = 1000; /* 1 second timeout in msec */
685 while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) {
686 ahc_delay(1000); /* delay 1 msec */
688 if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) {
689 SEEPROM_OUTB(sd, 0);
690 return (0);
692 return(1);
695 void
696 ahc_release_seeprom(struct seeprom_descriptor *sd)
698 /* Release access to the memory port and the serial EEPROM. */
699 SEEPROM_OUTB(sd, 0);
702 static void
703 write_brdctl(struct ahc_softc *ahc, uint8_t value)
705 uint8_t brdctl;
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;
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);
734 static uint8_t
735 read_brdctl(struct ahc_softc *ahc)
737 uint8_t brdctl;
738 uint8_t value;
740 if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
741 brdctl = BRDRW;
742 if (ahc->channel == 'B')
743 brdctl |= BRDCS;
744 } else if ((ahc->features & AHC_ULTRA2) != 0) {
745 brdctl = BRDRW_ULTRA2;
746 } else {
747 brdctl = BRDRW|BRDCS;
749 ahc_outb(ahc, BRDCTL, brdctl);
750 ahc_flush_device_writes(ahc);
751 value = ahc_inb(ahc, BRDCTL);
752 ahc_outb(ahc, BRDCTL, 0);
753 return (value);
756 static int
757 verify_seeprom_cksum(struct seeprom_config *sc)
759 int i;
760 int maxaddr;
761 uint32_t checksum;
762 uint16_t *scarray;
764 maxaddr = (sizeof(*sc)/2) - 1;
765 checksum = 0;
766 scarray = (uint16_t *)sc;
768 for (i = 0; i < maxaddr; i++)
769 checksum = checksum + scarray[i];
770 if (checksum == 0
771 || (checksum & 0xFFFF) != sc->checksum) {
772 return (0);
773 } else {
774 return(1);