summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/pci/pci_user.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-11-06 16:20:21 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-11-11 10:08:08 +0100
commit66659ff1ad6831b0ea7425fa6ecd8a8687523658 (patch)
tree48e22b475fa8854128e0861a33fed6f78c8094b5 /freebsd/sys/dev/pci/pci_user.c
parentDefine __GLOBL1() and __GLOBL() (diff)
downloadrtems-libbsd-66659ff1ad6831b0ea7425fa6ecd8a8687523658.tar.bz2
Update to FreeBSD 9.2
Diffstat (limited to 'freebsd/sys/dev/pci/pci_user.c')
-rw-r--r--freebsd/sys/dev/pci/pci_user.c246
1 files changed, 232 insertions, 14 deletions
diff --git a/freebsd/sys/dev/pci/pci_user.c b/freebsd/sys/dev/pci/pci_user.c
index c2723ad3..63d64c39 100644
--- a/freebsd/sys/dev/pci/pci_user.c
+++ b/freebsd/sys/dev/pci/pci_user.c
@@ -227,6 +227,51 @@ struct pci_io_old {
u_int32_t pi_data; /* data to write or result of read */
};
+#ifdef COMPAT_FREEBSD32
+struct pci_conf_old32 {
+ struct pcisel_old pc_sel; /* bus+slot+function */
+ uint8_t pc_hdr; /* PCI header type */
+ uint16_t pc_subvendor; /* card vendor ID */
+ uint16_t pc_subdevice; /* card device ID, assigned by
+ card vendor */
+ uint16_t pc_vendor; /* chip vendor ID */
+ uint16_t pc_device; /* chip device ID, assigned by
+ chip vendor */
+ uint8_t pc_class; /* chip PCI class */
+ uint8_t pc_subclass; /* chip PCI subclass */
+ uint8_t pc_progif; /* chip PCI programming interface */
+ uint8_t pc_revid; /* chip revision ID */
+ char pd_name[PCI_MAXNAMELEN + 1]; /* device name */
+ uint32_t pd_unit; /* device unit number (u_long) */
+};
+
+struct pci_match_conf_old32 {
+ struct pcisel_old pc_sel; /* bus+slot+function */
+ char pd_name[PCI_MAXNAMELEN + 1]; /* device name */
+ uint32_t pd_unit; /* Unit number (u_long) */
+ uint16_t pc_vendor; /* PCI Vendor ID */
+ uint16_t pc_device; /* PCI Device ID */
+ uint8_t pc_class; /* PCI class */
+ pci_getconf_flags_old flags; /* Matching expression */
+};
+
+struct pci_conf_io32 {
+ uint32_t pat_buf_len; /* pattern buffer length */
+ uint32_t num_patterns; /* number of patterns */
+ uint32_t patterns; /* pattern buffer
+ (struct pci_match_conf_old32 *) */
+ uint32_t match_buf_len; /* match buffer length */
+ uint32_t num_matches; /* number of matches returned */
+ uint32_t matches; /* match buffer
+ (struct pci_conf_old32 *) */
+ uint32_t offset; /* offset into device list */
+ uint32_t generation; /* device list generation */
+ pci_getconf_status status; /* request status */
+};
+
+#define PCIOCGETCONF_OLD32 _IOWR('p', 1, struct pci_conf_io32)
+#endif /* COMPAT_FREEBSD32 */
+
#define PCIOCGETCONF_OLD _IOWR('p', 1, struct pci_conf_io)
#define PCIOCREAD_OLD _IOWR('p', 2, struct pci_io_old)
#define PCIOCWRITE_OLD _IOWR('p', 3, struct pci_io_old)
@@ -297,7 +342,71 @@ pci_conf_match_old(struct pci_match_conf_old *matches, int num_matches,
return(1);
}
-#endif
+#ifdef COMPAT_FREEBSD32
+static int
+pci_conf_match_old32(struct pci_match_conf_old32 *matches, int num_matches,
+ struct pci_conf *match_buf)
+{
+ int i;
+
+ if ((matches == NULL) || (match_buf == NULL) || (num_matches <= 0))
+ return(1);
+
+ for (i = 0; i < num_matches; i++) {
+ if (match_buf->pc_sel.pc_domain != 0)
+ continue;
+
+ /*
+ * I'm not sure why someone would do this...but...
+ */
+ if (matches[i].flags == PCI_GETCONF_NO_MATCH_OLD)
+ continue;
+
+ /*
+ * Look at each of the match flags. If it's set, do the
+ * comparison. If the comparison fails, we don't have a
+ * match, go on to the next item if there is one.
+ */
+ if (((matches[i].flags & PCI_GETCONF_MATCH_BUS_OLD) != 0) &&
+ (match_buf->pc_sel.pc_bus != matches[i].pc_sel.pc_bus))
+ continue;
+
+ if (((matches[i].flags & PCI_GETCONF_MATCH_DEV_OLD) != 0) &&
+ (match_buf->pc_sel.pc_dev != matches[i].pc_sel.pc_dev))
+ continue;
+
+ if (((matches[i].flags & PCI_GETCONF_MATCH_FUNC_OLD) != 0) &&
+ (match_buf->pc_sel.pc_func != matches[i].pc_sel.pc_func))
+ continue;
+
+ if (((matches[i].flags & PCI_GETCONF_MATCH_VENDOR_OLD) != 0) &&
+ (match_buf->pc_vendor != matches[i].pc_vendor))
+ continue;
+
+ if (((matches[i].flags & PCI_GETCONF_MATCH_DEVICE_OLD) != 0) &&
+ (match_buf->pc_device != matches[i].pc_device))
+ continue;
+
+ if (((matches[i].flags & PCI_GETCONF_MATCH_CLASS_OLD) != 0) &&
+ (match_buf->pc_class != matches[i].pc_class))
+ continue;
+
+ if (((matches[i].flags & PCI_GETCONF_MATCH_UNIT_OLD) != 0) &&
+ ((u_int32_t)match_buf->pd_unit != matches[i].pd_unit))
+ continue;
+
+ if (((matches[i].flags & PCI_GETCONF_MATCH_NAME_OLD) != 0) &&
+ (strncmp(matches[i].pd_name, match_buf->pd_name,
+ sizeof(match_buf->pd_name)) != 0))
+ continue;
+
+ return (0);
+ }
+
+ return (1);
+}
+#endif /* COMPAT_FREEBSD32 */
+#endif /* PRE7_COMPAT */
static int
pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
@@ -306,7 +415,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
void *confdata;
const char *name;
struct devlist *devlist_head;
- struct pci_conf_io *cio;
+ struct pci_conf_io *cio = NULL;
struct pci_devinfo *dinfo;
struct pci_io *io;
struct pci_bar_io *bio;
@@ -315,13 +424,17 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
size_t confsz, iolen, pbufsz;
int error, ionum, i, num_patterns;
#ifdef PRE7_COMPAT
+#ifdef COMPAT_FREEBSD32
+ struct pci_conf_io32 *cio32 = NULL;
+ struct pci_conf_old32 conf_old32;
+ struct pci_match_conf_old32 *pattern_buf_old32 = NULL;
+#endif
struct pci_conf_old conf_old;
struct pci_io iodata;
struct pci_io_old *io_old;
- struct pci_match_conf_old *pattern_buf_old;
+ struct pci_match_conf_old *pattern_buf_old = NULL;
io_old = NULL;
- pattern_buf_old = NULL;
if (!(flag & FWRITE) && cmd != PCIOCGETBAR &&
cmd != PCIOCGETCONF && cmd != PCIOCGETCONF_OLD)
@@ -333,11 +446,36 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
switch(cmd) {
#ifdef PRE7_COMPAT
+#ifdef COMPAT_FREEBSD32
+ case PCIOCGETCONF_OLD32:
+ cio32 = (struct pci_conf_io32 *)data;
+ cio = malloc(sizeof(struct pci_conf_io), M_TEMP, M_WAITOK);
+ cio->pat_buf_len = cio32->pat_buf_len;
+ cio->num_patterns = cio32->num_patterns;
+ cio->patterns = (void *)(uintptr_t)cio32->patterns;
+ cio->match_buf_len = cio32->match_buf_len;
+ cio->num_matches = cio32->num_matches;
+ cio->matches = (void *)(uintptr_t)cio32->matches;
+ cio->offset = cio32->offset;
+ cio->generation = cio32->generation;
+ cio->status = cio32->status;
+ cio32->num_matches = 0;
+ break;
+#endif
case PCIOCGETCONF_OLD:
- /* FALLTHROUGH */
#endif
case PCIOCGETCONF:
cio = (struct pci_conf_io *)data;
+ }
+
+ switch(cmd) {
+#ifdef PRE7_COMPAT
+#ifdef COMPAT_FREEBSD32
+ case PCIOCGETCONF_OLD32:
+#endif
+ case PCIOCGETCONF_OLD:
+#endif
+ case PCIOCGETCONF:
pattern_buf = NULL;
num_patterns = 0;
@@ -355,7 +493,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
&& (cio->generation != pci_generation)){
cio->status = PCI_GETCONF_LIST_CHANGED;
error = 0;
- break;
+ goto getconfexit;
}
/*
@@ -365,7 +503,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
if (cio->offset >= pci_numdevs) {
cio->status = PCI_GETCONF_LAST_DEVICE;
error = 0;
- break;
+ goto getconfexit;
}
/* get the head of the device queue */
@@ -378,6 +516,11 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
* didn't specify a multiple of that size.
*/
#ifdef PRE7_COMPAT
+#ifdef COMPAT_FREEBSD32
+ if (cmd == PCIOCGETCONF_OLD32)
+ confsz = sizeof(struct pci_conf_old32);
+ else
+#endif
if (cmd == PCIOCGETCONF_OLD)
confsz = sizeof(struct pci_conf_old);
else
@@ -412,6 +555,11 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
* updated their kernel but not their userland.
*/
#ifdef PRE7_COMPAT
+#ifdef COMPAT_FREEBSD32
+ if (cmd == PCIOCGETCONF_OLD32)
+ pbufsz = sizeof(struct pci_match_conf_old32);
+ else
+#endif
if (cmd == PCIOCGETCONF_OLD)
pbufsz = sizeof(struct pci_match_conf_old);
else
@@ -421,20 +569,28 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
/* The user made a mistake, return an error. */
cio->status = PCI_GETCONF_ERROR;
error = EINVAL;
- break;
+ goto getconfexit;
}
/*
* Allocate a buffer to hold the patterns.
*/
#ifdef PRE7_COMPAT
+#ifdef COMPAT_FREEBSD32
+ if (cmd == PCIOCGETCONF_OLD32) {
+ pattern_buf_old32 = malloc(cio->pat_buf_len,
+ M_TEMP, M_WAITOK);
+ error = copyin(cio->patterns,
+ pattern_buf_old32, cio->pat_buf_len);
+ } else
+#endif /* COMPAT_FREEBSD32 */
if (cmd == PCIOCGETCONF_OLD) {
pattern_buf_old = malloc(cio->pat_buf_len,
M_TEMP, M_WAITOK);
error = copyin(cio->patterns,
pattern_buf_old, cio->pat_buf_len);
} else
-#endif
+#endif /* PRE7_COMPAT */
{
pattern_buf = malloc(cio->pat_buf_len, M_TEMP,
M_WAITOK);
@@ -453,7 +609,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
*/
cio->status = PCI_GETCONF_ERROR;
error = EINVAL;
- break;
+ goto getconfexit;
}
/*
@@ -485,7 +641,14 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
}
#ifdef PRE7_COMPAT
- if ((cmd == PCIOCGETCONF_OLD &&
+ if (
+#ifdef COMPAT_FREEBSD32
+ (cmd == PCIOCGETCONF_OLD32 &&
+ (pattern_buf_old32 == NULL ||
+ pci_conf_match_old32(pattern_buf_old32,
+ num_patterns, &dinfo->conf) == 0)) ||
+#endif
+ (cmd == PCIOCGETCONF_OLD &&
(pattern_buf_old == NULL ||
pci_conf_match_old(pattern_buf_old, num_patterns,
&dinfo->conf) == 0)) ||
@@ -510,6 +673,40 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
break;
#ifdef PRE7_COMPAT
+#ifdef COMPAT_FREEBSD32
+ if (cmd == PCIOCGETCONF_OLD32) {
+ conf_old32.pc_sel.pc_bus =
+ dinfo->conf.pc_sel.pc_bus;
+ conf_old32.pc_sel.pc_dev =
+ dinfo->conf.pc_sel.pc_dev;
+ conf_old32.pc_sel.pc_func =
+ dinfo->conf.pc_sel.pc_func;
+ conf_old32.pc_hdr = dinfo->conf.pc_hdr;
+ conf_old32.pc_subvendor =
+ dinfo->conf.pc_subvendor;
+ conf_old32.pc_subdevice =
+ dinfo->conf.pc_subdevice;
+ conf_old32.pc_vendor =
+ dinfo->conf.pc_vendor;
+ conf_old32.pc_device =
+ dinfo->conf.pc_device;
+ conf_old32.pc_class =
+ dinfo->conf.pc_class;
+ conf_old32.pc_subclass =
+ dinfo->conf.pc_subclass;
+ conf_old32.pc_progif =
+ dinfo->conf.pc_progif;
+ conf_old32.pc_revid =
+ dinfo->conf.pc_revid;
+ strncpy(conf_old32.pd_name,
+ dinfo->conf.pd_name,
+ sizeof(conf_old32.pd_name));
+ conf_old32.pd_name[PCI_MAXNAMELEN] = 0;
+ conf_old32.pd_unit =
+ (uint32_t)dinfo->conf.pd_unit;
+ confdata = &conf_old32;
+ } else
+#endif /* COMPAT_FREEBSD32 */
if (cmd == PCIOCGETCONF_OLD) {
conf_old.pc_sel.pc_bus =
dinfo->conf.pc_sel.pc_bus;
@@ -542,7 +739,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
dinfo->conf.pd_unit;
confdata = &conf_old;
} else
-#endif
+#endif /* PRE7_COMPAT */
confdata = &dinfo->conf;
/* Only if we can copy it out do we count it. */
if (!(error = copyout(confdata,
@@ -576,12 +773,23 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
cio->status = PCI_GETCONF_MORE_DEVS;
getconfexit:
- if (pattern_buf != NULL)
- free(pattern_buf, M_TEMP);
#ifdef PRE7_COMPAT
+#ifdef COMPAT_FREEBSD32
+ if (cmd == PCIOCGETCONF_OLD32) {
+ cio32->status = cio->status;
+ cio32->generation = cio->generation;
+ cio32->offset = cio->offset;
+ cio32->num_matches = cio->num_matches;
+ free(cio, M_TEMP);
+ }
+ if (pattern_buf_old32 != NULL)
+ free(pattern_buf_old32, M_TEMP);
+#endif
if (pattern_buf_old != NULL)
free(pattern_buf_old, M_TEMP);
#endif
+ if (pattern_buf != NULL)
+ free(pattern_buf, M_TEMP);
break;
@@ -696,6 +904,16 @@ getconfexit:
bio->pbi_enabled = pci_bar_enabled(pcidev, pm);
error = 0;
break;
+ case PCIOCATTACHED:
+ error = 0;
+ io = (struct pci_io *)data;
+ pcidev = pci_find_dbsf(io->pi_sel.pc_domain, io->pi_sel.pc_bus,
+ io->pi_sel.pc_dev, io->pi_sel.pc_func);
+ if (pcidev != NULL)
+ io->pi_data = device_is_attached(pcidev);
+ else
+ error = ENODEV;
+ break;
default:
error = ENOTTY;
break;