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