示例#1
0
void
ahc_pci_resume(struct ahc_softc *ahc)
{
	
	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG,
			     ahc->bus_softc.pci_softc.devconfig, 4);
	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
			     ahc->bus_softc.pci_softc.command, 1);
	ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME,
			     ahc->bus_softc.pci_softc.csize_lattime, 1);
	if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) {
		struct	seeprom_descriptor sd;
		u_int	sxfrctl1;

		sd.sd_ahc = ahc;
		sd.sd_control_offset = SEECTL;		
		sd.sd_status_offset = SEECTL;		
		sd.sd_dataout_offset = SEECTL;		

		ahc_acquire_seeprom(ahc, &sd);
		configure_termination(ahc, &sd,
				      ahc->seep_config->adapter_control,
				      &sxfrctl1);
		ahc_release_seeprom(&sd);
	}
}
示例#2
0
static int
ahc_proc_write_seeprom(struct ahc_softc *ahc, char *buffer, int length)
{
    struct seeprom_descriptor sd;
    int have_seeprom;
    u_long s;
    int paused;
    int written;

    /* Default to failure. */
    written = -EINVAL;
    ahc_lock(ahc, &s);
    paused = ahc_is_paused(ahc);
    if (!paused)
        ahc_pause(ahc);

    if (length != sizeof(struct seeprom_config)) {
        printf("ahc_proc_write_seeprom: incorrect buffer size\n");
        goto done;
    }

    have_seeprom = ahc_verify_cksum((struct seeprom_config*)buffer);
    if (have_seeprom == 0) {
        printf("ahc_proc_write_seeprom: cksum verification failed\n");
        goto done;
    }

    sd.sd_ahc = ahc;
#if AHC_PCI_CONFIG > 0
    if ((ahc->chip & AHC_PCI) != 0) {
        sd.sd_control_offset = SEECTL;
        sd.sd_status_offset = SEECTL;
        sd.sd_dataout_offset = SEECTL;
        if (ahc->flags & AHC_LARGE_SEEPROM)
            sd.sd_chip = C56_66;
        else
            sd.sd_chip = C46;
        sd.sd_MS = SEEMS;
        sd.sd_RDY = SEERDY;
        sd.sd_CS = SEECS;
        sd.sd_CK = SEECK;
        sd.sd_DO = SEEDO;
        sd.sd_DI = SEEDI;
        have_seeprom = ahc_acquire_seeprom(ahc, &sd);
    } else
#endif
        if ((ahc->chip & AHC_VL) != 0) {
            sd.sd_control_offset = SEECTL_2840;
            sd.sd_status_offset = STATUS_2840;
            sd.sd_dataout_offset = STATUS_2840;
            sd.sd_chip = C46;
            sd.sd_MS = 0;
            sd.sd_RDY = EEPROM_TF;
            sd.sd_CS = CS_2840;
            sd.sd_CK = CK_2840;
            sd.sd_DO = DO_2840;
            sd.sd_DI = DI_2840;
            have_seeprom = TRUE;
        } else {
            printf("ahc_proc_write_seeprom: unsupported adapter type\n");
            goto done;
        }

    if (!have_seeprom) {
        printf("ahc_proc_write_seeprom: No Serial EEPROM\n");
        goto done;
    } else {
        u_int start_addr;

        if (ahc->seep_config == NULL) {
            ahc->seep_config = malloc(sizeof(*ahc->seep_config),
                                      M_DEVBUF, M_NOWAIT);
            if (ahc->seep_config == NULL) {
                printf("aic7xxx: Unable to allocate serial "
                       "eeprom buffer.  Write failing\n");
                goto done;
            }
        }
        printf("aic7xxx: Writing Serial EEPROM\n");
        start_addr = 32 * (ahc->channel - 'A');
        ahc_write_seeprom(&sd, (u_int16_t *)buffer, start_addr,
                          sizeof(struct seeprom_config)/2);
        ahc_read_seeprom(&sd, (uint16_t *)ahc->seep_config,
                         start_addr, sizeof(struct seeprom_config)/2);
#if AHC_PCI_CONFIG > 0
        if ((ahc->chip & AHC_VL) == 0)
            ahc_release_seeprom(&sd);
#endif
        written = length;
    }

done:
    if (!paused)
        ahc_unpause(ahc);
    ahc_unlock(ahc, &s);
    return (written);
}
示例#3
0
static void
check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
{
	struct	seeprom_descriptor sd;
	struct	seeprom_config *sc;
	int	have_seeprom;
	int	have_autoterm;

	sd.sd_ahc = ahc;
	sd.sd_control_offset = SEECTL;		
	sd.sd_status_offset = SEECTL;		
	sd.sd_dataout_offset = SEECTL;		
	sc = ahc->seep_config;

	
	if (ahc->flags & AHC_LARGE_SEEPROM)
		sd.sd_chip = C56_66;
	else
		sd.sd_chip = C46;

	sd.sd_MS = SEEMS;
	sd.sd_RDY = SEERDY;
	sd.sd_CS = SEECS;
	sd.sd_CK = SEECK;
	sd.sd_DO = SEEDO;
	sd.sd_DI = SEEDI;

	have_seeprom = ahc_acquire_seeprom(ahc, &sd);
	if (have_seeprom) {

		if (bootverbose) 
			printf("%s: Reading SEEPROM...", ahc_name(ahc));

		for (;;) {
			u_int start_addr;

			start_addr = 32 * (ahc->channel - 'A');

			have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc,
							start_addr,
							sizeof(*sc)/2);

			if (have_seeprom)
				have_seeprom = ahc_verify_cksum(sc);

			if (have_seeprom != 0 || sd.sd_chip == C56_66) {
				if (bootverbose) {
					if (have_seeprom == 0)
						printf ("checksum error\n");
					else
						printf ("done.\n");
				}
				break;
			}
			sd.sd_chip = C56_66;
		}
		ahc_release_seeprom(&sd);

		
		if (sd.sd_chip == C56_66)
			ahc->flags |= AHC_LARGE_SEEPROM;
	}

	if (!have_seeprom) {
		
		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;
		}
		
		ahc_outb(ahc, CLRINT, CLRPARERR);
		ahc_outb(ahc, CLRINT, CLRBRKADRINT);
	}

	if (!have_seeprom) {
		if (bootverbose)
			printf("%s: No SEEPROM available.\n", ahc_name(ahc));
		ahc->flags |= AHC_USEDEFAULTS;
		free(ahc->seep_config, M_DEVBUF);
		ahc->seep_config = NULL;
		sc = NULL;
	} else {
		ahc_parse_pci_eeprom(ahc, sc);
	}

	
	have_autoterm = have_seeprom;

	
	if ((ahc->features & AHC_SPIOCAP) != 0) {
		if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0)
			have_autoterm = FALSE;
	}

	if (have_autoterm) {
		ahc->flags |= AHC_HAS_TERM_LOGIC;
		ahc_acquire_seeprom(ahc, &sd);
		configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1);
		ahc_release_seeprom(&sd);
	} else if (have_seeprom) {
		*sxfrctl1 &= ~STPWEN;
		if ((sc->adapter_control & CFSTERM) != 0)
			*sxfrctl1 |= STPWEN;
		if (bootverbose)
			printf("%s: Low byte termination %sabled\n",
			       ahc_name(ahc),
			       (*sxfrctl1 & STPWEN) ? "en" : "dis");
	}
}
示例#4
0
/*
 * Check the external port logic for a serial eeprom
 * and termination/cable detection contrls.
 */
void
ahc_check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
{
	struct	seeprom_descriptor sd;
	struct	seeprom_config *sc;
	int	have_seeprom;
	int	have_autoterm;

	sd.sd_tag = ahc->tag;
	sd.sd_bsh = ahc->bsh;
	sd.sd_regsize = 1;
	sd.sd_control_offset = SEECTL;
	sd.sd_status_offset = SEECTL;
	sd.sd_dataout_offset = SEECTL;
	sc = ahc->seep_config;

	/*
	 * 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;

	sd.sd_MS = SEEMS;
	sd.sd_RDY = SEERDY;
	sd.sd_CS = SEECS;
	sd.sd_CK = SEECK;
	sd.sd_DO = SEEDO;
	sd.sd_DI = SEEDI;

	have_seeprom = ahc_acquire_seeprom(ahc, &sd);
	if (have_seeprom) {

		if (bootverbose)
			printf("%s: Reading SEEPROM...", ahc_name(ahc));

		for (;;) {
			u_int start_addr;

			start_addr = 32 * (ahc->channel - 'A');
			have_seeprom = read_seeprom(&sd, (uint16_t *)sc,
							start_addr,
							sizeof(*sc)/2);

			if (have_seeprom)
				have_seeprom = verify_seeprom_cksum(sc);

			if (have_seeprom != 0 || sd.sd_chip == C56_66) {
				if (bootverbose) {
					if (have_seeprom == 0)
						printf ("checksum error\n");
					else
						printf ("done.\n");
				}
				break;
			}
			sd.sd_chip = C56_66;
		}
		ahc_release_seeprom(&sd);
	}

	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 = verify_seeprom_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)
			printf("%s: No SEEPROM available.\n", ahc_name(ahc));
		ahc->flags |= AHC_USEDEFAULTS;
		free(ahc->seep_config, M_DEVBUF);
		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;
	}

	if (have_autoterm) {
		ahc_acquire_seeprom(ahc, &sd);
		configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1);
		ahc_release_seeprom(&sd);
	} else if (have_seeprom) {
		*sxfrctl1 &= ~STPWEN;
		if ((sc->adapter_control & CFSTERM) != 0)
			*sxfrctl1 |= STPWEN;
		if (bootverbose)
			printf("%s: Low byte termination %sabled\n",
			       ahc_name(ahc),
			       (*sxfrctl1 & STPWEN) ? "en" : "dis");
	}
}