Deleted Added
full compact
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 */