xref: /netbsd/sys/arch/sparc/sparc/msiiep.c (revision bf9ec67e)
1 /*	$NetBSD: msiiep.c,v 1.9 2002/05/16 01:01:40 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.9 2002/05/16 01:01:40 thorpej Exp $");
31 
32 #include <sys/param.h>
33 #include <sys/malloc.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 <machine/bus.h>
42 #include <machine/autoconf.h>
43 #include <machine/promlib.h>
44 #include <machine/idprom.h>
45 
46 #include <dev/pci/pcireg.h>
47 #include <dev/pci/pcidevs.h>
48 #include <dev/pci/pcivar.h>
49 
50 #include <sparc/sparc/msiiepreg.h>
51 #include <sparc/sparc/msiiepvar.h>
52 
53 
54 /*
55  * Autoconfiguration.
56  *
57  * Normally, sparc autoconfiguration is driven by PROM device tree,
58  * however PROMs in ms-IIep machines usually don't have nodes for
59  * various important registers that are part of ms-IIep PCI controller.
60  * We work around by inserting a dummy device that acts as a parent
61  * for device drivers that deal with various functions of PCIC.  The
62  * other option is to hack mainbus_attach() to treat ms-IIep specially,
63  * but I'd rather insulate the rest of the source from ms-IIep quirks.
64  */
65 
66 /* parent "stub" device that knows how to attach various functions */
67 static int	msiiep_match(struct device *, struct cfdata *, void *);
68 static void	msiiep_attach(struct device *, struct device *, void *);
69 /* static int	msiiep_print(void *, const char *); */
70 
71 struct cfattach msiiep_ca = {
72 	sizeof(struct device), msiiep_match, msiiep_attach
73 };
74 
75 static struct idprom	msiiep_idprom_store;
76 static void		msiiep_getidprom(void);
77 
78 
79 /*
80  * The real thing.
81  */
82 static int	mspcic_match(struct device *, struct cfdata *, void *);
83 static void	mspcic_attach(struct device *, struct device *, void *);
84 static int	mspcic_print(void *, const char *);
85 
86 struct cfattach mspcic_ca = {
87 	sizeof(struct mspcic_softc), mspcic_match, mspcic_attach
88 };
89 
90 
91 /**
92  * ms-IIep PCIC registers are mapped at fixed VA
93  */
94 #define mspcic ((volatile struct msiiep_pcic_reg *)MSIIEP_PCIC_VA)
95 
96 
97 /**
98  * Only one PCI controller per MS-IIep and only one MS-IIep per system
99  * so don't bother with malloc'ing our tags.
100  */
101 
102 /*
103  * PCI chipset tag
104  */
105 static struct sparc_pci_chipset mspcic_pc_tag = { NULL };
106 
107 
108 /*
109  * Bus space tags for memory and i/o.
110  */
111 
112 struct mspcic_pci_map {
113 	u_int32_t sysbase;
114 	u_int32_t pcibase;
115 	u_int32_t size;
116 };
117 
118 /* fixed i/o and one set of i/o cycle translation registers */
119 static struct mspcic_pci_map mspcic_pci_iomap[2] = {
120 	{ 0x30000000, 0x0, 0x00010000 }		/* fixed i/o (decoded bits) */
121 };
122 
123 /* fixed mem and two sets of mem cycle translation registers */
124 static struct mspcic_pci_map mspcic_pci_memmap[3] = {
125 	{ 0x30100000, 0x30100000, 0x00f00000 }	/* fixed mem (pass through) */
126 };
127 
128 struct mspcic_cookie {
129 	struct mspcic_pci_map *map;
130 	int nmaps;
131 };
132 
133 static struct mspcic_cookie mspcic_io_cookie = { mspcic_pci_iomap, 0 };
134 static struct mspcic_cookie mspcic_mem_cookie = { mspcic_pci_memmap, 0 };
135 
136 
137 static void		mspcic_init_maps(void);
138 static void		mspcic_pci_map_from_reg(struct mspcic_pci_map *,
139 						u_int8_t, u_int8_t, u_int8_t);
140 static bus_addr_t	mspcic_pci_map_find(struct mspcic_pci_map *, int,
141 					    bus_addr_t, bus_size_t);
142 #ifdef DEBUG
143 static void	mspcic_pci_map_print(struct mspcic_pci_map *, const char *);
144 #endif
145 
146 
147 static int	mspcic_bus_map(bus_space_tag_t, bus_addr_t, bus_size_t,
148 			       int, vaddr_t, bus_space_handle_t *);
149 static paddr_t	mspcic_bus_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int);
150 static void	*mspcic_intr_establish(bus_space_tag_t, int, int, int,
151 				       int (*)(void *), void *);
152 
153 static struct sparc_bus_space_tag mspcic_io_tag = {
154 	&mspcic_io_cookie,	/* cookie */
155 	NULL,			/* parent bus tag */
156 	mspcic_bus_map,		/* bus_space_map */
157 	NULL,			/* bus_space_unmap */
158 	NULL,			/* bus_space_subregion */
159 	NULL,			/* bus_space_barrier */
160 	mspcic_bus_mmap,	/* bus_space_mmap */
161 	mspcic_intr_establish	/* bus_intr_establish */
162 };
163 
164 static struct sparc_bus_space_tag mspcic_mem_tag = {
165 	&mspcic_mem_cookie,	/* cookie */
166 	NULL,			/* parent bus tag */
167 	mspcic_bus_map,		/* bus_space_map */
168 	NULL,			/* bus_space_unmap */
169 	NULL,			/* bus_space_subregion */
170 	NULL,			/* bus_space_barrier */
171 	mspcic_bus_mmap,	/* bus_space_mmap */
172 	mspcic_intr_establish	/* bus_intr_establish */
173 };
174 
175 
176 /*
177  * DMA tag
178  */
179 static int	mspcic_dmamap_load(bus_dma_tag_t, bus_dmamap_t,
180 				   void *, bus_size_t, struct proc *, int);
181 static void	mspcic_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
182 static int	mspcic_dmamem_map(bus_dma_tag_t, bus_dma_segment_t *,
183 				  int, size_t, caddr_t *, int);
184 
185 static struct sparc_bus_dma_tag mspcic_dma_tag = {
186 	NULL,			/* _cookie */
187 
188 	_bus_dmamap_create,
189 	_bus_dmamap_destroy,
190 	mspcic_dmamap_load,
191 	_bus_dmamap_load_mbuf,
192 	_bus_dmamap_load_uio,
193 	_bus_dmamap_load_raw,
194 	mspcic_dmamap_unload,
195 	_bus_dmamap_sync,
196 
197 	_bus_dmamem_alloc,
198 	_bus_dmamem_free,
199 	mspcic_dmamem_map,
200 	_bus_dmamem_unmap,
201 	_bus_dmamem_mmap
202 };
203 
204 
205 
206 
207 
208 static int
209 msiiep_match(parent, cf, aux)
210 	struct device	*parent;
211 	struct cfdata	*cf;
212 	void		*aux;
213 {
214 	struct mainbus_attach_args *ma = aux;
215 	pcireg_t id;
216 
217 	/* match by PROM name */
218 	if (strcmp(ma->ma_name, "pci") != 0)
219 		return (0);
220 
221 	/*
222 	 * Verify that PCIC was successfully mapped by bootstrap code.
223 	 * Since PCIC contains all the registers vital to the kernel,
224 	 * bootstrap code maps them at a fixed va, MSIIEP_PCIC_VA, and
225 	 * switches the endian-swapping mode on.
226 	 */
227 	id = mspcic->pcic_id;
228 	if (PCI_VENDOR(id) != PCI_VENDOR_SUN
229 	    && PCI_PRODUCT(id) != PCI_PRODUCT_SUN_MS_IIep)
230 		panic("msiiep_match: id %08x", id);
231 
232 	return (1);
233 }
234 
235 
236 static void
237 msiiep_attach(parent, self, aux)
238 	struct device *parent;
239 	struct device *self;
240 	void *aux;
241 {
242 	struct mainbus_attach_args *ma = aux;
243 	struct msiiep_attach_args msa;
244 
245 	/*
246 	 * Ok, we know that we are on ms-IIep and the easy way to get
247 	 * idprom is to read it from root property (try this at prom:
248 	 * "see idprom@ seeprom see ee-read" if you don't believe me ;-).
249 	 */
250 	msiiep_getidprom();
251 
252 	/* pass on real mainbus_attach_args */
253 	msa.msa_ma = ma;
254 
255 	/* config timer/counter part of PCIC */
256 	msa.msa_name = "timer";
257 	config_found(self, &msa, NULL);
258 
259 	/* config PCI tree */
260 	msa.msa_name = "pcic";
261 	config_found(self, &msa, NULL);
262 }
263 
264 
265 /*
266  * idprom is in /pci/ebus/gpio but it's a pain to access.
267  * fortunately the PROM sets "idprom" property on the root node.
268  * XXX: the idprom stuff badly needs to be factored out....
269  */
270 static void
271 msiiep_getidprom()
272 {
273 	extern void establish_hostid(struct idprom *); /* clock.c */
274 	struct idprom *idp;
275 	int nitems;
276 
277 	idp = &msiiep_idprom_store;
278 	nitems = 1;
279 	if (PROM_getprop(prom_findroot(), "idprom",
280 			 sizeof(struct idprom), &nitems,
281 			 (void **)&idp) != 0)
282 		panic("unable to get \"idprom\" property from root node");
283 	establish_hostid(idp);
284 }
285 
286 
287 /*
288  * Turn PCIC endian swapping on/off.  The kernel runs with endian
289  * swapping turned on early in bootstrap(), but we need to turn it off
290  * before we pass control to PROM's repl (e.g. in OF_enter and OF_exit).
291  * PROM expects PCIC to be in little endian mode and would wedge if we
292  * didn't turn endian swapping off.
293  */
294 void
295 msiiep_swap_endian(on)
296 	int on;
297 {
298 	u_int8_t pioctl;
299 
300 	pioctl = mspcic->pcic_pio_ctrl;
301 	if (on)
302 		pioctl |= MSIIEP_PIO_CTRL_BIG_ENDIAN;
303 	else
304 		pioctl &= ~MSIIEP_PIO_CTRL_BIG_ENDIAN;
305 	mspcic->pcic_pio_ctrl = pioctl;
306 
307 	/* read it back to make sure transaction completed */
308 	pioctl = mspcic->pcic_pio_ctrl;
309 }
310 
311 
312 
313 /* ======================================================================
314  *
315  *		      Real ms-IIep PCIC driver.
316  */
317 
318 static int
319 mspcic_match(parent, cf, aux)
320 	struct device	*parent;
321 	struct cfdata	*cf;
322 	void		*aux;
323 {
324 	struct msiiep_attach_args *msa = aux;
325 
326 	return (strcmp(msa->msa_name, "pcic") == 0);
327 }
328 
329 
330 static void
331 mspcic_attach(parent, self, aux)
332 	struct device *parent;
333 	struct device *self;
334 	void *aux;
335 {
336 	struct mspcic_softc *sc = (struct mspcic_softc *)self;
337 	struct msiiep_attach_args *msa = aux;
338 	struct mainbus_attach_args *ma = msa->msa_ma;
339 	int node = ma->ma_node;
340 	char devinfo[256];
341 
342 	struct pcibus_attach_args pba;
343 
344 	sc->sc_node = node;
345 	sc->sc_clockfreq = PROM_getpropint(node, "clock-frequency", 33333333);
346 
347 	/* copy parent tags */
348 	sc->sc_bustag = ma->ma_bustag;
349 	sc->sc_dmatag = ma->ma_dmatag;
350 
351 	/*
352 	 * PCIC registers are mapped at a fixed VA because counters,
353 	 * interrupt registers etc are there.  Just save that mapping.
354 	 */
355 	sc->sc_bh = (bus_space_handle_t)MSIIEP_PCIC_VA;
356 
357 	/* print our PCI device info and bus clock frequency */
358 	pci_devinfo(mspcic->pcic_id, mspcic->pcic_class, 0, devinfo);
359 	printf(": %s: clock = %s MHz\n", devinfo, clockfreq(sc->sc_clockfreq));
360 
361 	mspcic_init_maps();
362 
363 	/* init cookies/parents in our statically allocated tags */
364 	mspcic_io_tag.parent = sc->sc_bustag;
365 	mspcic_mem_tag.parent = sc->sc_bustag;
366 	mspcic_dma_tag._cookie = sc;
367 	mspcic_pc_tag.cookie = sc;
368 
369 	/* save bus tags in softc */
370 	sc->sc_iot = &mspcic_io_tag;
371 	sc->sc_memt = &mspcic_mem_tag;
372 	sc->sc_dmat = &mspcic_dma_tag;
373 
374 	/*
375 	 * Attach the PCI bus.
376 	 */
377 	pba.pba_busname = "pci";
378 	pba.pba_bus = 0;
379 	pba.pba_bridgetag = NULL;
380 	pba.pba_iot = sc->sc_iot;
381 	pba.pba_memt = sc->sc_memt;
382 	pba.pba_dmat = sc->sc_dmat;
383 	pba.pba_pc = &mspcic_pc_tag;
384 	pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
385 
386 	config_found(self, &pba, mspcic_print);
387 }
388 
389 
390 static int
391 mspcic_print(args, busname)
392 	void *args;
393 	const char *busname;
394 {
395 
396 	if (busname == NULL)
397 		return (UNCONF);
398 	return (QUIET);
399 }
400 
401 
402 /*
403  * Get the PIL currently assigned for this interrupt input line.
404  */
405 int
406 mspcic_assigned_interrupt(line)
407 	int line;
408 {
409 	unsigned int intrmap;
410 
411 	if (line < 0 || line > 7)
412 		return (-1);
413 
414 	if (line < 4) {
415 		intrmap = mspcic->pcic_intr_asgn_sel;
416 	} else {
417 		intrmap = mspcic->pcic_intr_asgn_sel_hi;
418 		line -= 4;
419 	}
420 	return ((intrmap >> (line * 4)) & 0xf);
421 }
422 
423 /* ======================================================================
424  *
425  *			  BUS space methods
426  */
427 
428 static __inline__ void
429 mspcic_pci_map_from_reg(m, sbar, pbar, sizemask)
430 	struct mspcic_pci_map *m;
431 	u_int8_t sbar, pbar, sizemask;
432 {
433 	m->sysbase = 0x30000000 | ((sbar & 0x0f) << 24);
434 	m->pcibase = pbar << 24;
435 	m->size = ~((0xf0 | sizemask) << 24) + 1;
436 }
437 
438 
439 /* does [al, ar) and [bl, br) overlap? */
440 #define OVERLAP(al, ar, bl, br) (((al) < (br)) && ((bl) < (ar)))
441 
442 /* does map "m" overlap with fixed mapping region? */
443 #define OVERLAP_FIXED(m) OVERLAP((m)->sysbase, (m)->sysbase + (m)->size, \
444 				0x30000000, 0x31000000)
445 
446 /* does map "ma" overlap map "mb" (possibly NULL)? */
447 #define OVERLAP_MAP(ma, mb) \
448 	((mb != NULL) && OVERLAP((ma)->sysbase, (ma)->sysbase + (ma)->size, \
449 				 (mb)->sysbase, (mb)->sysbase + (mb)->size))
450 
451 /*
452  * Init auxiliary paddr->pci maps.
453  */
454 static void
455 mspcic_init_maps()
456 {
457 	struct mspcic_pci_map *m0, *m1, *io;
458 	int nmem, nio;
459 
460 #ifdef DEBUG
461 	printf("mspcic0: SMBAR0 %02x  PMBAR0 %02x  MSIZE0 %02x\n",
462 	       mspcic->pcic_smbar0, mspcic->pcic_pmbar0, mspcic->pcic_msize0);
463 	printf("mspcic0: SMBAR1 %02x  PMBAR1 %02x  MSIZE1 %02x\n",
464 	       mspcic->pcic_smbar1, mspcic->pcic_pmbar1, mspcic->pcic_msize1);
465 	printf("mspcic0: SIBAR  %02x  PIBAR  %02x  IOSIZE %02x\n",
466 	       mspcic->pcic_sibar, mspcic->pcic_pibar, mspcic->pcic_iosize);
467 #endif
468 	nmem = nio = 1;
469 
470 	m0 = &mspcic_pci_memmap[nmem];
471 	mspcic_pci_map_from_reg(m0, mspcic->pcic_smbar0, mspcic->pcic_pmbar0,
472 				mspcic->pcic_msize0);
473 	if (OVERLAP_FIXED(m0))
474 		m0 = NULL;
475 	else
476 		++nmem;
477 
478 	m1 = &mspcic_pci_memmap[nmem];
479 	mspcic_pci_map_from_reg(m1, mspcic->pcic_smbar1, mspcic->pcic_pmbar1,
480 				mspcic->pcic_msize1);
481 	if (OVERLAP_FIXED(m1) || OVERLAP_MAP(m1, m0))
482 		m1 = NULL;
483 	else
484 		++nmem;
485 
486 	io = &mspcic_pci_iomap[nio];
487 	mspcic_pci_map_from_reg(io, mspcic->pcic_sibar, mspcic->pcic_pibar,
488 				mspcic->pcic_iosize);
489 	if (OVERLAP_FIXED(io) || OVERLAP_MAP(io, m0) || OVERLAP_MAP(io, m1))
490 		io = NULL;
491 	else
492 		++nio;
493 
494 	mspcic_io_cookie.nmaps = nio;
495 	mspcic_mem_cookie.nmaps = nmem;
496 
497 #ifdef DEBUG
498 	mspcic_pci_map_print(&mspcic_pci_iomap[0], "i/o fixed");
499 	mspcic_pci_map_print(&mspcic_pci_memmap[0], "mem fixed");
500 	if (m0) mspcic_pci_map_print(m0, "mem map0");
501 	if (m1) mspcic_pci_map_print(m1, "mem map1");
502 	if (io) mspcic_pci_map_print(io, "i/0 map");
503 #endif
504 }
505 
506 
507 #ifdef DEBUG
508 static void
509 mspcic_pci_map_print(m, msg)
510 	struct mspcic_pci_map *m;
511 	const char *msg;
512 {
513 	printf("mspcic0: paddr [%08x..%08x] -> pci [%08x..%08x] %s\n",
514 	       m->sysbase, m->sysbase + m->size - 1,
515 	       m->pcibase, m->pcibase + m->size - 1,
516 	       msg);
517 }
518 #endif
519 
520 
521 static bus_addr_t
522 mspcic_pci_map_find(m, nmaps, pciaddr, size)
523 	struct mspcic_pci_map *m;
524 	int nmaps;
525 	bus_addr_t pciaddr;
526 	bus_size_t size;
527 {
528 	bus_size_t offset;
529 	int i;
530 
531 	for (i = 0; i < nmaps; ++i, ++m) {
532 		offset = pciaddr - m->pcibase;
533 		if (offset >= 0 && offset + size <= m->size)
534 			return (m->sysbase + offset);
535 	}
536 	return (0);
537 }
538 
539 
540 static int
541 mspcic_bus_map(t, ba, size, flags, va, hp)
542 	bus_space_tag_t t;
543 	bus_addr_t ba;
544 	bus_size_t size;
545 	int flags;
546 	vaddr_t va;
547 	bus_space_handle_t *hp;
548 {
549 	struct mspcic_cookie *c = t->cookie;
550 	bus_addr_t paddr;
551 
552 	paddr = mspcic_pci_map_find(c->map, c->nmaps, ba, size);
553 	if (paddr == 0)
554 		return (EINVAL);
555 	return (bus_space_map2(t->parent, paddr, size, flags, va, hp));
556 }
557 
558 
559 static paddr_t
560 mspcic_bus_mmap(t, ba, off, prot, flags)
561 	bus_space_tag_t t;
562 	bus_addr_t ba;
563 	off_t off;
564 	int prot;
565 	int flags;
566 {
567 	struct mspcic_cookie *c = t->cookie;
568 	bus_addr_t paddr;
569 
570 	/* verify that phys to pci mapping for the target page exists */
571 	paddr = mspcic_pci_map_find(c->map, c->nmaps, ba + off, PAGE_SIZE);
572 	if (paddr == 0)
573 		return (-1);
574 
575 	return (bus_space_mmap(t->parent, paddr - off, off, prot, flags));
576 }
577 
578 
579 /*
580  * Install an interrupt handler.
581  *
582  * Bus-specific interrupt argument is 'line', an interrupt input line
583  * for ms-IIep.  The PIL for is programmable via pcic interrupt
584  * assignment select registers (but we use existing assignments).
585  */
586 static void *
587 mspcic_intr_establish(t, line, ipl, flags, handler, arg)
588 	bus_space_tag_t t;
589 	int line;
590 	int ipl;
591 	int flags;
592 	int (*handler)(void *);
593 	void *arg;
594 {
595 	struct intrhand *ih;
596 	int pil;
597 
598 	ih = (struct intrhand *)
599 		malloc(sizeof(struct intrhand), M_DEVBUF, M_NOWAIT);
600 	if (ih == NULL)
601 		return (NULL);
602 
603 	/* use pil set-up by prom */
604 	pil = mspcic_assigned_interrupt(line);
605 	if (pil == -1)
606 		panic("mspcic_intr_establish: line %d", line);
607 
608 	ih->ih_fun = handler;
609 	ih->ih_arg = arg;
610 	intr_establish(pil, ih);
611 
612 	return(ih);
613 }
614 
615 
616 /* ======================================================================
617  *
618  *			     DMA methods
619  */
620 
621 static int
622 mspcic_dmamap_load(t, map, buf, buflen, p, flags)
623 	bus_dma_tag_t t;
624 	bus_dmamap_t map;
625 	void *buf;
626 	bus_size_t buflen;
627 	struct proc *p;
628 	int flags;
629 {
630 	pmap_t pmap;
631 	paddr_t pa;
632 
633 	if (p != NULL)
634 		pmap = p->p_vmspace->vm_map.pmap;
635 	else
636 		pmap = pmap_kernel();
637 
638 	if (!pmap_extract(pmap, (vaddr_t)buf, &pa))
639 		panic("mspcic_dmamap_load: dma memory not mapped");
640 
641 	/* we always use just one segment */
642 	map->dm_nsegs = 1;
643 	map->dm_segs[0].ds_addr = pa;
644 	map->dm_segs[0].ds_len = buflen;
645 	map->dm_mapsize = buflen;
646 
647 	return (0);
648 }
649 
650 static void
651 mspcic_dmamap_unload(t, dmam)
652 	bus_dma_tag_t t;
653 	bus_dmamap_t dmam;
654 {
655 
656 	panic("mspcic_dmamap_unload: not implemented");
657 }
658 
659 
660 static int
661 mspcic_dmamem_map(tag, segs, nsegs, size, kvap, flags)
662 	bus_dma_tag_t tag;
663 	bus_dma_segment_t *segs;
664 	int nsegs;
665 	size_t size;
666 	caddr_t *kvap;
667 	int flags;
668 {
669 	struct pglist *mlist;
670 	struct vm_page *m;
671 	vaddr_t va;
672 	int pagesz = PAGE_SIZE;
673 
674 	if (nsegs != 1)
675 		panic("mspcic_dmamem_map: nsegs = %d", nsegs);
676 
677 	size = round_page(size);
678 
679 	va = uvm_km_valloc(kernel_map, size);
680 	if (va == 0)
681 		return (ENOMEM);
682 
683 	segs[0]._ds_va = va;
684 	*kvap = (caddr_t)va;
685 
686 	/*
687 	 * Map the pages allocated in _bus_dmamem_alloc()
688 	 * to the kernel virtual address space.
689 	 */
690 	mlist = segs[0]._ds_mlist;
691 	TAILQ_FOREACH(m, mlist, pageq) {
692 		paddr_t pa;
693 
694 		if (size == 0)
695 			panic("mspcic_dmamem_map: size botch");
696 
697 		pa = VM_PAGE_TO_PHYS(m);
698 		pmap_kenter_pa(va, pa | PMAP_NC, VM_PROT_READ | VM_PROT_WRITE);
699 		va += pagesz;
700 		size -= pagesz;
701 	}
702 	pmap_update(pmap_kernel());
703 
704 	return (0);
705 }
706