예제 #1
0
void
gemattach_sbus(struct device *parent, struct device *self, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct gem_sbus_softc *gsc = (void *)self;
	struct gem_softc *sc = &gsc->gsc_gem;
	/* XXX the following declarations should be elsewhere */
	extern void myetheraddr(u_char *);

	/* Pass on the bus tags */
	sc->sc_bustag = sa->sa_bustag;
	sc->sc_dmatag = sa->sa_dmatag;

	if (sa->sa_nreg < 2) {
		printf("%s: only %d register sets\n",
			self->dv_xname, sa->sa_nreg);
		return;
	}

	/*
	 * Map two register banks:
	 *
	 *	bank 0: status, config, reset
	 *	bank 1: various gem parts
	 *
	 */
	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
			 (bus_addr_t)sa->sa_reg[0].sbr_offset,
			 (bus_size_t)sa->sa_reg[0].sbr_size, 0, 0,
			 &sc->sc_h2) != 0) {
		printf("%s: cannot map registers\n", self->dv_xname);
		return;
	}
	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
			 (bus_addr_t)sa->sa_reg[1].sbr_offset,
			 (bus_size_t)sa->sa_reg[1].sbr_size, 0, 0,
			 &sc->sc_h1) != 0) {
		printf("%s: cannot map registers\n", self->dv_xname);
		return;
	}

	if (OF_getprop(sa->sa_node, "local-mac-address",
	    sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN) <= 0)
		myetheraddr(sc->sc_arpcom.ac_enaddr);

	/*
	 * SBUS config
	 */
	bus_space_write_4(sa->sa_bustag, sc->sc_h2, GEM_SBUS_CONFIG,
	    GEM_SBUS_CFG_PARITY|GEM_SBUS_CFG_BMODE64);

	/* Establish interrupt handler */
	if (sa->sa_nintr != 0)
		(void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_NET, 0,
					gem_intr, sc, self->dv_xname);

	gem_config(sc);
}
예제 #2
0
void
apio_attach(struct device *parent, struct device *self, void *aux)
{
	struct apio_softc *sc = (void *)self;
	struct sbus_attach_args *sa = aux;
	struct apio_attach_args aaa;
	char *model;

	sc->sc_bt = sa->sa_bustag;

	model = getpropstring(sa->sa_node, "model");
	if (model == NULL) {
		printf(": empty model, unsupported\n");
		return;
	}
	if (strcmp(model, "210sj") != 0) {
		printf(": unsupported model %s\n", model);
		return;
	}

	if (sa->sa_nreg < 3) {
		printf(": %d registers expected, got %d\n",
		    3, sa->sa_nreg);
		return;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size,
	    0, 0, &sc->sc_csr_h)) {
		printf(": couldn't map csr\n");
		return;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[1].sbr_slot,
	    sa->sa_reg[1].sbr_offset, sa->sa_reg[1].sbr_size,
	    0, 0, &sc->sc_clk_h)) {
		printf(": couldn't map clk\n");
		return;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[2].sbr_slot,
	    sa->sa_reg[2].sbr_offset, sa->sa_reg[2].sbr_size,
	    0, 0, &sc->sc_lpt_h)) {
		printf(": couldn't map clk\n");
		return;
	}

	printf(": %s\n", model);

	aaa.aaa_name = "lpt";
	aaa.aaa_iot = sc->sc_bt;
	aaa.aaa_ioh = sc->sc_lpt_h;
	aaa.aaa_clkh = sc->sc_clk_h;
	aaa.aaa_inten = ASIO_CSR_SJ_PAR_INTEN;
	aaa.aaa_pri = sa->sa_intr[0].sbi_pri;
	sc->sc_port = config_found(self, &aaa, apio_print);
}
예제 #3
0
void
ti_sbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct ti_sbus_softc *tsc = (void *)self;
	struct ti_softc *sc = &tsc->tsc_sc;
	bus_space_handle_t ioh;

	/* Pass on the bus tags */
	sc->ti_btag = sa->sa_bustag;
	sc->sc_dmatag = sa->sa_dmatag;

	if (sa->sa_nintr < 1) {
                printf(": no interrupt\n");
                return;
        }

	if (sa->sa_nreg < 2) {
                printf(": only %d register sets\n", sa->sa_nreg);
		return;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[1].sbr_slot,
	    sa->sa_reg[1].sbr_offset, sa->sa_reg[1].sbr_size,
	    0, 0, &sc->ti_bhandle)) {
		printf(": can't map registers\n");
		return;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size,
	    0, 0, &ioh)) {
		printf(": can't map registers\n");
		goto unmap;
	}

	bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_NET, 0, ti_intr,
	    sc, self->dv_xname);

	bus_space_write_4(sa->sa_bustag, ioh, TI_PCI_CMDSTAT, 0x02000006);
	bus_space_write_4(sa->sa_bustag, ioh, TI_PCI_BIST, 0xffffffff);
	bus_space_write_4(sa->sa_bustag, ioh, TI_PCI_LOMEM, 0x00000400);

	bus_space_unmap(sa->sa_bustag, ioh, sa->sa_reg[0].sbr_size);

	sc->ti_sbus = 1;
	if (ti_attach(sc) == 0)
		return;

unmap:
	    bus_space_unmap(sa->sa_bustag, sc->ti_bhandle,
		sa->sa_reg[1].sbr_size);
}
예제 #4
0
/* ARGSUSED */
static void
memregattach_obio(device_t parent, device_t self, void *aux)
{
	union obio_attach_args *uoba = aux;
	bus_space_handle_t bh;

	if (uoba->uoba_isobio4 == 0) {
		struct sbus_attach_args *sa = &uoba->uoba_sbus;
		if (sa->sa_promvaddr != 0) {
			par_err_reg = (volatile int *)sa->sa_promvaddr;
			return;
		}

		if (sbus_bus_map(sa->sa_bustag,
				 sa->sa_slot, sa->sa_offset,
				 sizeof(par_err_reg),
				 BUS_SPACE_MAP_LINEAR, &bh) != 0) {
			printf("memregattach_obio: can't map register\n");
			return;
		}
		par_err_reg = (volatile int *)bh;
	}

	/* On sun4, `par_err_reg' has already been mapped in autoconf.c */
	if (par_err_reg == NULL)
		panic("memregattach");

	printf("\n");
}
예제 #5
0
static int
com_obio_match(device_t parent, cfdata_t cf, void *aux)
{
	union obio_attach_args *uoba = aux;
	struct sbus_attach_args *sa = &uoba->uoba_sbus;
	int tadpole = 0;
	int need_probe = 0;
	int rv = 0;
	uint8_t auxregval = 0;

	if (uoba->uoba_isobio4 != 0) {
		return (0);
	}

	/*
	 * Tadpole 3GX/3GS uses "modem" for a 16450 port
	 * (We need to enable it before probing)
	 */
	if (strcmp("modem", sa->sa_name) == 0) {
		auxregval = *AUXIO4M_REG;
		*AUXIO4M_REG = auxregval | (AUXIO4M_LED|AUXIO4M_LTE);
		DELAY(100);
		tadpole = 1;
		need_probe = 1;
	}

	/*
	 * Sun JavaStation 1 uses "su" for a 16550 port
	 */
	if (strcmp("su", sa->sa_name) == 0) {
		need_probe = 1;
	}

	if (need_probe) {
		bus_space_handle_t ioh;

		if (sbus_bus_map(sa->sa_bustag,
				 sa->sa_slot, sa->sa_offset, sa->sa_size,
				 BUS_SPACE_MAP_LINEAR, &ioh) == 0) {
			rv = comprobe1(sa->sa_bustag, ioh);
#if 0
			printf("modem: probe: lcr=0x%02x iir=0x%02x\n",
				bus_space_read_1(sa->sa_bustag, ioh, 3),
				bus_space_read_1(sa->sa_bustag, ioh, 2));
#endif
			bus_space_unmap(sa->sa_bustag, ioh, sa->sa_size);
		}
	}

	/* Disable the com port if tadpole */
	if (tadpole)
		*AUXIO4M_REG = auxregval;

	return (rv);
}
예제 #6
0
int
rfx_initialize(struct rfx_softc *sc, struct sbus_attach_args *sa,
    struct rfx_config *cf)
{
	u_int32_t *data, offset, value;
	size_t cnt;
	bus_space_handle_t bh;
	int error;

	/*
	 * Map the initialization data
	 */
	if ((error = sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset +
	    RFX_INIT_ADDR, RFX_INIT_SIZE, BUS_SPACE_MAP_LINEAR, 0, &bh)) != 0) {
		printf("\n%s: couldn't map initialization data\n",
		    sc->sc_sunfb.sf_dev.dv_xname);
		return error;
	}
	data = (u_int32_t *)bus_space_vaddr(sa->sa_bustag, bh);

	/*
	 * Skip copyright notice
	 */
	data += RFX_INIT_OFFSET / sizeof(u_int32_t);
	cnt = (RFX_INIT_SIZE - RFX_INIT_OFFSET) / sizeof(u_int32_t);
	cnt >>= 1;

	/*
	 * Parse and apply settings
	 */
	while (cnt != 0) {
		offset = *data++;
		value = *data++;

		if (offset == (u_int32_t)-1 && value == (u_int32_t)-1)
			break;

		/* Old PROM are little-endian */
		if (cf->version <= 1) {
			offset = letoh32(offset);
			value = letoh32(offset);
		}

		if (offset & (1 << 31)) {
			offset = (offset & ~(1 << 31)) - RFX_RAMDAC_ADDR;
			if (offset < RFX_RAMDAC_SIZE)
				sc->sc_ramdac[offset] = value >> 24;
		} else {
예제 #7
0
void
leattach_lebuffer(struct device *parent, struct device *self, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct le_softc *lesc = (struct le_softc *)self;
	struct am7990_softc *sc = &lesc->sc_am7990;
	struct lebuf_softc *lebuf = (struct lebuf_softc *)parent;
	/* XXX the following declarations should be elsewhere */
	extern void myetheraddr(u_char *);

	lesc->sc_bustag = sa->sa_bustag;
	lesc->sc_dmatag = sa->sa_dmatag;

	if (sbus_bus_map(sa->sa_bustag,
	    sa->sa_slot, sa->sa_offset, sa->sa_size,
	    0, 0, &lesc->sc_reg)) {
		printf(": cannot map registers\n");
		return;
	}

	sc->sc_mem = lebuf->sc_buffer;
	sc->sc_memsize = lebuf->sc_bufsiz;
	sc->sc_addr = 0; /* Lance view is offset by buffer location */
	lebuf->attached = 1;

	/* That old black magic... */
	sc->sc_conf3 = getpropint(sa->sa_node, "busmaster-regval",
	    LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON);

	myetheraddr(sc->sc_arpcom.ac_enaddr);

	sc->sc_copytodesc = am7990_copytobuf_contig;
	sc->sc_copyfromdesc = am7990_copyfrombuf_contig;
	sc->sc_copytobuf = am7990_copytobuf_contig;
	sc->sc_copyfrombuf = am7990_copyfrombuf_contig;
	sc->sc_zerobuf = am7990_zerobuf_contig;

	sc->sc_rdcsr = le_lebuffer_rdcsr;
	sc->sc_wrcsr = le_lebuffer_wrcsr;

	am7990_config(&lesc->sc_am7990);

	/* Establish interrupt handler */
	if (sa->sa_nintr != 0)
		(void)bus_intr_establish(lesc->sc_bustag, sa->sa_pri,
		    IPL_NET, 0, am7990_intr, sc, self->dv_xname);
}
예제 #8
0
파일: power.c 프로젝트: ryo/netbsd-src
/* ARGSUSED */
static void
powerattach(device_t parent, device_t self, void *aux)
{
	union obio_attach_args *uoba = aux;
	struct sbus_attach_args *sa = &uoba->uoba_sbus;
	bus_space_handle_t bh;

	/* Map the power configuration register. */
	if (sbus_bus_map(sa->sa_bustag,
			 sa->sa_slot, sa->sa_offset, sizeof(uint8_t),
			 BUS_SPACE_MAP_LINEAR, &bh) != 0) {
		printf("%s: cannot map register\n", device_xname(self));
		return;
	}
	power_reg = (volatile uint8_t *)bh;

	printf("\n");
}
예제 #9
0
void
uperf_sbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct uperf_sbus_softc *sc = (struct uperf_sbus_softc *)self;
	char *model;
	u_int32_t id;

	sc->sc_bus_t = sa->sa_bustag;
	sc->sc_usc.usc_cookie = sc;
	sc->sc_usc.usc_getcntsrc = uperf_sbus_getcntsrc;
	sc->sc_usc.usc_setcntsrc = uperf_sbus_setcntsrc;
	sc->sc_usc.usc_clrcnt = uperf_sbus_clrcnt;
	sc->sc_usc.usc_getcnt = uperf_sbus_getcnt;
	sc->sc_usc.usc_srcs = uperf_sbus_srcs;

	if (sa->sa_nreg != 1) {
		printf(": expected 1 register, got %d\n", sa->sa_nreg);
		return;
	}

	if (sbus_bus_map(sc->sc_bus_t, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size, 0, 0,
	    &sc->sc_bus_h) != 0) {
		printf(": couldn't map registers\n");
		return;
	}

	id = uperf_sbus_read_reg(sc, USC_ID);
	model = getpropstring(sa->sa_node, "model");
	if (model == NULL || strlen(model) == 0)
		model = "unknown";

	printf(": model %s (%x/%x) ports %d\n", model,
	    (id & USC_ID_IMPL_M) >> USC_ID_IMPL_S,
	    (id & USC_ID_VERS_M) >> USC_ID_VERS_S,
	    (id & USC_ID_UPANUM_M) >> USC_ID_UPANUM_S);

#ifdef DDB
	db_register_xir(uperf_sbus_xir, sc);
#endif
}
예제 #10
0
void
audioamd_sbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct sbus_attach_args *sa;
	struct audioamd_softc *sc;
	bus_space_handle_t bh;

	sa = aux;
	sc = (struct audioamd_softc *)self;
	sc->sc_bt = sa->sa_bustag;

	if (sbus_bus_map(sa->sa_bustag,
			 sa->sa_slot, sa->sa_offset,
			 AM7930_DREG_SIZE,
			 0, &bh) != 0) {
		printf("%s: cannot map registers\n", self->dv_xname);
		return;
	}
	sc->sc_bh = bh;
	audioamd_attach(sc, sa->sa_pri);
}
예제 #11
0
void
magma_attach(struct device *parent, struct device *dev, void *aux)
{
    struct sbus_attach_args *sa = aux;
    struct magma_softc *sc = (struct magma_softc *)dev;
    const struct magma_board_info *card;
    char magma_prom[40], *clockstr;
    int chip, cd_clock;

    getpropstringA(sa->sa_node, "magma_prom", magma_prom);
    for (card = supported_cards; card->mb_name != NULL; card++) {
        if (strcmp(sa->sa_name, card->mb_sbusname) != 0)
            continue;
        if (strcmp(magma_prom, card->mb_name) == 0)
            break;
    }
    if (card->mb_name == NULL) {
        printf(": %s (unsupported)\n", magma_prom);
        return;
    }

    sc->sc_bustag = sa->sa_bustag;

    clockstr = getpropstring(sa->sa_node, "clock");
    if (strlen(clockstr) == 0)
        cd_clock = 25;
    else {
        cd_clock = 0;
        while (*clockstr != '\0')
            cd_clock = cd_clock * 10 + *clockstr++ - '0';
    }

    if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
                     sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size,
                     0, 0, &sc->sc_iohandle) != 0) {
        printf(": can't map registers\n");
        return;
    }

    if (sa->sa_nintr < 1) {
        printf(": can't find interrupt\n");
        return;
    }
    sc->sc_ih = bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_TTY, 0,
                                   magma_hard, sc, dev->dv_xname);
    if (sc->sc_ih == NULL) {
        printf(": couldn't establish interrupt, pri %d\n",
               INTLEV(sa->sa_pri));
        bus_space_unmap(sc->sc_bustag, sc->sc_iohandle,
                        sa->sa_reg[0].sbr_size);
        return;
    }

    sc->sc_sih = softintr_establish(IPL_TTY, magma_soft, sc);
    if (sc->sc_sih == NULL) {
        printf(": can't get soft intr\n");
        bus_space_unmap(sc->sc_bustag, sc->sc_iohandle,
                        sa->sa_reg[0].sbr_size);
        return;
    }

    printf(": %s\n", card->mb_realname);

    sc->ms_board = card;
    sc->ms_ncd1400 = card->mb_ncd1400;
    sc->ms_ncd1190 = card->mb_ncd1190;

    /* the SVCACK* lines are daisychained */
    if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle,
                            card->mb_svcackr, 1, &sc->sc_svcackrh)) {
        printf(": failed to map svcackr\n");
        return;
    }
    if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle,
                            card->mb_svcackt, 1, &sc->sc_svcackth)) {
        printf(": failed to map svcackt\n");
        return;
    }
    if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle,
                            card->mb_svcackm, 1, &sc->sc_svcackmh)) {
        printf(": failed to map svcackm\n");
        return;
    }

    /* init the cd1400 chips */
    for (chip = 0 ; chip < card->mb_ncd1400 ; chip++) {
        struct cd1400 *cd = &sc->ms_cd1400[chip];

        cd->cd_clock = cd_clock;

        if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle,
                                card->mb_cd1400[chip], CD1400_REGMAPSIZE, &cd->cd_regh)) {
            printf(": failed to map cd1400 regs\n");
            return;
        }
        cd->cd_regt = sc->sc_bustag;

        /* getpropstring(sa->sa_node, "chiprev"); */
        /* seemingly the Magma drivers just ignore the propstring */
        cd->cd_chiprev = CD1400_READ_REG(cd, CD1400_GFRCR);

        dprintf(("%s attach CD1400 %d addr 0x%x rev %x clock %dMHz\n",
                 sc->ms_dev.dv_xname, chip, cd->cd_reg,
                 cd->cd_chiprev, cd->cd_clock));

        /* clear GFRCR */
        CD1400_WRITE_REG(cd, CD1400_GFRCR, 0x00);

        /* reset whole chip */
        cd1400_write_ccr(cd,
                         CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET);

        /* wait for revision code to be restored */
        while (CD1400_READ_REG(cd, CD1400_GFRCR) != cd->cd_chiprev)
            ;

        /* set the Prescaler Period Register to tick at 1ms */
        CD1400_WRITE_REG(cd, CD1400_PPR,
                         ((cd->cd_clock * 1000000 / CD1400_PPR_PRESCALER + 500)
                          / 1000));

        /*
         * The LC2+1Sp card is the only card that doesn't have a
         * CD1190 for the parallel port, but uses channel 0 of the
         * CD1400, so we make a note of it for later and set up the
         * CD1400 for parallel mode operation.
         */
        if (card->mb_npar && card->mb_ncd1190 == 0) {
            CD1400_WRITE_REG(cd, CD1400_GCR, CD1400_GCR_PARALLEL);
            cd->cd_parmode = 1;
        }
    }

    /* init the cd1190 chips */
    for (chip = 0 ; chip < card->mb_ncd1190 ; chip++) {
        struct cd1190 *cd = &sc->ms_cd1190[chip];

        if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle,
                                card->mb_cd1190[chip], CD1190_REGMAPSIZE, &cd->cd_regh)) {
            printf(": failed to map cd1190 regs\n");
            return;
        }
        cd->cd_regt = sc->sc_bustag;
        dprintf(("%s attach CD1190 %d addr 0x%x (failed)\n",
                 sc->ms_dev.dv_xname, chip, cd->cd_reg));
        /* XXX don't know anything about these chips yet */
    }

    /* configure the children */
    (void)config_found(dev, mtty_match, NULL);
    (void)config_found(dev, mbpp_match, NULL);
}
예제 #12
0
void
bppattach(device_t parent, device_t self, void *aux)
{
	struct bpp_softc *dsc = device_private(self);
	struct lsi64854_softc *sc = &dsc->sc_lsi64854;
	struct sbus_softc *sbsc = device_private(parent);
	struct sbus_attach_args *sa = aux;
	int burst, sbusburst;
	int node;

	sc->sc_dev = self;

	selinit(&dsc->sc_rsel);
	selinit(&dsc->sc_wsel);
	dsc->sc_sih = softint_establish(SOFTINT_CLOCK, bppsoftintr, dsc);

	sc->sc_bustag = sa->sa_bustag;
	sc->sc_dmatag = sa->sa_dmatag;
	node = sa->sa_node;

	/* Map device registers */
	if (sbus_bus_map(sa->sa_bustag,
			 sa->sa_slot, sa->sa_offset, sa->sa_size,
			 0, &sc->sc_regs) != 0) {
		aprint_error(": cannot map registers\n");
		return;
	}

	/*
	 * Get transfer burst size from PROM and plug it into the
	 * controller registers. This is needed on the Sun4m; do
	 * others need it too?
	 */
	sbusburst = sbsc->sc_burst;
	if (sbusburst == 0)
		sbusburst = SBUS_BURST_32 - 1; /* 1->16 */

	burst = prom_getpropint(node, "burst-sizes", -1);
	if (burst == -1)
		/* take SBus burst sizes */
		burst = sbusburst;

	/* Clamp at parent's burst sizes */
	burst &= sbusburst;
	sc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
		       (burst & SBUS_BURST_16) ? 16 : 0;

	/* Join the Sbus device family */
	dsc->sc_sd.sd_reset = NULL;
	sbus_establish(&dsc->sc_sd, self);

	/* Initialize the DMA channel */
	sc->sc_channel = L64854_CHANNEL_PP;
	lsi64854_attach(sc);

	/* Establish interrupt handler */
	if (sa->sa_nintr) {
		sc->sc_intrchain = bppintr;
		sc->sc_intrchainarg = dsc;
		(void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_TTY,
		    bppintr, sc);
	}

	/* Allocate buffer XXX - should actually use dmamap_uio() */
	dsc->sc_bufsz = 1024;
	dsc->sc_buf = malloc(dsc->sc_bufsz, M_DEVBUF, M_NOWAIT);

	/* XXX read default state */
	{
	bus_space_handle_t h = sc->sc_regs;
	struct hwstate *hw = &dsc->sc_hwdefault;
	int ack_rate = sa->sa_frequency / 1000000;

	hw->hw_hcr = bus_space_read_2(sc->sc_bustag, h, L64854_REG_HCR);
	hw->hw_ocr = bus_space_read_2(sc->sc_bustag, h, L64854_REG_OCR);
	hw->hw_tcr = bus_space_read_1(sc->sc_bustag, h, L64854_REG_TCR);
	hw->hw_or = bus_space_read_1(sc->sc_bustag, h, L64854_REG_OR);

	DPRINTF(("bpp: hcr %x ocr %x tcr %x or %x\n",
	    hw->hw_hcr, hw->hw_ocr, hw->hw_tcr, hw->hw_or));
	/* Set these to sane values */
	hw->hw_hcr = ((ack_rate<<BPP_HCR_DSS_SHFT)&BPP_HCR_DSS_MASK)
	    | ((ack_rate<<BPP_HCR_DSW_SHFT)&BPP_HCR_DSW_MASK);
	hw->hw_ocr |= BPP_OCR_ACK_OP;
	}
}
예제 #13
0
파일: agten.c 프로젝트: sofuture/bitrig
void
agtenattach(struct device *parent, struct device *self, void *args)
{
	struct agten_softc *sc = (struct agten_softc *)self;
	struct sbus_attach_args *sa = args;
	bus_space_tag_t bt;
	bus_space_handle_t bh;
	int node, isconsole;
	char *nam;

	bt = sa->sa_bustag;
	node = sa->sa_node;
	nam = getpropstring(node, "model");
	printf(": model %s", nam);

	isconsole = node == fbnode;

	/*
	 * Map the various beasts of this card we are interested in.
	 */

	sc->sc_bustag = bt;
	sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset);

	sc->sc_physoffset =
	    (off_t)getpropint(node, "i128_fb_physaddr", 0x8000000);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + sc->sc_physoffset,
	    getpropint(node, "i128_fb_size", 0x400000), BUS_SPACE_MAP_LINEAR,
	    0, &bh) != 0) {
		printf("\n%s: couldn't map video memory\n", self->dv_xname);
		return;
	}
	sc->sc_i128_fb = bus_space_vaddr(bt, bh);
	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset +
	    getpropint(node, "p9100_reg_physaddr", 0x10a0000), 0x4000,
	    BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("\n%s: couldn't map control registers\n", self->dv_xname);
		return;
	}
	sc->sc_p9100 = bus_space_vaddr(bt, bh);

	/*
	 * For some reason the agten does not use the canonical name for
	 * properties, but uses an ffb_ prefix; and the linebytes property is
	 * missing.
	 * The following is a specific version of
	 *   fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, BUS_SBUS);
	 * using the correct property names.
	 */
#ifdef notyet
	sc->sc_sunfb.sf_depth = 32;
#else
	sc->sc_sunfb.sf_depth = getpropint(node, "ffb_depth", 8);
#endif
	sc->sc_sunfb.sf_width = getpropint(node, "ffb_width", 1152);
	sc->sc_sunfb.sf_height = getpropint(node, "ffb_height", 900);
	sc->sc_sunfb.sf_linebytes =
	    roundup(sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_depth) *
	        sc->sc_sunfb.sf_depth / 8;
	sc->sc_sunfb.sf_fbsize =
	    sc->sc_sunfb.sf_height * sc->sc_sunfb.sf_linebytes;

	printf(", %dx%d, depth %d\n",
	    sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height,
	    sc->sc_sunfb.sf_depth);

	sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_i128_fb;
	
	sc->sc_sunfb.sf_ro.ri_hw = sc;
	fbwscons_init(&sc->sc_sunfb, 0, isconsole);
	fbwscons_setcolormap(&sc->sc_sunfb, agten_setcolor);

	if (isconsole)
		fbwscons_console_init(&sc->sc_sunfb, -1);

	fbwscons_attach(&sc->sc_sunfb, &agten_accessops, isconsole);
}
예제 #14
0
void
timerattach_obio_4m(device_t parent, device_t self, void *aux)
{
	union obio_attach_args *uoba = aux;
	struct sbus_attach_args *sa = &uoba->uoba_sbus;
	struct cpu_info *cpi;
	bus_space_handle_t bh;
	int i;
	CPU_INFO_ITERATOR n;

	if (sa->sa_nreg < 2) {
		printf(": only %d register sets\n", sa->sa_nreg);
		return;
	}

	/* Map the system timer */
	i = sa->sa_nreg - 1;
	if (bus_space_map2(sa->sa_bustag,
			   BUS_ADDR(sa->sa_reg[i].oa_space,
				    sa->sa_reg[i].oa_base),
			   sizeof(struct timer_4m),
			   BUS_SPACE_MAP_LINEAR,
			   TIMERREG_VA, &bh) != 0) {
		printf(": can't map registers\n");
		return;
	}
	timerreg4m = (struct timer_4m *)TIMERREG_VA;

	/* Map each CPU's counter */
	for (i = 0; i < sa->sa_nreg - 1; i++) {
		/*
		 * Check whether the CPU corresponding to this timer
		 * register is installed.
		 */
		for (CPU_INFO_FOREACH(n, cpi)) {
			if ((i == 0 && sparc_ncpus == 1) || cpi->mid == i + 8) {
				/* We got a corresponding MID. */
				break;
			}
			cpi = NULL;
		}
		if (cpi == NULL)
			continue;

		if (sbus_bus_map(sa->sa_bustag,
				 sa->sa_reg[i].oa_space,
				 sa->sa_reg[i].oa_base,
				 sizeof(struct timer_4m),
				 BUS_SPACE_MAP_LINEAR,
				 &bh) != 0) {
			printf(": can't map CPU counter %d\n", i);
			return;
		}
		cpi->counterreg_4m = (struct counter_4m *)bh;
	}

#if defined(MULTIPROCESSOR)
	if (sparc_ncpus > 1) {
		/*
		 * Note that we don't actually use this cookie after checking
		 * it was establised, we call directly via raise_ipi() on
		 * IPL_HARDCLOCK.
		 */
		void *hardclock_cookie;

		hardclock_cookie = sparc_softintr_establish(IPL_HARDCLOCK,
		    hardclock_ipi, NULL);
		if (hardclock_cookie == NULL)
			panic("timerattach: cannot establish hardclock_intr");
	}
#endif

	/* Put processor counter in "timer" mode */
	timerreg4m->t_cfg = 0;

	timerattach(&timerreg4m->t_counter, &timerreg4m->t_limit);
}
예제 #15
0
void
magma_attach(device_t parent, device_t self, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct magma_softc *sc = device_private(self);
	struct magma_board_info *card;
	bus_space_handle_t bh;
	char *magma_prom, *clockstr;
	int cd_clock;
	int node, chip;

	sc->ms_dev = self;
	node = sa->sa_node;

	/*
	 * Find the card model.
	 * Older models all have sbus node name `MAGMA_Sp' (see
	 * `supported_cards[]' above), and must be distinguished
	 * by the `magma_prom' property.
	 */
	magma_prom = prom_getpropstring(node, "magma_prom");

	for (card = supported_cards; card->mb_name != NULL; card++) {
		if (strcmp(sa->sa_name, card->mb_sbusname) != 0)
			/* Sbus node name doesn't match */
			continue;
		if (strcmp(magma_prom, card->mb_name) == 0)
			/* Model name match */
			break;
	}

	if( card->mb_name == NULL ) {
		printf(": %s (unsupported)\n", magma_prom);
		return;
	}

	dprintf((" addr %p", sc));
	printf(": %s\n", card->mb_realname);

	sc->ms_board = card;
	sc->ms_ncd1400 = card->mb_ncd1400;
	sc->ms_ncd1190 = card->mb_ncd1190;

	if (sbus_bus_map(sa->sa_bustag,
			 sa->sa_slot, sa->sa_offset, sa->sa_size,
			 BUS_SPACE_MAP_LINEAR, &bh) != 0) {
		aprint_error("%s @ sbus: cannot map registers\n",
			device_xname(self));
		return;
	}

	/* the SVCACK* lines are daisychained */
	sc->ms_svcackr = (char *)bus_space_vaddr(sa->sa_bustag, bh)
		+ card->mb_svcackr;
	sc->ms_svcackt = (char *)bus_space_vaddr(sa->sa_bustag, bh)
		+ card->mb_svcackt;
	sc->ms_svcackm = (char *)bus_space_vaddr(sa->sa_bustag, bh)
		+ card->mb_svcackm;

	/*
	 * Find the clock speed; it's the same for all CD1400 chips
	 * on the board.
	 */
	clockstr = prom_getpropstring(node, "clock");
	if (*clockstr == '\0')
		/* Default to 25MHz */
		cd_clock = 25;
	else {
		cd_clock = 0;
		while (*clockstr != '\0')
			cd_clock = (cd_clock * 10) + (*clockstr++ - '0');
	}

	/* init the cd1400 chips */
	for( chip = 0 ; chip < card->mb_ncd1400 ; chip++ ) {
		struct cd1400 *cd = &sc->ms_cd1400[chip];

		cd->cd_clock = cd_clock;
		cd->cd_reg = (char *)bus_space_vaddr(sa->sa_bustag, bh) +
		    card->mb_cd1400[chip];

		/* prom_getpropstring(node, "chiprev"); */
		/* seemingly the Magma drivers just ignore the propstring */
		cd->cd_chiprev = cd1400_read_reg(cd, CD1400_GFRCR);

		dprintf(("%s attach CD1400 %d addr %p rev %x clock %dMHz\n",
			device_xname(sc->ms_dev), chip,
			cd->cd_reg, cd->cd_chiprev, cd->cd_clock));

		/* clear GFRCR */
		cd1400_write_reg(cd, CD1400_GFRCR, 0x00);

		/* reset whole chip */
		cd1400_write_ccr(cd, CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET);

		/* wait for revision code to be restored */
		while( cd1400_read_reg(cd, CD1400_GFRCR) != cd->cd_chiprev )
		        ;

		/* set the Prescaler Period Register to tick at 1ms */
		cd1400_write_reg(cd, CD1400_PPR,
			((cd->cd_clock * 1000000 / CD1400_PPR_PRESCALER + 500) / 1000));

		/* The LC2+1Sp card is the only card that doesn't have
		 * a CD1190 for the parallel port, but uses channel 0 of
		 * the CD1400, so we make a note of it for later and set up
		 * the CD1400 for parallel mode operation.
		 */
		if( card->mb_npar && card->mb_ncd1190 == 0 ) {
			cd1400_write_reg(cd, CD1400_GCR, CD1400_GCR_PARALLEL);
			cd->cd_parmode = 1;
		}
	}

	/* init the cd1190 chips */
	for( chip = 0 ; chip < card->mb_ncd1190 ; chip++ ) {
		struct cd1190 *cd = &sc->ms_cd1190[chip];

		cd->cd_reg = (char *)bus_space_vaddr(sa->sa_bustag, bh) +
		    card->mb_cd1190[chip];

		/* XXX don't know anything about these chips yet */
		printf("%s: CD1190 %d addr %p (unsupported)\n",
			device_xname(self), chip, cd->cd_reg);
	}

	/* configure the children */
	(void)config_found(self, mtty_match, NULL);
	(void)config_found(self, mbpp_match, NULL);

	/*
	 * Establish the interrupt handlers.
	 */
	if (sa->sa_nintr == 0)
		return;		/* No interrupts to service!? */

	(void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_SERIAL,
				 magma_hard, sc);
	sc->ms_sicookie = softint_establish(SOFTINT_SERIAL, magma_soft, sc);
	if (sc->ms_sicookie == NULL) {
		aprint_normal("\n");
		aprint_error_dev(sc->ms_dev, "cannot establish soft int handler\n");
		return;
	}
	evcnt_attach_dynamic(&sc->ms_intrcnt, EVCNT_TYPE_INTR, NULL,
	    device_xname(sc->ms_dev), "intr");
}
예제 #16
0
void
leattach_ledma(device_t parent, device_t self, void *aux)
{
	struct le_softc *lesc = device_private(self);
	struct lance_softc *sc = &lesc->sc_am7990.lsc;
	struct lsi64854_softc *lsi = device_private(parent);
	struct sbus_attach_args *sa = aux;
	bus_dma_tag_t dmatag = sa->sa_dmatag;
	bus_dma_segment_t seg;
	int rseg, error;

	sc->sc_dev = self;
	lesc->sc_bustag = sa->sa_bustag;

	/* Establish link to `ledma' device */
	lesc->sc_dma = lsi;
	lesc->sc_dma->sc_client = lesc;

	/* Map device registers */
	if (sbus_bus_map(sa->sa_bustag,
			 sa->sa_slot,
			 sa->sa_offset,
			 sa->sa_size,
			 0, &lesc->sc_reg) != 0) {
		aprint_error(": cannot map registers\n");
		return;
	}

	/* Allocate buffer memory */
	sc->sc_memsize = MEMSIZE;

	/* Get a DMA handle */
	if ((error = bus_dmamap_create(dmatag, MEMSIZE, 1, MEMSIZE,
					LEDMA_BOUNDARY, BUS_DMA_NOWAIT,
					&lesc->sc_dmamap)) != 0) {
		aprint_error(": DMA map create error %d\n", error);
		return;
	}

	/* Allocate DMA buffer */
	if ((error = bus_dmamem_alloc(dmatag, MEMSIZE, 0, LEDMA_BOUNDARY,
				 &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
		aprint_error(": DMA buffer alloc error %d\n",error);
		return;
	}

	/* Map DMA buffer into kernel space */
	if ((error = bus_dmamem_map(dmatag, &seg, rseg, MEMSIZE,
			       (void **)&sc->sc_mem,
			       BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
		aprint_error(": DMA buffer map error %d\n", error);
		bus_dmamem_free(dmatag, &seg, rseg);
		return;
	}

	/* Load DMA buffer */
	if ((error = bus_dmamap_load(dmatag, lesc->sc_dmamap, sc->sc_mem,
			MEMSIZE, NULL, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
		aprint_error(": DMA buffer map load error %d\n", error);
		bus_dmamem_free(dmatag, &seg, rseg);
		bus_dmamem_unmap(dmatag, sc->sc_mem, MEMSIZE);
		return;
	}

	lesc->sc_laddr = lesc->sc_dmamap->dm_segs[0].ds_addr;
	sc->sc_addr = lesc->sc_laddr & 0xffffff;
	sc->sc_conf3 = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON;


	/* Assume SBus is grandparent */
	lesc->sc_sd.sd_reset = (void *)lance_reset;
	sbus_establish(&lesc->sc_sd, parent);

	sc->sc_mediachange = lemediachange;
	sc->sc_mediastatus = lemediastatus;
	sc->sc_supmedia = lemedia;
	sc->sc_nsupmedia = NLEMEDIA;
	sc->sc_defaultmedia = IFM_ETHER|IFM_AUTO;

	prom_getether(sa->sa_node, sc->sc_enaddr);

	sc->sc_copytodesc = lance_copytobuf_contig;
	sc->sc_copyfromdesc = lance_copyfrombuf_contig;
	sc->sc_copytobuf = lance_copytobuf_contig;
	sc->sc_copyfrombuf = lance_copyfrombuf_contig;
	sc->sc_zerobuf = lance_zerobuf_contig;

	sc->sc_rdcsr = lerdcsr;
	sc->sc_wrcsr = lewrcsr;
	sc->sc_hwinit = lehwinit;
	sc->sc_nocarrier = lenocarrier;
	sc->sc_hwreset = lehwreset;

	/* Establish interrupt handler */
	if (sa->sa_nintr != 0)
		(void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_NET,
					 am7990_intr, sc);

	am7990_config(&lesc->sc_am7990);

	/* now initialize DMA */
	lehwreset(sc);
}
예제 #17
0
/*
 * Attach and initialize a rfx display, as well as a child wsdisplay.
 */
void
rfxattach(struct device *parent, struct device *self, void *args)
{
	struct rfx_softc *sc = (struct rfx_softc *)self;
	struct sbus_attach_args *sa = args;
	const char *device = sa->sa_name;
	struct rfx_config cf;
	bus_space_tag_t bt;
	bus_space_handle_t bh;
	int node, cflen, isconsole = 0;

	/* skip vendor name (could be CWARE, VITec, ...) */
	while (*device != ',' && *device != '\0')
		device++;
	if (*device == '\0')
		device = sa->sa_name;
	else
		device++;

	printf(": %s", device);

	if (sa->sa_nreg == 0) {
		printf("\n%s: no SBus registers!\n", self->dv_xname);
		return;
	}

	bt = sa->sa_bustag;
	node = sa->sa_node;
	isconsole = node == fbnode;

	/*
	 * Parse configuration structure
	 */
	cflen = getproplen(node, "configuration");
	if (cflen != sizeof cf) {
		printf(", unknown %d bytes conf. structure", cflen);
		/* fill in default values */
		cf.version = 0;
		cf.scanline = 2048;
		cf.width = 1152;
		cf.height = 900;
	} else {
		OF_getprop(node, "configuration", &cf, cflen);
		printf(", revision %d", cf.version);
	}

	/*
	 * Map registers
	 */

	sc->sc_bustag = bt;
	sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + RFX_RAMDAC_ADDR,
	    RFX_RAMDAC_SIZE, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("\n%s: couldn't map ramdac registers\n", self->dv_xname);
		return;
	}
	sc->sc_ramdac = (u_int8_t *)bus_space_vaddr(bt, bh);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + RFX_CONTROL_ADDR,
	    RFX_CONTROL_SIZE, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("\n%s: couldn't map control registers\n", self->dv_xname);
		return;
	}
	sc->sc_ctrl = (u_int32_t *)bus_space_vaddr(bt, bh);

#if 0	/* not yet */
	sc->sc_ih.ih_fun = rfx_intr;
	sc->sc_ih.ih_arg = sc;
	intr_establish(ca->ca_ra.ra_intr[0].int_pri, &sc->sc_ih, IPL_FB);
#endif

	/*
	 * The following is an equivalent for
	 *   fb_setsize(&sc->sc_sunfb, 8, cf.width, cf.height,
	 *     node, ca->ca_bustype);
	 * forcing the correct scan line value. Since the usual frame buffer
	 * properties are missing on this card, no need to go through
	 * fb_setsize()...
	 */
	sc->sc_sunfb.sf_depth = 8;
	sc->sc_sunfb.sf_width = cf.width;
	sc->sc_sunfb.sf_height = cf.height;
	sc->sc_sunfb.sf_linebytes = cf.scanline;
	sc->sc_sunfb.sf_fbsize = cf.height * cf.scanline;

	printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + RFX_VRAM_ADDR,
	    round_page(sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR,
	    0, &bh) != 0) {
		printf("\n%s: couldn't map video memory\n", self->dv_xname);
		return;
	}
	sc->sc_sunfb.sf_ro.ri_bits = bus_space_vaddr(bt, bh);
	sc->sc_sunfb.sf_ro.ri_hw = sc;

	/*
	 * If we are not the console, the frame buffer has not been
	 * initialized by the PROM - do this ourselves.
	 */
	if (!isconsole) {
		if (rfx_initialize(sc, sa, &cf) != 0)
			return;
	}

	fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR);

	bzero(&sc->sc_cmap, sizeof(sc->sc_cmap));
	fbwscons_setcolormap(&sc->sc_sunfb, rfx_setcolor);

	if (isconsole) {
		fbwscons_console_init(&sc->sc_sunfb, -1);
	}

	/* enable video */
	rfx_burner(sc, 1, 0);

	fbwscons_attach(&sc->sc_sunfb, &rfx_accessops, isconsole);
}
예제 #18
0
void
zx_attach(struct device *parent, struct device *self, void *args)
{
	struct zx_softc *sc = (struct zx_softc *)self;
	struct sbus_attach_args *sa = args;
	struct rasops_info *ri;
	bus_space_tag_t bt;
	bus_space_handle_t bh;
	int node, isconsole = 0;
	const char *nam;

	bt = sa->sa_bustag;
	ri = &sc->sc_sunfb.sf_ro;
	node = sa->sa_node;

	/*
	 * Map the various parts of the card.
	 */
	sc->sc_bustag = bt;
	sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LC_SS0_USR,
	    sizeof(struct zx_command), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf(": couldn't map command registers\n");
		return;
	}
	sc->sc_zc = (struct zx_command *)bus_space_vaddr(bt, bh);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS0,
	    sizeof(struct zx_draw), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf(": couldn't map ss0 drawing registers\n");
		return;
	}
	sc->sc_zd_ss0 = (struct zx_draw *)bus_space_vaddr(bt, bh);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS1,
	    sizeof(struct zx_draw_ss1), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf(": couldn't map ss1 drawing registers\n");
		return;
	}
	sc->sc_zd_ss1 = (struct zx_draw_ss1 *)bus_space_vaddr(bt, bh);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CROSS,
	    sizeof(struct zx_cross), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf(": couldn't map cross registers\n");
		return;
	}
	sc->sc_zx = (struct zx_cross *)bus_space_vaddr(bt, bh);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CURSOR,
	    sizeof(struct zx_cursor), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf(": couldn't map cursor registers\n");
		return;
	}
	sc->sc_zcu = (struct zx_cursor *)bus_space_vaddr(bt, bh);

	nam = getpropstring(node, "model");
	if (*nam == '\0')
		nam = sa->sa_name;
	printf(": %s", nam);

	isconsole = node == fbnode;

	/*
	 * The console is using the 8-bit overlay plane, while the prom
	 * will correctly report 32 bit depth.
	 * The following is an equivalent for
	 *    fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype);
	 * forcing the depth value not to be overwritten.
	 * Furthermore, the linebytes value is in fact 8192 bytes.
	 */
	sc->sc_sunfb.sf_depth = 8;
	sc->sc_sunfb.sf_width = getpropint(node, "width", 1152);
	sc->sc_sunfb.sf_height = getpropint(node, "height", 900);
	sc->sc_sunfb.sf_linebytes = 1 << ZX_BWIDTH;
	sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height << ZX_BWIDTH;

	printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_SS0,
	    round_page(sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR,
	    0, &bh) != 0) {
		printf("%s: couldn't map video memory\n", self->dv_xname);
		return;
	}
	ri->ri_bits = bus_space_vaddr(bt, bh);
	ri->ri_hw = sc;

	fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR);

 	/*
	 * Watch out! rasops_init() invoked via fbwscons_init() did not
	 * compute ri_bits correctly when centering the display, because
	 * it has been tricked with the low depth value.
	 * Recompute now.
 	 */
	ri->ri_emustride = ri->ri_emuwidth * 4;
	ri->ri_delta = ri->ri_stride - ri->ri_emustride;
	ri->ri_pelbytes = 4;
	ri->ri_xscale = ri->ri_font->fontwidth * 4;
	ri->ri_bits = ri->ri_origbits;
	ri->ri_bits += (((ri->ri_width * 4) - ri->ri_emustride) >> 1) & ~3;
	ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
	    ri->ri_stride;
	ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits)
	    / ri->ri_stride;
	ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits)
	    % ri->ri_stride) / 4);

	ri->ri_ops.copyrows = zx_copyrows;
	ri->ri_ops.copycols = zx_copycols;
	ri->ri_ops.eraserows = zx_eraserows;
	ri->ri_ops.erasecols = zx_erasecols;
	ri->ri_ops.putchar = zx_putchar;
	ri->ri_do_cursor = zx_do_cursor;

	if (isconsole) {
		/* zx_reset() below will clear screen, so restart at 1st row */
		fbwscons_console_init(&sc->sc_sunfb, 0);
	}

	/* reset cursor & frame buffer controls */
	zx_reset(sc, WSDISPLAYIO_MODE_EMUL);

	/* enable video */
	zx_burner(sc, 1, 0);

	fbwscons_attach(&sc->sc_sunfb, &zx_accessops, isconsole);
}
예제 #19
0
/*
 * Attach a display.  We need to notice if it is the console, too.
 */
static void
p9100_sbus_attach(struct device *parent, struct device *self, void *args)
{
	struct p9100_softc *sc = device_private(self);
	struct sbus_attach_args *sa = args;
	struct fbdevice *fb = &sc->sc_fb;
	int isconsole;
	int node;
	int i, j;
	uint8_t ver;

#if NWSDISPLAY > 0
	struct wsemuldisplaydev_attach_args aa;
	struct rasops_info *ri;
	unsigned long defattr;
#endif

	sc->sc_last_offset = 0xffffffff;

	/* Remember cookies for p9100_mmap() */
	sc->sc_bustag = sa->sa_bustag;
	sc->sc_ctl_paddr = sbus_bus_addr(sa->sa_bustag,
		sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base);
	sc->sc_ctl_psize = 0x8000;/*(bus_size_t)sa->sa_reg[0].oa_size;*/

	sc->sc_cmd_paddr = sbus_bus_addr(sa->sa_bustag,
		sa->sa_reg[1].oa_space, sa->sa_reg[1].oa_base);
	sc->sc_cmd_psize = (bus_size_t)sa->sa_reg[1].oa_size;

	sc->sc_fb_paddr = sbus_bus_addr(sa->sa_bustag,
		sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base);
	sc->sc_fb_psize = (bus_size_t)sa->sa_reg[2].oa_size;

	fb->fb_driver = &p9100fbdriver;
	fb->fb_device = &sc->sc_dev;
	fb->fb_flags = device_cfdata(&sc->sc_dev)->cf_flags & FB_USERMASK;
#ifdef PNOZZ_EMUL_CG3
	fb->fb_type.fb_type = FBTYPE_SUN3COLOR;
#else
	fb->fb_type.fb_type = FBTYPE_P9100;
#endif
	fb->fb_pixels = NULL;

	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;

	node = sa->sa_node;
	isconsole = fb_is_console(node);
	if (!isconsole) {
		aprint_normal("\n");
		aprint_error_dev(self, "fatal error: PROM didn't configure device\n");
		return;
	}

	/*
	 * When the ROM has mapped in a p9100 display, the address
	 * maps only the video RAM, so in any case we have to map the
	 * registers ourselves.  We only need the video RAM if we are
	 * going to print characters via rconsole.
	 */
	if (sbus_bus_map(sc->sc_bustag,
			 sa->sa_reg[0].oa_space,
			 sa->sa_reg[0].oa_base,
			 /*
			  * XXX for some reason the SBus resources don't cover
			  * all registers, so we just map what we need
			  */
			 /*sc->sc_ctl_psize*/ 0x8000,
			 /*BUS_SPACE_MAP_LINEAR*/0, &sc->sc_ctl_memh) != 0) {
		aprint_error_dev(self, "cannot map control registers\n");
		return;
	}

	if (sa->sa_npromvaddrs != 0)
		fb->fb_pixels = (void *)sa->sa_promvaddrs[0];

	if (fb->fb_pixels == NULL) {
		if (sbus_bus_map(sc->sc_bustag,
				sa->sa_reg[2].oa_space,
				sa->sa_reg[2].oa_base,
				sc->sc_fb_psize,
				BUS_SPACE_MAP_LINEAR, &sc->sc_fb_memh) != 0) {
			aprint_error_dev(self, "cannot map framebuffer\n");
			return;
		}
		fb->fb_pixels = (char *)sc->sc_fb_memh;
	} else {
		sc->sc_fb_memh = (bus_space_handle_t) fb->fb_pixels;
	}

	i = p9100_ctl_read_4(sc, 0x0004);
	switch ((i >> 26) & 7) {
	    case 5: fb->fb_type.fb_depth = 32; break;
	    case 7: fb->fb_type.fb_depth = 24; break;
	    case 3: fb->fb_type.fb_depth = 16; break;
	    case 2: fb->fb_type.fb_depth = 8; break;
	    default: {
		panic("pnozz: can't determine screen depth (0x%02x)", i);
	    }
	}
	sc->sc_depth = (fb->fb_type.fb_depth >> 3);

	/* XXX for some reason I get a kernel trap with this */
	sc->sc_width = prom_getpropint(node, "width", 800);
	sc->sc_height = prom_getpropint(node, "height", 600);

	sc->sc_stride = prom_getpropint(node, "linebytes", sc->sc_width *
	    (fb->fb_type.fb_depth >> 3));

	/* check the RAMDAC */
	ver = p9100_ramdac_read_ctl(sc, DAC_VERSION);

	p9100_init_engine(sc);

	fb_setsize_obp(fb, fb->fb_type.fb_depth, sc->sc_width, sc->sc_height,
	    node);

	sbus_establish(&sc->sc_sd, &sc->sc_dev);
	bus_intr_establish(sc->sc_bustag, sa->sa_pri, IPL_BIO,
	    p9100_intr, sc);

	fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes;
	printf(": rev %d / %x, %dx%d, depth %d mem %x",
	       (i & 7), ver, fb->fb_type.fb_width, fb->fb_type.fb_height,
	       fb->fb_type.fb_depth, (unsigned int)sc->sc_fb_psize);

	fb->fb_type.fb_cmsize = prom_getpropint(node, "cmsize", 256);
	if ((1 << fb->fb_type.fb_depth) != fb->fb_type.fb_cmsize)
		printf(", %d entry colormap", fb->fb_type.fb_cmsize);

	/* Initialize the default color map. */
	/*bt_initcmap(&sc->sc_cmap, 256);*/
	j = 0;
	for (i = 0; i < 256; i++) {
		sc->sc_cmap.cm_map[i][0] = rasops_cmap[j];
		j++;
		sc->sc_cmap.cm_map[i][1] = rasops_cmap[j];
		j++;
		sc->sc_cmap.cm_map[i][2] = rasops_cmap[j];
		j++;
	}
	p9100loadcmap(sc, 0, 256);

	/* make sure we are not blanked */
	if (isconsole)
		p9100_set_video(sc, 1);

	if (shutdownhook_establish(p9100_shutdown, sc) == NULL) {
		panic("%s: could not establish shutdown hook",
		      device_xname(&sc->sc_dev));
	}

	if (isconsole) {
		printf(" (console)\n");
#ifdef RASTERCONSOLE
		/*p9100loadcmap(sc, 255, 1);*/
		fbrcons_init(fb);
#endif
	} else
		printf("\n");

#if NWSDISPLAY > 0
	wsfont_init();

	vcons_init(&sc->vd, sc, &p9100_defscreendesc, &p9100_accessops);
	sc->vd.init_screen = p9100_init_screen;

	vcons_init_screen(&sc->vd, &p9100_console_screen, 1, &defattr);
	p9100_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;

	sc->sc_bg = (defattr >> 16) & 0xff;
	p9100_clearscreen(sc);

	ri = &p9100_console_screen.scr_ri;

	p9100_defscreendesc.nrows = ri->ri_rows;
	p9100_defscreendesc.ncols = ri->ri_cols;
	p9100_defscreendesc.textops = &ri->ri_ops;
	p9100_defscreendesc.capabilities = ri->ri_caps;

	if(isconsole) {
		wsdisplay_cnattach(&p9100_defscreendesc, ri, 0, 0, defattr);
	}

	aa.console = isconsole;
	aa.scrdata = &p9100_screenlist;
	aa.accessops = &p9100_accessops;
	aa.accesscookie = &sc->vd;

	config_found(self, &aa, wsemuldisplaydevprint);
#endif
	/* cursor sprite handling */
	p9100_init_cursor(sc);

	/* attach the fb */
	fb_attach(fb, isconsole);

	/* register with power management */
	sc->sc_video = 1;
	sc->sc_powerstate = PWR_RESUME;
	powerhook_establish(device_xname(&sc->sc_dev), p9100_power_hook, sc);

#if NTCTRL > 0
	/* register callback for external monitor status change */
	tadpole_register_callback(p9100_set_extvga, sc);
#endif
}
예제 #20
0
static void
tctrl_attach(device_t parent, device_t self, void *aux)
{
	struct tctrl_softc *sc = device_private(self);
	union obio_attach_args *uoba = aux;
	struct sbus_attach_args *sa = &uoba->uoba_sbus;
	unsigned int i, v;

	/* We're living on a sbus slot that looks like an obio that
	 * looks like an sbus slot.
	 */
	sc->sc_dev = self;
	sc->sc_memt = sa->sa_bustag;
	if (sbus_bus_map(sc->sc_memt,
			 sa->sa_slot,
			 sa->sa_offset - TS102_REG_UCTRL_INT,
			 sa->sa_size,
			 BUS_SPACE_MAP_LINEAR, &sc->sc_memh) != 0) {
		printf(": can't map registers\n");
		return;
	}

	printf("\n");

	sc->sc_tft_on = 1;

	/* clear any pending data.
	 */
	for (i = 0; i < 10000; i++) {
		if ((TS102_UCTRL_STS_RXNE_STA &
		    tctrl_read(sc, TS102_REG_UCTRL_STS)) == 0) {
			break;
		}
		v = tctrl_read(sc, TS102_REG_UCTRL_DATA);
		tctrl_write(sc, TS102_REG_UCTRL_STS, TS102_UCTRL_STS_RXNE_STA);
	}

	if (sa->sa_nintr != 0) {
		(void)bus_intr_establish(sc->sc_memt, sa->sa_pri, IPL_NONE,
					 tctrl_intr, sc);
		evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
				     device_xname(sc->sc_dev), "intr");
	}

	/* See what the external status is */
	sc->sc_ext_status = 0;
	tctrl_read_ext_status();
	if (sc->sc_ext_status != 0) {
		const char *sep;

		printf("%s: ", device_xname(sc->sc_dev));
		v = sc->sc_ext_status;
		for (i = 0, sep = ""; v != 0; i++, v >>= 1) {
			if (v & 1) {
				printf("%s%s", sep, tctrl_ext_statuses[i]);
				sep = ", ";
			}
		}
		printf("\n");
	}

	/* Get a current of the control bitport */
	tctrl_setup_bitport_nop();
	tctrl_write(sc, TS102_REG_UCTRL_INT,
		    TS102_UCTRL_INT_RXNE_REQ|TS102_UCTRL_INT_RXNE_MSK);
	sc->sc_lid = (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) == 0;
	sc->sc_power_state = PWR_RESUME;
	
	sc->sc_extvga = (sc->sc_ext_status &
	    TS102_EXT_STATUS_EXTERNAL_VGA_ATTACHED) != 0;
	sc->sc_video_callback = NULL;
	
	
	sc->sc_wantdata = 0;
	sc->sc_event_count = 0;
	sc->sc_ext_pending = 0;
		sc->sc_ext_pending = 0;

	mutex_init(&sc->sc_requestlock, MUTEX_DEFAULT, IPL_NONE);
	selinit(&sc->sc_rsel);

	/* setup sensors and register the power button */
	tctrl_sensor_setup(sc);
	tctrl_lid_state(sc);
	tctrl_ac_state(sc);

	/* initialize the LCD */
	tctrl_init_lcd();

	/* initialize sc_lcdstate */
	sc->sc_lcdstate = 0;
	sc->sc_lcdwanted = 0;
	tadpole_set_lcd(2, 0);
	
	/* fire up the LCD event thread */
	sc->sc_events = 0;

	if (kthread_create(PRI_NONE, 0, NULL, tctrl_event_thread, sc,
	    &sc->sc_thread, "%s", device_xname(sc->sc_dev)) != 0) {
		printf("%s: unable to create event kthread",
		    device_xname(sc->sc_dev));
	}
}
예제 #21
0
/*
 * Attach all the sub-devices we can find
 */
void
lebufattach(struct device *parent, struct device *self, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct lebuf_softc *sc = (void *)self;
	int node;
	int sbusburst;
	struct sparc_bus_space_tag *sbt;
	bus_space_handle_t bh;

	sc->sc_bustag = sa->sa_bustag;
	sc->sc_dmatag = sa->sa_dmatag;

	if (sbus_bus_map(sa->sa_bustag,
	    sa->sa_slot, sa->sa_offset, sa->sa_size,
	    BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("%s: attach: cannot map registers\n", self->dv_xname);
		return;
	}

	/*
	 * This device's "register space" is just a buffer where the
	 * Lance ring-buffers can be stored. Note the buffer's location
	 * and size, so the `le' driver can pick them up.
	 */
	sc->sc_buffer = (void *)bus_space_vaddr(sa->sa_bustag, bh);
	sc->sc_bufsiz = sa->sa_size;

	node = sc->sc_node = sa->sa_node;

	/*
	 * Get transfer burst size from PROM
	 */
	sbusburst = ((struct sbus_softc *)parent)->sc_burst;
	if (sbusburst == 0)
		sbusburst = SBUS_BURST_32 - 1; /* 1->16 */

	sc->sc_burst = getpropint(node, "burst-sizes", -1);
	if (sc->sc_burst == -1)
		/* take SBus burst sizes */
		sc->sc_burst = sbusburst;

	/* Clamp at parent's burst sizes */
	sc->sc_burst &= sbusburst;

	/* Allocate a bus tag */
	sbt = malloc(sizeof(*sbt), M_DEVBUF, M_NOWAIT | M_ZERO);
	if (sbt == NULL) {
		printf("%s: attach: out of memory\n", self->dv_xname);
		return;
	}

	printf(": %dK memory\n", sc->sc_bufsiz / 1024);

	sbt->cookie = sc;
	sbt->parent = sc->sc_bustag;
	sbt->asi = sbt->parent->asi;
	sbt->sasi = sbt->parent->sasi;

	/* search through children */
	for (node = firstchild(node); node; node = nextsibling(node)) {
		struct sbus_attach_args sa;
		sbus_setup_attach_args((struct sbus_softc *)parent,
		    sbt, sc->sc_dmatag, node, &sa);
		(void)config_found(&sc->sc_dev, (void *)&sa, lebufprint);
		sbus_destroy_attach_args(&sa);
	}
}
예제 #22
0
void
bppattach(struct device *parent, struct device *self, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct bpp_softc *dsc = (void *)self;
	struct lsi64854_softc *sc = &dsc->sc_lsi64854;
	int burst, sbusburst;
	int node;

	node = sa->sa_node;

	sc->sc_bustag = sa->sa_bustag;
	sc->sc_dmatag = sa->sa_dmatag;

	/* Map device registers */
	if (sa->sa_npromvaddrs != 0) {
		if (sbus_bus_map(sa->sa_bustag, 0, sa->sa_promvaddrs[0],
		    sa->sa_size,		/* ???? */
		    BUS_SPACE_MAP_PROMADDRESS, 0, &sc->sc_regs) != 0) {
			printf(": cannot map registers\n");
			return;
		}
	} else if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset,
	    sa->sa_size, 0, 0, &sc->sc_regs) != 0) {
		printf(": cannot map registers\n");
		return;
	}

	/* Check for the interrupt property */
	if (sa->sa_nintr == 0) {
		printf(": no interrupt property\n");
		return;
	}

	/*
	 * Get transfer burst size from PROM and plug it into the
	 * controller registers. This is needed on the Sun4m; do
	 * others need it too?
	 */
	sbusburst = ((struct sbus_softc *)parent)->sc_burst;
	if (sbusburst == 0)
		sbusburst = SBUS_BURST_32 - 1; /* 1->16 */

	burst = getpropint(node, "burst-sizes", -1);
	if (burst == -1)
		/* take SBus burst sizes */
		burst = sbusburst;

	/* Clamp at parent's burst sizes */
	burst &= sbusburst;
	sc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
		       (burst & SBUS_BURST_16) ? 16 : 0;

	/* Initialize the DMA channel */
	sc->sc_channel = L64854_CHANNEL_PP;
	if (lsi64854_attach(sc) != 0)
		return;

	/* Establish interrupt handler */
	sc->sc_intrchain = bppintr;
	sc->sc_intrchainarg = dsc;
	(void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_TTY, 0,
	    bppintr, sc, self->dv_xname);

	/* Allocate buffer XXX - should actually use dmamap_uio() */
	dsc->sc_bufsz = 1024;
	dsc->sc_buf = malloc(dsc->sc_bufsz, M_DEVBUF, M_NOWAIT);

	/* XXX read default state */
    {
	bus_space_handle_t h = sc->sc_regs;
	struct hwstate *hw = &dsc->sc_hwstate;
	int ack_rate = sa->sa_frequency/1000000;

	hw->hw_hcr = bus_space_read_2(sc->sc_bustag, h, L64854_REG_HCR);
	hw->hw_ocr = bus_space_read_2(sc->sc_bustag, h, L64854_REG_OCR);
	hw->hw_tcr = bus_space_read_1(sc->sc_bustag, h, L64854_REG_TCR);
	hw->hw_or = bus_space_read_1(sc->sc_bustag, h, L64854_REG_OR);

	DPRINTF(("bpp: hcr %x ocr %x tcr %x or %x\n",
		 hw->hw_hcr, hw->hw_ocr, hw->hw_tcr, hw->hw_or));
	/* Set these to sane values */
	hw->hw_hcr = ((ack_rate<<BPP_HCR_DSS_SHFT)&BPP_HCR_DSS_MASK)
		| ((ack_rate<<BPP_HCR_DSW_SHFT)&BPP_HCR_DSW_MASK);
	hw->hw_ocr |= BPP_OCR_ACK_OP;
    }
}
예제 #23
0
파일: genfb_sbus.c 프로젝트: ryo/netbsd-src
/*
 * Attach a display.  We need to notice if it is the console, too.
 */
static void
genfb_attach_sbus(device_t parent, device_t self, void *args)
{
	struct genfb_sbus_softc *sc = device_private(self);
	struct sbus_attach_args *sa = args;
	static const struct genfb_ops zero_ops;
	struct genfb_ops ops = zero_ops;
	prop_dictionary_t dict;
	bus_space_handle_t bh;
	paddr_t fbpa;
	vaddr_t fbva;
	int node = sa->sa_node;
	int isconsole;

	aprint_normal("\n");
	sc->sc_gen.sc_dev = self;
	/* Remember cookies for genfb_mmap_sbus() */
	sc->sc_tag = sa->sa_bustag;
	sc->sc_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_slot, sa->sa_offset);

	/* read geometry information from the device tree */
	sc->sc_gen.sc_width = prom_getpropint(sa->sa_node, "width", 1152);
	sc->sc_gen.sc_height = prom_getpropint(sa->sa_node, "height", 900);
	sc->sc_gen.sc_depth = prom_getpropint(sa->sa_node, "depth", 8);
	sc->sc_gen.sc_stride = prom_getpropint(sa->sa_node, "linebytes",
	    (sc->sc_gen.sc_width * sc->sc_gen.sc_depth + 7) >> 3 );
	sc->sc_gen.sc_fbsize = sc->sc_gen.sc_height * sc->sc_gen.sc_stride;
	fbva = (uint32_t)prom_getpropint(sa->sa_node, "address", 0);
	if (fbva == 0)
		panic("this fb has no address property\n");
	aprint_normal_dev(self, "%d x %d at %d bit\n",
	    sc->sc_gen.sc_width, sc->sc_gen.sc_height, sc->sc_gen.sc_depth);

	pmap_extract(pmap_kernel(), fbva, &fbpa);
	sc->sc_gen.sc_fboffset = (fbpa & 0x01ffffff) - 
	    (sc->sc_paddr & 0x01ffffff);
	aprint_normal_dev(self, "framebuffer at offset 0x%x\n",
	    (uint32_t)sc->sc_gen.sc_fboffset);

#if notyet
	if (sc->sc_gen.sc_depth <= 8) {
		/* setup some ANSIish colour map */
		char boo[256];
		snprintf(boo, 256, "\" pal!\" %x %x %x %x %x call",
		    sa->sa_node, 0, 0xa0, 0xa0, 0);
		prom_interpret(boo);
	}
#endif

	isconsole = fb_is_console(node);
	dict = device_properties(self);
	prop_dictionary_set_bool(dict, "is_console", isconsole);
	
	if (sbus_bus_map(sa->sa_bustag,
			 sa->sa_slot,
			 sa->sa_offset + sc->sc_gen.sc_fboffset,
			 sc->sc_gen.sc_fbsize,
			 BUS_SPACE_MAP_LINEAR, &bh) != 0) {
		aprint_error_dev(self, "cannot map framebuffer\n");
		return;
	}
	sc->sc_gen.sc_fbaddr = (void *)bus_space_vaddr(sa->sa_bustag, bh);

	ops.genfb_ioctl = genfb_ioctl_sbus;
	ops.genfb_mmap = genfb_mmap_sbus;

	genfb_attach(&sc->sc_gen, &ops);
}
예제 #24
0
static void
zx_attach(device_t parent, device_t self, void *args)
{
	struct zx_softc *sc;
	struct sbus_attach_args *sa;
	bus_space_handle_t bh;
	bus_space_tag_t bt;
	struct fbdevice *fb;
#if NWSDISPLAY > 0
	struct wsemuldisplaydev_attach_args aa;
	struct rasops_info *ri = &zx_console_screen.scr_ri;
	unsigned long defattr;
#endif
	int isconsole, width, height;

	sc = device_private(self);
	sc->sc_dv = self;

	sa = args;
	fb = &sc->sc_fb;
	bt = sa->sa_bustag;
	sc->sc_bt = bt;
	sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_SS0,
	    0x800000, BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE, &bh) != 0) {
		aprint_error_dev(self, "can't map bits\n");
		return;
	}
	fb->fb_pixels = (void *)bus_space_vaddr(bt, bh);
	sc->sc_pixels = (uint32_t *)fb->fb_pixels;

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LC_SS0_USR,
	    PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) {
		aprint_error_dev(self, "can't map zc\n");
		return;
	}

	sc->sc_bhzc = bh;

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS0,
	    PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) {
		aprint_error_dev(self, "can't map ld/ss0\n");
		return;
	}
	sc->sc_bhzdss0 = bh;

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS1,
	    PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) {
		aprint_error_dev(self, "can't map ld/ss1\n");
		return;
	}
	sc->sc_bhzdss1 = bh;

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CROSS,
	    PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) {
		aprint_error_dev(self, "can't map zx\n");
		return;
	}
	sc->sc_bhzx = bh;

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CURSOR,
	    PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) {
		aprint_error_dev(self, "can't map zcu\n");
		return;
	}
	sc->sc_bhzcu = bh;

	fb->fb_driver = &zx_fbdriver;
	fb->fb_device = sc->sc_dv;
	fb->fb_flags = device_cfdata(sc->sc_dv)->cf_flags & FB_USERMASK;
	fb->fb_pfour = NULL;
	fb->fb_linebytes = prom_getpropint(sa->sa_node, "linebytes", 8192);

	width = prom_getpropint(sa->sa_node, "width", 1280);
	height = prom_getpropint(sa->sa_node, "height", 1024);
	fb_setsize_obp(fb, 32, width, height, sa->sa_node);

	fb->fb_type.fb_cmsize = 256;
	fb->fb_type.fb_depth = 32;
	fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes;
	fb->fb_type.fb_type = FBTYPE_SUNLEO;

	printf(": %d x %d", fb->fb_type.fb_width, fb->fb_type.fb_height);
	isconsole = fb_is_console(sa->sa_node);
	if (isconsole)
		printf(" (console)");
	printf("\n");

	if (sa->sa_nintr != 0)
		bus_intr_establish(bt, sa->sa_pri, IPL_NONE, zx_intr, sc);

	sc->sc_cmap = malloc(768, M_DEVBUF, M_NOWAIT);
	zx_reset(sc);

#if NWSDISPLAY > 0
	sc->sc_width = fb->fb_type.fb_width;
	sc->sc_stride = 8192; /* 32 bit */
	sc->sc_height = fb->fb_type.fb_height;

	/* setup rasops and so on for wsdisplay */
	wsfont_init();
	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
	sc->sc_bg = WS_DEFAULT_BG;

	vcons_init(&sc->vd, sc, &zx_defaultscreen, &zx_accessops);
	sc->vd.init_screen = zx_init_screen;

	if (isconsole) {
		/* we mess with zx_console_screen only once */
		vcons_init_screen(&sc->vd, &zx_console_screen, 1,
		    &defattr);
		zx_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
		
		zx_defaultscreen.textops = &ri->ri_ops;
		zx_defaultscreen.capabilities = WSSCREEN_WSCOLORS;
		zx_defaultscreen.nrows = ri->ri_rows;
		zx_defaultscreen.ncols = ri->ri_cols;
		zx_fillrect(sc, 0, 0, width, height,
		     ri->ri_devcmap[defattr >> 16], ZX_STD_ROP);
		wsdisplay_cnattach(&zx_defaultscreen, ri, 0, 0, defattr);
		vcons_replay_msgbuf(&zx_console_screen);
	} else {
		/* 
		 * we're not the console so we just clear the screen and don't 
		 * set up any sort of text display
		 */
		if (zx_defaultscreen.textops == NULL) {
예제 #25
0
void    
cs4231_attach(struct device *parent, struct device *self, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct cs4231_softc *sc = (struct cs4231_softc *)self;
	int node;
	u_int32_t sbusburst, burst;

	node = sa->sa_node;

	/* Pass on the bus tags */
	sc->sc_bustag = sa->sa_bustag;
	sc->sc_dmatag = sa->sa_dmatag;

	/* Make sure things are sane. */
	if (sa->sa_nintr != 1) {
		printf(": expected 1 interrupt, got %d\n", sa->sa_nintr);
		return;
	}
	if (sa->sa_nreg != 1) {
		printf(": expected 1 register set, got %d\n",
		    sa->sa_nreg);
		return;
	}

	if (bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_AUDIO, 0,
	    cs4231_intr, sc, self->dv_xname) == NULL) {
		printf(": couldn't establish interrupt, pri %d\n",
		    INTLEV(sa->sa_pri));
		return;
	}

	if (sbus_bus_map(sa->sa_bustag,
	    sa->sa_reg[0].sbr_slot,
	    (bus_addr_t)sa->sa_reg[0].sbr_offset,
	    (bus_size_t)sa->sa_reg[0].sbr_size,
	    BUS_SPACE_MAP_LINEAR, 0, &sc->sc_regs) != 0) {
		printf(": couldn't map registers\n");
		return;
	}

	sbusburst = ((struct sbus_softc *)parent)->sc_burst;
	if (sbusburst == 0)
		sbusburst = SBUS_BURST_32 - 1;	/* 1->16 */
	burst = getpropint(node, "burst-sizes", -1);
	if (burst == -1)
		burst = sbusburst;
	sc->sc_burst = burst & sbusburst;

	printf("\n");

	audio_attach_mi(&cs4231_sa_hw_if, sc, &sc->sc_dev);

	/* Default to speaker, unmuted, reasonable volume */
	sc->sc_out_port = CSPORT_SPEAKER;
	sc->sc_in_port = CSPORT_MICROPHONE;
	sc->sc_mute[CSPORT_SPEAKER] = 1;
	sc->sc_mute[CSPORT_MONITOR] = 1;
	sc->sc_volume[CSPORT_SPEAKER].left = 192;
	sc->sc_volume[CSPORT_SPEAKER].right = 192;
}
예제 #26
0
void
spif_attach(device_t parent, device_t self, void *aux)
{
	struct spif_softc *sc = device_private(self);
	struct sbus_attach_args *sa = aux;

	sc->sc_dev = self;

	if (sa->sa_nintr != 2) {
		printf(": expected %d interrupts, got %d\n", 2, sa->sa_nintr);
		return;
	}

	if (sa->sa_nreg != 1) {
		printf(": expected %d registers, got %d\n", 1, sa->sa_nreg);
		return;
	}

	sc->sc_bustag = sa->sa_bustag;
	if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
	    sa->sa_offset, sa->sa_size,
	    0, &sc->sc_regh) != 0) {
		printf(": can't map registers\n");
		return;
	}

	if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
	    DTR_REG_OFFSET, DTR_REG_LEN, &sc->sc_dtrh) != 0) {
		printf(": can't map dtr regs\n");
		goto fail_unmapregs;
	}

	if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
	    STC_REG_OFFSET, STC_REG_LEN, &sc->sc_stch) != 0) {
		printf(": can't map dtr regs\n");
		goto fail_unmapregs;
	}

	if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
	    ISTC_REG_OFFSET, ISTC_REG_LEN, &sc->sc_istch) != 0) {
		printf(": can't map dtr regs\n");
		goto fail_unmapregs;
	}

	if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
	    PPC_REG_OFFSET, PPC_REG_LEN, &sc->sc_ppch) != 0) {
		printf(": can't map dtr regs\n");
		goto fail_unmapregs;
	}

	sc->sc_ppcih = bus_intr_establish(sa->sa_bustag,
	    sa->sa_intr[PARALLEL_INTR].oi_pri, IPL_SERIAL, spif_ppcintr, sc);
	if (sc->sc_ppcih == NULL) {
		printf(": failed to establish ppc interrupt\n");
		goto fail_unmapregs;
	}

	sc->sc_stcih = bus_intr_establish(sa->sa_bustag,
	    sa->sa_intr[SERIAL_INTR].oi_pri, IPL_SERIAL, spif_stcintr, sc);
	if (sc->sc_stcih == NULL) {
		printf(": failed to establish stc interrupt\n");
		goto fail_unmapregs;
	}

	sc->sc_softih = softint_establish(SOFTINT_SERIAL, spif_softintr, sc);
	if (sc->sc_softih == NULL) {
		printf(": can't get soft intr\n");
		goto fail_unmapregs;
	}

	sc->sc_node = sa->sa_node;

	sc->sc_rev = prom_getpropint(sc->sc_node, "revlev", 0);

	sc->sc_osc = prom_getpropint(sc->sc_node, "verosc", 0);
	switch (sc->sc_osc) {
	case SPIF_OSC10:
		sc->sc_osc = 10000000;
		break;
	case SPIF_OSC9:
	default:
		sc->sc_osc = 9830400;
		break;
	}

	sc->sc_nser = 8;
	sc->sc_npar = 1;

	sc->sc_rev2 = STC_READ(sc, STC_GFRCR);
	STC_WRITE(sc, STC_GSVR, 0);

	stty_write_ccr(sc, CD180_CCR_CMD_RESET | CD180_CCR_RESETALL);
	while (STC_READ(sc, STC_GSVR) != 0xff);
	while (STC_READ(sc, STC_GFRCR) != sc->sc_rev2);

	STC_WRITE(sc, STC_PPRH, CD180_PPRH);
	STC_WRITE(sc, STC_PPRL, CD180_PPRL);
	STC_WRITE(sc, STC_MSMR, SPIF_MSMR);
	STC_WRITE(sc, STC_TSMR, SPIF_TSMR);
	STC_WRITE(sc, STC_RSMR, SPIF_RSMR);
	STC_WRITE(sc, STC_GSVR, 0);
	STC_WRITE(sc, STC_GSCR1, 0);
	STC_WRITE(sc, STC_GSCR2, 0);
	STC_WRITE(sc, STC_GSCR3, 0);

	printf(": rev %x chiprev %x osc %sMHz\n",
	    sc->sc_rev, sc->sc_rev2, clockfreq(sc->sc_osc));

	(void)config_found(self, stty_match, NULL);
	(void)config_found(self, sbpp_match, NULL);

	return;

fail_unmapregs:
	bus_space_unmap(sa->sa_bustag, sc->sc_regh, sa->sa_size);
}
예제 #27
0
파일: mgx.c 프로젝트: sofuture/bitrig
/*
 * Attach an MGX frame buffer.
 * This will keep the frame buffer in the actual PROM mode, and attach
 * a wsdisplay child device to itself.
 */
void
mgxattach(struct device *parent, struct device *self, void *args)
{
	struct mgx_softc *sc = (struct mgx_softc *)self;
	struct sbus_attach_args *sa = args;
	bus_space_tag_t bt;
	bus_space_handle_t bh;
	int node, fbsize;
	int isconsole;
	uint16_t chipid;

	bt = sa->sa_bustag;
	node = sa->sa_node;

	printf(": %s", getpropstring(node, "model"));

	isconsole = node == fbnode;

	/* Check registers */
	if (sa->sa_nreg < MGX_NREG) {
		printf("\n%s: expected %d registers, got %d\n",
		    self->dv_xname, MGX_NREG, sa->sa_nreg);
		return;
	}

	sc->sc_bustag = bt;
	if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_CRTC].sbr_slot,
	    sa->sa_reg[MGX_REG_CRTC].sbr_offset, PAGE_SIZE,
	    BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("\n%s: couldn't map crtc registers\n", self->dv_xname);
		return;
	}
	sc->sc_vidc = (vaddr_t)bus_space_vaddr(bt, bh);

	sc->sc_bustag = bt;
	if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_ATREG].sbr_slot,
	    sa->sa_reg[MGX_REG_ATREG].sbr_offset + MGX_REG_ATREG_OFFSET,
	    MGX_REG_ATREG_SIZE, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("\n%s: couldn't map crtc registers\n", self->dv_xname);
		/* XXX unmap vidc */
		return;
	}
	sc->sc_xreg = (vaddr_t)bus_space_vaddr(bt, bh);

	/*
	 * Check the chip ID. If it's not an AT24, prefer not to access
	 * the extended registers at all.
	 */
	chipid = mgx_read_2(sc->sc_xreg, ATR_ID);
	if (chipid != ID_AT24) {
		sc->sc_xreg = (vaddr_t)0;
	}

	/* enable video */
	mgx_burner(sc, 1, 0);

	fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);

	/* Sanity check frame buffer memory */
	fbsize = getpropint(node, "fb_size", 0);
	if (fbsize != 0 && sc->sc_sunfb.sf_fbsize > fbsize) {
		printf("\n%s: expected at least %d bytes of vram, but card "
		    "only provides %d\n",
		    self->dv_xname, sc->sc_sunfb.sf_fbsize, fbsize);
		return;
	}

	/* Map the frame buffer memory area we're interested in */
	sc->sc_paddr = sbus_bus_addr(bt, sa->sa_reg[MGX_REG_VRAM8].sbr_slot,
	    sa->sa_reg[MGX_REG_VRAM8].sbr_offset);
	if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_VRAM8].sbr_slot,
	    sa->sa_reg[MGX_REG_VRAM8].sbr_offset,
	    round_page(sc->sc_sunfb.sf_fbsize),
	    BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("\n%s: couldn't map video memory\n", self->dv_xname);
		/* XXX unmap vidc and xreg */
		return;
	}
	sc->sc_sunfb.sf_ro.ri_bits = bus_space_vaddr(bt, bh);
	sc->sc_sunfb.sf_ro.ri_hw = sc;

	printf(", %dx%d\n",
	    sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);

	fbwscons_init(&sc->sc_sunfb, 0, isconsole);

	bzero(sc->sc_cmap, sizeof(sc->sc_cmap));
	fbwscons_setcolormap(&sc->sc_sunfb, mgx_setcolor);

	if (chipid != ID_AT24) {
		printf("%s: unexpected engine id %04x\n",
		    self->dv_xname, chipid);
	}

	mgx_ras_init(sc, chipid);

	if (isconsole)
		fbwscons_console_init(&sc->sc_sunfb, -1);

	fbwscons_attach(&sc->sc_sunfb, &mgx_accessops, isconsole);
}
예제 #28
0
static void
com_obio_attach(device_t parent, device_t self, void *aux)
{
	struct com_obio_softc *osc = device_private(self);
	struct com_softc *sc = &osc->osc_com;
	union obio_attach_args *uoba = aux;
	struct sbus_attach_args *sa = &uoba->uoba_sbus;
	bus_space_handle_t ioh;
	bus_space_tag_t iot;
	bus_addr_t iobase;

	sc->sc_dev = self;

	if (strcmp("modem", sa->sa_name) == 0) {
		osc->osc_tadpole = 1;
	}

	/*
	 * We're living on an obio that looks like an sbus slot.
	 */
	iot = sa->sa_bustag;
	iobase = sa->sa_offset;
	sc->sc_frequency = COM_FREQ;

	/*
	 * XXX: It would be nice to be able to split console input and
	 * output to different devices.  For now switch to serial
	 * console if PROM stdin is on serial (so that we can use DDB).
	 */
	if (prom_instance_to_package(prom_stdin()) == sa->sa_node)
		comcnattach(iot, iobase, B9600, sc->sc_frequency,
		    COM_TYPE_NORMAL, (CLOCAL | CREAD | CS8));

	if (!com_is_console(iot, iobase, &ioh) &&
	    sbus_bus_map(iot, sa->sa_slot, iobase, sa->sa_size,
			 BUS_SPACE_MAP_LINEAR, &ioh) != 0) {
		aprint_error(": can't map registers\n");
		return;
	}

	COM_INIT_REGS(sc->sc_regs, iot, ioh, iobase);

	if (osc->osc_tadpole) {
		*AUXIO4M_REG |= (AUXIO4M_LED|AUXIO4M_LTE);
		do {
			DELAY(100);
		} while (!com_probe_subr(&sc->sc_regs));
#if 0
		printf("modem: attach: lcr=0x%02x iir=0x%02x\n",
			bus_space_read_1(sc->sc_regs.iot, sc->sc_regs.ioh, 3),
			bus_space_read_1(sc->sc_regs.iot, sc->sc_regs.ioh, 2));
#endif
	}

	com_attach_subr(sc);

	if (sa->sa_nintr != 0) {
		(void)bus_intr_establish(sc->sc_regs.cr_iot, sa->sa_pri,
		    IPL_SERIAL, comintr, sc);
		evcnt_attach_dynamic(&osc->osc_intrcnt, EVCNT_TYPE_INTR, NULL,
		    device_xname(self), "intr");
	}

	if (!pmf_device_register1(self, com_suspend, com_resume, com_cleanup)) {
		aprint_error_dev(self, "could not establish shutdown hook");
	}
}
예제 #29
0
파일: cgtwelve.c 프로젝트: sofuture/bitrig
/*
 * Attach and initialize a cgtwelve.
 */
void
cgtwelveattach(struct device *parent, struct device *self, void *args)
{
	struct cgtwelve_softc *sc = (struct cgtwelve_softc *)self;
	struct sbus_attach_args *sa = args;
	bus_space_tag_t bt;
	bus_space_handle_t bh;
	int node, isconsole = 0;
	char *ps;

	bt = sa->sa_bustag;
	node = sa->sa_node;

	printf(": %s", getpropstring(node, "model"));
	ps = getpropstring(node, "dev_id");
	if (*ps != '\0')
		printf(" (%s)", ps);
	printf("\n");

	isconsole = node == fbnode;

	if (sa->sa_nreg == 0) {
		printf("%s: no SBus registers!\n", self->dv_xname);
		return;
	}

	sc->sc_bustag = bt;

	/*
	 * Map registers
	 */
	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset +
	    CG12_OFF_DPU, sizeof(struct cgtwelve_dpu),
	    BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("%s: can't map DPU registers\n", self->dv_xname);
		return;
	}
	sc->sc_dpu = bus_space_vaddr(bt, bh);
	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset +
	    CG12_OFF_APU, sizeof(struct cgtwelve_apu),
	    BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("%s: can't map APU registers\n", self->dv_xname);
		return;
	}
	sc->sc_apu = bus_space_vaddr(bt, bh);
	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset +
	    CG12_OFF_DAC, sizeof(struct cgtwelve_dac),
	    BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("%s: can't map RAMDAC registers\n", self->dv_xname);
		return;
	}
	sc->sc_ramdac = bus_space_vaddr(bt, bh);

	/*
	 * The console is using the 1-bit overlay plane, while the prom
	 * will correctly report 32 bit depth.
	 */
	fb_setsize(&sc->sc_sunfb, 1, CG12_WIDTH, CG12_HEIGHT,
	    node, 0);
	sc->sc_sunfb.sf_depth = 1;
	sc->sc_sunfb.sf_linebytes = sc->sc_sunfb.sf_width / 8;
	sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height *
	    sc->sc_sunfb.sf_linebytes;

	sc->sc_highres = sc->sc_sunfb.sf_width == CG12_WIDTH_HR;

	/*
	 * Map planes
	 */
	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset +
	    (sc->sc_highres ? CG12_OFF_OVERLAY0_HR : CG12_OFF_OVERLAY0),
	    round_page(sc->sc_highres ? CG12_SIZE_OVERLAY_HR :
	        CG12_SIZE_OVERLAY), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("%s: can't map overlay plane\n", self->dv_xname);
		return;
	}
	sc->sc_overlay = bus_space_vaddr(bt, bh);
	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset +
	    (sc->sc_highres ? CG12_OFF_INTEN_HR : CG12_OFF_INTEN),
	    round_page(sc->sc_highres ? CG12_SIZE_COLOR24_HR :
	        CG12_SIZE_COLOR24), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("%s: can't map color plane\n", self->dv_xname);
		return;
	}
	sc->sc_inten = bus_space_vaddr(bt, bh);
	sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset +
	    (sc->sc_highres ? CG12_OFF_INTEN_HR : CG12_OFF_INTEN));

	/* reset cursor & frame buffer controls */
	sc->sc_sunfb.sf_depth = 0;	/* force action */
	cgtwelve_reset(sc, 1);

	sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_overlay;
	sc->sc_sunfb.sf_ro.ri_hw = sc;
	fbwscons_init(&sc->sc_sunfb, 0, isconsole);

	if (isconsole) {
		fbwscons_console_init(&sc->sc_sunfb, -1);
		shutdownhook_establish(cgtwelve_prom, sc);
	}

	printf("%s: %dx%d", self->dv_xname,
	    sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
	ps = getpropstring(node, "ucoderev");
	if (*ps != '\0')
		printf(", microcode rev. %s", ps);
	printf("\n");

	fbwscons_attach(&sc->sc_sunfb, &cgtwelve_accessops, isconsole);
}
예제 #30
0
void
qla_sbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct qla_softc *sc = (void *)self;
	struct sbus_attach_args *sa = aux;
	struct sparc_bus_space_tag *iot;
	bus_space_handle_t ioh;
	pcireg_t id, class;
	char devinfo[256];

	if (sa->sa_nintr < 1) {
		printf(": no interrupt\n");
		return;
	}

	if (sa->sa_nreg < 1) {
		printf(": no registers\n");
		return;
	}

	/*
	 * These cards have a standard PCI chips that sit behind an
	 * FPGA with some bridging logic.  Since the PCI bus is
	 * little-endian, we need a little-endian bus tag.  So we
	 * build one here.
	 */
	iot = malloc(sizeof(*iot), M_DEVBUF, M_NOWAIT);
	if (iot == NULL) {
		printf(": can't allocate bus tag\n");
		return;
	}
	*iot = *sa->sa_bustag;
	iot->asi = ASI_PRIMARY_LITTLE;

	if (sbus_bus_map(iot, sa->sa_slot, sa->sa_offset,
	    sa->sa_size, 0, 0, &ioh) != 0) {
		printf(": can't map registers\n");
		goto free;
	}

	/*
	 * PCI config space is mapped at the start of the SBus
	 * register space.  We use it to identify the ISP chip.
	 */
	id = bus_space_read_4(iot, ioh, PCI_ID_REG);
	class = bus_space_read_4(iot, ioh, PCI_CLASS_REG);

	pci_devinfo(id, class, 0, devinfo, sizeof(devinfo));
	printf(": %s\n", devinfo);

	switch (PCI_PRODUCT(id)) {
	case PCI_PRODUCT_QLOGIC_ISP2200:
		sc->sc_isp_gen = QLA_GEN_ISP2200;
		sc->sc_isp_type = QLA_ISP2200;
		break;

	case PCI_PRODUCT_QLOGIC_ISP2300:
		sc->sc_isp_gen = QLA_GEN_ISP23XX;
		sc->sc_isp_type = QLA_ISP2300;
		break;

	case PCI_PRODUCT_QLOGIC_ISP2312:
		sc->sc_isp_gen = QLA_GEN_ISP23XX;
		sc->sc_isp_type = QLA_ISP2312;
		break;

	default:
		printf("%s: unsupported ISP chip\n", DEVNAME(sc));
		goto unmap;
	}

	if (bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_BIO, 0,
	    qla_intr, sc, sc->sc_dev.dv_xname) == NULL) {
		printf("%s: can't establish interrupt\n", DEVNAME(sc));
		goto unmap;
	}

	if (bus_space_subregion(iot, ioh, QLA_SBUS_REG_OFFSET,
	    QLA_SBUS_REG_SIZE, &sc->sc_ioh) != 0) {
		printf("%s: can't submap registers\n", DEVNAME(sc));
		goto unmap;
	}

	sc->sc_iot = iot;
	sc->sc_ios = QLA_SBUS_REG_SIZE;
	sc->sc_dmat = sa->sa_dmatag;

	qla_attach(sc);
	return;

unmap:
	bus_space_unmap(iot, ioh, sa->sa_size);
free:
	free(iot, M_DEVBUF, 0);
}