Home | History | Annotate | Line # | Download | only in dev
intio.c revision 1.1.2.2
      1 /*	$NetBSD: intio.c,v 1.1.2.2 1998/12/27 14:13:04 minoura Exp $	*/
      2 
      3 /*
      4  *
      5  * Copyright (c) 1998 NetBSD Foundation, Inc.
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *      This product includes software developed by Charles D. Cranor and
     19  *      Washington University.
     20  * 4. The name of the author may not be used to endorse or promote products
     21  *    derived from this software without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     33  */
     34 
     35 /*
     36  * NetBSD/x68k internal I/O virtual bus.
     37  */
     38 
     39 #include <sys/param.h>
     40 #include <sys/systm.h>
     41 #include <sys/device.h>
     42 #include <sys/malloc.h>
     43 #include <sys/extent.h>
     44 
     45 #include <machine/bus.h>
     46 #include <machine/cpu.h>
     47 #include <machine/frame.h>
     48 
     49 #include <arch/x68k/dev/intiovar.h>
     50 #include <arch/x68k/dev/mfp.h>
     51 
     52 
     53 /*
     54  * bus_space(9) interface
     55  */
     56 static int intio_bus_space_map __P((bus_space_tag_t, bus_addr_t, bus_size_t, int, bus_space_handle_t *));
     57 static void intio_bus_space_unmap __P((bus_space_tag_t, bus_space_handle_t, bus_size_t));
     58 static int intio_bus_space_subregion __P((bus_space_tag_t, bus_space_handle_t, bus_size_t, bus_size_t, bus_space_handle_t *));
     59 
     60 static struct x68k_bus_space intio_bus = {
     61 #if 0
     62 	X68K_INTIO_BUS,
     63 #endif
     64 	intio_bus_space_map, intio_bus_space_unmap, intio_bus_space_subregion,
     65 	x68k_bus_space_alloc, x68k_bus_space_free,
     66 #if 0
     67 	x68k_bus_space_barrier,
     68 #endif
     69 	x68k_bus_space_read_1, x68k_bus_space_read_2, x68k_bus_space_read_4,
     70 	x68k_bus_space_read_multi_1, x68k_bus_space_read_multi_2,
     71 	x68k_bus_space_read_multi_4,
     72 	x68k_bus_space_read_region_1, x68k_bus_space_read_region_2,
     73 	x68k_bus_space_read_region_4,
     74 
     75 	x68k_bus_space_write_1, x68k_bus_space_write_2, x68k_bus_space_write_4,
     76 	x68k_bus_space_write_multi_1, x68k_bus_space_write_multi_2,
     77 	x68k_bus_space_write_multi_4,
     78 	x68k_bus_space_write_region_1, x68k_bus_space_write_region_2,
     79 	x68k_bus_space_write_region_4,
     80 
     81 	x68k_bus_space_set_region_1, x68k_bus_space_set_region_2,
     82 	x68k_bus_space_set_region_4,
     83 	x68k_bus_space_copy_region_1, x68k_bus_space_copy_region_2,
     84 	x68k_bus_space_copy_region_4,
     85 
     86 	0
     87 };
     88 
     89 
     90 /*
     91  * autoconf stuff
     92  */
     93 static int intio_match __P((struct device *, struct cfdata *, void *));
     94 static void intio_attach __P((struct device *, struct device *, void *));
     95 static int intio_search __P((struct device *, struct cfdata *cf, void *));
     96 static int intio_print __P((void *, const char *));
     97 static void intio_alloc_system_ports __P((struct intio_softc*));
     98 
     99 struct cfattach intio_ca = {
    100 	sizeof(struct intio_softc), intio_match, intio_attach
    101 };
    102 
    103 static struct intio_interrupt_vector {
    104 	intio_intr_handler_t	iiv_handler;
    105 	void			*iiv_arg;
    106 } iiv[256] = {0,};
    107 
    108 extern struct cfdriver intio_cd;
    109 
    110 /* used in console initialization */
    111 extern int x68k_realconfig;
    112 int x68k_config_found __P((struct cfdata *, struct device *,
    113 			   void *, cfprint_t));
    114 static struct cfdata *cfdata_intiobus = NULL;
    115 
    116 static int
    117 intio_match(parent, cf, aux)
    118 	struct device *parent;
    119 	struct cfdata *cf;
    120 	void *aux;		/* NULL */
    121 {
    122 	if (strcmp(aux, intio_cd.cd_name) != 0)
    123 		return (0);
    124 	if (cf->cf_unit != 0)
    125 		return (0);
    126 	if (x68k_realconfig == 0)
    127 		cfdata_intiobus = cf; /* XXX */
    128 
    129 	return (1);
    130 }
    131 
    132 
    133 /* used in console initialization: configure only MFP */
    134 static struct intio_attach_args initial_ia = {
    135 	&intio_bus,
    136 	0/*XXX*/,
    137 
    138 	"mfp",			/* ia_name */
    139 	MFP_ADDR,		/* ia_addr */
    140 	MFP_INTR,		/* ia_intr */
    141 	-1,			/* ia_errintr */
    142 	-1			/* ia_dma */
    143 };
    144 
    145 static void
    146 intio_attach(parent, self, aux)
    147 	struct device *parent, *self;
    148 	void *aux;		/* NULL */
    149 {
    150 	struct intio_softc *sc = (struct intio_softc *)self;
    151 	struct intio_attach_args ia;
    152 
    153 	if (self == NULL) {
    154 		/* console only init */
    155 		x68k_config_found(cfdata_intiobus, NULL, &initial_ia, NULL);
    156 		return;
    157 	}
    158 
    159 	printf (" mapped at 0x%08p\n", intiobase);
    160 
    161 	sc->sc_map = extent_create("intiomap",
    162 				  PHYS_INTIODEV,
    163 				  PHYS_INTIODEV + 0x400000,
    164 				  M_DEVBUF, NULL, NULL, EX_NOWAIT);
    165 	intio_alloc_system_ports (sc);
    166 
    167 	sc->sc_bst = &intio_bus;
    168 	sc->sc_bst->x68k_bus_device = self;
    169 #if 0
    170 	sc->sc_dmat = &intio_dma;
    171 #endif
    172 	bzero(iiv, sizeof (struct intio_interrupt_vector) * 256);
    173 
    174 	ia.ia_bst = sc->sc_bst;
    175 	ia.ia_dmat = sc->sc_dmat;
    176 
    177 	config_search (intio_search, self, &ia);
    178 }
    179 
    180 static int
    181 intio_search(parent, cf, aux)
    182 	struct device *parent;
    183 	struct cfdata *cf;
    184 	void *aux;
    185 {
    186 	struct intio_attach_args *ia = aux;
    187 	struct intio_softc *sc = (struct intio_softc *)parent;
    188 
    189 	ia->ia_bst = sc->sc_bst;
    190 	ia->ia_dmat = sc->sc_dmat;
    191 	ia->ia_name = cf->cf_driver->cd_name;
    192 	ia->ia_addr = cf->cf_addr;
    193 	ia->ia_intr = cf->cf_intr;
    194 	ia->ia_errintr = cf->cf_errintr;
    195 	ia->ia_dma = cf->cf_dma;
    196 
    197 	if ((*cf->cf_attach->ca_match)(parent, cf, ia) > 0)
    198 		config_attach(parent, cf, ia, intio_print);
    199 
    200 	return (0);
    201 }
    202 
    203 static int
    204 intio_print(aux, name)
    205 	void *aux;
    206 	const char *name;
    207 {
    208 	struct intio_attach_args *ia = aux;
    209 
    210 /*	if (ia->ia_addr > 0)	*/
    211 		printf (" addr 0x%06x", ia->ia_addr);
    212 	if (ia->ia_intr > 0) {
    213 		printf (" interrupting at 0x%02x", ia->ia_intr);
    214 		if (ia->ia_errintr > 0)
    215 			printf (" and 0x%02x", ia->ia_errintr);
    216 	}
    217 	if (ia->ia_dma >= 0)
    218 		printf (" using DMA ch%d", ia->ia_dma);
    219 
    220 	return (QUIET);
    221 }
    222 
    223 /*
    224  * intio memory map manager
    225  */
    226 
    227 int
    228 intio_map_allocate_region(parent, ia, flag)
    229 	struct device *parent;
    230 	struct intio_attach_args *ia;
    231 	enum intio_map_flag flag; /* INTIO_MAP_TESTONLY or INTIO_MAP_ALLOCATE */
    232 {
    233 	struct intio_softc *sc = (struct intio_softc*) parent;
    234 	struct extent *map = sc->sc_map;
    235 	int r;
    236 
    237 	r = extent_alloc_region (map, ia->ia_addr, ia->ia_size, 0);
    238 #ifdef DEBUG
    239 	extent_print (map);
    240 #endif
    241 	if (r == 0) {
    242 		if (flag != INTIO_MAP_ALLOCATE)
    243 		extent_free (map, ia->ia_addr, ia->ia_size, 0);
    244 		return 0;
    245 	}
    246 
    247 	return -1;
    248 }
    249 
    250 int
    251 intio_map_free_region(parent, ia)
    252 	struct device *parent;
    253 	struct intio_attach_args *ia;
    254 {
    255 	struct intio_softc *sc = (struct intio_softc*) parent;
    256 	struct extent *map = sc->sc_map;
    257 
    258 	extent_free (map, ia->ia_addr, ia->ia_size, 0);
    259 #ifdef DEBUG
    260 	extent_print (map);
    261 #endif
    262 	return 0;
    263 }
    264 
    265 void
    266 intio_alloc_system_ports(sc)
    267 	struct intio_softc *sc;
    268 {
    269 	extent_alloc_region (sc->sc_map, INTIO_SYSPORT, 16, 0);
    270 }
    271 
    272 
    273 /*
    274  * intio bus space stuff.
    275  */
    276 static int
    277 intio_bus_space_map(t, bpa, size, flags, bshp)
    278 	bus_space_tag_t t;
    279 	bus_addr_t bpa;
    280 	bus_size_t size;
    281 	int flags;
    282 	bus_space_handle_t *bshp;
    283 {
    284 	/*
    285 	 * Intio bus is mapped permanently.
    286 	 */
    287 	*bshp = (bus_space_handle_t)
    288 	  ((u_int) bpa - PHYS_INTIODEV + intiobase);
    289 
    290 	return (0);
    291 }
    292 
    293 static void
    294 intio_bus_space_unmap(t, bsh, size)
    295 	bus_space_tag_t t;
    296 	bus_space_handle_t bsh;
    297 	bus_size_t size;
    298 {
    299 	return;
    300 }
    301 
    302 static int
    303 intio_bus_space_subregion(t, bsh, offset, size, nbshp)
    304 	bus_space_tag_t t;
    305 	bus_space_handle_t bsh;
    306 	bus_size_t offset, size;
    307 	bus_space_handle_t *nbshp;
    308 {
    309 
    310 	*nbshp = bsh + offset;
    311 	return (0);
    312 }
    313 
    314 
    315 /*
    316  * interrupt handler
    317  */
    318 int
    319 intio_intr_establish (vector, name, handler, arg)
    320 	int vector;
    321 	const char *name;	/* XXX */
    322 	intio_intr_handler_t handler;
    323 	void *arg;
    324 {
    325 	if (vector < 16)
    326 		panic ("Invalid interrupt vector");
    327 	if (iiv[vector].iiv_handler)
    328 		return EBUSY;
    329 	iiv[vector].iiv_handler = handler;
    330 	iiv[vector].iiv_arg = arg;
    331 
    332 	return 0;
    333 }
    334 
    335 int
    336 intio_intr_disestablish (vector, arg)
    337 	int vector;
    338 	void *arg;
    339 {
    340 	if (iiv[vector].iiv_handler == 0 || iiv[vector].iiv_arg != arg)
    341 		return EINVAL;
    342 	iiv[vector].iiv_handler = 0;
    343 	iiv[vector].iiv_arg = 0;
    344 
    345 	return 0;
    346 }
    347 
    348 int
    349 intio_intr (frame)
    350 	struct frame *frame;
    351 {
    352 	int vector = frame->f_vector / 4;
    353 
    354 	/* CAUTION: HERE WE ARE IN SPLHIGH() */
    355 	/* LOWER TO APPROPRIATE IPL AT VERY FIRST IN THE HANDLER!! */
    356 
    357 	if (iiv[vector].iiv_handler == 0) {
    358 		printf ("Stray interrupt: %d type %x\n", vector, frame->f_format);
    359 		return 0;
    360 	}
    361 
    362 	return (*(iiv[vector].iiv_handler)) (iiv[vector].iiv_arg);
    363 }
    364