1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
/*
* Purpose: Wrapper functions for PCI drivers under FreeBSD
*/
/*
* Copyright (C) 4Front Technologies 2005-2007. Released under BSD license.
*/
#include <dev/pci/pcivar.h> /* For pci_get macros! */
#include <dev/pci/pcireg.h>
/* PCI Support Functions */
static oss_device_t *device_list[16];
static device_t bsd_devices[16];
static int ndevs = 0;
/*
* Compare the device ID of this device against the IDs that this driver
* supports. If there is a match, set the description and return success.
*/
static int
osspci_probe (device_t dev)
{
#ifdef DEVTYPE_PCI
int i, ok = 0;
int vendor, device, class;
oss_device_t *osdev;
for (i = 0; i < ndevs; i++)
if (dev == bsd_devices[i]) /* Already detected */
{
return ENXIO;
}
if (ndevs >= 16)
{
printf (DRIVER_NICK ": Too many instances\n");
return ENXIO;
}
vendor = pci_get_vendor (dev);
device = pci_get_device (dev);
class = pci_get_class (dev);
// printf("PCI dev %08lx c=%x, v=%04x, d=%04x\n", (unsigned long)dev, class, vendor, device);
if (class != 4) /* Not a multimedia device */
return ENXIO;
for (i = 0; id_table[i].vendor != 0; i++)
if (vendor == id_table[i].vendor && device == id_table[i].device) /* Match */
{
ok = 1;
break;
}
if (!ok)
{
return (ENXIO);
}
if ((osdev =
osdev_create (dev, DRIVER_TYPE, ndevs, DRIVER_NICK, NULL)) == NULL)
{
return ENOMEM;
}
if (!DRIVER_ATTACH (osdev))
return EIO;
bsd_devices[ndevs] = dev;
device_list[ndevs++] = osdev;
#endif
return (BUS_PROBE_DEFAULT);
}
/* Attach function is only called if the probe is successful */
static int
osspci_attach (device_t dev)
{
return 0;
}
/* Detach device. */
static int
osspci_detach (device_t dev)
{
oss_device_t *osdev;
int i;
for (i = 0; i < ndevs; i++)
{
osdev = device_list[i];
if (osdev->dip == dev)
{
if (device_get_state(dev) == DS_BUSY)
device_unbusy(dev);
if (!DRIVER_DETACH (osdev))
{
printf (DRIVER_NICK ": Unloading busy device\n");
return EBUSY;
}
osdev_delete (osdev);
}
}
return (0);
}
/* Called during system shutdown after sync. */
static int
osspci_shutdown (device_t dev)
{
printf ("Mypci shutdown!\n");
return (0);
}
/*
* Device suspend routine.
*/
static int
osspci_suspend (device_t dev)
{
printf ("Mypci suspend!\n");
return (0);
}
/*
* Device resume routine.
*/
static int
osspci_resume (device_t dev)
{
printf ("Mypci resume!\n");
return (0);
}
static device_method_t osspci_methods[] = {
/* Device interface */
DEVMETHOD (device_probe, osspci_probe),
DEVMETHOD (device_attach, osspci_attach),
DEVMETHOD (device_detach, osspci_detach),
DEVMETHOD (device_shutdown, osspci_shutdown),
DEVMETHOD (device_suspend, osspci_suspend),
DEVMETHOD (device_resume, osspci_resume),
{0, 0}
};
static devclass_t osspci_devclass;
|