Home | History | Annotate | Line # | Download | only in sparc
      1 /*	$NetBSD: msiiep.c,v 1.54 2025/10/04 16:11:17 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.54 2025/10/04 16:11:17 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 	devhandle_t selfh = device_handle(self);
    231 
    232 	/* pass on real mainbus_attach_args */
    233 	msa.msa_ma = ma;
    234 	KASSERT(prom_devhandle_to_node(selfh) == ma->ma_node);
    235 
    236 	/* config timer/counter part of PCIC */
    237 	msa.msa_name = "timer";
    238 	config_found(self, &msa, NULL, CFARGS_NONE);
    239 
    240 	/* config PCI tree */
    241 	msa.msa_name = "pcic";
    242 	config_found(self, &msa, NULL,
    243 	    CFARGS(.devhandle = selfh));
    244 }
    245 
    246 /* ARGSUSED */
    247 void
    248 msiiep_cpu_sleep(void)
    249 {
    250 	uint32_t reg;
    251 
    252 	if (msiiep_mid == 0)
    253 		return;
    254 	reg = *msiiep_mid;
    255 	*msiiep_mid = (reg & MID_MASK) | MID_STANDBY;
    256 }
    257 
    258 
    259 /* ======================================================================
    260  *
    261  *		      Real ms-IIep PCIC driver.
    262  */
    263 
    264 static int
    265 mspcic_match(device_t parent, cfdata_t cf, void *aux)
    266 {
    267 	struct msiiep_attach_args *msa = aux;
    268 
    269 	return (strcmp(msa->msa_name, "pcic") == 0);
    270 }
    271 
    272 
    273 static void
    274 mspcic_attach(device_t parent, device_t self, void *aux)
    275 {
    276 	struct mspcic_softc *sc = device_private(self);
    277 	devhandle_t selfh = device_handle(self);
    278 	struct msiiep_attach_args *msa = aux;
    279 	struct mainbus_attach_args *ma = msa->msa_ma;
    280 	int node = ma->ma_node;
    281 	char devinfo[256], buf[32], *model;
    282 
    283 	struct pcibus_attach_args pba;
    284 
    285 	sc->sc_node = node;
    286 	KASSERT(prom_devhandle_to_node(selfh) == node);
    287 
    288 	/* copy parent tags */
    289 	sc->sc_bustag = ma->ma_bustag;
    290 	sc->sc_dmatag = ma->ma_dmatag;
    291 
    292 	/* print our PCI device info and bus clock frequency */
    293 	pci_devinfo(mspcic_read_4(pcic_id), mspcic_read_4(pcic_class), 0,
    294 		    devinfo, sizeof(devinfo));
    295 	printf(": %s: clock = %s MHz\n", devinfo,
    296 	       clockfreq(prom_getpropint(node, "clock-frequency", 33333333)));
    297 
    298 	mspcic_init_maps();
    299 
    300 	/*
    301 	 * On Espresso, we need to adjust the interrupt mapping on
    302 	 * lines 4-7, as onboard devices and cards in the PCI slots use
    303 	 * those lines.  Note, that enabling line 5 (onboard ide) causes
    304 	 * a continuous interrupt stream, so leave that unmapped (0).
    305 	 * Any other device using line 5 can't be used.
    306 	 * Interrupt line wiring for slots is set in pci_machdep.c.
    307 	 * Set the PCI Trdy and Retry Counters to non-zero values, otherwise
    308 	 * we'll lock up when using devices behind a PCI-PCI bridge.
    309 	 */
    310 	model = prom_getpropstringA(prom_findroot(), "model", buf, sizeof(buf));
    311 	if (model != NULL && !strcmp(model, "SUNW,375-0059")) {
    312 		mspcic_write_2(pcic_intr_asgn_sel_hi, (uint16_t) 0x7502);
    313 		mspcic_write_4(pcic_cntrs, (uint32_t) 0x00808000);
    314 	}
    315 
    316 	/* init cookies/parents in our statically allocated tags */
    317 	mspcic_io_tag = *sc->sc_bustag;
    318 	mspcic_io_tag.cookie = &mspcic_io_cookie;
    319 	mspcic_io_tag.ranges = NULL;
    320 	mspcic_io_tag.nranges = 0;
    321 	mspcic_io_tag.sparc_bus_map = mspcic_bus_map;
    322 	mspcic_io_tag.sparc_bus_mmap = mspcic_bus_mmap;
    323 	mspcic_io_tag.sparc_intr_establish = mspcic_intr_establish;
    324 	mspcic_io_tag.parent = sc->sc_bustag;
    325 
    326 	mspcic_io_tag.sparc_read_2 = mspcic_bus_read_2;
    327 	mspcic_io_tag.sparc_read_4 = mspcic_bus_read_4;
    328 	mspcic_io_tag.sparc_read_8 = mspcic_bus_read_8;
    329 	mspcic_io_tag.sparc_write_2 = mspcic_bus_write_2;
    330 	mspcic_io_tag.sparc_write_4 = mspcic_bus_write_4;
    331 	mspcic_io_tag.sparc_write_8 = mspcic_bus_write_8;
    332 
    333 	mspcic_mem_tag = *sc->sc_bustag;
    334 	mspcic_mem_tag.cookie = &mspcic_mem_cookie;
    335 	mspcic_mem_tag.ranges = NULL;
    336 	mspcic_mem_tag.nranges = 0;
    337 	mspcic_mem_tag.sparc_bus_map = mspcic_bus_map;
    338 	mspcic_mem_tag.sparc_bus_mmap = mspcic_bus_mmap;
    339 	mspcic_mem_tag.sparc_intr_establish = mspcic_intr_establish;
    340 	mspcic_mem_tag.parent = sc->sc_bustag;
    341 
    342 	mspcic_mem_tag.sparc_read_2 = mspcic_bus_read_2;
    343 	mspcic_mem_tag.sparc_read_4 = mspcic_bus_read_4;
    344 	mspcic_mem_tag.sparc_read_8 = mspcic_bus_read_8;
    345 	mspcic_mem_tag.sparc_write_2 = mspcic_bus_write_2;
    346 	mspcic_mem_tag.sparc_write_4 = mspcic_bus_write_4;
    347 	mspcic_mem_tag.sparc_write_8 = mspcic_bus_write_8;
    348 
    349 	mspcic_dma_tag._cookie = sc;
    350 	mspcic_pc_tag.cookie = sc;
    351 
    352 	/* save bus tags in softc */
    353 	sc->sc_iot = &mspcic_io_tag;
    354 	sc->sc_memt = &mspcic_mem_tag;
    355 	sc->sc_dmat = &mspcic_dma_tag;
    356 
    357 	/*
    358 	 * Attach the PCI bus.
    359 	 */
    360 	pba.pba_bus = 0;
    361 	pba.pba_bridgetag = NULL;
    362 	pba.pba_iot = sc->sc_iot;
    363 	pba.pba_memt = sc->sc_memt;
    364 	pba.pba_dmat = sc->sc_dmat;
    365 	pba.pba_dmat64 = NULL;
    366 	pba.pba_pc = &mspcic_pc_tag;
    367 	pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY;
    368 
    369 	mspcic_pci_scan(sc->sc_node);
    370 
    371 	config_found(self, &pba, mspcic_print,
    372 	    CFARGS(.devhandle = selfh));
    373 }
    374 
    375 
    376 static int
    377 mspcic_print(void *args, const char *busname)
    378 {
    379 
    380 	if (busname == NULL)
    381 		return (UNCONF);
    382 	return (QUIET);
    383 }
    384 
    385 
    386 /*
    387  * Get the PIL currently assigned for this interrupt input line.
    388  */
    389 int
    390 mspcic_assigned_interrupt(int line)
    391 {
    392 	unsigned int intrmap;
    393 
    394 	if (line < 0 || line > 7)
    395 		return (-1);
    396 
    397 	if (line < 4) {
    398 		intrmap = mspcic_read_2(pcic_intr_asgn_sel);
    399 	} else {
    400 		intrmap = mspcic_read_2(pcic_intr_asgn_sel_hi);
    401 		line -= 4;
    402 	}
    403 	return ((intrmap >> (line * 4)) & 0xf);
    404 }
    405 
    406 
    407 /* ======================================================================
    408  *
    409  *			  BUS space methods
    410  */
    411 
    412 static inline void
    413 mspcic_pci_map_from_reg(struct mspcic_pci_map *m,
    414 			uint8_t sbar, uint8_t pbar, uint8_t sizemask)
    415 {
    416 	m->sysbase = 0x30000000 | ((sbar & 0x0f) << 24);
    417 	m->pcibase = pbar << 24;
    418 	m->size = ~((0xf0 | sizemask) << 24) + 1;
    419 }
    420 
    421 
    422 /* does [al, ar) and [bl, br) overlap? */
    423 #define OVERLAP(al, ar, bl, br) (((al) < (br)) && ((bl) < (ar)))
    424 
    425 /* does map "m" overlap with fixed mapping region? */
    426 #define OVERLAP_FIXED(m) OVERLAP((m)->sysbase, (m)->sysbase + (m)->size, \
    427 				0x30000000, 0x31000000)
    428 
    429 /* does map "ma" overlap map "mb" (possibly NULL)? */
    430 #define OVERLAP_MAP(ma, mb) \
    431 	((mb != NULL) && OVERLAP((ma)->sysbase, (ma)->sysbase + (ma)->size, \
    432 				 (mb)->sysbase, (mb)->sysbase + (mb)->size))
    433 
    434 /*
    435  * Init auxiliary paddr->pci maps.
    436  */
    437 static void
    438 mspcic_init_maps(void)
    439 {
    440 	struct mspcic_pci_map *m0, *m1, *io;
    441 	int nmem, nio;
    442 
    443 #ifdef DEBUG
    444 	printf("mspcic0: SMBAR0 %02x  PMBAR0 %02x  MSIZE0 %02x\n",
    445 	       mspcic_read_1(pcic_smbar0), mspcic_read_1(pcic_pmbar0),
    446 	       mspcic_read_1(pcic_msize0));
    447 	printf("mspcic0: SMBAR1 %02x  PMBAR1 %02x  MSIZE1 %02x\n",
    448 	       mspcic_read_1(pcic_smbar1), mspcic_read_1(pcic_pmbar1),
    449 	       mspcic_read_1(pcic_msize1));
    450 	printf("mspcic0: SIBAR  %02x  PIBAR  %02x  IOSIZE %02x\n",
    451 	       mspcic_read_1(pcic_sibar), mspcic_read_1(pcic_pibar),
    452 	       mspcic_read_1(pcic_iosize));
    453 #endif
    454 	nmem = nio = 1;
    455 
    456 	m0 = &mspcic_pci_memmap[nmem];
    457 	mspcic_pci_map_from_reg(m0,
    458 		mspcic_read_1(pcic_smbar0), mspcic_read_1(pcic_pmbar0),
    459 		mspcic_read_1(pcic_msize0));
    460 	if (OVERLAP_FIXED(m0))
    461 		m0 = NULL;
    462 	else
    463 		++nmem;
    464 
    465 	m1 = &mspcic_pci_memmap[nmem];
    466 	mspcic_pci_map_from_reg(m1,
    467 		mspcic_read_1(pcic_smbar1), mspcic_read_1(pcic_pmbar1),
    468 		mspcic_read_1(pcic_msize1));
    469 	if (OVERLAP_FIXED(m1) || OVERLAP_MAP(m1, m0))
    470 		m1 = NULL;
    471 	else
    472 		++nmem;
    473 
    474 	io = &mspcic_pci_iomap[nio];
    475 	mspcic_pci_map_from_reg(io,
    476 		mspcic_read_1(pcic_sibar), mspcic_read_1(pcic_pibar),
    477 		mspcic_read_1(pcic_iosize));
    478 	if (OVERLAP_FIXED(io) || OVERLAP_MAP(io, m0) || OVERLAP_MAP(io, m1))
    479 		io = NULL;
    480 	else
    481 		++nio;
    482 
    483 	mspcic_io_cookie.nmaps = nio;
    484 	mspcic_mem_cookie.nmaps = nmem;
    485 
    486 #ifdef DEBUG
    487 	mspcic_pci_map_print(&mspcic_pci_iomap[0], "i/o fixed");
    488 	mspcic_pci_map_print(&mspcic_pci_memmap[0], "mem fixed");
    489 	if (m0) mspcic_pci_map_print(m0, "mem map0");
    490 	if (m1) mspcic_pci_map_print(m1, "mem map1");
    491 	if (io) mspcic_pci_map_print(io, "i/0 map");
    492 #endif
    493 }
    494 
    495 
    496 #ifdef DEBUG
    497 static void
    498 mspcic_pci_map_print(struct mspcic_pci_map *m, const char *msg)
    499 {
    500 	printf("mspcic0: paddr [%08x..%08x] -> pci [%08x..%08x] %s\n",
    501 	       m->sysbase, m->sysbase + m->size - 1,
    502 	       m->pcibase, m->pcibase + m->size - 1,
    503 	       msg);
    504 }
    505 #endif
    506 
    507 
    508 static bus_addr_t
    509 mspcic_pci_map_find(struct mspcic_pci_map *m, int nmaps,
    510 		    bus_addr_t pciaddr, bus_size_t size)
    511 {
    512 	bus_size_t offset;
    513 	int i;
    514 
    515 	for (i = 0; i < nmaps; ++i, ++m) {
    516 		offset = pciaddr - m->pcibase;
    517 		if (offset + size <= m->size)
    518 			return (m->sysbase + offset);
    519 	}
    520 	return (0);
    521 }
    522 
    523 
    524 static int
    525 mspcic_bus_map(bus_space_tag_t t, bus_addr_t ba, bus_size_t size,
    526 	       int flags, vaddr_t va, bus_space_handle_t *hp)
    527 {
    528 	struct mspcic_cookie *c = t->cookie;
    529 	bus_addr_t paddr;
    530 
    531 	paddr = mspcic_pci_map_find(c->map, c->nmaps, ba, size);
    532 	if (paddr == 0)
    533 		return (EINVAL);
    534 	return (bus_space_map2(t->parent, paddr, size, flags, va, hp));
    535 }
    536 
    537 
    538 static paddr_t
    539 mspcic_bus_mmap(bus_space_tag_t t, bus_addr_t ba, off_t off,
    540 		int prot, int flags)
    541 {
    542 	struct mspcic_cookie *c = t->cookie;
    543 	bus_addr_t paddr;
    544 
    545 	/* verify that phys to pci mapping for the target page exists */
    546 	paddr = mspcic_pci_map_find(c->map, c->nmaps, ba + off, PAGE_SIZE);
    547 	if (paddr == 0)
    548 		return (-1);
    549 
    550 	return (bus_space_mmap(t->parent, paddr - off, off, prot, flags));
    551 }
    552 
    553 
    554 /*
    555  * Install an interrupt handler.
    556  *
    557  * Bus-specific interrupt argument is 'line', an interrupt input line
    558  * for ms-IIep.  The PIL for each line is programmable via pcic interrupt
    559  * assignment select registers (but we use existing assignments).
    560  */
    561 static void *
    562 mspcic_intr_establish(bus_space_tag_t t, int line, int ipl,
    563 		      int (*handler)(void *), void *arg,
    564 		      void (*fastvec)(void))
    565 {
    566 	struct intrhand *ih;
    567 	int pil;
    568 
    569 	ih = kmem_alloc(sizeof(*ih), KM_SLEEP);
    570 
    571 	/* use pil set-up by prom */
    572 	pil = mspcic_assigned_interrupt(line);
    573 	if (pil == -1)
    574 		panic("mspcic_intr_establish: line %d", line);
    575 
    576 	ih->ih_fun = handler;
    577 	ih->ih_arg = arg;
    578 	intr_establish(pil, ipl, ih, fastvec, false);
    579 
    580 	return(ih);
    581 }
    582 
    583 
    584 static uint16_t
    585 mspcic_bus_read_2(bus_space_tag_t space, bus_space_handle_t handle,
    586 		  bus_size_t offset)
    587 {
    588 	uint16_t val = *(volatile uint16_t *)(handle + offset);
    589 
    590 	return le16toh(val);
    591 }
    592 
    593 
    594 static uint32_t
    595 mspcic_bus_read_4(bus_space_tag_t space, bus_space_handle_t handle,
    596 		  bus_size_t offset)
    597 {
    598 	uint32_t val = *(volatile uint32_t *)(handle + offset);
    599 
    600 	return le32toh(val);
    601 }
    602 
    603 
    604 static uint64_t
    605 mspcic_bus_read_8(bus_space_tag_t space, bus_space_handle_t handle,
    606 		  bus_size_t offset)
    607 {
    608 	uint64_t val = *(volatile uint64_t *)(handle + offset);
    609 
    610 	return le64toh(val);
    611 }
    612 
    613 
    614 static void
    615 mspcic_bus_write_2(bus_space_tag_t space, bus_space_handle_t handle,
    616 		   bus_size_t offset, uint16_t value)
    617 {
    618 
    619 	(*(volatile uint16_t *)(handle + offset)) = htole16(value);
    620 }
    621 
    622 
    623 static void
    624 mspcic_bus_write_4(bus_space_tag_t space, bus_space_handle_t handle,
    625 		   bus_size_t offset, uint32_t value)
    626 {
    627 
    628 	(*(volatile uint32_t *)(handle + offset)) = htole32(value);
    629 }
    630 
    631 
    632 static void
    633 mspcic_bus_write_8(bus_space_tag_t space, bus_space_handle_t handle,
    634 		   bus_size_t offset, uint64_t value)
    635 {
    636 
    637 	(*(volatile uint64_t *)(handle + offset)) = htole64(value);
    638 }
    639 
    640 
    641 /* ======================================================================
    642  *
    643  *			     DMA methods
    644  */
    645 
    646 static int
    647 mspcic_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map,
    648 		   void *buf, bus_size_t buflen,
    649 		   struct proc *p, int flags)
    650 {
    651 	pmap_t pmap;
    652 	paddr_t pa;
    653 
    654 	if (p != NULL)
    655 		pmap = p->p_vmspace->vm_map.pmap;
    656 	else
    657 		pmap = pmap_kernel();
    658 
    659 	if (!pmap_extract(pmap, (vaddr_t)buf, &pa))
    660 		panic("mspcic_dmamap_load: dma memory not mapped");
    661 
    662 	/* we always use just one segment */
    663 	map->dm_nsegs = 1;
    664 	map->dm_segs[0].ds_addr = pa;
    665 	map->dm_segs[0].ds_len = buflen;
    666 	map->dm_mapsize = buflen;
    667 
    668 	return (0);
    669 }
    670 
    671 static void
    672 mspcic_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map)
    673 {
    674 
    675 	/* Mark the mappings as invalid. */
    676 	map->dm_mapsize = 0;
    677 	map->dm_nsegs = 0;
    678 }
    679 
    680 
    681 static int
    682 mspcic_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs,
    683 		  size_t size, void **kvap, int flags)
    684 {
    685 	struct pglist *mlist;
    686 	struct vm_page *m;
    687 	vaddr_t va;
    688 	int pagesz = PAGE_SIZE;
    689 	const uvm_flag_t kmflags =
    690 	    (flags & BUS_DMA_NOWAIT) != 0 ? UVM_KMF_NOWAIT : 0;
    691 
    692 	if (nsegs != 1)
    693 		panic("mspcic_dmamem_map: nsegs = %d", nsegs);
    694 
    695 	size = round_page(size);
    696 
    697 	va = uvm_km_alloc(kernel_map, size, 0, UVM_KMF_VAONLY | kmflags);
    698 	if (va == 0)
    699 		return (ENOMEM);
    700 
    701 	segs[0]._ds_va = va;
    702 	*kvap = (void *)va;
    703 
    704 	/*
    705 	 * Map the pages allocated in _bus_dmamem_alloc()
    706 	 * to the kernel virtual address space.
    707 	 */
    708 	mlist = segs[0]._ds_mlist;
    709 	TAILQ_FOREACH(m, mlist, pageq.queue) {
    710 		paddr_t pa;
    711 
    712 		if (size == 0)
    713 			panic("mspcic_dmamem_map: size botch");
    714 
    715 		pa = VM_PAGE_TO_PHYS(m);
    716 		pmap_kenter_pa(va,
    717 		    pa | PMAP_NC, VM_PROT_READ | VM_PROT_WRITE, 0);
    718 		va += pagesz;
    719 		size -= pagesz;
    720 	}
    721 	pmap_update(pmap_kernel());
    722 
    723 	return (0);
    724 }
    725