From owner-svn-src-stable-9@FreeBSD.ORG Fri Jul 12 18:02:11 2013 Return-Path: Delivered-To: svn-src-stable-9@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 1DDAAE4E; Fri, 12 Jul 2013 18:02:11 +0000 (UTC) (envelope-from marius@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 0F084137B; Fri, 12 Jul 2013 18:02:11 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r6CI2A7l094956; Fri, 12 Jul 2013 18:02:10 GMT (envelope-from marius@svn.freebsd.org) Received: (from marius@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r6CI2Agj094955; Fri, 12 Jul 2013 18:02:10 GMT (envelope-from marius@svn.freebsd.org) Message-Id: <201307121802.r6CI2Agj094955@svn.freebsd.org> From: Marius Strobl Date: Fri, 12 Jul 2013 18:02:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r253278 - stable/9/sys/dev/pci X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-9@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for only the 9-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 12 Jul 2013 18:02:11 -0000 Author: marius Date: Fri Jul 12 18:02:10 2013 New Revision: 253278 URL: http://svnweb.freebsd.org/changeset/base/253278 Log: MFC: r240981, r240990, r240992, r244695 Add 32-bit ABI compat shims. Those are necessary for i386 binary-only tools like sysutils/hpacucli (HP P4xx RAID controller management suite) working on amd64 systems. PR: 139271 Submitted by: Kazumi MORINAGA, Eugene Grosbein Approved by: re (kib) Modified: stable/9/sys/dev/pci/pci_user.c Directory Properties: stable/9/sys/ (props changed) stable/9/sys/dev/ (props changed) Modified: stable/9/sys/dev/pci/pci_user.c ============================================================================== --- stable/9/sys/dev/pci/pci_user.c Fri Jul 12 17:37:05 2013 (r253277) +++ stable/9/sys/dev/pci/pci_user.c Fri Jul 12 18:02:10 2013 (r253278) @@ -225,6 +225,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) @@ -295,7 +340,71 @@ pci_conf_match_old(struct pci_match_conf 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) @@ -304,7 +413,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, 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; @@ -313,13 +422,17 @@ pci_ioctl(struct cdev *dev, u_long cmd, 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) @@ -331,11 +444,36 @@ pci_ioctl(struct cdev *dev, u_long cmd, 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; @@ -353,7 +491,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, && (cio->generation != pci_generation)){ cio->status = PCI_GETCONF_LIST_CHANGED; error = 0; - break; + goto getconfexit; } /* @@ -363,7 +501,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, if (cio->offset >= pci_numdevs) { cio->status = PCI_GETCONF_LAST_DEVICE; error = 0; - break; + goto getconfexit; } /* get the head of the device queue */ @@ -376,6 +514,11 @@ pci_ioctl(struct cdev *dev, u_long cmd, * 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 @@ -410,6 +553,11 @@ pci_ioctl(struct cdev *dev, u_long cmd, * 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 @@ -419,20 +567,28 @@ pci_ioctl(struct cdev *dev, u_long cmd, /* 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); @@ -451,7 +607,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, */ cio->status = PCI_GETCONF_ERROR; error = EINVAL; - break; + goto getconfexit; } /* @@ -483,7 +639,14 @@ pci_ioctl(struct cdev *dev, u_long cmd, } #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)) || @@ -508,6 +671,40 @@ pci_ioctl(struct cdev *dev, u_long cmd, 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; @@ -540,7 +737,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, 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, @@ -574,12 +771,23 @@ pci_ioctl(struct cdev *dev, u_long cmd, 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;