Home | History | Annotate | Line # | Download | only in dev
intio.c revision 1.1.2.1
      1 /*	$NetBSD: intio.c,v 1.1.2.1 1998/12/23 16:47:29 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_ADDR,		/* ia_addr */
    139 	MFP_INTR,		/* ia_intr */
    140 	-1,			/* ia_errintr */
    141 	-1			/* ia_dma */
    142 };
    143 
    144 static void
    145 intio_attach(parent, self, aux)
    146 	struct device *parent, *self;
    147 	void *aux;		/* NULL */
    148 {
    149 	struct intio_softc *sc = (struct intio_softc *)self;
    150 	struct intio_attach_args ia;
    151 
    152 	if (self == NULL) {
    153 		/* console only init */
    154 		x68k_config_found(cfdata_intiobus, NULL, &initial_ia, NULL);
    155 		return;
    156 	}
    157 
    158 	printf (" mapped at 0x%08p\n", intiobase);
    159 
    160 	sc->sc_map = extent_create("intiomap",
    161 				  PHYS_INTIODEV,
    162 				  PHYS_INTIODEV + 0x400000,
    163 				  M_DEVBUF, NULL, NULL, EX_NOWAIT);
    164 	intio_alloc_system_ports (sc);
    165 
    166 	sc->sc_bst = &intio_bus;
    167 	sc->sc_bst->x68k_bus_device = self;
    168 #if 0
    169 	sc->sc_dmat = &intio_dma;
    170 #endif
    171 	bzero(iiv, sizeof (struct intio_interrupt_vector) * 256);
    172 
    173 	ia.ia_bst = sc->sc_bst;
    174 	ia.ia_dmat = sc->sc_dmat;
    175 
    176 	config_search (intio_search, self, &ia);
    177 }
    178 
    179 static int
    180 intio_search(parent, cf, aux)
    181 	struct device *parent;
    182 	struct cfdata *cf;
    183 	void *aux;
    184 {
    185 	struct intio_attach_args *ia = aux;
    186 	struct intio_softc *sc = (struct intio_softc *)parent;
    187 
    188 	ia->ia_bst = sc->sc_bst;
    189 	ia->ia_dmat = sc->sc_dmat;
    190 	ia->ia_addr = cf->cf_addr;
    191 	ia->ia_intr = cf->cf_intr;
    192 	ia->ia_errintr = cf->cf_errintr;
    193 	ia->ia_dma = cf->cf_dma;
    194 
    195 	if ((*cf->cf_attach->ca_match)(parent, cf, ia) > 0)
    196 		config_attach(parent, cf, ia, intio_print);
    197 
    198 	return (0);
    199 }
    200 
    201 static int
    202 intio_print(aux, name)
    203 	void *aux;
    204 	const char *name;
    205 {
    206 	struct intio_attach_args *ia = aux;
    207 
    208 /*	if (ia->ia_addr > 0)	*/
    209 		printf (" addr 0x%06x", ia->ia_addr);
    210 	if (ia->ia_intr > 0) {
    211 		printf (" interrupting at 0x%02x", ia->ia_intr);
    212 		if (ia->ia_errintr > 0)
    213 			printf (" and 0x%02x", ia->ia_errintr);
    214 	}
    215 	if (ia->ia_dma >= 0)
    216 		printf (" using DMA ch%d", ia->ia_dma);
    217 
    218 	return (QUIET);
    219 }
    220 
    221 /*
    222  * intio memory map manager
    223  */
    224 
    225 int
    226 intio_map_allocate_region(parent, ia, flag)
    227 	struct device *parent;
    228 	struct intio_attach_args *ia;
    229 	enum intio_map_flag flag; /* INTIO_MAP_TESTONLY or INTIO_MAP_ALLOCATE */
    230 {
    231 	struct intio_softc *sc = (struct intio_softc*) parent;
    232 	struct extent *map = sc->sc_map;
    233 	int r;
    234 
    235 	r = extent_alloc_region (map, ia->ia_addr, ia->ia_size, 0);
    236 #ifdef DEBUG
    237 	extent_print (map);
    238 #endif
    239 	if (r == 0) {
    240 		if (flag != INTIO_MAP_ALLOCATE)
    241 		extent_free (map, ia->ia_addr, ia->ia_size, 0);
    242 		return 0;
    243 	}
    244 
    245 	return -1;
    246 }
    247 
    248 int
    249 intio_map_free_region(parent, ia)
    250 	struct device *parent;
    251 	struct intio_attach_args *ia;
    252 {
    253 	struct intio_softc *sc = (struct intio_softc*) parent;
    254 	struct extent *map = sc->sc_map;
    255 
    256 	extent_free (map, ia->ia_addr, ia->ia_size, 0);
    257 #ifdef DEBUG
    258 	extent_print (map);
    259 #endif
    260 	return 0;
    261 }
    262 
    263 void
    264 intio_alloc_system_ports(sc)
    265 	struct intio_softc *sc;
    266 {
    267 	extent_alloc_region (sc->sc_map, INTIO_SYSPORT, 16, 0);
    268 }
    269 
    270 
    271 /*
    272  * intio bus space stuff.
    273  */
    274 static int
    275 intio_bus_space_map(t, bpa, size, flags, bshp)
    276 	bus_space_tag_t t;
    277 	bus_addr_t bpa;
    278 	bus_size_t size;
    279 	int flags;
    280 	bus_space_handle_t *bshp;
    281 {
    282 	/*
    283 	 * Intio bus is mapped permanently.
    284 	 */
    285 	*bshp = (bus_space_handle_t)
    286 	  ((u_int) bpa - PHYS_INTIODEV + intiobase);
    287 
    288 	return (0);
    289 }
    290 
    291 static void
    292 intio_bus_space_unmap(t, bsh, size)
    293 	bus_space_tag_t t;
    294 	bus_space_handle_t bsh;
    295 	bus_size_t size;
    296 {
    297 	return;
    298 }
    299 
    300 static int
    301 intio_bus_space_subregion(t, bsh, offset, size, nbshp)
    302 	bus_space_tag_t t;
    303 	bus_space_handle_t bsh;
    304 	bus_size_t offset, size;
    305 	bus_space_handle_t *nbshp;
    306 {
    307 
    308 	*nbshp = bsh + offset;
    309 	return (0);
    310 }
    311 
    312 
    313 /*
    314  * interrupt handler
    315  */
    316 int
    317 intio_intr_establish (vector, name, handler, arg)
    318 	int vector;
    319 	const char *name;	/* XXX */
    320 	intio_intr_handler_t handler;
    321 	void *arg;
    322 {
    323 	if (vector < 16)
    324 		panic ("Invalid interrupt vector");
    325 	if (iiv[vector].iiv_handler)
    326 		return EBUSY;
    327 	iiv[vector].iiv_handler = handler;
    328 	iiv[vector].iiv_arg = arg;
    329 
    330 	return 0;
    331 }
    332 
    333 int
    334 intio_intr_disestablish (vector, arg)
    335 	int vector;
    336 	void *arg;
    337 {
    338 	if (iiv[vector].iiv_handler == 0 || iiv[vector].iiv_arg != arg)
    339 		return EINVAL;
    340 	iiv[vector].iiv_handler = 0;
    341 	iiv[vector].iiv_arg = 0;
    342 
    343 	return 0;
    344 }
    345 
    346 int
    347 intio_intr (frame)
    348 	struct frame *frame;
    349 {
    350 	int vector = frame->f_vector / 4;
    351 
    352 	/* CAUTION: HERE WE ARE IN SPLHIGH() */
    353 	/* LOWER TO APPROPRIATE IPL AT VERY FIRST IN THE HANDLER!! */
    354 
    355 	if (iiv[vector].iiv_handler == 0) {
    356 		printf ("Stray interrupt: %d type %x\n", vector, frame->f_format);
    357 		return 0;
    358 	}
    359 
    360 	return (*(iiv[vector].iiv_handler)) (iiv[vector].iiv_arg);
    361 }
    362