Exemplo n.º 1
0
void
ahc_isa_attach(device_t parent, device_t self, void *aux)
{
	struct ahc_softc *ahc = device_private(self);
	struct isa_attach_args *ia = aux;
	bus_space_tag_t iot = ia->ia_iot;
	bus_space_handle_t ioh;
	int irq, intrtype;
	const char *intrtypestr;
	char idstring[EISA_IDSTRINGLEN];
	u_char intdef;

	ahc->sc_dev = self;
	aprint_naive(": SCSI controller\n");

	if (bus_space_map(iot, ia->ia_io[0].ir_addr, ia->ia_io[0].ir_size,
	    0, &ioh)) {
		aprint_error(": can't map i/o space\n");
		return;
	}
	if (!ahc_isa_idstring(iot, ioh, idstring)) {
		aprint_error(": can't read ID string\n");
		goto free_io;
	}
	if ((irq = ahc_aic77xx_irq(iot, ioh)) < 0) {
		aprint_error(": ahc_aic77xx_irq failed\n");
		goto free_io;
	}

	if (strcmp(idstring, "ADP7756") == 0) {
		aprint_normal(": %s\n", EISA_PRODUCT_ADP7756);
	} else if (strcmp(idstring, "ADP7757") == 0) {
		aprint_normal(": %s\n", EISA_PRODUCT_ADP7757);
	} else {
		aprint_error(": unknown device type %s\n", idstring);
		goto free_io;
	}

	/*
	 * Tell the bus-DMA interface that we can do 32bit DMA
	 * NOTE: this variable is first referenced in ahc_init().
	 */
	ahc->sc_dmaflags = ISABUS_DMA_32BIT;

	ahc_set_name(ahc, device_xname(ahc->sc_dev));
	ahc->parent_dmat = ia->ia_dmat;
	ahc->channel = 'A';
	ahc->chip =  AHC_AIC7770|AHC_VL;
	ahc->features = AHC_AIC7770_FE;
	ahc->bugs |= AHC_TMODE_WIDEODD_BUG;
	ahc->flags |= AHC_PAGESCBS;
	ahc->tag = iot;
	ahc->bsh = ioh;

	if (ahc_softc_init(ahc) != 0)
		goto free_io;

	ahc_intr_enable(ahc, false);

	if (ahc_reset(ahc) != 0)
		goto free_io;

	intdef = bus_space_read_1(iot, ioh, INTDEF);

	if (intdef & EDGE_TRIG) {
		intrtype = IST_EDGE;
		intrtypestr = "edge triggered";
	} else {
		intrtype = IST_LEVEL;
		intrtypestr = "level sensitive";
	}
	ahc->ih = isa_intr_establish(ia->ia_ic, irq,
	    intrtype, IPL_BIO, ahc_intr, ahc);
	if (ahc->ih == NULL) {
		aprint_error_dev(ahc->sc_dev,
		    "couldn't establish %s interrupt\n", intrtypestr);
		goto free_io;
	}

	/*
	 * Tell the user what type of interrupts we're using.
	 * useful for debugging irq problems
	 */
	if (bootverbose) {
		aprint_verbose_dev(ahc->sc_dev, "Using %s interrupts\n",
		       intrtypestr);
	}

	/*
	 * Now that we know we own the resources we need, do the
	 * card initialization.
	 */
	aha2840_load_seeprom(ahc);

	/* Attach sub-devices */
	if (ahc_aic77xx_attach(ahc) == 0)
		return; /* succeed */

	/* failed */
	isa_intr_disestablish(ia->ia_ic, ahc->ih);
free_io:
	bus_space_unmap(iot, ioh, ia->ia_io[0].ir_size);
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
0
void
ahc_isa_attach(struct device *parent, struct device *self, void *aux)
{
	struct ahc_softc *ahc = (void *)self;
	struct isa_attach_args *ia = aux;
	bus_space_tag_t iot = ia->ia_iot;
	bus_space_handle_t ioh;
	int irq;
	char idstring[EISA_IDSTRINGLEN];
	const char *model;
	u_int intdef;
	
	ahc_set_name(ahc, ahc->sc_dev.dv_xname);
	ahc_set_unit(ahc, ahc->sc_dev.dv_unit);
	
	/* set dma tags */
	ahc->parent_dmat = ia->ia_dmat;
	
	ahc->chip = AHC_VL; /* We are a VL Bus Controller */  
	
	if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh))
		panic("ahc_isa_attach: can't map slot i/o addresses");
	if (!ahc_isa_idstring(iot, ioh, idstring))
		panic("ahc_isa_attach: could not read ID string");
	if ((irq = ahc_isa_irq(iot, ioh)) < 0)
		panic("ahc_isa_attach: ahc_isa_irq failed!");

	if (strcmp(idstring, "ADP7756") == 0) {
		model = EISA_PRODUCT_ADP7756;
	} else if (strcmp(idstring, "ADP7757") == 0) {
		model = EISA_PRODUCT_ADP7757;
	} else {
		panic("ahc_isa_attach: Unknown device type %s", idstring);
	}
	printf(": %s\n", model);
	
	ahc->channel = 'A';
	ahc->chip = AHC_AIC7770;
	ahc->features = AHC_AIC7770_FE;
	ahc->bugs |= AHC_TMODE_WIDEODD_BUG;
	ahc->flags |= AHC_PAGESCBS;
	
	/* set tag and handle */
	ahc->tag = iot;
	ahc->bsh = ioh;

#ifdef DEBUG
	/*
	 * Tell the user what type of interrupts we're using.
	 * useful for debugging irq problems
	 */
	printf( "%s: Using %s Interrupts\n", ahc_name(ahc),
	    ahc->pause & IRQMS ?  "Level Sensitive" : "Edge Triggered");
#endif

	if (ahc_reset(ahc, /*reinit*/FALSE) != 0)
		return;
	
	/* See if we are edge triggered */
	intdef = ahc_inb(ahc, INTDEF);
	if ((intdef & EDGE_TRIG) != 0)
		ahc->flags |= AHC_EDGE_INTERRUPT;

	/*
	 * Now that we know we own the resources we need, do the 
	 * card initialization.
	 */
	aha2840_load_seeprom(ahc);

	/*      
	 * See if we have a Rev E or higher aic7770. Anything below a
	 * Rev E will have a R/O autoflush disable configuration bit.
	 * It's still not clear exactly what is differenent about the Rev E.
	 * We think it allows 8 bit entries in the QOUTFIFO to support
	 * "paging" SCBs so you can have more than 4 commands active at
	 * once.
	 */     
	{
		char *id_string;
		u_char sblkctl;
		u_char sblkctl_orig;

		sblkctl_orig = ahc_inb(ahc, SBLKCTL);
		sblkctl = sblkctl_orig ^ AUTOFLUSHDIS;
		ahc_outb(ahc, SBLKCTL, sblkctl);
		sblkctl = ahc_inb(ahc, SBLKCTL);
		if(sblkctl != sblkctl_orig)
		{
			id_string = "aic7770 >= Rev E, ";
			/*
			 * Ensure autoflush is enabled
			 */
			sblkctl &= ~AUTOFLUSHDIS;
			ahc_outb(ahc, SBLKCTL, sblkctl);

			/* Allow paging on this adapter */
			ahc->flags |= AHC_PAGESCBS;
		}
		else
			id_string = "aic7770 <= Rev C, ";

		printf("%s: %s", ahc_name(ahc), id_string);
	}

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

	/*
	 * Generic aic7xxx initialization.
	 */
	if(ahc_init(ahc)){
		ahc_free(ahc);
		return;
	}
	
	/*
	 * Link this softc in with all other ahc instances.
	 */
	ahc_softc_insert(ahc);

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

	/*
	 * The IRQMS bit enables level sensitive interrupts only allow
	 * IRQ sharing if its set.
	 */
	ahc->ih = isa_intr_establish(ia->ia_ic, irq,
	    ahc->pause & IRQMS ? IST_LEVEL : IST_EDGE, IPL_BIO, ahc_platform_intr,
	    ahc, ahc->sc_dev.dv_xname);
	if (ahc->ih == NULL) {
		printf("%s: couldn't establish interrupt\n",
		       ahc->sc_dev.dv_xname);
		ahc_free(ahc);
		return;
	}

	ahc_intr_enable(ahc, TRUE);
	
	/* Attach sub-devices - always succeeds */
	ahc_attach(ahc);
}