static void do_pci_device(config_t *cpe, struct rs_start *rs_start)
{
- u16_t vid, did;
+ u16_t vid, did, sub_vid, sub_did;
char *check, *check2;
/* Process a list of PCI device IDs */
cpe->file, cpe->line);
}
vid= strtoul(cpe->word, &check, 0x10);
- if (check[0] == '/')
- did= strtoul(check+1, &check2, 0x10);
- if (check[0] != '/' || check2[0] != '\0')
- {
+ if (check[0] != ':' && /* LEGACY: */ check[0] != '/') {
+ fatal("do_pci_device: bad ID '%s' at %s:%d",
+ cpe->word, cpe->file, cpe->line);
+ }
+ did= strtoul(check+1, &check, 0x10);
+ if (check[0] == '/') {
+ sub_vid= strtoul(check+1, &check, 0x10);
+ if (check[0] == ':')
+ sub_did= strtoul(check+1, &check2, 0x10);
+ if (check[0] != ':' || check2[0] != '\0') {
+ fatal("do_pci_device: bad ID '%s' at %s:%d",
+ cpe->word, cpe->file, cpe->line);
+ }
+ } else if (check[0] != '\0') {
fatal("do_pci_device: bad ID '%s' at %s:%d",
cpe->word, cpe->file, cpe->line);
+ } else {
+ sub_vid = NO_SUB_VID;
+ sub_did = NO_SUB_DID;
}
if (rs_start->rss_nr_pci_id >= RS_NR_PCI_DEVICE)
{
}
rs_start->rss_pci_id[rs_start->rss_nr_pci_id].vid= vid;
rs_start->rss_pci_id[rs_start->rss_nr_pci_id].did= did;
+ rs_start->rss_pci_id[rs_start->rss_nr_pci_id].sub_vid= sub_vid;
+ rs_start->rss_pci_id[rs_start->rss_nr_pci_id].sub_did= sub_did;
rs_start->rss_nr_pci_id++;
}
}
u8_t pd_infclass;
u16_t pd_vid;
u16_t pd_did;
+ u16_t pd_sub_vid;
+ u16_t pd_sub_did;
u8_t pd_ilr;
u8_t pd_inuse;
dstr= "unknown device";
if (debug)
{
- printf("pci_intel_init: %s (%04X/%04X)\n",
+ printf("pci_intel_init: %s (%04X:%04X)\n",
dstr, vid, did);
}
static void probe_bus(int busind)
{
u32_t dev, func, t3;
- u16_t vid, did, sts;
+ u16_t vid, did, sts, sub_vid, sub_did;
u8_t headt;
u8_t baseclass, subclass, infclass;
int devind, busnr;
}
}
+ sub_vid= pci_attr_r16(devind, PCI_SUBVID);
+ sub_did= pci_attr_r16(devind, PCI_SUBDID);
+
dstr= pci_dev_name(vid, did);
if (debug)
{
if (dstr)
{
- printf("%d.%lu.%lu: %s (%04X/%04X)\n",
+ printf("%d.%lu.%lu: %s (%04X:%04X)\n",
busnr, (unsigned long)dev,
(unsigned long)func, dstr,
vid, did);
}
printf("Device index: %d\n", devind);
printf("Subsystem: Vid 0x%x, did 0x%x\n",
- pci_attr_r16(devind, PCI_SUBVID),
- pci_attr_r16(devind, PCI_SUBDID));
+ sub_vid, sub_did);
}
baseclass= pci_attr_r8_u(devind, PCI_BCR);
pcidev[devind].pd_infclass= infclass;
pcidev[devind].pd_vid= vid;
pcidev[devind].pd_did= did;
+ pcidev[devind].pd_sub_vid= sub_vid;
+ pcidev[devind].pd_sub_did= sub_did;
pcidev[devind].pd_inuse= 0;
pcidev[devind].pd_bar_nr= 0;
record_irq(devind);
if (debug)
{
printf(
- "pci device %d (%04x/%04x), bar %d: base 0x%x, size 0x%x\n",
+ "pci device %d (%04x:%04x), bar %d: base 0x%x, size 0x%x\n",
i, pcidev[i].pd_vid, pcidev[i].pd_did,
j, base, size);
}
dstr= "unknown device";
if (debug)
{
- printf("found ISA bridge (%04X/%04X) %s\n",
+ printf("found ISA bridge (%04X:%04X) %s\n",
vid, did, dstr);
}
pcibus[busind].pb_isabridge_dev= bridge_dev;
if (debug)
{
printf(
- "(warning) unsupported ISA bridge %04X/%04X for bus %d\n",
+ "(warning) unsupported ISA bridge %04X:%04X for bus %d\n",
pcidev[unknown_bridge].pd_vid,
pcidev[unknown_bridge].pd_did, busind);
}
t3 != PCI_T3_PCI2PCI_SUBTR)
{
printf(
-"Unknown PCI class %02x:%02x:%02x for PCI-to-PCI bridge, device %04X/%04X\n",
+"Unknown PCI class %02x/%02x/%02x for PCI-to-PCI bridge, device %04X:%04X\n",
baseclass, subclass, infclass,
vid, did);
continue;
t3 != PCI_T3_CARDBUS)
{
printf(
-"Unknown PCI class %02x:%02x:%02x for Cardbus bridge, device %04X/%04X\n",
+"Unknown PCI class %02x/%02x/%02x for Cardbus bridge, device %04X:%04X\n",
baseclass, subclass, infclass,
vid, did);
continue;
if (debug)
{
- printf("%u.%u.%u: PCI-to-PCI bridge: %04X/%04X\n",
+ printf("%u.%u.%u: PCI-to-PCI bridge: %04X:%04X\n",
pcidev[devind].pd_busnr,
pcidev[devind].pd_dev,
pcidev[devind].pd_func, vid, did);
struct rs_pci *aclp;
int devind;
{
+ u16_t acl_sub_vid, acl_sub_did;
int i;
u32_t class_id;
/* Check whether the caller is allowed to get this device. */
for (i= 0; i<aclp->rsp_nr_device; i++)
{
+ acl_sub_vid = aclp->rsp_device[i].sub_vid;
+ acl_sub_did = aclp->rsp_device[i].sub_did;
if (aclp->rsp_device[i].vid == pcidev[devind].pd_vid &&
- aclp->rsp_device[i].did == pcidev[devind].pd_did)
+ aclp->rsp_device[i].did == pcidev[devind].pd_did &&
+ (acl_sub_vid == NO_SUB_VID ||
+ acl_sub_vid == pcidev[devind].pd_sub_vid) &&
+ (acl_sub_did == NO_SUB_DID ||
+ acl_sub_did == pcidev[devind].pd_sub_did))
{
return TRUE;
}
size_t l_len;
};
+struct rs_pci_id {
+ u16_t vid;
+ u16_t did;
+ u16_t sub_vid;
+ u16_t sub_did;
+};
+#define NO_SUB_VID 0xffff
+#define NO_SUB_DID 0xffff
+
+struct rs_pci_class {
+ u32_t pciclass;
+ u32_t mask;
+};
+
/* Arguments needed to start a new driver or server */
struct rs_start
{
int rss_nr_io;
struct { unsigned base; unsigned len; } rss_io[RSS_NR_IO];
int rss_nr_pci_id;
- struct { u16_t vid; u16_t did; } rss_pci_id[RS_NR_PCI_DEVICE];
+ struct rs_pci_id rss_pci_id[RS_NR_PCI_DEVICE];
int rss_nr_pci_class;
- struct { u32_t pciclass; u32_t mask; } rss_pci_class[RS_NR_PCI_CLASS];
+ struct rs_pci_class rss_pci_class[RS_NR_PCI_CLASS];
bitchunk_t rss_system[SYS_CALL_MASK_SIZE];
struct rss_label rss_label;
char *rss_ipc;
char rsp_label[RS_MAX_LABEL_LEN];
int rsp_endpoint;
int rsp_nr_device;
- struct { u16_t vid; u16_t did; } rsp_device[RS_NR_PCI_DEVICE];
+ struct rs_pci_id rsp_device[RS_NR_PCI_DEVICE];
int rsp_nr_class;
- struct { u32_t pciclass; u32_t mask; } rsp_class[RS_NR_PCI_CLASS];
+ struct rs_pci_class rsp_class[RS_NR_PCI_CLASS];
};
/* Definition of a public entry of the system process table. */
The default is specified in \fB<minix/priv.h>\fR (see macro \fBDSRV_QT\fR).
.RE
.PP
-\fBpci device\fR \fI<vid/did>\fR\fB;\fR
+\fBpci device\fR \fI<vid:did[/subvid:subdid]>\fR\fB;\fR
.PP
.RS
specifies the PCI device IDs the system service is allowed to use
-(only used for device drivers).
+(only used for device drivers). Optionally, a subsystem ID may be provided
+for more precise (limited) matching.
The default is to allow no PCI device IDs.
.RE
.PP
-\fBpci class\fR \fI<class1/mask1 class2/mask2...classN/maskN>\fR\fB;\fR
+\fBpci class\fR \fI<class[/subclass[/progif]]>\fR\fB;\fR
.PP
.RS
specifies the PCI classes the system service is allowed to use
(only used for device drivers).
+Optionally, a subclass code and a programming interface code may be provided
+for more precise (limited) matching.
The default is to allow no PCI classes.
.RE
.PP
for (i= 0; i<rpub->pci_acl.rsp_nr_device; i++) {
rpub->pci_acl.rsp_device[i].vid= rs_start->rss_pci_id[i].vid;
rpub->pci_acl.rsp_device[i].did= rs_start->rss_pci_id[i].did;
+ rpub->pci_acl.rsp_device[i].sub_vid= rs_start->rss_pci_id[i].sub_vid;
+ rpub->pci_acl.rsp_device[i].sub_did= rs_start->rss_pci_id[i].sub_did;
if(rs_verbose)
- printf("RS: init_slot: PCI %04x/%04x\n",
+ printf("RS: init_slot: PCI %04x/%04x (sub %04x:%04x)\n",
rpub->pci_acl.rsp_device[i].vid,
- rpub->pci_acl.rsp_device[i].did);
+ rpub->pci_acl.rsp_device[i].did,
+ rpub->pci_acl.rsp_device[i].sub_vid,
+ rpub->pci_acl.rsp_device[i].sub_did);
}
if (rs_start->rss_nr_pci_class > RS_NR_PCI_CLASS) {
printf("RS: init_slot: too many PCI class IDs\n");