gvpio.c revision 1.8
11.8Sis/*	$NetBSD: gvpio.c,v 1.8 2002/01/27 14:51:10 is Exp $ */
21.1Sis
31.1Sis/*
41.1Sis * Copyright (c) 1997 Ignatios Souvatzis
51.1Sis * All rights reserved.
61.1Sis *
71.1Sis * Redistribution and use in source and binary forms, with or without
81.1Sis * modification, are permitted provided that the following conditions
91.1Sis * are met:
101.1Sis * 1. Redistributions of source code must retain the above copyright
111.1Sis *    notice, this list of conditions and the following disclaimer.
121.1Sis * 2. Redistributions in binary form must reproduce the above copyright
131.1Sis *    notice, this list of conditions and the following disclaimer in the
141.1Sis *    documentation and/or other materials provided with the distribution.
151.1Sis * 3. All advertising materials mentioning features or use of this software
161.1Sis *    must display the following acknowledgement:
171.1Sis *      This product includes software developed by Ignatios Souvatzis
181.1Sis *      for the NetBSD Project.
191.1Sis * 4. The name of the author may not be used to endorse or promote products
201.1Sis *    derived from this software without specific prior written permission
211.1Sis *
221.1Sis * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
231.1Sis * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
241.1Sis * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
251.1Sis * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
261.1Sis * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
271.1Sis * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
281.1Sis * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
291.1Sis * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
301.1Sis * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
311.1Sis * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
321.1Sis */
331.1Sis
341.1Sis/*
351.1Sis * GVP I/O Extender
361.1Sis */
371.1Sis
381.1Sis#include <sys/types.h>
391.1Sis
401.1Sis#include <sys/conf.h>
411.1Sis#include <sys/device.h>
421.1Sis#include <sys/systm.h>
431.1Sis#include <sys/param.h>
441.1Sis
451.1Sis#include <machine/bus.h>
461.1Sis#include <machine/conf.h>
471.1Sis#include <machine/intr.h>
481.1Sis
491.1Sis#include <amiga/include/cpu.h>
501.1Sis
511.1Sis#include <amiga/amiga/device.h>
521.1Sis#include <amiga/amiga/drcustom.h>
531.1Sis
541.1Sis#include <amiga/dev/supio.h>
551.1Sis#include <amiga/dev/zbusvar.h>
561.1Sis#include <amiga/dev/gvpbusvar.h>
571.1Sis
581.1Sisstruct gvpio_softc {
591.1Sis	struct device sc_dev;
601.1Sis	struct bus_space_tag sc_bst;
611.1Sis	caddr_t sc_cntr;
621.1Sis	LIST_HEAD(, gvpcom_int_hdl) sc_comhdls;
631.1Sis	struct isr sc_comisr;
641.1Sis};
651.1Sis
661.7Saymericint gvpiomatch(struct device *, struct cfdata *, void *);
671.7Saymericvoid gvpioattach(struct device *, struct device *, void *);
681.7Saymericint gvpioprint(void *auxp, const char *);
691.7Saymericint gvp_com_intr(void *);
701.6Sisvoid gvp_com_intr_establish(struct device *, struct gvpcom_int_hdl *);
711.1Sis
721.1Sisstruct cfattach gvpio_ca = {
731.1Sis	sizeof(struct gvpio_softc), gvpiomatch, gvpioattach
741.1Sis};
751.1Sis
761.1Sisint
771.7Saymericgvpiomatch(struct device *parent, struct cfdata *cfp, void *auxp)
781.1Sis{
791.1Sis
801.1Sis	struct gvpbus_args *gap;
811.1Sis
821.1Sis	gap = auxp;
831.1Sis
841.1Sis	if (gap->flags & GVP_IO)
851.1Sis		return (1);
861.1Sis
871.1Sis	return (0);
881.1Sis}
891.1Sis
901.1Sisstruct gvpio_devs {
911.1Sis	char *name;
921.1Sis	int off;
931.1Sis	int arg;
941.1Sis	int ipl;
951.1Sis} gvpiodevs[] = {
961.1Sis	{ "com", 0x0b0, 115200 * 16 * 4, 6 },
971.1Sis	{ "com", 0x130, 115200 * 16 * 4, 6 },
981.1Sis	{ "lpt", 0x1b0, 0, 2 },
991.1Sis	{ 0 }
1001.1Sis};
1011.1Sis
1021.1Sisvoid
1031.7Saymericgvpioattach(struct device *parent, struct device *self, void *auxp)
1041.1Sis{
1051.1Sis	struct gvpio_softc *giosc;
1061.1Sis	struct gvpio_devs  *giosd;
1071.1Sis	struct gvpbus_args *gap;
1081.1Sis	struct supio_attach_args supa;
1091.1Sis	volatile caddr_t gbase;
1101.1Sis	u_int16_t needpsl;
1111.1Sis
1121.1Sis	giosc = (struct gvpio_softc *)self;
1131.1Sis	gap = auxp;
1141.1Sis
1151.1Sis	if (parent)
1161.1Sis		printf("\n");
1171.1Sis
1181.1Sis	gbase = gap->zargs.va;
1191.1Sis	giosc->sc_cntr = &gbase[0x41];
1201.1Sis	giosc->sc_bst.base = (u_long)gbase + 1;
1211.6Sis	giosc->sc_bst.absm = &amiga_bus_stride_2;
1221.1Sis	LIST_INIT(&giosc->sc_comhdls);
1231.1Sis	giosd = gvpiodevs;
1241.1Sis
1251.1Sis	supa.supio_iot = &giosc->sc_bst;
1261.1Sis
1271.1Sis	gbase[0x041] = 0;
1281.1Sis	gbase[0x161 + 1*2] = 0;
1291.1Sis	gbase[0x261 + 1*2] = 0;
1301.1Sis	gbase[0x361 + 2*2] = 0;
1311.1Sis	gbase[0x461] = 0xd0;
1321.1Sis
1331.1Sis	while (giosd->name) {
1341.1Sis		supa.supio_name = giosd->name;
1351.1Sis		supa.supio_iobase = giosd->off;
1361.1Sis		supa.supio_arg = giosd->arg;
1371.1Sis		supa.supio_ipl = giosd->ipl;
1381.1Sis		config_found(self, &supa, gvpioprint); /* XXX */
1391.1Sis		++giosd;
1401.1Sis	}
1411.1Sis	if (giosc->sc_comhdls.lh_first) {
1421.1Sis		/* XXX this should be really in the interupt stuff */
1431.1Sis		needpsl = PSL_S|PSL_IPL6;
1441.3Sis		if (amiga_serialspl < needpsl) {
1451.3Sis			printf("%s: raising amiga_serialspl from 0x%x to 0x%x\n",
1461.3Sis			    giosc->sc_dev.dv_xname, amiga_serialspl, needpsl);
1471.3Sis			amiga_serialspl = needpsl;
1481.1Sis		}
1491.1Sis		giosc->sc_comisr.isr_intr = gvp_com_intr;
1501.1Sis		giosc->sc_comisr.isr_arg = giosc;
1511.1Sis		giosc->sc_comisr.isr_ipl = 6;
1521.1Sis		add_isr(&giosc->sc_comisr);
1531.1Sis	}
1541.1Sis	gbase[0x041] = 0x08;
1551.1Sis}
1561.1Sis
1571.1Sisint
1581.7Saymericgvpioprint(void *auxp, const char *pnp)
1591.1Sis{
1601.1Sis	struct supio_attach_args *supa;
1611.1Sis	supa = auxp;
1621.1Sis
1631.1Sis	if (pnp == NULL)
1641.1Sis		return(QUIET);
1651.1Sis
1661.1Sis	printf("%s at %s port 0x%02x ipl %d",
1671.1Sis	    supa->supio_name, pnp, supa->supio_iobase, supa->supio_ipl);
1681.1Sis
1691.1Sis	return(UNCONF);
1701.1Sis}
1711.1Sis
1721.1Sisvoid
1731.8Sisgvp_com_intr_establish(struct device *self, struct gvpcom_int_hdl *p)
1741.1Sis{
1751.1Sis	struct gvpio_softc *sc;
1761.1Sis
1771.1Sis	sc = (struct gvpio_softc *)self;
1781.1Sis	LIST_INSERT_HEAD(&sc->sc_comhdls, p, next);
1791.1Sis
1801.1Sis}
1811.1Sis
1821.1Sisint
1831.7Saymericgvp_com_intr(void *p)
1841.1Sis{
1851.1Sis	struct gvpio_softc *sc;
1861.1Sis	struct gvpcom_int_hdl *np;
1871.1Sis	volatile caddr_t cntr;
1881.1Sis
1891.1Sis	sc = (struct gvpio_softc *)p;
1901.1Sis
1911.1Sis	cntr = sc->sc_cntr;
1921.1Sis
1931.1Sis	if (!(*cntr & 0x2))
1941.1Sis		return (0);
1951.1Sis
1961.1Sis	*cntr &= ~0xa;
1971.1Sis
1981.1Sis	for (np = sc->sc_comhdls.lh_first; np != NULL;
1991.1Sis	    np = np->next.le_next) {
2001.1Sis
2011.1Sis		(*np->f)(np->p);
2021.1Sis	}
2031.1Sis	*cntr |= 0x8;
2041.1Sis
2051.1Sis	return (1);
2061.1Sis}
207