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