pci.c (45573) | pci.c (45720) |
---|---|
1/* 2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * | 1/* 2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * |
26 * $Id: pci.c,v 1.93 1999/01/19 23:29:18 se Exp $ | 26 * $Id: pci.c,v 1.94 1999/04/11 02:47:31 eivind Exp $ |
27 * 28 */ 29 | 27 * 28 */ 29 |
30#include "opt_bus.h" 31 |
|
30#include "pci.h" 31#if NPCI > 0 32 33#include "opt_devfs.h" 34#include "opt_simos.h" 35 36#include <sys/param.h> 37#include <sys/systm.h> --- 7 unchanged lines hidden (view full) --- 45#ifdef DEVFS 46#include <sys/devfsext.h> 47#endif /* DEVFS */ 48 49#include <vm/vm.h> 50#include <vm/pmap.h> 51#include <vm/vm_extern.h> 52 | 32#include "pci.h" 33#if NPCI > 0 34 35#include "opt_devfs.h" 36#include "opt_simos.h" 37 38#include <sys/param.h> 39#include <sys/systm.h> --- 7 unchanged lines hidden (view full) --- 47#ifdef DEVFS 48#include <sys/devfsext.h> 49#endif /* DEVFS */ 50 51#include <vm/vm.h> 52#include <vm/pmap.h> 53#include <vm/vm_extern.h> 54 |
55#include <sys/bus.h> 56#include <machine/bus.h> 57#include <sys/rman.h> 58#include <machine/resource.h> 59 |
|
53#include <pci/pcireg.h> 54#include <pci/pcivar.h> 55#include <pci/pci_ioctl.h> 56 57#ifdef APIC_IO 58#include <machine/smp.h> 59#endif /* APIC_IO */ 60 --- 272 unchanged lines hidden (view full) --- 333 334 devlist_entry = NULL; 335 336 if (pci_cfgread(probe, PCIR_DEVVENDOR, 4) != -1) { 337 devlist_entry = malloc(sizeof(struct pci_devinfo), 338 M_DEVBUF, M_WAITOK); 339 if (devlist_entry == NULL) 340 return (NULL); | 60#include <pci/pcireg.h> 61#include <pci/pcivar.h> 62#include <pci/pci_ioctl.h> 63 64#ifdef APIC_IO 65#include <machine/smp.h> 66#endif /* APIC_IO */ 67 --- 272 unchanged lines hidden (view full) --- 340 341 devlist_entry = NULL; 342 343 if (pci_cfgread(probe, PCIR_DEVVENDOR, 4) != -1) { 344 devlist_entry = malloc(sizeof(struct pci_devinfo), 345 M_DEVBUF, M_WAITOK); 346 if (devlist_entry == NULL) 347 return (NULL); |
348 bzero(devlist_entry, sizeof *devlist_entry); |
|
341 342 cfg = &devlist_entry->cfg; 343 | 349 350 cfg = &devlist_entry->cfg; 351 |
344 bzero(cfg, sizeof *cfg); 345 | |
346 cfg->bus = probe->bus; 347 cfg->slot = probe->slot; 348 cfg->func = probe->func; 349 cfg->vendor = pci_cfgread(cfg, PCIR_VENDOR, 2); 350 cfg->device = pci_cfgread(cfg, PCIR_DEVICE, 2); 351 cfg->cmdreg = pci_cfgread(cfg, PCIR_COMMAND, 2); 352 cfg->statreg = pci_cfgread(cfg, PCIR_STATUS, 2); 353 cfg->baseclass = pci_cfgread(cfg, PCIR_CLASS, 1); --- 91 unchanged lines hidden (view full) --- 445 pci_generation++; 446 447 /* we're losing one device */ 448 pci_numdevs--; 449 return (0); 450} 451#endif 452 | 352 cfg->bus = probe->bus; 353 cfg->slot = probe->slot; 354 cfg->func = probe->func; 355 cfg->vendor = pci_cfgread(cfg, PCIR_VENDOR, 2); 356 cfg->device = pci_cfgread(cfg, PCIR_DEVICE, 2); 357 cfg->cmdreg = pci_cfgread(cfg, PCIR_COMMAND, 2); 358 cfg->statreg = pci_cfgread(cfg, PCIR_STATUS, 2); 359 cfg->baseclass = pci_cfgread(cfg, PCIR_CLASS, 1); --- 91 unchanged lines hidden (view full) --- 451 pci_generation++; 452 453 /* we're losing one device */ 454 pci_numdevs--; 455 return (0); 456} 457#endif 458 |
453static void 454pci_addcfg(struct pci_devinfo *dinfo) 455{ 456 if (bootverbose) { 457 int i; 458 pcicfgregs *cfg = &dinfo->cfg; 459 460 printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n", 461 cfg->vendor, cfg->device, cfg->revid); 462 printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n", 463 cfg->baseclass, cfg->subclass, cfg->progif, 464 cfg->hdrtype, cfg->mfdev); 465 printf("\tsubordinatebus=%x \tsecondarybus=%x\n", 466 cfg->subordinatebus, cfg->secondarybus); 467#ifdef PCI_DEBUG 468 printf("\tcmdreg=0x%04x, statreg=0x%04x, cachelnsz=%d (dwords)\n", 469 cfg->cmdreg, cfg->statreg, cfg->cachelnsz); 470 printf("\tlattimer=0x%02x (%d ns), mingnt=0x%02x (%d ns), maxlat=0x%02x (%d ns)\n", 471 cfg->lattimer, cfg->lattimer * 30, 472 cfg->mingnt, cfg->mingnt * 250, cfg->maxlat, cfg->maxlat * 250); 473#endif /* PCI_DEBUG */ 474 if (cfg->intpin > 0) 475 printf("\tintpin=%c, irq=%d\n", cfg->intpin +'a' -1, cfg->intline); 476 477 for (i = 0; i < cfg->nummaps; i++) { 478 pcimap *m = &cfg->map[i]; 479 printf("\tmap[%d]: type %x, range %2d, base %08x, size %2d\n", 480 i, m->type, m->ln2range, m->base, m->ln2size); 481 } 482 } 483 pci_drvattach(dinfo); /* XXX currently defined in pci_compat.c */ 484} 485 486/* scan one PCI bus for devices */ 487 488static int 489pci_probebus(int bus) 490{ 491 pcicfgregs probe; 492 int bushigh = bus; 493 494#ifdef SIMOS 495#undef PCI_SLOTMAX 496#define PCI_SLOTMAX 0 497#endif 498 499 bzero(&probe, sizeof probe); 500 /* XXX KDM */ 501 /* probe.parent = pci_bridgeto(bus); */ 502 probe.bus = bus; 503 for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) { 504 int pcifunchigh = 0; 505 for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) { 506 struct pci_devinfo *dinfo = pci_readcfg(&probe); 507 if (dinfo != NULL) { 508 if (dinfo->cfg.mfdev) 509 pcifunchigh = 7; 510 /* 511 * XXX: Temporarily move pci_addcfg() up before 512 * the use of cfg->subordinatebus. This is 513 * necessary, since pci_addcfg() calls the 514 * device's probe(), which may read the bus# 515 * from some device dependent register of 516 * some host to PCI bridges. The probe will 517 * eventually be moved to pci_readcfg(), and 518 * pci_addcfg() will then be moved back down 519 * below the conditional statement ... 520 */ 521 pci_addcfg(dinfo); 522 523 if (bushigh < dinfo->cfg.subordinatebus) 524 bushigh = dinfo->cfg.subordinatebus; 525 if (bushigh < dinfo->cfg.secondarybus) 526 bushigh = dinfo->cfg.secondarybus; 527 528 /* XXX KDM */ 529 /* cfg = NULL; we don't own this anymore ... */ 530 } 531 } 532 } 533 return (bushigh); 534} 535 536/* scan a PCI bus tree reached through one PCI attachment point */ 537 538int 539pci_probe(pciattach *parent) 540{ 541 int bushigh; 542 int bus = 0; 543 544 STAILQ_INIT(&pci_devq); 545 546 bushigh = pci_bushigh(); 547 while (bus <= bushigh) { 548 int newbushigh; 549 550 printf("Probing for devices on PCI bus %d:\n", bus); 551 newbushigh = pci_probebus(bus); 552 553 if (bushigh < newbushigh) 554 bushigh = newbushigh; 555 bus++; 556 } 557 return (bushigh); 558} 559 | |
560/* 561 * This is the user interface to PCI configuration space. 562 */ 563 564static int 565pci_open(dev_t dev, int oflags, int devtype, struct proc *p) 566{ 567 if ((oflags & FWRITE) && securelevel > 0) { --- 177 unchanged lines hidden (view full) --- 745 sizeof(struct pci_match_conf)) != cio->pat_buf_len){ 746 /* The user made a mistake, return an error*/ 747 cio->status = PCI_GETCONF_ERROR; 748 printf("pci_ioctl: pat_buf_len %d != " 749 "num_patterns (%d) * sizeof(struct " 750 "pci_match_conf) (%d)\npci_ioctl: " 751 "pat_buf_len should be = %d\n", 752 cio->pat_buf_len, cio->num_patterns, | 459/* 460 * This is the user interface to PCI configuration space. 461 */ 462 463static int 464pci_open(dev_t dev, int oflags, int devtype, struct proc *p) 465{ 466 if ((oflags & FWRITE) && securelevel > 0) { --- 177 unchanged lines hidden (view full) --- 644 sizeof(struct pci_match_conf)) != cio->pat_buf_len){ 645 /* The user made a mistake, return an error*/ 646 cio->status = PCI_GETCONF_ERROR; 647 printf("pci_ioctl: pat_buf_len %d != " 648 "num_patterns (%d) * sizeof(struct " 649 "pci_match_conf) (%d)\npci_ioctl: " 650 "pat_buf_len should be = %d\n", 651 cio->pat_buf_len, cio->num_patterns, |
753 sizeof(struct pci_match_conf), 754 sizeof(struct pci_match_conf) * | 652 (int)sizeof(struct pci_match_conf), 653 (int)sizeof(struct pci_match_conf) * |
755 cio->num_patterns); 756 printf("pci_ioctl: do your headers match your " 757 "kernel?\n"); 758 cio->num_matches = 0; 759 error = EINVAL; 760 break; 761 } 762 --- 177 unchanged lines hidden (view full) --- 940#ifdef DEVFS 941 pci_devfs_token = devfs_add_devswf(&pcicdev, 0, DV_CHR, 942 UID_ROOT, GID_WHEEL, 0644, "pci"); 943#endif 944} 945 946SYSINIT(pcidev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+PCI_CDEV, pci_cdevinit, NULL); 947 | 654 cio->num_patterns); 655 printf("pci_ioctl: do your headers match your " 656 "kernel?\n"); 657 cio->num_matches = 0; 658 error = EINVAL; 659 break; 660 } 661 --- 177 unchanged lines hidden (view full) --- 839#ifdef DEVFS 840 pci_devfs_token = devfs_add_devswf(&pcicdev, 0, DV_CHR, 841 UID_ROOT, GID_WHEEL, 0644, "pci"); 842#endif 843} 844 845SYSINIT(pcidev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+PCI_CDEV, pci_cdevinit, NULL); 846 |
847#include "pci_if.h" 848 849/* 850 * A simple driver to wrap the old pci driver mechanism for back-compat. 851 */ 852 853static int 854pci_compat_probe(device_t dev) 855{ 856 struct pci_device *dvp; 857 struct pci_devinfo *dinfo; 858 pcicfgregs *cfg; 859 const char *name; 860 int error; 861 862 dinfo = device_get_ivars(dev); 863 cfg = &dinfo->cfg; 864 dvp = device_get_driver(dev)->priv; 865 866 /* 867 * Do the wrapped probe. 868 */ 869 error = ENXIO; 870 if (dvp && dvp->pd_probe) { 871 name = dvp->pd_probe(cfg, (cfg->device << 16) + cfg->vendor); 872 if (name) { 873 device_set_desc_copy(dev, name); 874 error = 0; 875 } 876 } 877 878 return error; 879} 880 881static int 882pci_compat_attach(device_t dev) 883{ 884 struct pci_device *dvp; 885 struct pci_devinfo *dinfo; 886 pcicfgregs *cfg; 887 int unit; 888 889 dinfo = device_get_ivars(dev); 890 cfg = &dinfo->cfg; 891 dvp = device_get_driver(dev)->priv; 892 893 unit = device_get_unit(dev); 894 if (unit > *dvp->pd_count) 895 *dvp->pd_count = unit; 896 if (dvp->pd_attach) 897 dvp->pd_attach(cfg, unit); 898 899 /* 900 * XXX KDM for some devices, dvp->pd_name winds up NULL. 901 * I haven't investigated enough to figure out why this 902 * would happen. 903 */ 904 if (dvp->pd_name != NULL) 905 strncpy(dinfo->conf.pd_name, dvp->pd_name, 906 sizeof(dinfo->conf.pd_name)); 907 else 908 strncpy(dinfo->conf.pd_name, "????", 909 sizeof(dinfo->conf.pd_name)); 910 dinfo->conf.pd_name[sizeof(dinfo->conf.pd_name) - 1] = 0; 911 dinfo->conf.pd_unit = unit; 912 913 return 0; 914} 915 916static device_method_t pci_compat_methods[] = { 917 /* Device interface */ 918 DEVMETHOD(device_probe, pci_compat_probe), 919 DEVMETHOD(device_attach, pci_compat_attach), 920 921 { 0, 0 } 922}; 923 924static devclass_t pci_devclass; 925 926/* 927 * Create a new style driver around each old pci driver. 928 */ 929static void 930pci_wrap_old_drivers(void) 931{ 932 struct pci_device **dvpp, *dvp; 933 934 dvpp = (struct pci_device **)pcidevice_set.ls_items; 935 while ((dvp = *dvpp++) != NULL) { 936 driver_t *driver; 937 driver = malloc(sizeof(driver_t), M_DEVBUF, M_NOWAIT); 938 if (!driver) 939 continue; 940 bzero(driver, sizeof(driver_t)); 941 driver->name = dvp->pd_name; 942 driver->methods = pci_compat_methods; 943 driver->type = 0; /* XXX fixup in pci_map_int() */ 944 driver->softc = sizeof(struct pci_devinfo *); 945 driver->priv = dvp; 946 devclass_add_driver(pci_devclass, driver); 947 } 948} 949 950/* 951 * New style pci driver. Parent device is either a pci-host-bridge or a 952 * pci-pci-bridge. Both kinds are represented by instances of pcib. 953 */ 954 955static void 956pci_print_verbose(struct pci_devinfo *dinfo) 957{ 958 if (bootverbose) { 959 int i; 960 pcicfgregs *cfg = &dinfo->cfg; 961 962 printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n", 963 cfg->vendor, cfg->device, cfg->revid); 964 printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n", 965 cfg->baseclass, cfg->subclass, cfg->progif, 966 cfg->hdrtype, cfg->mfdev); 967 printf("\tsubordinatebus=%x \tsecondarybus=%x\n", 968 cfg->subordinatebus, cfg->secondarybus); 969#ifdef PCI_DEBUG 970 printf("\tcmdreg=0x%04x, statreg=0x%04x, cachelnsz=%d (dwords)\n", 971 cfg->cmdreg, cfg->statreg, cfg->cachelnsz); 972 printf("\tlattimer=0x%02x (%d ns), mingnt=0x%02x (%d ns), maxlat=0x%02x (%d ns)\n", 973 cfg->lattimer, cfg->lattimer * 30, 974 cfg->mingnt, cfg->mingnt * 250, cfg->maxlat, cfg->maxlat * 250); 975#endif /* PCI_DEBUG */ 976 if (cfg->intpin > 0) 977 printf("\tintpin=%c, irq=%d\n", cfg->intpin +'a' -1, cfg->intline); 978 979 for (i = 0; i < cfg->nummaps; i++) { 980 pcimap *m = &cfg->map[i]; 981 printf("\tmap[%d]: type %x, range %2d, base %08x, size %2d\n", 982 i, m->type, m->ln2range, m->base, m->ln2size); 983 } 984 } 985} 986 987static int 988pci_add_children(device_t dev, int busno) 989{ 990 pcicfgregs probe; 991 int bushigh = busno; 992 993#ifdef SIMOS 994#undef PCI_SLOTMAX 995#define PCI_SLOTMAX 0 996#endif 997 998 bzero(&probe, sizeof probe); 999 /* XXX KDM */ 1000 /* probe.parent = pci_bridgeto(bus); */ 1001 probe.bus = busno; 1002 for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) { 1003 int pcifunchigh = 0; 1004 for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) { 1005 struct pci_devinfo *dinfo = pci_readcfg(&probe); 1006 if (dinfo != NULL) { 1007 if (dinfo->cfg.mfdev) 1008 pcifunchigh = 7; 1009 1010 pci_print_verbose(dinfo); 1011 dinfo->cfg.dev = 1012 device_add_child(dev, NULL, -1, dinfo); 1013 1014 if (bushigh < dinfo->cfg.subordinatebus) 1015 bushigh = dinfo->cfg.subordinatebus; 1016 if (bushigh < dinfo->cfg.secondarybus) 1017 bushigh = dinfo->cfg.secondarybus; 1018 } 1019 } 1020 } 1021 1022 return bushigh; 1023} 1024 1025static int 1026pci_new_probe(device_t dev) 1027{ 1028 STAILQ_INIT(&pci_devq); 1029 device_set_desc(dev, "PCI bus"); 1030 1031 pci_add_children(dev, device_get_unit(dev)); 1032 1033 return 0; 1034} 1035 1036static void 1037pci_print_child(device_t dev, device_t child) 1038{ 1039 printf(" at device %d.%d", pci_get_slot(child), pci_get_function(child)); 1040 printf(" on %s%d", device_get_name(dev), device_get_unit(dev)); 1041} 1042 1043static int 1044pci_read_ivar(device_t dev, device_t child, int which, u_long *result) 1045{ 1046 struct pci_devinfo *dinfo; 1047 pcicfgregs *cfg; 1048 1049 dinfo = device_get_ivars(child); 1050 cfg = &dinfo->cfg; 1051 1052 switch (which) { 1053 case PCI_IVAR_SUBVENDOR: 1054 *result = cfg->subvendor; 1055 break; 1056 case PCI_IVAR_SUBDEVICE: 1057 *result = cfg->subdevice; 1058 break; 1059 case PCI_IVAR_VENDOR: 1060 *result = cfg->vendor; 1061 break; 1062 case PCI_IVAR_DEVICE: 1063 *result = cfg->device; 1064 break; 1065 case PCI_IVAR_DEVID: 1066 *result = (cfg->device << 16) | cfg->vendor; 1067 break; 1068 case PCI_IVAR_CLASS: 1069 *result = cfg->baseclass; 1070 break; 1071 case PCI_IVAR_SUBCLASS: 1072 *result = cfg->subclass; 1073 break; 1074 case PCI_IVAR_PROGIF: 1075 *result = cfg->progif; 1076 break; 1077 case PCI_IVAR_REVID: 1078 *result = cfg->revid; 1079 break; 1080 case PCI_IVAR_INTPIN: 1081 *result = cfg->intpin; 1082 break; 1083 case PCI_IVAR_IRQ: 1084 *result = cfg->intline; 1085 break; 1086 case PCI_IVAR_BUS: 1087 *result = cfg->bus; 1088 break; 1089 case PCI_IVAR_SLOT: 1090 *result = cfg->slot; 1091 break; 1092 case PCI_IVAR_FUNCTION: 1093 *result = cfg->func; 1094 break; 1095 case PCI_IVAR_SECONDARYBUS: 1096 *result = cfg->secondarybus; 1097 break; 1098 case PCI_IVAR_SUBORDINATEBUS: 1099 *result = cfg->subordinatebus; 1100 break; 1101 default: 1102 return ENOENT; 1103 } 1104 return 0; 1105} 1106 1107static int 1108pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 1109{ 1110 struct pci_devinfo *dinfo; 1111 pcicfgregs *cfg; 1112 1113 dinfo = device_get_ivars(child); 1114 cfg = &dinfo->cfg; 1115 1116 switch (which) { 1117 case PCI_IVAR_SUBVENDOR: 1118 case PCI_IVAR_SUBDEVICE: 1119 case PCI_IVAR_VENDOR: 1120 case PCI_IVAR_DEVICE: 1121 case PCI_IVAR_DEVID: 1122 case PCI_IVAR_CLASS: 1123 case PCI_IVAR_SUBCLASS: 1124 case PCI_IVAR_PROGIF: 1125 case PCI_IVAR_REVID: 1126 case PCI_IVAR_INTPIN: 1127 case PCI_IVAR_IRQ: 1128 case PCI_IVAR_BUS: 1129 case PCI_IVAR_SLOT: 1130 case PCI_IVAR_FUNCTION: 1131 return EINVAL; /* disallow for now */ 1132 1133 case PCI_IVAR_SECONDARYBUS: 1134 cfg->secondarybus = value; 1135 break; 1136 case PCI_IVAR_SUBORDINATEBUS: 1137 cfg->subordinatebus = value; 1138 break; 1139 default: 1140 return ENOENT; 1141 } 1142 return 0; 1143} 1144 1145static int 1146pci_mapno(pcicfgregs *cfg, int reg) 1147{ 1148 int i, nummaps; 1149 pcimap *map; 1150 1151 nummaps = cfg->nummaps; 1152 map = cfg->map; 1153 1154 for (i = 0; i < nummaps; i++) 1155 if (map[i].reg == reg) 1156 return (i); 1157 return (-1); 1158} 1159 1160static int 1161pci_porten(pcicfgregs *cfg) 1162{ 1163 return ((cfg->cmdreg & PCIM_CMD_PORTEN) != 0); 1164} 1165 1166static int 1167pci_isportmap(pcicfgregs *cfg, int map) 1168 1169{ 1170 return ((unsigned)map < cfg->nummaps 1171 && (cfg->map[map].type & PCI_MAPPORT) != 0); 1172} 1173 1174static int 1175pci_memen(pcicfgregs *cfg) 1176{ 1177 return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0); 1178} 1179 1180static int 1181pci_ismemmap(pcicfgregs *cfg, int map) 1182{ 1183 return ((unsigned)map < cfg->nummaps 1184 && (cfg->map[map].type & PCI_MAPMEM) != 0); 1185} 1186 1187static struct resource * 1188pci_alloc_resource(device_t dev, device_t child, int type, int *rid, 1189 u_long start, u_long end, u_long count, u_int flags) 1190{ 1191 int isdefault; 1192 struct pci_devinfo *dinfo = device_get_ivars(child); 1193 pcicfgregs *cfg = &dinfo->cfg; 1194 struct resource *rv, **rvp = 0; 1195 int map; 1196 1197 isdefault = (device_get_parent(child) == dev 1198 && start == 0UL && end == ~0UL && count == 1); 1199 1200 switch (type) { 1201 case SYS_RES_IRQ: 1202 if (*rid != 0) 1203 return 0; 1204 if (isdefault && cfg->intline != 255) { 1205 start = cfg->intline; 1206 end = cfg->intline; 1207 count = 1; 1208 } 1209 break; 1210 1211 case SYS_RES_DRQ: /* passthru for child isa */ 1212 break; 1213 1214 case SYS_RES_MEMORY: 1215 if (isdefault) { 1216 map = pci_mapno(cfg, *rid); 1217 if (pci_memen(cfg) && pci_ismemmap(cfg, map)) { 1218 start = cfg->map[map].base; 1219 count = 1 << cfg->map[map].ln2size; 1220 end = start + count; 1221 rvp = &cfg->map[map].res; 1222 } else 1223 return 0; 1224 } 1225 break; 1226 1227 case SYS_RES_IOPORT: 1228 if (isdefault) { 1229 map = pci_mapno(cfg, *rid); 1230 if (pci_porten(cfg) && pci_isportmap(cfg, map)) { 1231 start = cfg->map[map].base; 1232 count = 1 << cfg->map[map].ln2size; 1233 end = start + count; 1234 rvp = &cfg->map[map].res; 1235 } else 1236 return 0; 1237 } 1238 break; 1239 1240 default: 1241 return 0; 1242 } 1243 1244 rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, 1245 type, rid, start, end, count, flags); 1246 if (rvp) 1247 *rvp = rv; 1248 1249 return rv; 1250} 1251 1252static int 1253pci_release_resource(device_t dev, device_t child, int type, int rid, 1254 struct resource *r) 1255{ 1256 int rv; 1257 struct pci_devinfo *dinfo = device_get_ivars(child); 1258 pcicfgregs *cfg = &dinfo->cfg; 1259 int map = 0; 1260 1261 switch (type) { 1262 case SYS_RES_IRQ: 1263 if (rid != 0) 1264 return EINVAL; 1265 break; 1266 1267 case SYS_RES_DRQ: /* passthru for child isa */ 1268 break; 1269 1270 case SYS_RES_MEMORY: 1271 case SYS_RES_IOPORT: 1272 /* 1273 * Only check the map registers if this is a direct 1274 * descendant. 1275 */ 1276 if (device_get_parent(child) == dev) 1277 map = pci_mapno(cfg, rid); 1278 else 1279 map = -1; 1280 break; 1281 1282 default: 1283 return (ENOENT); 1284 } 1285 1286 rv = BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, rid, r); 1287 1288 if (rv == 0) { 1289 switch (type) { 1290 case SYS_RES_IRQ: 1291 cfg->irqres = 0; 1292 break; 1293 1294 case SYS_RES_DRQ: /* passthru for child isa */ 1295 break; 1296 1297 case SYS_RES_MEMORY: 1298 case SYS_RES_IOPORT: 1299 if (map != -1) 1300 cfg->map[map].res = 0; 1301 break; 1302 1303 default: 1304 return ENOENT; 1305 } 1306 } 1307 1308 return rv; 1309} 1310 1311static u_int32_t 1312pci_read_config_method(device_t dev, device_t child, int reg, int width) 1313{ 1314 struct pci_devinfo *dinfo = device_get_ivars(child); 1315 pcicfgregs *cfg = &dinfo->cfg; 1316 return pci_cfgread(cfg, reg, width); 1317} 1318 1319static void 1320pci_write_config_method(device_t dev, device_t child, int reg, 1321 u_int32_t val, int width) 1322{ 1323 struct pci_devinfo *dinfo = device_get_ivars(child); 1324 pcicfgregs *cfg = &dinfo->cfg; 1325 pci_cfgwrite(cfg, reg, val, width); 1326} 1327 1328static int 1329pci_modevent(module_t mod, int what, void *arg) 1330{ 1331 switch (what) { 1332 case MOD_LOAD: 1333 pci_wrap_old_drivers(); 1334 break; 1335 1336 case MOD_UNLOAD: 1337 break; 1338 } 1339 1340 return 0; 1341} 1342 1343static device_method_t pci_methods[] = { 1344 /* Device interface */ 1345 DEVMETHOD(device_probe, pci_new_probe), 1346 DEVMETHOD(device_attach, bus_generic_attach), 1347 DEVMETHOD(device_shutdown, bus_generic_shutdown), 1348 1349 /* Bus interface */ 1350 DEVMETHOD(bus_print_child, pci_print_child), 1351 DEVMETHOD(bus_read_ivar, pci_read_ivar), 1352 DEVMETHOD(bus_write_ivar, pci_write_ivar), 1353 DEVMETHOD(bus_driver_added, bus_generic_driver_added), 1354 DEVMETHOD(bus_alloc_resource, pci_alloc_resource), 1355 DEVMETHOD(bus_release_resource, pci_release_resource), 1356 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 1357 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 1358 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 1359 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 1360 1361 /* PCI interface */ 1362 DEVMETHOD(pci_read_config, pci_read_config_method), 1363 DEVMETHOD(pci_write_config, pci_write_config_method), 1364 1365 { 0, 0 } 1366}; 1367 1368static driver_t pci_driver = { 1369 "pci", 1370 pci_methods, 1371 DRIVER_TYPE_MISC, 1372 1, /* no softc */ 1373}; 1374 1375DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, 0); 1376 |
|
948#endif /* NPCI > 0 */ | 1377#endif /* NPCI > 0 */ |