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