/* * Product specific probe and attach routines for: * 3940, 2940, aic7895, aic7890, aic7880, * aic7870, aic7860 and aic7850 SCSI controllers * * Copyright (c) 1994-2001 Justin T. Gibbs. * Copyright (c) 2000-2001 Adaptec Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * substantially similar to the "NO WARRANTY" disclaimer below * ("Disclaimer") and any redistribution must be conditioned upon * including a substantially similar Disclaimer requirement for further * binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names * of any contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#79 $
*/
staticvoid ahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low, int *enableSEC_high, int *enablePRI_low, int *enablePRI_high, int *eeprom_present); staticvoid aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present, int *internal68_present, int *externalcable_present, int *eeprom_present); staticvoid aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, int *externalcable_present, int *eeprom_present); staticvoid write_brdctl(struct ahc_softc *ahc, uint8_t value); static uint8_t read_brdctl(struct ahc_softc *ahc); staticvoid ahc_pci_intr(struct ahc_softc *ahc); staticint ahc_pci_chip_init(struct ahc_softc *ahc);
/* Default to invalid. */
result = 0; if (vendor == 0x9005
&& subvendor == 0x9005
&& subdevice != device
&& SUBID_9005_TYPE_KNOWN(subdevice) != 0) {
switch (SUBID_9005_TYPE(subdevice)) { case SUBID_9005_TYPE_MB: break; case SUBID_9005_TYPE_CARD: case SUBID_9005_TYPE_LCCARD: /* * Currently only trust Adaptec cards to * get the sub device info correct.
*/ if (DEVID_9005_TYPE(device) == DEVID_9005_TYPE_HBA)
result = 1; break; case SUBID_9005_TYPE_RAID: break; default: break;
}
} return (result);
}
/* * If the second function is not hooked up, ignore it. * Unfortunately, not all MB vendors implement the * subdevice ID as per the Adaptec spec, so do our best * to sanity check it prior to accepting the subdevice * ID as valid.
*/ if (ahc_get_pci_function(pci) > 0
&& ahc_9005_subdevinfo_valid(device, vendor, subdevice, subvendor)
&& SUBID_9005_MFUNCENB(subdevice) == 0) return (NULL);
for (i = 0; i < ahc_num_pci_devs; i++) {
entry = &ahc_pci_ident_table[i]; if (entry->full_id == (full_id & entry->id_mask)) { /* Honor exclusion entries. */ if (entry->name == NULL) return (NULL); return (entry);
}
} return (NULL);
}
error = ahc_pci_map_registers(ahc); if (error != 0) return (error);
/* * Before we continue probing the card, ensure that * its interrupts are *disabled*. We don't want * a misstep to hang the machine in an interrupt * storm.
*/
ahc_intr_enable(ahc, FALSE);
/* * If we need to support high memory, enable dual * address cycles. This bit must be set to enable * high address bit generation even if we are on a * 64bit bus (PCI64BIT set in devconfig).
*/ if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
/* On all PCI adapters, we allow SCB paging */
ahc->flags |= AHC_PAGESCBS;
error = ahc_softc_init(ahc); if (error != 0) return (error);
/* * Disable PCI parity error checking. Users typically * do this to work around broken PCI chipsets that get * the parity timing wrong and thus generate lots of spurious * errors. The chip only allows us to disable *all* parity * error reporting when doing this, so CIO bus, scb ram, and * scratch ram parity errors will be ignored too.
*/ if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0)
ahc->seqctl |= FAILDIS;
/* * We cannot perform ULTRA speeds without the presence * of the external precision resistor.
*/ if ((ahc->features & AHC_ULTRA) != 0) {
uint32_t devconfig;
if (ahc->flags & AHC_USEDEFAULTS) { /* * PCI Adapter default setup * Should only be used if the adapter does not have * a SEEPROM.
*/ /* See if someone else set us up already */ if ((ahc->flags & AHC_NO_BIOS_INIT) == 0
&& scsiseq != 0) {
printk("%s: Using left over BIOS settings\n",
ahc_name(ahc));
ahc->flags &= ~AHC_USEDEFAULTS;
ahc->flags |= AHC_BIOS_ENABLED;
} else { /* * Assume only one connector and always turn * on termination.
*/
our_id = 0x07;
sxfrctl1 = STPWEN;
}
ahc_outb(ahc, SCSICONF, our_id|ENSPCHK|RESET_SCSI);
ahc->our_id = our_id;
}
/* * Take a look to see if we have external SRAM. * We currently do not attempt to use SRAM that is * shared among multiple controllers.
*/
ahc_probe_ext_scbram(ahc);
/* * Record our termination setting for the * generic initialization routine.
*/ if ((sxfrctl1 & STPWEN) != 0)
ahc->flags |= AHC_TERM_ENB_A;
/* * Save chip register configuration data for chip resets * that occur during runtime and resume events.
*/
ahc->bus_softc.pci_softc.devconfig =
ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
ahc->bus_softc.pci_softc.command =
ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1);
ahc->bus_softc.pci_softc.csize_lattime =
ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1);
ahc->bus_softc.pci_softc.dscommand0 = ahc_inb(ahc, DSCOMMAND0);
ahc->bus_softc.pci_softc.dspcistatus = ahc_inb(ahc, DSPCISTATUS); if ((ahc->features & AHC_DT) != 0) {
u_int sfunct;
/* * Allow interrupts now that we are completely setup.
*/ return ahc_pci_map_int(ahc);
}
/* * Test for the presence of external sram in an * "unshared" configuration.
*/ staticint
ahc_ext_scbram_present(struct ahc_softc *ahc)
{
u_int chip; int ramps; int single_user;
uint32_t devconfig;
if ((ahc->features & AHC_ULTRA2) != 0)
ramps = (ahc_inb(ahc, DSCOMMAND0) & RAMPS) != 0; elseif (chip == AHC_AIC7895 || chip == AHC_AIC7895C) /* * External SCBRAM arbitration is flakey * on these chips. Unfortunately this means * we don't use the extra SCB ram space on the * 3940AUW.
*/
ramps = 0; elseif (chip >= AHC_AIC7870)
ramps = (devconfig & RAMPSM) != 0; else
ramps = 0;
if (ramps && single_user) return (1); return (0);
}
/* * Enable external scbram.
*/ staticvoid
ahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck, int fast, int large)
{
uint32_t devconfig;
if (ahc->features & AHC_MULTI_FUNC) { /* * Set the SCB Base addr (highest address bit) * depending on which channel we are.
*/
ahc_outb(ahc, SCBBADDR, ahc_get_pci_function(ahc->dev_softc));
}
/* * Take a look to see if we have external SRAM. * We currently do not attempt to use SRAM that is * shared among multiple controllers.
*/ staticvoid
ahc_probe_ext_scbram(struct ahc_softc *ahc)
{ int num_scbs; int test_num_scbs; int enable; int pcheck; int fast; int large;
enable = FALSE;
pcheck = FALSE;
fast = FALSE;
large = FALSE;
num_scbs = 0;
if (ahc_ext_scbram_present(ahc) == 0) goto done;
/* * Probe for the best parameters to use.
*/
ahc_scbram_config(ahc, /*enable*/TRUE, pcheck, fast, large);
num_scbs = ahc_probe_scbs(ahc); if (num_scbs == 0) { /* The SRAM wasn't really present. */ goto done;
}
enable = TRUE;
/* * Clear any outstanding parity error * and ensure that parity error reporting * is enabled.
*/
ahc_outb(ahc, SEQCTL, 0);
ahc_outb(ahc, CLRINT, CLRPARERR);
ahc_outb(ahc, CLRINT, CLRBRKADRINT);
/* Now see if we can do parity */
ahc_scbram_config(ahc, enable, /*pcheck*/TRUE, fast, large);
num_scbs = ahc_probe_scbs(ahc); if ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0
|| (ahc_inb(ahc, ERROR) & MPARERR) == 0)
pcheck = TRUE;
/* Now see if we can do fast timing */
ahc_scbram_config(ahc, enable, pcheck, /*fast*/TRUE, large);
test_num_scbs = ahc_probe_scbs(ahc); if (test_num_scbs == num_scbs
&& ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0
|| (ahc_inb(ahc, ERROR) & MPARERR) == 0))
fast = TRUE;
/* * See if we can use large SCBs and still maintain * the same overall count of SCBs.
*/ if ((ahc->features & AHC_LARGE_SCBS) != 0) {
ahc_scbram_config(ahc, enable, pcheck, fast, /*large*/TRUE);
test_num_scbs = ahc_probe_scbs(ahc); if (test_num_scbs >= num_scbs) {
large = TRUE;
num_scbs = test_num_scbs; if (num_scbs >= 64) { /* * We have enough space to move the * "busy targets table" into SCB space * and make it qualify all the way to the * lun level.
*/
ahc->flags |= AHC_SCB_BTT;
}
}
}
done: /* * Disable parity error reporting until we * can load instruction ram.
*/
ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS); /* Clear any latched parity error */
ahc_outb(ahc, CLRINT, CLRPARERR);
ahc_outb(ahc, CLRINT, CLRBRKADRINT); if (bootverbose && enable) {
printk("%s: External SRAM, %s access%s, %dbytes/SCB\n",
ahc_name(ahc), fast ? "fast" : "slow",
pcheck ? ", parity checking enabled" : "",
large ? 64 : 32);
}
ahc_scbram_config(ahc, enable, pcheck, fast, large);
}
/* * Perform some simple tests that should catch situations where * our registers are invalidly mapped.
*/ int
ahc_pci_test_register_access(struct ahc_softc *ahc)
{ int error;
u_int status1;
uint32_t cmd;
uint8_t hcntrl;
error = EIO;
/* * Enable PCI error interrupt status, but suppress NMIs * generated by SERR raised due to target aborts.
*/
cmd = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);
ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2);
/* * First a simple test to see if any * registers can be read. Reading * HCNTRL has no side effects and has * at least one bit that is guaranteed to * be zero so it is a good register to * use for this test.
*/
hcntrl = ahc_inb(ahc, HCNTRL);
if (hcntrl == 0xFF) goto fail;
if ((hcntrl & CHIPRST) != 0) { /* * The chip has not been initialized since * PCI/EISA/VLB bus reset. Don't trust * "left over BIOS data".
*/
ahc->flags |= AHC_NO_BIOS_INIT;
}
/* * Next create a situation where write combining * or read prefetching could be initiated by the * CPU or host bridge. Our device does not support * either, so look for data corruption and/or flagged * PCI errors. First pause without causing another * chip reset.
*/
hcntrl &= ~CHIPRST;
ahc_outb(ahc, HCNTRL, hcntrl|PAUSE); while (ahc_is_paused(ahc) == 0)
;
/* Clear any PCI errors that occurred before our driver attached. */
status1 = ahc_pci_read_config(ahc->dev_softc,
PCIR_STATUS + 1, /*bytes*/1);
ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
status1, /*bytes*/1);
ahc_outb(ahc, CLRINT, CLRPARERR);
/* * Check the external port logic for a serial eeprom * and termination/cable detection contrls.
*/ staticvoid
check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
{ struct seeprom_descriptor sd; struct seeprom_config *sc; int have_seeprom; int have_autoterm;
/* * For some multi-channel devices, the c46 is simply too * small to work. For the other controller types, we can * get our information from either SEEPROM type. Set the * type to start our probe with accordingly.
*/ if (ahc->flags & AHC_LARGE_SEEPROM)
sd.sd_chip = C56_66; else
sd.sd_chip = C46;
if (have_seeprom)
have_seeprom = ahc_verify_cksum(sc);
if (have_seeprom != 0 || sd.sd_chip == C56_66) { if (bootverbose) { if (have_seeprom == 0)
printk ("checksum error\n"); else
printk ("done.\n");
} break;
}
sd.sd_chip = C56_66;
}
ahc_release_seeprom(&sd);
/* Remember the SEEPROM type for later */ if (sd.sd_chip == C56_66)
ahc->flags |= AHC_LARGE_SEEPROM;
}
if (!have_seeprom) { /* * Pull scratch ram settings and treat them as * if they are the contents of an seeprom if * the 'ADPT' signature is found in SCB2. * We manually compose the data as 16bit values * to avoid endian issues.
*/
ahc_outb(ahc, SCBPTR, 2); if (ahc_inb(ahc, SCB_BASE) == 'A'
&& ahc_inb(ahc, SCB_BASE + 1) == 'D'
&& ahc_inb(ahc, SCB_BASE + 2) == 'P'
&& ahc_inb(ahc, SCB_BASE + 3) == 'T') {
uint16_t *sc_data; int i;
sc_data = (uint16_t *)sc; for (i = 0; i < 32; i++, sc_data++) { int j;
j = i * 2;
*sc_data = ahc_inb(ahc, SRAM_BASE + j)
| ahc_inb(ahc, SRAM_BASE + j + 1) << 8;
}
have_seeprom = ahc_verify_cksum(sc); if (have_seeprom)
ahc->flags |= AHC_SCB_CONFIG_USED;
} /* * Clear any SCB parity errors in case this data and * its associated parity was not initialized by the BIOS
*/
ahc_outb(ahc, CLRINT, CLRPARERR);
ahc_outb(ahc, CLRINT, CLRBRKADRINT);
}
if (!have_seeprom) { if (bootverbose)
printk("%s: No SEEPROM available.\n", ahc_name(ahc));
ahc->flags |= AHC_USEDEFAULTS;
kfree(ahc->seep_config);
ahc->seep_config = NULL;
sc = NULL;
} else {
ahc_parse_pci_eeprom(ahc, sc);
}
/* * 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;
/* * 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)
have_autoterm = FALSE;
}
staticvoid
ahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc)
{ /* * Put the data we've collected down into SRAM * where ahc_init will find it.
*/ int i; int max_targ = sc->max_targets & CFMAXTARG;
u_int scsi_conf;
uint16_t discenable;
uint16_t ultraenb;
discenable = 0;
ultraenb = 0; if ((sc->adapter_control & CFULTRAEN) != 0) { /* * Determine if this adapter has a "newstyle" * SEEPROM format.
*/ for (i = 0; i < max_targ; i++) { if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) {
ahc->flags |= AHC_NEWEEPROM_FMT; break;
}
}
}
for (i = 0; i < max_targ; i++) {
u_int scsirate;
uint16_t target_mask;
/* * Update the settings in sxfrctl1 to match the * termination settings
*/
*sxfrctl1 = 0;
/* * SEECS must be on for the GALS to latch * the data properly. Be sure to leave MS * on or we will release the seeprom.
*/
SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS); if ((adapter_control & CFAUTOTERM) != 0
|| (ahc->features & AHC_NEW_TERMCTL) != 0) { int internal50_present; int internal68_present; int externalcable_present; int eeprom_present; int enableSEC_low; int enableSEC_high; int enablePRI_low; int enablePRI_high; int sum;
if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) { /* * The 50 pin connector is a separate bus, * so force it to always be terminated. * In the future, perform current sensing * to determine if we are in the middle of * a properly terminated bus.
*/
internal50_present = 0;
}
/* * Now set the termination based on what * we found. * Flash Enable = BRDDAT7 * Secondary High Term Enable = BRDDAT6 * Secondary Low Term Enable = BRDDAT5 (7890) * Primary High Term Enable = BRDDAT4 (7890)
*/ if ((ahc->features & AHC_ULTRA2) == 0
&& (internal50_present != 0)
&& (internal68_present != 0)
&& (externalcable_present != 0)) {
printk("%s: Illegal cable configuration!!. " "Only two connectors on the " "adapter may be used at a " "time!\n", ahc_name(ahc));
/* * Pretend there are no cables in the hope * that having all of the termination on * gives us a more stable bus.
*/
internal50_present = 0;
internal68_present = 0;
externalcable_present = 0;
}
staticvoid
ahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low, int *enableSEC_high, int *enablePRI_low, int *enablePRI_high, int *eeprom_present)
{
uint8_t brdctl;
staticvoid
aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present, int *internal68_present, int *externalcable_present, int *eeprom_present)
{
uint8_t brdctl;
/* * First read the status of our cables. * Set the rom bank to 0 since the * bank setting serves as a multiplexor * for the cable detection logic. * BRDDAT5 controls the bank switch.
*/
write_brdctl(ahc, 0);
/* * Now read the state of the internal * connectors. BRDDAT6 is INT50 and * BRDDAT7 is INT68.
*/
brdctl = read_brdctl(ahc);
*internal50_present = (brdctl & BRDDAT6) ? 0 : 1;
*internal68_present = (brdctl & BRDDAT7) ? 0 : 1;
/* * Set the rom bank to 1 and determine * the other signals.
*/
write_brdctl(ahc, BRDDAT5);
/* * Now read the state of the external * connectors. BRDDAT6 is EXT68 and * BRDDAT7 is EPROMPS.
*/
brdctl = read_brdctl(ahc);
*externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
*eeprom_present = (brdctl & BRDDAT7) ? 1 : 0;
}
staticvoid
aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, int *externalcable_present, int *eeprom_present)
{
uint8_t brdctl;
uint8_t spiocap;
/* * Request access of the memory port. When access is * granted, SEERDY will go high. We use a 1 second * timeout which should be near 1 second more than * is needed. Reason: after the chip reset, there * should be no contention.
*/
SEEPROM_OUTB(sd, sd->sd_MS);
wait = 1000; /* 1 second timeout in msec */ while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) {
ahc_delay(1000); /* delay 1 msec */
} if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) {
SEEPROM_OUTB(sd, 0); return (0);
} return(1);
}
void
ahc_release_seeprom(struct seeprom_descriptor *sd)
{ /* Release access to the memory port and the serial EEPROM. */
SEEPROM_OUTB(sd, 0);
}
if (status1 & DPE) {
ahc->pci_target_perr_count++;
printk("%s: Data Parity Error Detected during address " "or write data phase\n", ahc_name(ahc));
} if (status1 & SSE) {
printk("%s: Signal System Error Detected\n", ahc_name(ahc));
} if (status1 & RMA) {
printk("%s: Received a Master Abort\n", ahc_name(ahc));
} if (status1 & RTA) {
printk("%s: Received a Target Abort\n", ahc_name(ahc));
} if (status1 & STA) {
printk("%s: Signaled a Target Abort\n", ahc_name(ahc));
} if (status1 & DPR) {
printk("%s: Data Parity Error has been reported via PERR#\n",
ahc_name(ahc));
}
if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) {
printk("%s: Latched PCIERR interrupt with " "no status bits set\n", ahc_name(ahc));
} else {
ahc_outb(ahc, CLRINT, CLRPARERR);
}
if (ahc->pci_target_perr_count > AHC_PCI_TARGET_PERR_THRESH) {
printk( "%s: WARNING WARNING WARNING WARNING\n" "%s: Too many PCI parity errors observed as a target.\n" "%s: Some device on this bus is generating bad parity.\n" "%s: This is an error *observed by*, not *generated by*, this controller.\n" "%s: PCI parity error checking has been disabled.\n" "%s: WARNING WARNING WARNING WARNING\n",
ahc_name(ahc), ahc_name(ahc), ahc_name(ahc),
ahc_name(ahc), ahc_name(ahc), ahc_name(ahc));
ahc->seqctl |= FAILDIS;
ahc_outb(ahc, SEQCTL, ahc->seqctl);
}
ahc_unpause(ahc);
}
if ((ahc->features & AHC_ULTRA2) != 0)
ahc_outb(ahc, DFF_THRSH, ahc->bus_softc.pci_softc.dff_thrsh);
return (ahc_chip_init(ahc));
}
void __maybe_unused
ahc_pci_resume(struct ahc_softc *ahc)
{ /* * We assume that the OS has restored our register * mappings, etc. Just update the config space registers * that the OS doesn't know about and rely on our chip * reset handler to handle the rest.
*/
ahc_pci_write_config(ahc->dev_softc, DEVCONFIG,
ahc->bus_softc.pci_softc.devconfig, /*bytes*/4);
ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
ahc->bus_softc.pci_softc.command, /*bytes*/1);
ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME,
ahc->bus_softc.pci_softc.csize_lattime, /*bytes*/1); if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) { struct seeprom_descriptor sd;
u_int sxfrctl1;
/* * The BIOS disables the use of MWI transactions * since it does not have the MWI bug work around * we have. Disabling MWI reduces performance, so * turn it on again.
*/
command = ahc_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1);
command |= PCIM_CMD_MWRICEN;
ahc_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1);
ahc->bugs |= AHC_PCI_MWI_BUG;
} /* * XXX Does CACHETHEN really not work??? What about PCI retry? * on C level chips. Need to test, but for now, play it safe.
*/
ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG
| AHC_CACHETHEN_BUG;
#if 0
uint32_t devconfig;
/* * Cachesize must also be zero due to stray DAC * problem when sitting behind some bridges.
*/
ahc_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1);
devconfig = ahc_pci_read_config(pci, DEVCONFIG, /*bytes*/1);
devconfig |= MRDCEN;
ahc_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1); #endif
ahc->flags |= AHC_NEWEEPROM_FMT;
ahc->instruction_ram_size = 512; return (0);
}
staticint
ahc_aic7895h_setup(struct ahc_softc *ahc)
{ int error = ahc_aic7895_setup(ahc);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.