Home | History | Annotate | Line # | Download | only in sparc
      1 /*	$NetBSD: msiiep.c,v 1.53 2022/01/21 19:14:14 thorpej Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2001 Valeriy E. Ushakov
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. The name of the author may not be used to endorse or promote products
     16  *    derived from this software without specific prior written permission
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: msiiep.c,v 1.53 2022/01/21 19:14:14 thorpej Exp $");
     31 
     32 #include <sys/param.h>
     33 #include <sys/kmem.h>
     34 #include <sys/kernel.h>
     35 #include <sys/systm.h>
     36 #include <sys/device.h>
     37 
     38 #include <uvm/uvm.h>
     39 
     40 #define _SPARC_BUS_DMA_PRIVATE
     41 #include <sys/bus.h>
     42 #include <machine/autoconf.h>
     43 #include <machine/promlib.h>
     44 
     45 #include <dev/pci/pcireg.h>
     46 #include <dev/pci/pcidevs.h>
     47 #include <dev/pci/pcivar.h>
     48 
     49 #include <sparc/sparc/msiiepreg.h>
     50 #include <sparc/sparc/msiiepvar.h>
     51 #include <sparc/sparc/pci_fixup.h>
     52 
     53 /*
     54  * Autoconfiguration.
     55  *
     56  * Normally, sparc autoconfiguration is driven by PROM device tree,
     57  * however PROMs in ms-IIep machines usually don't have nodes for
     58  * various important registers that are part of ms-IIep PCI controller.
     59  * We work around by inserting a dummy device that acts as a parent
     60  * for device drivers that deal with various functions of PCIC.  The
     61  * other option is to hack mainbus_attach() to treat ms-IIep specially,
     62  * but I'd rather insulate the rest of the source from ms-IIep quirks.
     63  */
     64 
     65 /*
     66  * "Stub" ms-IIep parent that knows how to attach various functions.
     67  */
     68 static int	msiiep_match(device_t, cfdata_t, void *);
     69 static void	msiiep_attach(device_t, device_t, void *);
     70 
     71 CFATTACH_DECL_NEW(msiiep, 0, msiiep_match, msiiep_attach, NULL, NULL);
     72 
     73 
     74 /* sleep in idle spin */
     75 static void	msiiep_cpu_sleep(void);
     76 volatile uint32_t *msiiep_mid = NULL;
     77 
     78 
     79 /*
     80  * The real thing.
     81  */
     82 static int	mspcic_match(device_t, cfdata_t, void *);
     83 static void	mspcic_attach(device_t, device_t, void *);
     84 static int	mspcic_print(void *, const char *);
     85 
     86 CFATTACH_DECL_NEW(mspcic, sizeof(struct mspcic_softc),
     87     mspcic_match, mspcic_attach, NULL, NULL);
     88 
     89 
     90 /**
     91  * Only one PCI controller per MS-IIep and only one MS-IIep per system
     92  * so don't bother with malloc'ing our tags.
     93  */
     94 
     95 /*
     96  * PCI chipset tag
     97  */
     98 static struct sparc_pci_chipset mspcic_pc_tag = { NULL };
     99 
    100 
    101 /* fixed i/o and one set of i/o cycle translation registers */
    102 struct mspcic_pci_map mspcic_pci_iomap[IOMAP_SIZE] = {
    103 	{ 0x30000000, 0x0, 0x00010000 }		/* fixed i/o (decoded bits) */
    104 };
    105 
    106 /* fixed mem and two sets of mem cycle translation registers */
    107 struct mspcic_pci_map mspcic_pci_memmap[MEMMAP_SIZE] = {
    108 	{ 0x30100000, 0x00100000, 0x00f00000 }	/* fixed mem (pass through) */
    109 };
    110 
    111 struct mspcic_cookie {
    112 	struct mspcic_pci_map *map;
    113 	int nmaps;
    114 };
    115 
    116 static struct mspcic_cookie mspcic_io_cookie = { mspcic_pci_iomap, 0 };
    117 static struct mspcic_cookie mspcic_mem_cookie = { mspcic_pci_memmap, 0 };
    118 
    119 
    120 static void		mspcic_init_maps(void);
    121 static void		mspcic_pci_map_from_reg(struct mspcic_pci_map *,
    122 						uint8_t, uint8_t, uint8_t);
    123 static bus_addr_t	mspcic_pci_map_find(struct mspcic_pci_map *, int,
    124 					    bus_addr_t, bus_size_t);
    125 #ifdef DEBUG
    126 static void	mspcic_pci_map_print(struct mspcic_pci_map *, const char *);
    127 #endif
    128 
    129 
    130 static int	mspcic_bus_map(bus_space_tag_t, bus_addr_t, bus_size_t,
    131 			       int, vaddr_t, bus_space_handle_t *);
    132 static paddr_t	mspcic_bus_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int);
    133 static void	*mspcic_intr_establish(bus_space_tag_t, int, int,
    134 				       int (*)(void *), void *, void (*)(void));
    135 
    136 /* bus space methods that do byteswapping */
    137 static uint16_t	mspcic_bus_read_2(bus_space_tag_t, bus_space_handle_t,
    138 				  bus_size_t);
    139 static uint32_t	mspcic_bus_read_4(bus_space_tag_t, bus_space_handle_t,
    140 				  bus_size_t);
    141 static uint64_t	mspcic_bus_read_8(bus_space_tag_t, bus_space_handle_t,
    142 				  bus_size_t);
    143 static void	mspcic_bus_write_2(bus_space_tag_t, bus_space_handle_t,
    144 				   bus_size_t, uint16_t);
    145 static void	mspcic_bus_write_4(bus_space_tag_t, bus_space_handle_t,
    146 				   bus_size_t, uint32_t);
    147 static void	mspcic_bus_write_8(bus_space_tag_t, bus_space_handle_t,
    148 				   bus_size_t, uint64_t);
    149 
    150 static struct sparc_bus_space_tag mspcic_io_tag;
    151 static struct sparc_bus_space_tag mspcic_mem_tag;
    152 
    153 
    154 /*
    155  * DMA tag
    156  */
    157 static int	mspcic_dmamap_load(bus_dma_tag_t, bus_dmamap_t,
    158 				   void *, bus_size_t, struct proc *, int);
    159 static void	mspcic_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
    160 static int	mspcic_dmamem_map(bus_dma_tag_t, bus_dma_segment_t *,
    161 				  int, size_t, void **, int);
    162 
    163 static struct sparc_bus_dma_tag mspcic_dma_tag = {
    164 	NULL,			/* _cookie */
    165 
    166 	_bus_dmamap_create,
    167 	_bus_dmamap_destroy,
    168 	mspcic_dmamap_load,
    169 	_bus_dmamap_load_mbuf,
    170 	_bus_dmamap_load_uio,
    171 	_bus_dmamap_load_raw,
    172 	mspcic_dmamap_unload,
    173 	_bus_dmamap_sync,
    174 
    175 	_bus_dmamem_alloc,
    176 	_bus_dmamem_free,
    177 	mspcic_dmamem_map,
    178 	_bus_dmamem_unmap,
    179 	_bus_dmamem_mmap
    180 };
    181 
    182 
    183 static int
    184 msiiep_match(device_t parent, cfdata_t cf, void *aux)
    185 {
    186 	struct mainbus_attach_args *ma = aux;
    187 	pcireg_t id;
    188 
    189 	/* match by PROM name */
    190 	if (strcmp(ma->ma_name, "pci") != 0)
    191 		return (0);
    192 
    193 	/*
    194 	 * Verify that PCIC was successfully mapped by bootstrap code.
    195 	 * Since PCIC contains all the registers vital to the kernel,
    196 	 * bootstrap code maps them at a fixed va, MSIIEP_PCIC_VA
    197 	 */
    198 	id = mspcic_read_4(pcic_id);
    199 	if (PCI_VENDOR(id) != PCI_VENDOR_SUN
    200 	    && PCI_PRODUCT(id) != PCI_PRODUCT_SUN_MS_IIep)
    201 		panic("msiiep_match: id %08x", id);
    202 
    203 	return (1);
    204 }
    205 
    206 
    207 static void
    208 msiiep_attach(device_t parent, device_t self, void *aux)
    209 {
    210 	struct mainbus_attach_args *ma = aux;
    211 	struct msiiep_attach_args msa;
    212 	bus_space_handle_t hmid;
    213 	struct cpu_info *cur;
    214 
    215 	aprint_normal("\n");
    216 
    217 	if (bus_space_map(ma->ma_bustag, MSIIEP_MID_PA, 4, 0, &hmid) == 0) {
    218 #ifdef DIAGNOSTICS
    219 		uint32_t mid;
    220 
    221 		mid = bus_space_read_4(ma->ma_bustag, hmid, 0);
    222 		printf("MID: %08x\n", mid);
    223 #endif
    224 		msiiep_mid = (volatile uint32_t *)bus_space_vaddr(ma->ma_bustag,
    225 		    hmid);
    226 		cur = curcpu();
    227 		cur->idlespin = msiiep_cpu_sleep;
    228 	}
    229 
    230 	/* pass on real mainbus_attach_args */
    231 	msa.msa_ma = ma;
    232 
    233 	/* config timer/counter part of PCIC */
    234 	msa.msa_name = "timer";
    235 	config_found(self, &msa, NULL, CFARGS_NONE);
    236 
    237 	/* config PCI tree */
    238 	msa.msa_name = "pcic";
    239 	config_found(self, &msa, NULL, CFARGS_NONE);
    240 }
    241 
    242 /* ARGSUSED */
    243 void
    244 msiiep_cpu_sleep(void)
    245 {
    246 	uint32_t reg;
    247 
    248 	if (msiiep_mid == 0)
    249 		return;
    250 	reg = *msiiep_mid;
    251 	*msiiep_mid = (reg & MID_MASK) | MID_STANDBY;
    252 }
    253 
    254 
    255 /* ======================================================================
    256  *
    257  *		      Real ms-IIep PCIC driver.
    258  */
    259 
    260 static int
    261 mspcic_match(device_t parent, cfdata_t cf, void *aux)
    262 {
    263 	struct msiiep_attach_args *msa = aux;
    264 
    265 	return (strcmp(msa->msa_name, "pcic") == 0);
    266 }
    267 
    268 
    269 static void
    270 mspcic_attach(device_t parent, device_t self, void *aux)
    271 {
    272 	struct mspcic_softc *sc = device_private(self);
    273 	struct msiiep_attach_args *msa = aux;
    274 	struct mainbus_attach_args *ma = msa->msa_ma;
    275 	int node = ma->ma_node;
    276 	char devinfo[256], buf[32], *model;
    277 
    278 	struct pcibus_attach_args pba;
    279 
    280 	sc->sc_node = node;
    281 
    282 	/* copy parent tags */
    283 	sc->sc_bustag = ma->ma_bustag;
    284 	sc->sc_dmatag = ma->ma_dmatag;
    285 
    286 	/* print our PCI device info and bus clock frequency */
    287 	pci_devinfo(mspcic_read_4(pcic_id), mspcic_read_4(pcic_class), 0,
    288 		    devinfo, sizeof(devinfo));
    289 	printf(": %s: clock = %s MHz\n", devinfo,
    290 	       clockfreq(prom_getpropint(node, "clock-frequency", 33333333)));
    291 
    292 	mspcic_init_maps();
    293 
    294 	/*
    295 	 * On Espresso, we need to adjust the interrupt mapping on
    296 	 * lines 4-7, as onboard devices and cards in the PCI slots use
    297 	 * those lines.  Note, that enabling line 5 (onboard ide) causes
    298 	 * a continuous interrupt stream, so leave that unmapped (0).
    299 	 * Any other device using line 5 can't be used.
    300 	 * Interrupt line wiring for slots is set in pci_machdep.c.
    301 	 * Set the PCI Trdy and Retry Counters to non-zero values, otherwise
    302 	 * we'll lock up when using devices behind a PCI-PCI bridge.
    303 	 */
    304 	model = prom_getpropstringA(prom_findroot(), "model", buf, sizeof(buf));
    305 	if (model != NULL && !strcmp(model, "SUNW,375-0059")) {
    306 		mspcic_write_2(pcic_intr_asgn_sel_hi, (uint16_t) 0x7502);
    307 		mspcic_write_4(pcic_cntrs, (uint32_t) 0x00808000);
    308 	}
    309 
    310 	/* init cookies/parents in our statically allocated tags */
    311 	mspcic_io_tag = *sc->sc_bustag;
    312 	mspcic_io_tag.cookie = &mspcic_io_cookie;
    313 	mspcic_io_tag.ranges = NULL;
    314 	mspcic_io_tag.nranges = 0;
    315 	mspcic_io_tag.sparc_bus_map = mspcic_bus_map;
    316 	mspcic_io_tag.sparc_bus_mmap = mspcic_bus_mmap;
    317 	mspcic_io_tag.sparc_intr_establish = mspcic_intr_establish;
    318 	mspcic_io_tag.parent = sc->sc_bustag;
    319 
    320 	mspcic_io_tag.sparc_read_2 = mspcic_bus_read_2;
    321 	mspcic_io_tag.sparc_read_4 = mspcic_bus_read_4;
    322 	mspcic_io_tag.sparc_read_8 = mspcic_bus_read_8;
    323 	mspcic_io_tag.sparc_write_2 = mspcic_bus_write_2;
    324 	mspcic_io_tag.sparc_write_4 = mspcic_bus_write_4;
    325 	mspcic_io_tag.sparc_write_8 = mspcic_bus_write_8;
    326 
    327 	mspcic_mem_tag = *sc->sc_bustag;
    328 	mspcic_mem_tag.cookie = &mspcic_mem_cookie;
    329 	mspcic_mem_tag.ranges = NULL;
    330 	mspcic_mem_tag.nranges = 0;
    331 	mspcic_mem_tag.sparc_bus_map = mspcic_bus_map;
    332 	mspcic_mem_tag.sparc_bus_mmap = mspcic_bus_mmap;
    333 	mspcic_mem_tag.sparc_intr_establish = mspcic_intr_establish;
    334 	mspcic_mem_tag.parent = sc->sc_bustag;
    335 
    336 	mspcic_mem_tag.sparc_read_2 = mspcic_bus_read_2;
    337 	mspcic_mem_tag.sparc_read_4 = mspcic_bus_read_4;
    338 	mspcic_mem_tag.sparc_read_8 = mspcic_bus_read_8;
    339 	mspcic_mem_tag.sparc_write_2 = mspcic_bus_write_2;
    340 	mspcic_mem_tag.sparc_write_4 = mspcic_bus_write_4;
    341 	mspcic_mem_tag.sparc_write_8 = mspcic_bus_write_8;
    342 
    343 	mspcic_dma_tag._cookie = sc;
    344 	mspcic_pc_tag.cookie = sc;
    345 
    346 	/* save bus tags in softc */
    347 	sc->sc_iot = &mspcic_io_tag;
    348 	sc->sc_memt = &mspcic_mem_tag;
    349 	sc->sc_dmat = &mspcic_dma_tag;
    350 
    351 	/*
    352 	 * Attach the PCI bus.
    353 	 */
    354 	pba.pba_bus = 0;
    355 	pba.pba_bridgetag = NULL;
    356 	pba.pba_iot = sc->sc_iot;
    357 	pba.pba_memt = sc->sc_memt;
    358 	pba.pba_dmat = sc->sc_dmat;
    359 	pba.pba_dmat64 = NULL;
    360 	pba.pba_pc = &mspcic_pc_tag;
    361 	pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY;
    362 
    363 	mspcic_pci_scan(sc->sc_node);
    364 
    365 	config_found(self, &pba, mspcic_print,
    366 	    CFARGS(.devhandle = device_handle(self)));
    367 }
    368 
    369 
    370 static int
    371 mspcic_print(void *args, const char *busname)
    372 {
    373 
    374 	if (busname == NULL)
    375 		return (UNCONF);
    376 	return (QUIET);
    377 }
    378 
    379 
    380 /*
    381  * Get the PIL currently assigned for this interrupt input line.
    382  */
    383 int
    384 mspcic_assigned_interrupt(int line)
    385 {
    386 	unsigned int intrmap;
    387 
    388 	if (line < 0 || line > 7)
    389 		return (-1);
    390 
    391 	if (line < 4) {
    392 		intrmap = mspcic_read_2(pcic_intr_asgn_sel);
    393 	} else {
    394 		intrmap = mspcic_read_2(pcic_intr_asgn_sel_hi);
    395 		line -= 4;
    396 	}
    397 	return ((intrmap >> (line * 4)) & 0xf);
    398 }
    399 
    400 
    401 /* ======================================================================
    402  *
    403  *			  BUS space methods
    404  */
    405 
    406 static inline void
    407 mspcic_pci_map_from_reg(struct mspcic_pci_map *m,
    408 			uint8_t sbar, uint8_t pbar, uint8_t sizemask)
    409 {
    410 	m->sysbase = 0x30000000 | ((sbar & 0x0f) << 24);
    411 	m->pcibase = pbar << 24;
    412 	m->size = ~((0xf0 | sizemask) << 24) + 1;
    413 }
    414 
    415 
    416 /* does [al, ar) and [bl, br) overlap? */
    417 #define OVERLAP(al, ar, bl, br) (((al) < (br)) && ((bl) < (ar)))
    418 
    419 /* does map "m" overlap with fixed mapping region? */
    420 #define OVERLAP_FIXED(m) OVERLAP((m)->sysbase, (m)->sysbase + (m)->size, \
    421 				0x30000000, 0x31000000)
    422 
    423 /* does map "ma" overlap map "mb" (possibly NULL)? */
    424 #define OVERLAP_MAP(ma, mb) \
    425 	((mb != NULL) && OVERLAP((ma)->sysbase, (ma)->sysbase + (ma)->size, \
    426 				 (mb)->sysbase, (mb)->sysbase + (mb)->size))
    427 
    428 /*
    429  * Init auxiliary paddr->pci maps.
    430  */
    431 static void
    432 mspcic_init_maps(void)
    433 {
    434 	struct mspcic_pci_map *m0, *m1, *io;
    435 	int nmem, nio;
    436 
    437 #ifdef DEBUG
    438 	printf("mspcic0: SMBAR0 %02x  PMBAR0 %02x  MSIZE0 %02x\n",
    439 	       mspcic_read_1(pcic_smbar0), mspcic_read_1(pcic_pmbar0),
    440 	       mspcic_read_1(pcic_msize0));
    441 	printf("mspcic0: SMBAR1 %02x  PMBAR1 %02x  MSIZE1 %02x\n",
    442 	       mspcic_read_1(pcic_smbar1), mspcic_read_1(pcic_pmbar1),
    443 	       mspcic_read_1(pcic_msize1));
    444 	printf("mspcic0: SIBAR  %02x  PIBAR  %02x  IOSIZE %02x\n",
    445 	       mspcic_read_1(pcic_sibar), mspcic_read_1(pcic_pibar),
    446 	       mspcic_read_1(pcic_iosize));
    447 #endif
    448 	nmem = nio = 1;
    449 
    450 	m0 = &mspcic_pci_memmap[nmem];
    451 	mspcic_pci_map_from_reg(m0,
    452 		mspcic_read_1(pcic_smbar0), mspcic_read_1(pcic_pmbar0),
    453 		mspcic_read_1(pcic_msize0));
    454 	if (OVERLAP_FIXED(m0))
    455 		m0 = NULL;
    456 	else
    457 		++nmem;
    458 
    459 	m1 = &mspcic_pci_memmap[nmem];
    460 	mspcic_pci_map_from_reg(m1,
    461 		mspcic_read_1(pcic_smbar1), mspcic_read_1(pcic_pmbar1),
    462 		mspcic_read_1(pcic_msize1));
    463 	if (OVERLAP_FIXED(m1) || OVERLAP_MAP(m1, m0))
    464 		m1 = NULL;
    465 	else
    466 		++nmem;
    467 
    468 	io = &mspcic_pci_iomap[nio];
    469 	mspcic_pci_map_from_reg(io,
    470 		mspcic_read_1(pcic_sibar), mspcic_read_1(pcic_pibar),
    471 		mspcic_read_1(pcic_iosize));
    472 	if (OVERLAP_FIXED(io) || OVERLAP_MAP(io, m0) || OVERLAP_MAP(io, m1))
    473 		io = NULL;
    474 	else
    475 		++nio;
    476 
    477 	mspcic_io_cookie.nmaps = nio;
    478 	mspcic_mem_cookie.nmaps = nmem;
    479 
    480 #ifdef DEBUG
    481 	mspcic_pci_map_print(&mspcic_pci_iomap[0], "i/o fixed");
    482 	mspcic_pci_map_print(&mspcic_pci_memmap[0], "mem fixed");
    483 	if (m0) mspcic_pci_map_print(m0, "mem map0");
    484 	if (m1) mspcic_pci_map_print(m1, "mem map1");
    485 	if (io) mspcic_pci_map_print(io, "i/0 map");
    486 #endif
    487 }
    488 
    489 
    490 #ifdef DEBUG
    491 static void
    492 mspcic_pci_map_print(struct mspcic_pci_map *m, const char *msg)
    493 {
    494 	printf("mspcic0: paddr [%08x..%08x] -> pci [%08x..%08x] %s\n",
    495 	       m->sysbase, m->sysbase + m->size - 1,
    496 	       m->pcibase, m->pcibase + m->size - 1,
    497 	       msg);
    498 }
    499 #endif
    500 
    501 
    502 static bus_addr_t
    503 mspcic_pci_map_find(struct mspcic_pci_map *m, int nmaps,
    504 		    bus_addr_t pciaddr, bus_size_t size)
    505 {
    506 	bus_size_t offset;
    507 	int i;
    508 
    509 	for (i = 0; i < nmaps; ++i, ++m) {
    510 		offset = pciaddr - m->pcibase;
    511 		if (offset + size <= m->size)
    512 			return (m->sysbase + offset);
    513 	}
    514 	return (0);
    515 }
    516 
    517 
    518 static int
    519 mspcic_bus_map(bus_space_tag_t t, bus_addr_t ba, bus_size_t size,
    520 	       int flags, vaddr_t va, bus_space_handle_t *hp)
    521 {
    522 	struct mspcic_cookie *c = t->cookie;
    523 	bus_addr_t paddr;
    524 
    525 	paddr = mspcic_pci_map_find(c->map, c->nmaps, ba, size);
    526 	if (paddr == 0)
    527 		return (EINVAL);
    528 	return (bus_space_map2(t->parent, paddr, size, flags, va, hp));
    529 }
    530 
    531 
    532 static paddr_t
    533 mspcic_bus_mmap(bus_space_tag_t t, bus_addr_t ba, off_t off,
    534 		int prot, int flags)
    535 {
    536 	struct mspcic_cookie *c = t->cookie;
    537 	bus_addr_t paddr;
    538 
    539 	/* verify that phys to pci mapping for the target page exists */
    540 	paddr = mspcic_pci_map_find(c->map, c->nmaps, ba + off, PAGE_SIZE);
    541 	if (paddr == 0)
    542 		return (-1);
    543 
    544 	return (bus_space_mmap(t->parent, paddr - off, off, prot, flags));
    545 }
    546 
    547 
    548 /*
    549  * Install an interrupt handler.
    550  *
    551  * Bus-specific interrupt argument is 'line', an interrupt input line
    552  * for ms-IIep.  The PIL for each line is programmable via pcic interrupt
    553  * assignment select registers (but we use existing assignments).
    554  */
    555 static void *
    556 mspcic_intr_establish(bus_space_tag_t t, int line, int ipl,
    557 		      int (*handler)(void *), void *arg,
    558 		      void (*fastvec)(void))
    559 {
    560 	struct intrhand *ih;
    561 	int pil;
    562 
    563 	ih = kmem_alloc(sizeof(*ih), KM_SLEEP);
    564 
    565 	/* use pil set-up by prom */
    566 	pil = mspcic_assigned_interrupt(line);
    567 	if (pil == -1)
    568 		panic("mspcic_intr_establish: line %d", line);
    569 
    570 	ih->ih_fun = handler;
    571 	ih->ih_arg = arg;
    572 	intr_establish(pil, ipl, ih, fastvec, false);
    573 
    574 	return(ih);
    575 }
    576 
    577 
    578 static uint16_t
    579 mspcic_bus_read_2(bus_space_tag_t space, bus_space_handle_t handle,
    580 		  bus_size_t offset)
    581 {
    582 	uint16_t val = *(volatile uint16_t *)(handle + offset);
    583 
    584 	return le16toh(val);
    585 }
    586 
    587 
    588 static uint32_t
    589 mspcic_bus_read_4(bus_space_tag_t space, bus_space_handle_t handle,
    590 		  bus_size_t offset)
    591 {
    592 	uint32_t val = *(volatile uint32_t *)(handle + offset);
    593 
    594 	return le32toh(val);
    595 }
    596 
    597 
    598 static uint64_t
    599 mspcic_bus_read_8(bus_space_tag_t space, bus_space_handle_t handle,
    600 		  bus_size_t offset)
    601 {
    602 	uint64_t val = *(volatile uint64_t *)(handle + offset);
    603 
    604 	return le64toh(val);
    605 }
    606 
    607 
    608 static void
    609 mspcic_bus_write_2(bus_space_tag_t space, bus_space_handle_t handle,
    610 		   bus_size_t offset, uint16_t value)
    611 {
    612 
    613 	(*(volatile uint16_t *)(handle + offset)) = htole16(value);
    614 }
    615 
    616 
    617 static void
    618 mspcic_bus_write_4(bus_space_tag_t space, bus_space_handle_t handle,
    619 		   bus_size_t offset, uint32_t value)
    620 {
    621 
    622 	(*(volatile uint32_t *)(handle + offset)) = htole32(value);
    623 }
    624 
    625 
    626 static void
    627 mspcic_bus_write_8(bus_space_tag_t space, bus_space_handle_t handle,
    628 		   bus_size_t offset, uint64_t value)
    629 {
    630 
    631 	(*(volatile uint64_t *)(handle + offset)) = htole64(value);
    632 }
    633 
    634 
    635 /* ======================================================================
    636  *
    637  *			     DMA methods
    638  */
    639 
    640 static int
    641 mspcic_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map,
    642 		   void *buf, bus_size_t buflen,
    643 		   struct proc *p, int flags)
    644 {
    645 	pmap_t pmap;
    646 	paddr_t pa;
    647 
    648 	if (p != NULL)
    649 		pmap = p->p_vmspace->vm_map.pmap;
    650 	else
    651 		pmap = pmap_kernel();
    652 
    653 	if (!pmap_extract(pmap, (vaddr_t)buf, &pa))
    654 		panic("mspcic_dmamap_load: dma memory not mapped");
    655 
    656 	/* we always use just one segment */
    657 	map->dm_nsegs = 1;
    658 	map->dm_segs[0].ds_addr = pa;
    659 	map->dm_segs[0].ds_len = buflen;
    660 	map->dm_mapsize = buflen;
    661 
    662 	return (0);
    663 }
    664 
    665 static void
    666 mspcic_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map)
    667 {
    668 
    669 	/* Mark the mappings as invalid. */
    670 	map->dm_mapsize = 0;
    671 	map->dm_nsegs = 0;
    672 }
    673 
    674 
    675 static int
    676 mspcic_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs,
    677 		  size_t size, void **kvap, int flags)
    678 {
    679 	struct pglist *mlist;
    680 	struct vm_page *m;
    681 	vaddr_t va;
    682 	int pagesz = PAGE_SIZE;
    683 	const uvm_flag_t kmflags =
    684 	    (flags & BUS_DMA_NOWAIT) != 0 ? UVM_KMF_NOWAIT : 0;
    685 
    686 	if (nsegs != 1)
    687 		panic("mspcic_dmamem_map: nsegs = %d", nsegs);
    688 
    689 	size = round_page(size);
    690 
    691 	va = uvm_km_alloc(kernel_map, size, 0, UVM_KMF_VAONLY | kmflags);
    692 	if (va == 0)
    693 		return (ENOMEM);
    694 
    695 	segs[0]._ds_va = va;
    696 	*kvap = (void *)va;
    697 
    698 	/*
    699 	 * Map the pages allocated in _bus_dmamem_alloc()
    700 	 * to the kernel virtual address space.
    701 	 */
    702 	mlist = segs[0]._ds_mlist;
    703 	TAILQ_FOREACH(m, mlist, pageq.queue) {
    704 		paddr_t pa;
    705 
    706 		if (size == 0)
    707 			panic("mspcic_dmamem_map: size botch");
    708 
    709 		pa = VM_PAGE_TO_PHYS(m);
    710 		pmap_kenter_pa(va,
    711 		    pa | PMAP_NC, VM_PROT_READ | VM_PROT_WRITE, 0);
    712 		va += pagesz;
    713 		size -= pagesz;
    714 	}
    715 	pmap_update(pmap_kernel());
    716 
    717 	return (0);
    718 }
    719