pci.c revision 6630
1/************************************************************************** 2** 3** $Id: pci.c,v 1.14 1995/02/14 23:33:38 se Exp $ 4** 5** General subroutines for the PCI bus on 80*86 systems. 6** pci_configure () 7** 8** 386bsd / FreeBSD 9** 10**------------------------------------------------------------------------- 11** 12** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved. 13** 14** Redistribution and use in source and binary forms, with or without 15** modification, are permitted provided that the following conditions 16** are met: 17** 1. Redistributions of source code must retain the above copyright 18** notice, this list of conditions and the following disclaimer. 19** 2. Redistributions in binary form must reproduce the above copyright 20** notice, this list of conditions and the following disclaimer in the 21** documentation and/or other materials provided with the distribution. 22** 3. The name of the author may not be used to endorse or promote products 23** derived from this software without specific prior written permission. 24** 25** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 26** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 29** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 30** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35** 36*************************************************************************** 37*/ 38 39#define PCI_PATCHLEVEL "pl2 95/02/21" 40 41#include <pci.h> 42#if NPCI > 0 43 44#ifndef __FreeBSD2__ 45#if __FreeBSD__ >= 2 46#define __FreeBSD2__ 47#endif 48#endif 49 50/*======================================================== 51** 52** #includes and declarations 53** 54**======================================================== 55*/ 56 57#include <sys/param.h> 58#include <sys/systm.h> 59#include <sys/malloc.h> 60#include <sys/errno.h> 61#include <sys/kernel.h> 62 63#include <vm/vm.h> 64#include <vm/vm_param.h> 65 66#include <pci/pcivar.h> 67#include <pci/pcireg.h> 68#include <pci/pcibus.h> 69 70#include <machine/pmap.h> 71#ifdef __FreeBSD2__ 72#include <sys/devconf.h> 73 74struct pci_devconf { 75 struct kern_devconf pdc_kdc; 76 struct pci_info pdc_pi; 77}; 78 79static int 80pci_externalize (struct proc *, struct kern_devconf *, void *, size_t); 81 82static int 83pci_internalize (struct proc *, struct kern_devconf *, void *, size_t); 84#else /* __FreeBSD2__ */ 85 86/* 87** Function prototypes missing in system headers 88*/ 89 90extern pmap_t pmap_kernel(void); 91static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize); 92#endif /* __FreeBSD2__ */ 93 94 95/*======================================================== 96** 97** Autoconfiguration of pci devices. 98** 99** This is reverse to the isa configuration. 100** (1) find a pci device. 101** (2) look for a driver. 102** 103**======================================================== 104*/ 105 106/*-------------------------------------------------------- 107** 108** The pci devices can be mapped to any address. 109** This is a list of possible starting addresses. 110** It can be prepended by a config option. 111** 112**-------------------------------------------------------- 113*/ 114 115static u_long pci_stable[] = { 116#ifdef PCI_PMEM_START 117 (PCI_PMEM_START), 118#endif 119 0xf1000000, 120 0x53900000, 121 0xc0000000, 122 0x81000000, 123 0x0f000000, 124}; 125 126static vm_offset_t pci_paddr = 0; 127static vm_offset_t pci_pold = 0; 128static vm_offset_t pci_pidx = 0; 129 130 131/*-------------------------------------------------------- 132** 133** The pci ports can be mapped to any address. 134** As default we start at 0x400 135** 136**-------------------------------------------------------- 137*/ 138 139#ifndef PCI_PORT_START 140#define PCI_PORT_START 0xbc00 141#endif 142 143static u_short pci_ioaddr = PCI_PORT_START; 144 145/*-------------------------------------------------------- 146** 147** The pci device interrupt lines should have been 148** assigned by the bios. But if the bios failed to 149** to it, we set it. 150** 151**-------------------------------------------------------- 152*/ 153 154#ifndef PCI_IRQ 155#define PCI_IRQ 0 156#endif 157 158static u_long pci_irq = PCI_IRQ; 159 160/*--------------------------------------------------------- 161** 162** pci_configure () 163** 164** Probe all devices on pci bus and attach them. 165** 166** May be called more than once. 167** Any device is attached only once. 168** (Attached devices are remembered in pci_seen.) 169** 170**--------------------------------------------------------- 171*/ 172 173static void not_supported (pcici_t tag, u_long type); 174 175static unsigned long pci_seen[NPCI]; 176 177static int pci_conf_count; 178 179void pci_configure() 180{ 181 u_char device,last_device; 182 u_short bus; 183 pcici_t tag; 184 pcidi_t type; 185 u_long data; 186 int unit; 187 int pci_mechanism; 188 int pciint; 189 int irq; 190 char* name=0; 191 u_short old_ioaddr=pci_ioaddr; 192 193 int dvi; 194 struct pci_device *dvp=0; 195 196#ifdef __FreeBSD2__ 197 struct pci_devconf *pdcp; 198#endif 199 200 /* 201 ** first check pci bus driver available 202 */ 203 204 if (pcibus_set.ls_length <= 0) 205 return; 206 207#define pcibus (*((struct pcibus*) pcibus_set.ls_items[0])) 208 /* 209 ** check pci bus present 210 */ 211 212 pci_mechanism = pcibus.pb_mode (); 213 if (!pci_mechanism) return; 214 last_device = pci_mechanism==1 ? 31 : 15; 215 216 /* 217 ** hello world .. 218 */ 219 220 pci_pold=pci_paddr; 221 for (bus=0;bus<NPCI;bus++) { 222#ifndef PCI_QUIET 223 printf ("%s%d: scanning device 0..%d, mechanism=%d.\n", 224 pcibus.pb_name, bus, last_device, pci_mechanism); 225#endif 226 for (device=0; device<=last_device; device ++) { 227 228 if (pci_seen[bus] & (1ul << device)) 229 continue; 230 231 tag = pcibus.pb_tag (bus, device, 0); 232 type = pcibus.pb_read (tag, PCI_ID_REG); 233 234 if ((!type) || (type==0xfffffffful)) continue; 235 236 /* 237 ** lookup device in ioconfiguration: 238 */ 239 240 for (dvi=0; dvi<pcidevice_set.ls_length; dvi++) { 241 dvp = (struct pci_device*) pcidevice_set.ls_items[dvi]; 242 if ((name=(*dvp->pd_probe)(tag, type))) 243 break; 244 dvp = NULL; 245 }; 246 247 if (dvp==NULL) { 248#ifndef PCI_QUIET 249 if (pci_conf_count) 250 continue; 251 printf("%s%d:%d: ", pcibus.pb_name, bus, device); 252 not_supported (tag, type); 253#endif 254 continue; 255 }; 256 257 pci_seen[bus] |= (1ul << device); 258 /* 259 ** Get and increment the unit. 260 */ 261 262 unit = (*dvp->pd_count)++; 263 264 /* 265 ** ignore device ? 266 */ 267 268 if (!*name) continue; 269 270 /* 271 ** Announce this device 272 */ 273 274 printf ("%s%d <%s>", dvp->pd_name, unit, name); 275 276 /* 277 ** Get the int pin number (pci interrupt number a-d) 278 ** from the pci configuration space. 279 */ 280 281 data = pcibus.pb_read (tag, PCI_INTERRUPT_REG); 282 pciint = PCI_INTERRUPT_PIN_EXTRACT(data); 283 284 if (pciint) { 285 286 printf (" int %c", 0x60+pciint); 287 288 /* 289 ** If the interrupt line register is not set, 290 ** set it now from PCI_IRQ. 291 */ 292 293 if (!(PCI_INTERRUPT_LINE_EXTRACT(data))) { 294 295 irq = pci_irq & 0x0f; 296 pci_irq >>= 4; 297 298 data = PCI_INTERRUPT_LINE_INSERT(data, irq); 299 printf (" (config)"); 300 pcibus.pb_write (tag, PCI_INTERRUPT_REG, data); 301 }; 302 303 irq = PCI_INTERRUPT_LINE_EXTRACT(data); 304 305 /* 306 ** If it's zero, the isa irq number is unknown, 307 ** and we cannot bind the pci interrupt to isa. 308 */ 309 310 if (irq) 311 printf (" irq %d", irq); 312 else 313 printf (" not bound"); 314 }; 315 316 /* 317 ** enable memory access 318 */ 319 320 data = (pcibus.pb_read (tag, PCI_COMMAND_STATUS_REG) 321 & 0xffff) | PCI_COMMAND_MEM_ENABLE; 322 323 pcibus.pb_write (tag, (u_char) PCI_COMMAND_STATUS_REG, data); 324 325 /* 326 ** show pci slot. 327 */ 328 329 printf (" on pci%d:%d\n", bus, device); 330 331#ifdef __FreeBSD2__ 332 333 /* 334 ** Allocate a devconf structure 335 */ 336 337 pdcp = (struct pci_devconf *) 338 malloc (sizeof (struct pci_devconf),M_DEVBUF,M_WAITOK); 339 340 /* 341 ** Fill in. 342 ** 343 ** Sorry, this is not yet complete. 344 ** We should, and eventually will, set the 345 ** parent pointer to a pci bus devconf structure, 346 ** and arrange to set the state field dynamically. 347 ** 348 ** But I'll go to vacation today, and after all, 349 ** wasn't there a new feature freeze on Oct 1.? 350 */ 351 352 pdcp -> pdc_pi.pi_bus = bus; 353 pdcp -> pdc_pi.pi_device = device; 354 355 pdcp -> pdc_kdc.kdc_name = dvp->pd_name; 356 pdcp -> pdc_kdc.kdc_unit = unit; 357 358 pdcp -> pdc_kdc.kdc_md.mddc_devtype = MDDT_PCI; 359 360 pdcp -> pdc_kdc.kdc_externalize = pci_externalize; 361 pdcp -> pdc_kdc.kdc_internalize = pci_internalize; 362 363 pdcp -> pdc_kdc.kdc_datalen = PCI_EXTERNAL_LEN; 364 pdcp -> pdc_kdc.kdc_parentdata = &pdcp->pdc_pi; 365 pdcp -> pdc_kdc.kdc_state = DC_UNKNOWN; 366 pdcp -> pdc_kdc.kdc_description = name; 367 368 /* 369 ** And register this device 370 */ 371 372 dev_attach (&pdcp->pdc_kdc); 373 374#endif /* __FreeBSD2__ */ 375 376 377 /* 378 ** attach device 379 ** may produce additional log messages, 380 ** i.e. when installing subdevices. 381 */ 382 383 (*dvp->pd_attach) (tag, unit); 384 }; 385 }; 386 387#ifndef PCI_QUIET 388 if (pci_paddr != pci_pold) 389 printf ("pci uses physical addresses from 0x%lx to 0x%lx\n", 390 (u_long)pci_pold, (u_long)pci_paddr); 391 if (pci_ioaddr != old_ioaddr) 392 printf ("pci devices use ioports from 0x%x to 0x%x\n", 393 (unsigned)PCI_PORT_START, (unsigned)pci_ioaddr); 394#endif 395 pci_conf_count++; 396} 397 398/*----------------------------------------------------------------- 399** 400** The following functions are provided for the device driver 401** to read/write the configuration space. 402** 403** pci_conf_read(): 404** Read a long word from the pci configuration space. 405** Requires a tag (from pcitag) and the register 406** number (should be a long word alligned one). 407** 408** pci_conf_write(): 409** Writes a long word to the pci configuration space. 410** Requires a tag (from pcitag), the register number 411** (should be a long word alligned one), and a value. 412** 413**----------------------------------------------------------------- 414*/ 415 416u_long 417pci_conf_read (pcici_t tag, u_long reg) 418{ 419 return (pcibus.pb_read (tag, reg)); 420} 421 422void 423pci_conf_write (pcici_t tag, u_long reg, u_long data) 424{ 425 pcibus.pb_write (tag, reg, data); 426} 427 428/*----------------------------------------------------------------------- 429** 430** Map device into port space. 431** 432** PCI-Specification: 6.2.5.1: address maps 433** 434**----------------------------------------------------------------------- 435*/ 436 437int pci_map_port (pcici_t tag, u_long reg, u_short* pa) 438{ 439 u_long data,oldmap; 440 u_short size, ioaddr; 441 442 /* 443 ** sanity check 444 */ 445 446 if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) { 447 printf ("pci_map_port failed: bad register=0x%x\n", 448 (unsigned)reg); 449 return (0); 450 }; 451 452 /* 453 ** get size and type of port 454 ** 455 ** type is in the lowest two bits. 456 ** If device requires 2^n bytes, the next 457 ** n-2 bits are hardwired as 0. 458 */ 459 460#ifdef PCI_REMAP 461 oldmap = 0; 462#else 463 oldmap = pcibus.pb_read (tag, reg) & 0xfffffffc; 464 if (oldmap==0xfffffffc) oldmap=0; 465#endif 466 pcibus.pb_write (tag, reg, 0xfffffffful); 467 data = pcibus.pb_read (tag, reg); 468 469 switch (data & 0x03) { 470 471 case PCI_MAP_IO: 472 break; 473 474 default: /* unknown */ 475 printf ("pci_map_port failed: bad port type=0x%x\n", 476 (unsigned) data); 477 return (0); 478 }; 479 480 /* 481 ** get the size 482 */ 483 484 size = -(data & PCI_MAP_IO_ADDRESS_MASK); 485 486 if (!size) return (0); 487 488 /* 489 ** align physical address to virtual size, 490 ** set ioaddr, 491 ** and don't forget to increment pci_ioaddr 492 */ 493 494 if (oldmap) { 495 ioaddr = oldmap; 496 } else { 497 if ((data = pci_ioaddr % size)) 498 pci_ioaddr += size - data; 499 ioaddr = pci_ioaddr; 500 pci_ioaddr += size; 501 }; 502 503#ifndef PCI_QUIET 504 /* 505 ** display values. 506 */ 507 508 printf ("\treg%d: ioaddr=0x%x size=0x%x\n", 509 (unsigned) reg, (unsigned) ioaddr, (unsigned) size); 510#endif 511 512 /* 513 ** set device address 514 */ 515 516 pcibus.pb_write (tag, reg, (u_long) ioaddr); 517 518 /* 519 ** return them to the driver 520 */ 521 522 *pa = pci_ioaddr; 523 524 return (1); 525} 526 527/*----------------------------------------------------------------------- 528** 529** Map device into virtual and physical space 530** 531** PCI-Specification: 6.2.5.1: address maps 532** 533**----------------------------------------------------------------------- 534*/ 535 536int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa) 537{ 538 u_long data,oldmap,paddr; 539 vm_size_t vsize; 540 vm_offset_t vaddr; 541 int i; 542 543 /* 544 ** sanity check 545 */ 546 547 if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) { 548 printf ("pci_map_mem failed: bad register=0x%x\n", 549 (unsigned)reg); 550 return (0); 551 }; 552 553 /* 554 ** save old mapping, get size and type of memory 555 ** 556 ** type is in the lowest four bits. 557 ** If device requires 2^n bytes, the next 558 ** n-4 bits are read as 0. 559 */ 560 561#ifdef PCI_REMAP 562 oldmap = 0; 563#else 564 oldmap = pcibus.pb_read (tag, reg) & 0xfffffff0; 565 if (oldmap==0xfffffff0) oldmap = 0; 566#endif 567 pcibus.pb_write (tag, reg, 0xfffffffful); 568 data = pcibus.pb_read (tag, reg); 569 570 switch (data & 0x0f) { 571 572 case PCI_MAP_MEMORY_TYPE_32BIT: /* 32 bit non cachable */ 573 break; 574 575 default: /* unknown */ 576 printf ("pci_map_mem failed: bad memory type=0x%x\n", 577 (unsigned) data); 578 return (0); 579 }; 580 581 /* 582 ** mask out the type, 583 ** and round up to a page size 584 */ 585 586 vsize = round_page (-(data & PCI_MAP_MEMORY_ADDRESS_MASK)); 587 588 if (!vsize) return (0); 589 590 if (oldmap) { 591 paddr = oldmap; 592 goto domap; 593 }; 594 595next_try: 596 if (!pci_paddr) { 597 /* 598 ** Get a starting address. 599 */ 600 if (pci_pidx >= sizeof(pci_stable)/sizeof(u_long)) { 601 printf ("pci_map_mem: out of start addresses.\n"); 602 return (0); 603 }; 604 605 pci_paddr = pci_stable[pci_pidx++]; 606 pci_pold = 0; 607 608 if (pci_pidx>1) 609 printf ("\t(retry at 0x%x)\n", 610 (unsigned) pci_paddr); 611 }; 612 /* 613 ** align physical address to virtual size 614 */ 615 616 if ((data = pci_paddr % vsize)) 617 pci_paddr += vsize - data; 618 619 if (!pci_pold) 620 pci_pold = pci_paddr; 621 622 /* 623 ** set physical mapping address, 624 ** and reserve physical address range 625 */ 626 627 paddr = pci_paddr; 628 pci_paddr += vsize; 629 630domap: 631 vaddr = (vm_offset_t) pmap_mapdev (paddr, vsize); 632 633 if (!vaddr) return (0); 634 635#ifndef PCI_QUIET 636 /* 637 ** display values. 638 */ 639 640 printf ("\treg%d: virtual=0x%lx physical=0x%lx\n", 641 (unsigned) reg, (u_long)vaddr, (u_long)paddr); 642#endif 643 644 /* 645 ** probe for already mapped device. 646 */ 647 648 if (!oldmap) for (i=0; i<vsize; i+=4) { 649 u_long* addr = (u_long*) (vaddr+i); 650 data = *addr; 651 if (data != 0xffffffff) { 652 printf ("\t(possible address conflict: " 653 "at 0x%x read: 0x%x)\n", 654 (unsigned) paddr+i, (unsigned) data); 655 pci_paddr = 0; 656 goto next_try; 657 }; 658 }; 659 660 /* 661 ** Set device address 662 */ 663 664 pcibus.pb_write (tag, reg, paddr); 665 666 /* 667 ** Check if correctly mapped. 668 ** 669 ** W A R N I N G 670 ** 671 ** This code assumes that the device will NOT return 672 ** only ones (0xffffffff) from all offsets. 673 */ 674 675 for (i=0; i<vsize; i+=4) { 676 u_long* addr = (u_long*) (vaddr+i); 677 data = *addr; 678 if (data != 0xffffffff) 679 break; 680 }; 681 682 if (data==0xffffffff) { 683 printf ("\t(possible mapping problem: " 684 "at 0x%x read 0xffffffff)\n", 685 (unsigned) paddr); 686 pci_paddr = 0; 687 goto next_try; 688 }; 689 690 /* 691 ** Return addresses to the driver 692 */ 693 694 *va = vaddr; 695 *pa = paddr; 696 697 return (1); 698} 699 700/*------------------------------------------------------------ 701** 702** Interface functions for the devconf module. 703** 704**------------------------------------------------------------ 705*/ 706 707static int 708pci_externalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t l) 709{ 710 struct pci_externalize_buffer buffer; 711 struct pci_info * pip = kdcp->kdc_parentdata; 712 pcici_t tag; 713 int i; 714 715 if (l < sizeof buffer) { 716 return ENOMEM; 717 }; 718 719 tag = pcibus.pb_tag (pip->pi_bus, pip->pi_device, 0); 720 721 buffer.peb_pci_info = *pip; 722 723 for (i=0; i<PCI_EXT_CONF_LEN; i++) { 724 buffer.peb_config[i] = pcibus.pb_read (tag, i*4); 725 }; 726 727 return copyout(&buffer, u, sizeof buffer); 728} 729 730 731static int 732pci_internalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t s) 733{ 734 return EOPNOTSUPP; 735} 736 737/*----------------------------------------------------------------------- 738** 739** Map pci interrupts to isa interrupts. 740** 741**----------------------------------------------------------------------- 742*/ 743 744int pci_map_int (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr) 745{ 746 int irq, result; 747 748 irq = PCI_INTERRUPT_LINE_EXTRACT( 749 pcibus.pb_read (tag, PCI_INTERRUPT_REG)); 750 751 if (irq >= 16 || irq <= 0) { 752 printf ("pci_map_int failed: no int line set.\n"); 753 return (0); 754 } 755 756 result = pcibus.pb_regint (tag, func, arg, maskptr); 757 758 if (!result) { 759 printf ("pci_map_int failed.\n"); 760 return (0); 761 }; 762 763 return (1); 764} 765 766/*----------------------------------------------------------- 767** 768** Display of unknown devices. 769** 770**----------------------------------------------------------- 771*/ 772struct vt { 773 u_short ident; 774 char* name; 775}; 776 777static struct vt VendorTable[] = { 778 {0x1002, "ATI TECHNOLOGIES INC"}, 779 {0x1011, "DIGITAL EQUIPMENT CORPORATION"}, 780 {0x101A, "NCR"}, 781 {0x102B, "MATROX"}, 782 {0x1045, "OPTI"}, 783 {0x5333, "S3 INC."}, 784 {0x8086, "INTEL CORPORATION"}, 785 {0,0} 786}; 787 788static const char *const majclasses[] = { 789 "old", "storage", "network", "display", 790 "multimedia", "memory", "bridge" 791}; 792 793void not_supported (pcici_t tag, u_long type) 794{ 795 u_char reg; 796 u_long data; 797 struct vt * vp; 798 799 /* 800 ** lookup the names. 801 */ 802 803 for (vp=VendorTable; vp->ident; vp++) 804 if (vp->ident == (type & 0xffff)) 805 break; 806 807 /* 808 ** and display them. 809 */ 810 811 if (vp->ident) printf (vp->name); 812 else printf ("vendor=0x%lx", type & 0xffff); 813 814 printf (", device=0x%lx", type >> 16); 815 816 data = (pcibus.pb_read(tag, PCI_CLASS_REG) >> 24) & 0xff; 817 if (data < sizeof(majclasses) / sizeof(majclasses[0])) 818 printf(", class=%s", majclasses[data]); 819 820 printf (" [not supported]\n"); 821 822 for (reg=PCI_MAP_REG_START; reg<PCI_MAP_REG_END; reg+=4) { 823 data = pcibus.pb_read (tag, reg); 824 if (!data) continue; 825 switch (data&7) { 826 827 case 1: 828 case 5: 829 printf (" map(%x): io(%lx)\n", 830 reg, data & ~3); 831 break; 832 case 0: 833 printf (" map(%x): mem32(%lx)\n", 834 reg, data & ~7); 835 break; 836 case 2: 837 printf (" map(%x): mem20(%lx)\n", 838 reg, data & ~7); 839 break; 840 case 4: 841 printf (" map(%x): mem64(%lx)\n", 842 reg, data & ~7); 843 break; 844 } 845 } 846} 847 848#ifndef __FreeBSD2__ 849/*----------------------------------------------------------- 850** 851** Mapping of physical to virtual memory 852** 853**----------------------------------------------------------- 854*/ 855 856extern vm_map_t kernel_map; 857 858static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize) 859{ 860 vm_offset_t vaddr,value; 861 u_long result; 862 863 vaddr = vm_map_min (kernel_map); 864 865 result = vm_map_find (kernel_map, (void*)0, (vm_offset_t) 0, 866 &vaddr, vsize, TRUE); 867 868 if (result != KERN_SUCCESS) { 869 printf (" vm_map_find failed(%d)\n", result); 870 return (0); 871 }; 872 873 /* 874 ** map physical 875 */ 876 877 value = vaddr; 878 while (vsize >= NBPG) { 879 pmap_enter (pmap_kernel(), vaddr, paddr, 880 VM_PROT_READ|VM_PROT_WRITE, TRUE); 881 vaddr += NBPG; 882 paddr += NBPG; 883 vsize -= NBPG; 884 }; 885 return (value); 886} 887 888/*------------------------------------------------------------ 889** 890** Emulate the register_intr() function of FreeBSD 2.0 891** 892** requires a patch: 893** FreeBSD 2.0: "/sys/i386/isa/vector.s" 894** 386bsd0.1: "/sys/i386/isa/icu.s" 895** 386bsd1.0: Please ask Jesus Monroy Jr. 896** 897**------------------------------------------------------------ 898*/ 899 900#include <machine/segments.h> 901 902int pci_int_unit [16]; 903inthand2_t* (pci_int_hdlr [16]); 904unsigned int * pci_int_mptr [16]; 905unsigned int pci_int_count[16]; 906 907extern void 908 Vpci3(), Vpci4(), Vpci5(), Vpci6(), Vpci7(), Vpci8(), Vpci9(), 909 Vpci10(), Vpci11(), Vpci12(), Vpci13(), Vpci14(), Vpci15(); 910 911static inthand_t* pci_int_glue[16] = { 912 0, 0, 0, Vpci3, Vpci4, Vpci5, Vpci6, Vpci7, Vpci8, 913 Vpci9, Vpci10, Vpci11, Vpci12, Vpci13, Vpci14, Vpci15 }; 914 915static int 916register_intr __P((int intr, int device_id, unsigned int flags, 917 inthand2_t *handler, unsigned int* mptr, int unit)) 918{ 919 if (intr >= 16 || intr <= 2) 920 return (EINVAL); 921 if (pci_int_hdlr [intr]) 922 return (EBUSY); 923 924 pci_int_hdlr [intr] = handler; 925 pci_int_unit [intr] = unit; 926 pci_int_mptr [intr] = mptr; 927 928 setidt(NRSVIDT + intr, pci_int_glue[intr], SDT_SYS386IGT, SEL_KPL); 929 return (0); 930} 931#endif /* __FreeBSD2__ */ 932#endif /* NPCI */ 933