Exemplo n.º 1
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);
}
Exemplo n.º 2
0
void    
cgsixattach(struct device *parent, struct device *self, void *aux)
{
	struct cgsix_softc *sc = (struct cgsix_softc *)self;
	struct sbus_attach_args *sa = aux;
	int node, console;
	u_int32_t fhc, rev;
	const char *nam;

	node = sa->sa_node;
	sc->sc_bustag = sa->sa_bustag;
	sc->sc_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_slot, sa->sa_offset);

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

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

	/*
	 * Map just BT, FHC, FBC, THC, and video RAM.
	 */
	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset + CGSIX_BT_OFFSET,
	    CGSIX_BT_SIZE, 0, 0, &sc->sc_bt_regs) != 0) {
		printf(": cannot map bt registers\n");
		goto fail_bt;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset + CGSIX_FHC_OFFSET,
	    CGSIX_FHC_SIZE, 0, 0, &sc->sc_fhc_regs) != 0) {
		printf(": cannot map fhc registers\n");
		goto fail_fhc;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset + CGSIX_THC_OFFSET,
	    CGSIX_THC_SIZE, 0, 0, &sc->sc_thc_regs) != 0) {
		printf(": cannot map thc registers\n");
		goto fail_thc;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset + CGSIX_VID_OFFSET,
	    sc->sc_sunfb.sf_fbsize, BUS_SPACE_MAP_LINEAR,
	    0, &sc->sc_vid_regs) != 0) {
		printf(": cannot map vid registers\n");
		goto fail_vid;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset + CGSIX_TEC_OFFSET,
	    CGSIX_TEC_SIZE, 0, 0, &sc->sc_tec_regs) != 0) {
		printf(": cannot map tec registers\n");
		goto fail_tec;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset + CGSIX_FBC_OFFSET,
	    CGSIX_FBC_SIZE, 0, 0, &sc->sc_fbc_regs) != 0) {
		printf(": cannot map fbc registers\n");
		goto fail_fbc;
	}

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

	/* if prom didn't initialize us, do it the hard way */
	if (OF_getproplen(node, "width") != sizeof(u_int32_t))
		cgsix_hardreset(sc);

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

	console = cgsix_is_console(node);

	fhc = FHC_READ(sc);
	rev = (fhc & FHC_REV_MASK) >> FHC_REV_SHIFT;
	cgsix_reset(sc, rev);

	cgsix_burner(sc, 1, 0);

	sc->sc_sunfb.sf_ro.ri_bits = (void *)bus_space_vaddr(sc->sc_bustag,
	    sc->sc_vid_regs);
	sc->sc_sunfb.sf_ro.ri_hw = sc;

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

	fbwscons_init(&sc->sc_sunfb, 0, console);
	fbwscons_setcolormap(&sc->sc_sunfb, cgsix_setcolor);

	/*
	 * Old rev. cg6 cards do not like the current acceleration code.
	 *
	 * Some hints from Sun point out at timing and cache problems, which
	 * will be investigated later.
	 */
	if (rev < 5)
		sc->sc_sunfb.sf_dev.dv_cfdata->cf_flags |= CG6_CFFLAG_NOACCEL;

	if ((sc->sc_sunfb.sf_dev.dv_cfdata->cf_flags & CG6_CFFLAG_NOACCEL)
	    == 0) {
		sc->sc_sunfb.sf_ro.ri_ops.copyrows = cgsix_ras_copyrows;
		sc->sc_sunfb.sf_ro.ri_ops.copycols = cgsix_ras_copycols;
		sc->sc_sunfb.sf_ro.ri_ops.eraserows = cgsix_ras_eraserows;
		sc->sc_sunfb.sf_ro.ri_ops.erasecols = cgsix_ras_erasecols;
		sc->sc_sunfb.sf_ro.ri_do_cursor = cgsix_ras_do_cursor;
		cgsix_ras_init(sc);
	}

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

	fbwscons_attach(&sc->sc_sunfb, &cgsix_accessops, console);

	return;

fail_fbc:
	bus_space_unmap(sa->sa_bustag, sc->sc_tec_regs, CGSIX_TEC_SIZE);
fail_tec:
	bus_space_unmap(sa->sa_bustag, sc->sc_vid_regs, sc->sc_sunfb.sf_fbsize);
fail_vid:
	bus_space_unmap(sa->sa_bustag, sc->sc_thc_regs, CGSIX_THC_SIZE);
fail_thc:
	bus_space_unmap(sa->sa_bustag, sc->sc_fhc_regs, CGSIX_FHC_SIZE);
fail_fhc:
	bus_space_unmap(sa->sa_bustag, sc->sc_bt_regs, CGSIX_BT_SIZE);
fail_bt:
fail:
	return;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
/*
 * Attach and initialize a vigra display, as well as a child wsdisplay.
 */
void
vigraattach(struct device *parent, struct device *self, void *args)
{
	struct vigra_softc *sc = (struct vigra_softc *)self;
	struct sbus_attach_args *sa = args;
	bus_space_tag_t bt;
	bus_space_handle_t bh;
	int node, row, isconsole = 0;
	char *nam;

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

	isconsole = node == fbnode;

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

	/*
	 * Check whether we are using an G300 or an G335 chip.
	 * The VS10 and VS12 use the G300, while the VS11 uses a G335.
	 */
	sc->sc_g300 = strncmp(nam, "VIGRA,vs11", strlen("VIGRA,vs11"));

	sc->sc_bustag = bt;
	if (sbus_bus_map(bt, sa->sa_reg[VIGRA_REG_CSR].sbr_slot,
	    sa->sa_reg[VIGRA_REG_CSR].sbr_offset,
	    sa->sa_reg[VIGRA_REG_CSR].sbr_size, BUS_SPACE_MAP_LINEAR, 0,
	    &bh) != 0) {
		printf("\n%s: can't map control registers\n", self->dv_xname);
		return;
	}
	sc->sc_regs = bus_space_vaddr(bt, bh);
	if (sbus_bus_map(bt, sa->sa_reg[VIGRA_REG_RAMDAC].sbr_slot,
	    sa->sa_reg[VIGRA_REG_RAMDAC].sbr_offset,
	    sa->sa_reg[VIGRA_REG_RAMDAC].sbr_size, BUS_SPACE_MAP_LINEAR, 0,
	    &bh) != 0) {
		printf("\n%s: can't map ramdac registers\n", self->dv_xname);
		return;
	}
	sc->sc_ramdac = bus_space_vaddr(bt, bh);

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

	fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);
	if (sbus_bus_map(bt, sa->sa_reg[VIGRA_REG_VRAM].sbr_slot,
	    sa->sa_reg[VIGRA_REG_VRAM].sbr_offset,
	    round_page(sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR, 0,
	    &bh) != 0) {
		printf("\n%s: can'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;
	sc->sc_paddr = sbus_bus_addr(bt, sa->sa_reg[VIGRA_REG_VRAM].sbr_slot,
	    sa->sa_reg[VIGRA_REG_VRAM].sbr_offset);

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

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

	/*
	 * If the framebuffer width is under 1024x768, we will switch from the
	 * PROM font to the more adequate 8x16 font here.
	 * However, we need to adjust two things in this case:
	 * - the display row should be overrided from the current PROM metrics,
	 *   to prevent us from overwriting the last few lines of text.
	 * - if the 80x34 screen would make a large margin appear around it,
	 *   choose to clear the screen rather than keeping old prom output in
	 *   the margins.
	 * XXX there should be a rasops "clear margins" feature
	 *
	 * Also, in 1280x1024 resolution, the PROM display is not centered
	 * vertically (why? no other frame buffer does this in such a mode!),
	 * so be lazy and clear the screen here too anyways...
	 */
	fbwscons_init(&sc->sc_sunfb, isconsole && (sc->sc_sunfb.sf_width != 800
	    && sc->sc_sunfb.sf_width != 1280) ? 0 : RI_CLEAR);
	fbwscons_setcolormap(&sc->sc_sunfb, vigra_setcolor);

	if (isconsole) {
		switch (sc->sc_sunfb.sf_width) {
		case 640:
			row = sc->sc_sunfb.sf_ro.ri_rows - 1;
			break;
		case 800:
		case 1280:
			row = 0;	/* screen has been cleared above */
			break;
		default:
			row = -1;
			break;
		}

		fbwscons_console_init(&sc->sc_sunfb, row);
	}

	fbwscons_attach(&sc->sc_sunfb, &vigra_accessops, isconsole);
}