static int
aic7770_eisa_dev_remove(struct device *dev)
{
	struct ahc_softc *ahc;
	u_long l;

	/*
	 * We should be able to just perform
	 * the free directly, but check our
	 * list for extra sanity.
	 */
	ahc_list_lock(&l);
	ahc = ahc_find_softc((struct ahc_softc *)dev->driver_data);
	if (ahc != NULL) {
		u_long s;

		ahc_lock(ahc, &s);
		ahc_intr_enable(ahc, FALSE);
		ahc_unlock(ahc, &s);
		ahc_free(ahc);
	}
	ahc_list_unlock(&l);

	return (0);
}
Beispiel #2
0
static void
ahc_linux_pci_dev_remove(struct pci_dev *pdev)
{
	struct ahc_softc *ahc = pci_get_drvdata(pdev);
	u_long s;

	ahc_lock(ahc, &s);
	ahc_intr_enable(ahc, FALSE);
	ahc_unlock(ahc, &s);
	ahc_free(ahc);
}
static void
ahc_linux_pci_dev_remove(struct pci_dev *pdev)
{
	struct ahc_softc *ahc = pci_get_drvdata(pdev);
	u_long s;

	if (ahc->platform_data && ahc->platform_data->host)
			scsi_remove_host(ahc->platform_data->host);

	ahc_lock(ahc, &s);
	ahc_intr_enable(ahc, FALSE);
	ahc_unlock(ahc, &s);
	ahc_free(ahc);
}
static int
aic7770_remove(struct device *dev)
{
	struct ahc_softc *ahc = dev_get_drvdata(dev);
	u_long s;

	if (ahc->platform_data && ahc->platform_data->host)
			scsi_remove_host(ahc->platform_data->host);

	ahc_lock(ahc, &s);
	ahc_intr_enable(ahc, FALSE);
	ahc_unlock(ahc, &s);

	ahc_free(ahc);
	return 0;
}
Beispiel #5
0
int
aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
{
	u_long	l;
	u_long	s;
	int	error;
	int	have_seeprom;
	u_int	hostconf;
	u_int   irq;
	u_int	intdef;

	error = entry->setup(ahc);
	have_seeprom = 0;
	if (error != 0)
		return (error);

	error = aic7770_map_registers(ahc, io);
	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);

	ahc->description = entry->name;
	error = ahc_softc_init(ahc);

	error = ahc_reset(ahc);
	if (error != 0)
		return (error);

	/* Make sure we have a valid interrupt vector */
	intdef = ahc_inb(ahc, INTDEF);
	irq = intdef & VECTOR;
	switch (irq) {
	case 9:
	case 10:
	case 11:
	case 12:
	case 14:
	case 15:
		break;
	default:
		printf("aic7770_config: illegal irq setting %d\n", intdef);
		return (ENXIO);
	}

	if ((intdef & EDGE_TRIG) != 0)
		ahc->flags |= AHC_EDGE_INTERRUPT;

	switch (ahc->chip & (AHC_EISA|AHC_VL)) {
	case AHC_EISA:
	{
		u_int biosctrl;
		u_int scsiconf;
		u_int scsiconf1;

		biosctrl = ahc_inb(ahc, HA_274_BIOSCTRL);
		scsiconf = ahc_inb(ahc, SCSICONF);
		scsiconf1 = ahc_inb(ahc, SCSICONF + 1);

		/* Get the primary channel information */
		if ((biosctrl & CHANNEL_B_PRIMARY) != 0)
			ahc->flags |= 1;

		if ((biosctrl & BIOSMODE) == BIOSDISABLED) {
			ahc->flags |= AHC_USEDEFAULTS;
		} else {
			if ((ahc->features & AHC_WIDE) != 0) {
				ahc->our_id = scsiconf1 & HWSCSIID;
				if (scsiconf & TERM_ENB)
					ahc->flags |= AHC_TERM_ENB_A;
			} else {
				ahc->our_id = scsiconf & HSCSIID;
				ahc->our_id_b = scsiconf1 & HSCSIID;
				if (scsiconf & TERM_ENB)
					ahc->flags |= AHC_TERM_ENB_A;
				if (scsiconf1 & TERM_ENB)
					ahc->flags |= AHC_TERM_ENB_B;
			}
		}
		if ((ahc_inb(ahc, HA_274_BIOSGLOBAL) & HA_274_EXTENDED_TRANS))
			ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B;
		break;
	}
	case AHC_VL:
	{
		have_seeprom = aha2840_load_seeprom(ahc);
		break;
	}
	default:
		break;
	}
	if (have_seeprom == 0) {
		free(ahc->seep_config, M_DEVBUF);
		ahc->seep_config = NULL;
	}

	/*
	 * Ensure autoflush is enabled
	 */
	ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~AUTOFLUSHDIS);

	/* Setup the FIFO threshold and the bus off time */
	hostconf = ahc_inb(ahc, HOSTCONF);
	ahc_outb(ahc, BUSSPD, hostconf & DFTHRSH);
	ahc_outb(ahc, BUSTIME, (hostconf << 2) & BOFF);

	/*
	 * Generic aic7xxx initialization.
	 */
	error = ahc_init(ahc);
	if (error != 0)
		return (error);

	error = aic7770_map_int(ahc, irq);
	if (error != 0)
		return (error);

	ahc_list_lock(&l);
	/*
	 * Link this softc in with all other ahc instances.
	 */
	ahc_softc_insert(ahc);

	/*
	 * Enable the board's BUS drivers
	 */
	ahc_outb(ahc, BCTL, ENABLE);

	/*
	 * Allow interrupts.
	 */
	ahc_lock(ahc, &s);
	ahc_intr_enable(ahc, TRUE);
	ahc_unlock(ahc, &s);

	ahc_list_unlock(&l);

	return (0);
}
Beispiel #6
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);
}