summaryrefslogtreecommitdiffstats
path: root/sys/pci
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>1999-12-06 18:29:03 +0000
committergibbs <gibbs@FreeBSD.org>1999-12-06 18:29:03 +0000
commit7ed7dfa1b1ec590e2f3ae57fb900ab4caf6bfc97 (patch)
tree20fba1893acb720f3c347be31e28c7f8d11c33e2 /sys/pci
parent7de5d2d4188cf51ce23905b7e5c99cd44523a0e4 (diff)
downloadFreeBSD-src-7ed7dfa1b1ec590e2f3ae57fb900ab4caf6bfc97.zip
FreeBSD-src-7ed7dfa1b1ec590e2f3ae57fb900ab4caf6bfc97.tar.gz
Simplify my license.
Don't arbitrarily limit the initiator ID of the card to something <= 7. Fix a bug in the checksum code that would incorrectly prevent a valid checksum of zero. (cp) Don't touch rely on seeprom data when configuring termination. We may not have seeprom data. (cp) Treat all ULTRA2 capable adapters the same way when reading or writing the BRDCTL register. We previously only did this correctly for aic7890/91 chips. This should correct some problems with termination settings on aic7896/97 adapters. (cp) Changes marked with "(cp)" Pointed out by: Chuck Paterson <cp@bsdi.com>
Diffstat (limited to 'sys/pci')
-rw-r--r--sys/pci/ahc_pci.c91
1 files changed, 52 insertions, 39 deletions
diff --git a/sys/pci/ahc_pci.c b/sys/pci/ahc_pci.c
index fd91f5e..78a6ce4 100644
--- a/sys/pci/ahc_pci.c
+++ b/sys/pci/ahc_pci.c
@@ -175,7 +175,7 @@ struct ahc_pci_identity ahc_pci_ident_table [] =
},
/* aic7859 based controllers */
{
- ID_AHA_2930CU,
+ ID_AHA_2930CU & ID_DEV_VENDOR_MASK,
ID_DEV_VENDOR_MASK,
"Adaptec 2930CU SCSI adapter",
ahc_aic7859_setup
@@ -194,7 +194,7 @@ struct ahc_pci_identity ahc_pci_ident_table [] =
ahc_aic7860_setup
},
{
- ID_AHA_2930C_VAR,
+ ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK,
ID_DEV_VENDOR_MASK,
"Adaptec 2930C SCSI adapter (VAR)",
ahc_aic7860_setup
@@ -467,8 +467,8 @@ static const int ahc_num_pci_devs =
static struct ahc_pci_identity *ahc_find_pci_device(device_t dev);
static void check_extport(struct ahc_softc *ahc, u_int *sxfrctl1);
static void configure_termination(struct ahc_softc *ahc,
- struct seeprom_config *sc,
struct seeprom_descriptor *sd,
+ u_int adapter_control,
u_int *sxfrctl1);
static void ahc_ultra2_term_detect(struct ahc_softc *ahc,
@@ -589,7 +589,6 @@ ahc_pci_attach(device_t dev)
&regs_id, 0, ~0, 1, RF_ACTIVE);
}
#endif
-
if (regs == NULL && (command & PCI_COMMAND_IO_ENABLE) != 0) {
regs_type = SYS_RES_IOPORT;
regs_id = AHC_PCI_IOADDR;
@@ -850,8 +849,7 @@ ahc_pci_attach(device_t dev)
our_id = 0x07;
sxfrctl1 = STPWEN;
}
- ahc_outb(ahc, SCSICONF,
- (our_id & 0x07)|ENSPCHK|RESET_SCSI);
+ ahc_outb(ahc, SCSICONF, our_id|ENSPCHK|RESET_SCSI);
ahc->our_id = our_id;
}
@@ -879,7 +877,6 @@ ahc_pci_attach(device_t dev)
}
ahc_attach(ahc);
-
return (0);
}
@@ -892,8 +889,10 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
{
struct seeprom_descriptor sd;
struct seeprom_config sc;
- u_int8_t scsi_conf;
+ u_int scsi_conf;
+ u_int adapter_control;
int have_seeprom;
+ int have_autoterm;
sd.sd_tag = ahc->tag;
sd.sd_bsh = ahc->bsh;
@@ -920,7 +919,6 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
sd.sd_DI = SEEDI;
have_seeprom = acquire_seeprom(ahc, &sd);
-
if (have_seeprom) {
if (bootverbose)
@@ -938,8 +936,8 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
/* Check checksum */
int i;
int maxaddr;
+ u_int32_t checksum;
u_int16_t *scarray;
- u_int16_t checksum;
maxaddr = (sizeof(sc)/2) - 1;
checksum = 0;
@@ -947,7 +945,8 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
for (i = 0; i < maxaddr; i++)
checksum = checksum + scarray[i];
- if (checksum == 0 || checksum != sc.checksum) {
+ if (checksum == 0
+ || (checksum & 0xFFFF) != sc.checksum) {
if (bootverbose && sd.sd_chip == C56_66)
printf ("checksum error\n");
have_seeprom = 0;
@@ -1060,24 +1059,42 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff);
}
+ /*
+ * Cards that have the external logic necessary to talk to
+ * a SEEPROM, are almost certain to have the remaining logic
+ * necessary for auto-termination control. This assumption
+ * hasn't failed yet...
+ */
+ have_autoterm = have_seeprom;
+ if (have_seeprom)
+ adapter_control = sc.adapter_control;
+ else
+ adapter_control = CFAUTOTERM;
+
+ /*
+ * Some low-cost chips have SEEPROM and auto-term control built
+ * in, instead of using a GAL. They can tell us directly
+ * if the termination logic is enabled.
+ */
if ((ahc->features & AHC_SPIOCAP) != 0) {
- if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) != 0) {
- configure_termination(ahc, &sc, &sd, sxfrctl1);
- }
- } else if (have_seeprom) {
- configure_termination(ahc, &sc, &sd, sxfrctl1);
+ if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) != 0)
+ have_autoterm = TRUE;
+ else
+ have_autoterm = FALSE;
}
+ if (have_autoterm)
+ configure_termination(ahc, &sd, adapter_control, sxfrctl1);
+
release_seeprom(&sd);
}
static void
configure_termination(struct ahc_softc *ahc,
- struct seeprom_config *sc,
struct seeprom_descriptor *sd,
+ u_int adapter_control,
u_int *sxfrctl1)
{
- int max_targ = sc->max_targets & CFMAXTARG;
u_int8_t brddat;
brddat = 0;
@@ -1094,7 +1111,7 @@ configure_termination(struct ahc_softc *ahc,
* on or we will release the seeprom.
*/
SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS);
- if ((sc->adapter_control & CFAUTOTERM) != 0
+ if ((adapter_control & CFAUTOTERM) != 0
|| (ahc->features & AHC_ULTRA2) != 0) {
int internal50_present;
int internal68_present;
@@ -1115,14 +1132,13 @@ configure_termination(struct ahc_softc *ahc,
&enablePRI_low,
&enablePRI_high,
&eeprom_present);
- if ((sc->adapter_control & CFSEAUTOTERM) == 0) {
- enableSEC_low = (sc->adapter_control & CFSTERM);
- enableSEC_high =
- (sc->adapter_control & CFWSTERM);
+ if ((adapter_control & CFSEAUTOTERM) == 0) {
+ enableSEC_low = (adapter_control & CFSTERM);
+ enableSEC_high = (adapter_control & CFWSTERM);
}
- if ((sc->adapter_control & CFAUTOTERM) == 0) {
+ if ((adapter_control & CFAUTOTERM) == 0) {
enablePRI_low = enablePRI_high =
- (sc->adapter_control & CFLVDSTERM);
+ (adapter_control & CFLVDSTERM);
}
/* Make the table calculations below happy */
internal50_present = 0;
@@ -1139,9 +1155,8 @@ configure_termination(struct ahc_softc *ahc,
&eeprom_present);
}
- if (max_targ <= 8) {
+ if ((ahc->features & AHC_WIDE) == 0)
internal68_present = 0;
- }
if (bootverbose) {
if ((ahc->features & AHC_ULTRA2) == 0) {
@@ -1178,7 +1193,7 @@ configure_termination(struct ahc_softc *ahc,
"time!\n", ahc_name(ahc));
}
- if ((max_targ > 8)
+ if ((ahc->features & AHC_WIDE) != 0
&& ((externalcable_present == 0)
|| (internal68_present == 0)
|| (enableSEC_high != 0))) {
@@ -1221,11 +1236,8 @@ configure_termination(struct ahc_softc *ahc,
write_brdctl(ahc, brddat);
} else {
- if (sc->adapter_control & CFSTERM) {
- if ((ahc->features & AHC_ULTRA2) != 0)
- brddat |= BRDDAT5;
- else
- *sxfrctl1 |= STPWEN;
+ if ((adapter_control & CFSTERM) != 0) {
+ *sxfrctl1 |= STPWEN;
if (bootverbose)
printf("%s: %sLow byte termination Enabled\n",
@@ -1234,7 +1246,7 @@ configure_termination(struct ahc_softc *ahc,
: "");
}
- if (sc->adapter_control & CFWSTERM) {
+ if ((adapter_control & CFWSTERM) != 0) {
brddat |= BRDDAT6;
if (bootverbose)
printf("%s: %sHigh byte termination Enabled\n",
@@ -1263,7 +1275,6 @@ ahc_ultra2_term_detect(struct ahc_softc *ahc, int *enableSEC_low,
* BRDDAT3 = Enable Primary low byte termination
*/
brdctl = read_brdctl(ahc);
-
*eeprom_present = brdctl & BRDDAT7;
*enableSEC_high = (brdctl & BRDDAT6);
*enableSEC_low = (brdctl & BRDDAT5);
@@ -1374,7 +1385,7 @@ write_brdctl(ahc, value)
brdctl = BRDSTB;
if (ahc->channel == 'B')
brdctl |= BRDCS;
- } else if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7890) {
+ } else if ((ahc->features & AHC_ULTRA2) != 0) {
brdctl = 0;
} else {
brdctl = BRDSTB|BRDCS;
@@ -1382,12 +1393,12 @@ write_brdctl(ahc, value)
ahc_outb(ahc, BRDCTL, brdctl);
brdctl |= value;
ahc_outb(ahc, BRDCTL, brdctl);
- if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7890)
+ if ((ahc->features & AHC_ULTRA2) != 0)
brdctl |= BRDSTB_ULTRA2;
else
brdctl &= ~BRDSTB;
ahc_outb(ahc, BRDCTL, brdctl);
- if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7890)
+ if ((ahc->features & AHC_ULTRA2) != 0)
brdctl = 0;
else
brdctl &= ~BRDCS;
@@ -1405,7 +1416,7 @@ read_brdctl(ahc)
brdctl = BRDRW;
if (ahc->channel == 'B')
brdctl |= BRDCS;
- } else if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7890) {
+ } else if ((ahc->features & AHC_ULTRA2) != 0) {
brdctl = BRDRW_ULTRA2;
} else {
brdctl = BRDRW|BRDCS;
@@ -1634,6 +1645,7 @@ ahc_aha394XX_setup(device_t dev, char *channel, ahc_chip *chip,
printf("adapter at unexpected slot %d\n"
"unable to map to a channel\n",
pci_get_slot(dev));
+ *channel = 'A';
}
return (0);
}
@@ -1656,6 +1668,7 @@ ahc_aha398XX_setup(device_t dev, char *channel, ahc_chip *chip,
printf("adapter at unexpected slot %d\n"
"unable to map to a channel\n",
pci_get_slot(dev));
+ *channel = 'A';
}
*flags |= AHC_LARGE_SEEPROM;
return (0);
OpenPOWER on IntegriCloud