From nobody@FreeBSD.org  Thu Oct  1 06:45:59 2009
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 36F80106566B
	for <freebsd-gnats-submit@FreeBSD.org>; Thu,  1 Oct 2009 06:45:59 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 247478FC13
	for <freebsd-gnats-submit@FreeBSD.org>; Thu,  1 Oct 2009 06:45:59 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n916jwtD072272
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 1 Oct 2009 06:45:58 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id n916jwlG072271;
	Thu, 1 Oct 2009 06:45:58 GMT
	(envelope-from nobody)
Message-Id: <200910010645.n916jwlG072271@www.freebsd.org>
Date: Thu, 1 Oct 2009 06:45:58 GMT
From: Kazumi MORINAGA <morinaga@riken.jp>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [PATCH] hpacucli does not work on the amd64 kernel
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         139271
>Category:       kern
>Synopsis:       [pci] [patch] sysutils/hpacucli does not work on the amd64 kernel
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Oct 01 06:50:01 UTC 2009
>Closed-Date:    Thu Sep 27 04:32:32 UTC 2012
>Last-Modified:  Fri Jul 12 18:10:02 UTC 2013
>Originator:     Kazumi MORINAGA
>Release:        amd64 FreeBSD 7.2-RELEASE, amd64 FreeBSD 8.0 beta3
>Organization:
RIKEN, Japan
>Environment:
FreeBSD test 7.2-RELEASE FreeBSD 7.2-RELEASE #0: Fri Sep 18
20:35:39 JST 2009     root@test:/usr/obj/usr/src/sys/GENERIC  amd64
(patched GENERIC kernel)
>Description:
The hpacucli (ports/sysutils/hpacucli) that is an utility for the HP
Smart Array RAID controller could not detect controller cards on the
amd64 kernel.

I tested the patch for pci_users.c that was posted to the
freebsd-proliant@freebsd.org by Mr. John Hay on March 30, 2009.
- http://lists.freebsd.org/pipermail/freebsd-proliant/2009-March/000498.html
- Subject: hpacucli on 7-stable amd64, some progress


The environment of the test is as follows,
- HP DL360G5 with Smart Array P400i.
- Patched GENERIC kernel amd64 ( FreeBSD 7.2-RELEASE / FreeBSD 8.0 beta3 )

It seems to work correctly in some commands (show, modify cacheratio=....,
array all show, logcaldrive show, physicaldrive show).

--- show all information
ctrl all show
Controller Smart Array P400i at 0
   Bus Interface: PCI
   Slot: 0
   Serial Number: PH91MQ2642     
   Cache serialnumber: PA82C0J9SX32IG
   RAID 6 (ADG) Status: Enabled
   RAID 6 (ADG) Enabler Status: Enabled
   Controller Status: OK
   Chassis Slot: 1
   Hardware Revision: Rev E
   Firmware Version: 5.26
   Rebuild Priority: Medium
   Expand Priority: Medium
   Surface Scan Delay: 15 sec
   Cache Board Present: True
   Cache Status: OK
   Accelerator Ratio: 100/0 (read/write)
   Total Cache Size: 256 MB
   Battery Pack Count: 1
   Battery Status: OK

--- modify cacheratio
controller slot=0 modify cacheratio=25/75
controller slot=0 show
  ...
&#12288;Cache Status: OK
&#12288;Accelerator Ratio: 25/75 (read/write)
  ...

ctrl slot=0 modify cacheratio=100/0
ctrl slot=0 show
  ...
&#12288;Cache Status: OK
&#12288;Accelerator Ratio: 100/0 (read/write)
  ...

--- show array information
ctrl slot=0 array all show
&#12288;Smart Array P400i in Slot 0
&#12288; Array: A
&#12288; Interface Type: SAS
&#12288; Unused Space: 0 MB
&#12288; Status: OK

--- show logcaldrive information
ctrl slot=0 logcaldrive all show
&#12288;Smart Array P400i in Slot 0
&#12288; Logical Drive: 1
&#12288; Size: 68.3 GB
&#12288; Fault Tolerance: 1+0
&#12288; Heads: 255
&#12288; Sectors Per Track: 32
&#12288; Cylinders: 17562
&#12288; Stripe Size: 128 KB
&#12288; Status: Ok
&#12288; Array Accelerator: Enabled
&#12288; Has Data On Drive: True
&#12288; Unique Identifier: xxxx (masked)
&#12288; Preferred Controller Chassis Slot: 1

--- show physicaldrive information
ctrl slot=0 physicaldrive all show
&#12288;Smart Array P400i in Slot 0
&#12288;physicaldrive 1:1
&#12288; Port: 1I
&#12288; Box: 1
&#12288; Bay: 1
&#12288; Status: OK
&#12288; Drive Type: Data Drive
&#12288; Interface Type: SAS
&#12288; Size: 73.4 GB
&#12288; Transfer Speed: 3.0 Gbps
&#12288; Rotational Speed: 15000
&#12288; Firmware Revision: HPD3
&#12288; Serial Number: xxxx (masked)
&#12288;physicaldrive 1:2
&#12288; Port: 1I
&#12288; Box: 1
&#12288; Bay: 2
&#12288; Status: OK
&#12288; Drive Type: Data Drive
&#12288; Interface Type: SAS
&#12288; Size: 73.4 GB
&#12288; Transfer Speed: 3.0 Gbps
&#12288; Rotational Speed: 15000
&#12288; Firmware Revision: HPD3
&#12288; Serial Number: xxxx (masked)


>How-To-Repeat:
Install the hpacucli from ports (required: modification of the makefile).
Run the hpacucli with "ctrl all show" option.
It will display the following message.

Error: No controllers detected.

>Fix:
Patch to /usr/src/sys/dev/pci/pci_user.c.

This patch is same as Mr. Jhon Hay's patch that was posted to the
freebsd-proliant@freebsd.org by Mr. John Hay on March 30, 2009.
- http://lists.freebsd.org/pipermail/freebsd-proliant/2009-March/000498.html
- Subject: hpacucli on 7-stable amd64, some progress


Patch attached with submission follows:

--- pci_user.c.orig	2009-09-10 11:36:37.000000000 +0900
+++ pci_user.c	2009-09-10 11:36:41.000000000 +0900
@@ -225,6 +225,49 @@
 	u_int32_t	pi_data;	/* data to write or result of read */
 };
 
+#ifdef COMPAT_IA32
+struct pci_conf_old32 {
+       struct pcisel_old pc_sel;       /* bus+slot+function */
+       u_int8_t        pc_hdr;         /* PCI header type */
+       u_int16_t       pc_subvendor;   /* card vendor ID */
+       u_int16_t       pc_subdevice;   /* card device ID, assigned by
+                                          card vendor */
+       u_int16_t       pc_vendor;      /* chip vendor ID */
+       u_int16_t       pc_device;      /* chip device ID, assigned by
+                                          chip vendor */
+       u_int8_t        pc_class;       /* chip PCI class */
+       u_int8_t        pc_subclass;    /* chip PCI subclass */
+       u_int8_t        pc_progif;      /* chip PCI programming interface */
+       u_int8_t        pc_revid;       /* chip revision ID */
+       char            pd_name[PCI_MAXNAMELEN + 1];  /* device name */
+       u_int32_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 */
+       u_int32_t               pd_unit;        /* Unit number (u_long) */
+       u_int16_t               pc_vendor;      /* PCI Vendor ID */
+       u_int16_t               pc_device;      /* PCI Device ID */
+       u_int8_t                pc_class;       /* PCI class */
+       pci_getconf_flags_old   flags;          /* Matching expression */
+};
+
+struct pci_conf_io32 {
+       u_int32_t               pat_buf_len;    /* pattern buffer length */
+       u_int32_t               num_patterns;   /* number of patterns */
+       u_int32_t               patterns;       /* pattern buffer (struct pci_match_conf_old32 *) */
+       u_int32_t               match_buf_len;  /* match buffer length */
+       u_int32_t               num_matches;    /* number of matches returned */
+       u_int32_t               matches;        /* match buffer (struct pci_conf_old32 *) */
+       u_int32_t               offset;         /* offset into device list */
+       u_int32_t               generation;     /* device list generation */
+       pci_getconf_status      status;         /* request status */
+};
+
+#define        PCIOCGETCONF_OLD32      _IOWR('p', 1, struct pci_conf_io32)
+#endif
+
 #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,6 +338,69 @@
 	return(1);
 }
 
+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
 
 static int
@@ -314,13 +420,21 @@
 	size_t confsz, iolen, pbufsz;
 	int error, ionum, i, num_patterns;
 #ifdef PRE7_COMPAT
+#ifdef COMPAT_IA32
+       struct pci_conf_io32 *cio32;
+#endif
 	struct pci_conf_old conf_old;
+       struct pci_conf_old32 conf_old32;
 	struct pci_io iodata;
 	struct pci_io_old *io_old;
 	struct pci_match_conf_old *pattern_buf_old;
+       struct pci_match_conf_old32 *pattern_buf_old32;
 
+       cio = NULL;
+       cio32 = NULL;
 	io_old = NULL;
 	pattern_buf_old = NULL;
+       pattern_buf_old32 = NULL;
 
 	if (!(flag & FWRITE) && cmd != PCIOCGETBAR &&
 	    cmd != PCIOCGETCONF && cmd != PCIOCGETCONF_OLD)
@@ -332,11 +446,27 @@
 
 	switch(cmd) {
 #ifdef PRE7_COMPAT
+       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;
+               /* FALLTHROUGH */
+
 	case PCIOCGETCONF_OLD:
 		/* FALLTHROUGH */
 #endif
 	case PCIOCGETCONF:
-		cio = (struct pci_conf_io *)data;
+               if (cio == NULL)
+                       cio = (struct pci_conf_io *)data;
 
 		pattern_buf = NULL;
 		num_patterns = 0;
@@ -354,7 +484,7 @@
 		 && (cio->generation != pci_generation)){
 			cio->status = PCI_GETCONF_LIST_CHANGED;
 			error = 0;
-			break;
+                       goto getconfexit;
 		}
 
 		/*
@@ -364,7 +494,7 @@
 		if (cio->offset >= pci_numdevs) {
 			cio->status = PCI_GETCONF_LAST_DEVICE;
 			error = 0;
-			break;
+                       goto getconfexit;
 		}
 
 		/* get the head of the device queue */
@@ -377,6 +507,11 @@
 		 * didn't specify a multiple of that size.
 		 */
 #ifdef PRE7_COMPAT
+#ifdef COMPAT_IA32
+               if (cmd == PCIOCGETCONF_OLD32)
+                       confsz = sizeof(struct pci_conf_old32);
+               else
+#endif
 		if (cmd == PCIOCGETCONF_OLD)
 			confsz = sizeof(struct pci_conf_old);
 		else
@@ -411,6 +546,11 @@
 			 * updated their kernel but not their userland.
 			 */
 #ifdef PRE7_COMPAT
+#ifdef COMPAT_IA32
+                       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
@@ -420,13 +560,19 @@
 				/* 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
+                       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
 			if (cmd == PCIOCGETCONF_OLD) {
 				pattern_buf_old = malloc(cio->pat_buf_len,
 				    M_TEMP, M_WAITOK);
@@ -452,7 +598,7 @@
 			 */
 			cio->status = PCI_GETCONF_ERROR;
 			error = EINVAL;
-			break;
+                       goto getconfexit;
 		}
 
 		/*
@@ -484,7 +630,11 @@
 			}
 
 #ifdef PRE7_COMPAT
-			if ((cmd == PCIOCGETCONF_OLD &&
+                       if ((cmd == PCIOCGETCONF_OLD32 &&
+                           (pattern_buf_old32 == NULL ||
+                           pci_conf_match_old32(pattern_buf_old32,
+                           num_patterns, &dinfo->conf) == 0)) ||
+                           (cmd == PCIOCGETCONF_OLD &&
 			    (pattern_buf_old == NULL ||
 			    pci_conf_match_old(pattern_buf_old, num_patterns,
 			    &dinfo->conf) == 0)) ||
@@ -509,6 +659,38 @@
 					break;
 
 #ifdef PRE7_COMPAT
+                               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 =
+                                           (u_int32_t)dinfo->conf.pd_unit;
+                                       confdata = &conf_old32;
+                               } else
 				if (cmd == PCIOCGETCONF_OLD) {
 					conf_old.pc_sel.pc_bus =
 					    dinfo->conf.pc_sel.pc_bus;
@@ -575,9 +757,22 @@
 			cio->status = PCI_GETCONF_MORE_DEVS;
 
 getconfexit:
+#ifdef COMPAT_IA32
+               if (cmd == PCIOCGETCONF_OLD32) {
+                       cio32->status = cio->status;
+                       cio32->generation = cio->generation;
+                       cio32->offset = cio->offset;
+                       cio32->num_matches = cio->num_matches;
+                       if (cio != NULL)
+                               free(cio, M_TEMP);
+               }
+#endif
+
 		if (pattern_buf != NULL)
 			free(pattern_buf, M_TEMP);
 #ifdef PRE7_COMPAT
+               if (pattern_buf_old32 != NULL)
+                       free(pattern_buf_old32, M_TEMP);
 		if (pattern_buf_old != NULL)
 			free(pattern_buf_old, M_TEMP);
 #endif


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-amd64->freebsd-ports-bugs 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Fri Oct 2 02:56:52 UTC 2009 
Responsible-Changed-Why:  
ports PR. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=139271 
Responsible-Changed-From-To: freebsd-ports-bugs->freebsd-bugs 
Responsible-Changed-By: miwi 
Responsible-Changed-When: Sat Nov 21 15:43:12 UTC 2009 
Responsible-Changed-Why:  
back to bug it's not really for ports. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=139271 

From: William Lloyd <wlloyd@slap.net>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/139271: [pci] [patch] sysutils/hpacucli does not work on the amd64 kernel
Date: Wed, 2 Dec 2009 21:05:56 -0500

 I've tested this patch also on 8.0-RELEASE AMD64 and it works fine.
 
 Thanks.
 
 -bill
 wlloyd@slap.net
 
 
 
 

From: Eugene Grosbein <egrosbein@rdtc.ru>
To: bug-followup@FreeBSD.ORG
Cc:  
Subject: Re: kern/139271: [pci] [patch] sysutils/hpacucli does not work on
 the amd64 kernel
Date: Mon, 06 Feb 2012 12:36:29 +0700

 This is a multi-part message in MIME format.
 --------------050604090701010107000907
 Content-Type: text/plain; charset=us-ascii
 Content-Transfer-Encoding: 7bit
 
 Hi!
 
 Here is same patch modified for 8.2-STABLE/amd64:
 COMPAT_IA32 replaced with COMPAT_FREEBSD32, no other changes.
 
 Work just fine with my HP SmartArray P400i.
 
 Please commit.
 
 Eugene Grosbein
 
 --------------050604090701010107000907
 Content-Type: text/plain;
  name="pci_user.c.diff"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="pci_user.c.diff"
 
 --- sys/dev/pci/pci_user.c.orig	2009-09-19 16:13:10.000000000 +0800
 +++ sys/dev/pci/pci_user.c	2012-02-04 01:52:50.000000000 +0700
 @@ -225,6 +225,49 @@
  	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 */
 +       u_int8_t        pc_hdr;         /* PCI header type */
 +       u_int16_t       pc_subvendor;   /* card vendor ID */
 +       u_int16_t       pc_subdevice;   /* card device ID, assigned by
 +                                          card vendor */
 +       u_int16_t       pc_vendor;      /* chip vendor ID */
 +       u_int16_t       pc_device;      /* chip device ID, assigned by
 +                                          chip vendor */
 +       u_int8_t        pc_class;       /* chip PCI class */
 +       u_int8_t        pc_subclass;    /* chip PCI subclass */
 +       u_int8_t        pc_progif;      /* chip PCI programming interface */
 +       u_int8_t        pc_revid;       /* chip revision ID */
 +       char            pd_name[PCI_MAXNAMELEN + 1];  /* device name */
 +       u_int32_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 */
 +       u_int32_t               pd_unit;        /* Unit number (u_long) */
 +       u_int16_t               pc_vendor;      /* PCI Vendor ID */
 +       u_int16_t               pc_device;      /* PCI Device ID */
 +       u_int8_t                pc_class;       /* PCI class */
 +       pci_getconf_flags_old   flags;          /* Matching expression */
 +};
 +
 +struct pci_conf_io32 {
 +       u_int32_t               pat_buf_len;    /* pattern buffer length */
 +       u_int32_t               num_patterns;   /* number of patterns */
 +       u_int32_t               patterns;       /* pattern buffer (struct pci_match_conf_old32 *) */
 +       u_int32_t               match_buf_len;  /* match buffer length */
 +       u_int32_t               num_matches;    /* number of matches returned */
 +       u_int32_t               matches;        /* match buffer (struct pci_conf_old32 *) */
 +       u_int32_t               offset;         /* offset into device list */
 +       u_int32_t               generation;     /* device list generation */
 +       pci_getconf_status      status;         /* request status */
 +};
 +
 +#define        PCIOCGETCONF_OLD32      _IOWR('p', 1, struct pci_conf_io32)
 +#endif
 +
  #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,6 +338,69 @@
  	return(1);
  }
  
 +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
  
  static int
 @@ -314,13 +420,21 @@
  	size_t confsz, iolen, pbufsz;
  	int error, ionum, i, num_patterns;
  #ifdef PRE7_COMPAT
 +#ifdef COMPAT_FREEBSD32
 +       struct pci_conf_io32 *cio32;
 +#endif
  	struct pci_conf_old conf_old;
 +       struct pci_conf_old32 conf_old32;
  	struct pci_io iodata;
  	struct pci_io_old *io_old;
  	struct pci_match_conf_old *pattern_buf_old;
 +       struct pci_match_conf_old32 *pattern_buf_old32;
  
 +       cio = NULL;
 +       cio32 = NULL;
  	io_old = NULL;
  	pattern_buf_old = NULL;
 +       pattern_buf_old32 = NULL;
  
  	if (!(flag & FWRITE) && cmd != PCIOCGETBAR &&
  	    cmd != PCIOCGETCONF && cmd != PCIOCGETCONF_OLD)
 @@ -332,11 +446,27 @@
  
  	switch(cmd) {
  #ifdef PRE7_COMPAT
 +       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;
 +               /* FALLTHROUGH */
 +
  	case PCIOCGETCONF_OLD:
  		/* FALLTHROUGH */
  #endif
  	case PCIOCGETCONF:
 -		cio = (struct pci_conf_io *)data;
 +               if (cio == NULL)
 +                       cio = (struct pci_conf_io *)data;
  
  		pattern_buf = NULL;
  		num_patterns = 0;
 @@ -354,7 +484,7 @@
  		 && (cio->generation != pci_generation)){
  			cio->status = PCI_GETCONF_LIST_CHANGED;
  			error = 0;
 -			break;
 +                       goto getconfexit;
  		}
  
  		/*
 @@ -364,7 +494,7 @@
  		if (cio->offset >= pci_numdevs) {
  			cio->status = PCI_GETCONF_LAST_DEVICE;
  			error = 0;
 -			break;
 +                       goto getconfexit;
  		}
  
  		/* get the head of the device queue */
 @@ -377,6 +507,11 @@
  		 * 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
 @@ -411,6 +546,11 @@
  			 * 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
 @@ -420,13 +560,19 @@
  				/* 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
 +                       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
  			if (cmd == PCIOCGETCONF_OLD) {
  				pattern_buf_old = malloc(cio->pat_buf_len,
  				    M_TEMP, M_WAITOK);
 @@ -452,7 +598,7 @@
  			 */
  			cio->status = PCI_GETCONF_ERROR;
  			error = EINVAL;
 -			break;
 +                       goto getconfexit;
  		}
  
  		/*
 @@ -484,7 +630,11 @@
  			}
  
  #ifdef PRE7_COMPAT
 -			if ((cmd == PCIOCGETCONF_OLD &&
 +                       if ((cmd == PCIOCGETCONF_OLD32 &&
 +                           (pattern_buf_old32 == NULL ||
 +                           pci_conf_match_old32(pattern_buf_old32,
 +                           num_patterns, &dinfo->conf) == 0)) ||
 +                           (cmd == PCIOCGETCONF_OLD &&
  			    (pattern_buf_old == NULL ||
  			    pci_conf_match_old(pattern_buf_old, num_patterns,
  			    &dinfo->conf) == 0)) ||
 @@ -509,6 +659,38 @@
  					break;
  
  #ifdef PRE7_COMPAT
 +                               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 =
 +                                           (u_int32_t)dinfo->conf.pd_unit;
 +                                       confdata = &conf_old32;
 +                               } else
  				if (cmd == PCIOCGETCONF_OLD) {
  					conf_old.pc_sel.pc_bus =
  					    dinfo->conf.pc_sel.pc_bus;
 @@ -575,9 +757,22 @@
  			cio->status = PCI_GETCONF_MORE_DEVS;
  
  getconfexit:
 +#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;
 +                       if (cio != NULL)
 +                               free(cio, M_TEMP);
 +               }
 +#endif
 +
  		if (pattern_buf != NULL)
  			free(pattern_buf, M_TEMP);
  #ifdef PRE7_COMPAT
 +               if (pattern_buf_old32 != NULL)
 +                       free(pattern_buf_old32, M_TEMP);
  		if (pattern_buf_old != NULL)
  			free(pattern_buf_old, M_TEMP);
  #endif
 
 --------------050604090701010107000907--

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/139271: commit references a PR
Date: Thu, 27 Sep 2012 04:29:12 +0000 (UTC)

 Author: sobomax
 Date: Thu Sep 27 04:28:55 2012
 New Revision: 240981
 URL: http://svn.freebsd.org/changeset/base/240981
 
 Log:
   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
   MFC after:	1 week
 
 Modified:
   head/sys/dev/pci/pci_user.c
 
 Modified: head/sys/dev/pci/pci_user.c
 ==============================================================================
 --- head/sys/dev/pci/pci_user.c	Thu Sep 27 04:06:20 2012	(r240980)
 +++ head/sys/dev/pci/pci_user.c	Thu Sep 27 04:28:55 2012	(r240981)
 @@ -225,6 +225,49 @@ 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 */
 +       u_int8_t        pc_hdr;         /* PCI header type */
 +       u_int16_t       pc_subvendor;   /* card vendor ID */
 +       u_int16_t       pc_subdevice;   /* card device ID, assigned by
 +                                          card vendor */
 +       u_int16_t       pc_vendor;      /* chip vendor ID */
 +       u_int16_t       pc_device;      /* chip device ID, assigned by
 +                                          chip vendor */
 +       u_int8_t        pc_class;       /* chip PCI class */
 +       u_int8_t        pc_subclass;    /* chip PCI subclass */
 +       u_int8_t        pc_progif;      /* chip PCI programming interface */
 +       u_int8_t        pc_revid;       /* chip revision ID */
 +       char            pd_name[PCI_MAXNAMELEN + 1];  /* device name */
 +       u_int32_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 */
 +       u_int32_t               pd_unit;        /* Unit number (u_long) */
 +       u_int16_t               pc_vendor;      /* PCI Vendor ID */
 +       u_int16_t               pc_device;      /* PCI Device ID */
 +       u_int8_t                pc_class;       /* PCI class */
 +       pci_getconf_flags_old   flags;          /* Matching expression */
 +};
 +
 +struct pci_conf_io32 {
 +       u_int32_t               pat_buf_len;    /* pattern buffer length */
 +       u_int32_t               num_patterns;   /* number of patterns */
 +       u_int32_t               patterns;       /* pattern buffer (struct pci_match_conf_old32 *) */
 +       u_int32_t               match_buf_len;  /* match buffer length */
 +       u_int32_t               num_matches;    /* number of matches returned */
 +       u_int32_t               matches;        /* match buffer (struct pci_conf_old32 *) */
 +       u_int32_t               offset;         /* offset into device list */
 +       u_int32_t               generation;     /* device list generation */
 +       pci_getconf_status      status;         /* request status */
 +};
 +
 +#define        PCIOCGETCONF_OLD32      _IOWR('p', 1, struct pci_conf_io32)
 +#endif
 +
  #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,6 +338,69 @@ pci_conf_match_old(struct pci_match_conf
  	return(1);
  }
  
 +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
  
  static int
 @@ -313,13 +419,21 @@ 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;
 +#endif
  	struct pci_conf_old conf_old;
 +       struct pci_conf_old32 conf_old32;
  	struct pci_io iodata;
  	struct pci_io_old *io_old;
  	struct pci_match_conf_old *pattern_buf_old;
 +       struct pci_match_conf_old32 *pattern_buf_old32;
  
 +       cio = NULL;
 +       cio32 = NULL;
  	io_old = NULL;
  	pattern_buf_old = NULL;
 +       pattern_buf_old32 = NULL;
  
  	if (!(flag & FWRITE) && cmd != PCIOCGETBAR &&
  	    cmd != PCIOCGETCONF && cmd != PCIOCGETCONF_OLD)
 @@ -331,11 +445,27 @@ pci_ioctl(struct cdev *dev, u_long cmd, 
  
  	switch(cmd) {
  #ifdef PRE7_COMPAT
 +       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;
 +               /* FALLTHROUGH */
 +
  	case PCIOCGETCONF_OLD:
  		/* FALLTHROUGH */
  #endif
  	case PCIOCGETCONF:
 -		cio = (struct pci_conf_io *)data;
 +               if (cio == NULL)
 +                       cio = (struct pci_conf_io *)data;
  
  		pattern_buf = NULL;
  		num_patterns = 0;
 @@ -353,7 +483,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 +493,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 +506,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 +545,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,13 +559,19 @@ 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
 +                       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
  			if (cmd == PCIOCGETCONF_OLD) {
  				pattern_buf_old = malloc(cio->pat_buf_len,
  				    M_TEMP, M_WAITOK);
 @@ -451,7 +597,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, 
  			 */
  			cio->status = PCI_GETCONF_ERROR;
  			error = EINVAL;
 -			break;
 +                       goto getconfexit;
  		}
  
  		/*
 @@ -483,7 +629,11 @@ pci_ioctl(struct cdev *dev, u_long cmd, 
  			}
  
  #ifdef PRE7_COMPAT
 -			if ((cmd == PCIOCGETCONF_OLD &&
 +                       if ((cmd == PCIOCGETCONF_OLD32 &&
 +                           (pattern_buf_old32 == NULL ||
 +                           pci_conf_match_old32(pattern_buf_old32,
 +                           num_patterns, &dinfo->conf) == 0)) ||
 +                           (cmd == PCIOCGETCONF_OLD &&
  			    (pattern_buf_old == NULL ||
  			    pci_conf_match_old(pattern_buf_old, num_patterns,
  			    &dinfo->conf) == 0)) ||
 @@ -508,6 +658,38 @@ pci_ioctl(struct cdev *dev, u_long cmd, 
  					break;
  
  #ifdef PRE7_COMPAT
 +                               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 =
 +                                           (u_int32_t)dinfo->conf.pd_unit;
 +                                       confdata = &conf_old32;
 +                               } else
  				if (cmd == PCIOCGETCONF_OLD) {
  					conf_old.pc_sel.pc_bus =
  					    dinfo->conf.pc_sel.pc_bus;
 @@ -574,9 +756,22 @@ pci_ioctl(struct cdev *dev, u_long cmd, 
  			cio->status = PCI_GETCONF_MORE_DEVS;
  
  getconfexit:
 +#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;
 +                       if (cio != NULL)
 +                               free(cio, M_TEMP);
 +               }
 +#endif
 +
  		if (pattern_buf != NULL)
  			free(pattern_buf, M_TEMP);
  #ifdef PRE7_COMPAT
 +               if (pattern_buf_old32 != NULL)
 +                       free(pattern_buf_old32, M_TEMP);
  		if (pattern_buf_old != NULL)
  			free(pattern_buf_old, M_TEMP);
  #endif
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->closed 
State-Changed-By: sobomax 
State-Changed-When: Thu Sep 27 04:31:35 UTC 2012 
State-Changed-Why:  
Patch has been committed into the CURRENT. I'll MFC it into 9-stable and 
8-stable in 1 week. Thank you for submission! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=139271 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/139271: commit references a PR
Date: Fri, 12 Jul 2013 18:02:24 +0000 (UTC)

 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;
  
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
