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