[ patch .24-rc0 1/5 ] SuperIO locks coordinator - add the module

2007-10-14 Thread Jim Cromie

01 - adds superio_locks module

User-drivers specify the sio-port characteristics they can support
device-ids, sio-port-addrs, enter & exit sequences, etc in 
a struct superio_search (in __devinit, preferably). 

superio_find() then searches existing slots/shared-reservations 
for a matching sio-port, and returns it if found. 
Otherwize it probes port-addrs, specified by find() user, 
and makes and returns a new reservation.


   superio_find()	finds and reserves the slot, 
			returned as ptr or null

   superio_release()relinguishes the slot (ref-counted)

Once theyve got the reservation in struct superio * gate 
(as named in patches 2-5) they *may* use


   superio_lock(gate)
   superio_enter/exit(gate)
   superio_inb/w(gate, regaddr),
   superio_outb/w(gate, regaddr, val)

or they can do it themselves with inb/outb, by using gate->sioaddr, etc.

The API names (superio_find etc) were chosen to fit the idiom 
used in hwmon/*.c, patches 2-5 remove the per-user-driver

copies of the superio_*() fns.

I added the module to /drivers/hwmon, mostly cuz thats where
Ive used it - perhaps drivers/isa is better ?


Signed-off-by:  Jim Cromie <[EMAIL PROTECTED]>
---
hwmon-superio-module
drivers/hwmon/Kconfig |9 +
drivers/hwmon/Makefile|1 
drivers/hwmon/superio_locks.c |  235 ++

include/linux/superio-locks.h |  112 
4 files changed, 357 insertions(+)

diff -ruNp -X dontdiff -X exclude-diffs 
hwmon-fan-push-offset/drivers/hwmon/Kconfig 
hwmon-superio.old/drivers/hwmon/Kconfig
--- hwmon-fan-push-offset/drivers/hwmon/Kconfig 2007-10-14 13:00:24.0 
-0600
+++ hwmon-superio.old/drivers/hwmon/Kconfig 2007-10-14 17:22:23.0 
-0600
@@ -750,4 +765,13 @@ config HWMON_DEBUG_CHIP
  a problem with I2C support and want to see more of what is going
  on.

+config SUPERIO_LOCKS
+   tristate "Super-IO port sharing"
+   default n
+   help
+ This module provides a shared reservation for use by drivers
+ which need to share access to a multi-function device via
+ its superio port, and which register that port.
+
endif # HWMON
+
diff -ruNp -X dontdiff -X exclude-diffs 
hwmon-fan-push-offset/drivers/hwmon/Makefile 
hwmon-superio.old/drivers/hwmon/Makefile
--- hwmon-fan-push-offset/drivers/hwmon/Makefile2007-10-14 
13:00:24.0 -0600
+++ hwmon-superio.old/drivers/hwmon/Makefile2007-10-14 17:22:23.0 
-0600
@@ -72,3 +72,4 @@ ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
endif

+obj-$(CONFIG_SUPERIO_LOCKS)+= superio_locks.o
diff -ruNp -X dontdiff -X exclude-diffs 
hwmon-fan-push-offset/drivers/hwmon/superio_locks.c 
hwmon-superio.old/drivers/hwmon/superio_locks.c
--- hwmon-fan-push-offset/drivers/hwmon/superio_locks.c 1969-12-31 
17:00:00.0 -0700
+++ hwmon-superio.old/drivers/hwmon/superio_locks.c 2007-10-14 
20:27:49.0 -0600
@@ -0,0 +1,235 @@
+
+#define DRVNAME "superio_locks"
+#define DEBUG 1
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+MODULE_AUTHOR("Jim Cromie <[EMAIL PROTECTED]");
+MODULE_LICENSE("GPL");
+
+/*
+ * This module allows multiple driver modules to coordinate their use
+ * of a Super-IO port to control the multiple logical devices behind
+ * it.  Drivers will superio_find() their port, and 2 such modules
+ * will share a slot containing the lock.
+ */
+static int max_locks = 3;  /* 3 is enough for 90% uses */
+module_param(max_locks, int, 0);
+MODULE_PARM_DESC(max_locks,
+" Number of sio-lock clients to serve (default=3)");
+
+static int paranoid;
+module_param(paranoid, int, 0);
+MODULE_PARM_DESC(paranoid,
+" when true, fails if superio-port region is claimed");
+
+static struct superio *sio_locks;
+static struct mutex reservation_lock;
+
+#define SIO_DEVID_ADDR_STD 0x20
+#define SIO_LDN_ADDR_STD 0x07
+
+struct superio* superio_probe_reserve(const struct superio_search * const 
where,
+ int cmd_addr, int want_devid)
+{
+   struct superio *gate;
+   u16 devid_addr = where->devid_addr;
+   u16 mydevid;
+   int slot, rc, i;
+
+   if (!devid_addr)
+   devid_addr = SIO_DEVID_ADDR_STD;
+
+
+   /* send superio-enter sequence for devices which need them */
+   for (i = 0; i < SEQ_SZ && where->enter_seq[i]; i++)
+   outb(where->enter_seq[i], cmd_addr);
+
+   outb(devid_addr, cmd_addr);
+
+   /* sanity check that cmd-reg remembers the val just written
+   rc = inb(cmd_addr);
+   if (rc != (devid_addr & 0xFF)) {
+   pr_debug("cmd-reg absent at %x, got %x\n", cmd_addr, rc);
+   return NULL;
+   }
+   */
+   /* Read the device-id register(s), using cmd written above */
+   if (!where->devid_word) {
+   mydevid = inb(cmd_addr+1);
+   } else {
+   /* want 16 bit devid, so get it 

[ patch .24-rc0 1/5 ] SuperIO locks coordinator - add the module

2007-10-14 Thread Jim Cromie

01 - adds superio_locks module

User-drivers specify the sio-port characteristics they can support
device-ids, sio-port-addrs, enter  exit sequences, etc in 
a struct superio_search (in __devinit, preferably). 

superio_find() then searches existing slots/shared-reservations 
for a matching sio-port, and returns it if found. 
Otherwize it probes port-addrs, specified by find() user, 
and makes and returns a new reservation.


   superio_find()	finds and reserves the slot, 
			returned as ptr or null

   superio_release()relinguishes the slot (ref-counted)

Once theyve got the reservation in struct superio * gate 
(as named in patches 2-5) they *may* use


   superio_lock(gate)
   superio_enter/exit(gate)
   superio_inb/w(gate, regaddr),
   superio_outb/w(gate, regaddr, val)

or they can do it themselves with inb/outb, by using gate-sioaddr, etc.

The API names (superio_find etc) were chosen to fit the idiom 
used in hwmon/*.c, patches 2-5 remove the per-user-driver

copies of the superio_*() fns.

I added the module to /drivers/hwmon, mostly cuz thats where
Ive used it - perhaps drivers/isa is better ?


Signed-off-by:  Jim Cromie [EMAIL PROTECTED]
---
hwmon-superio-module
drivers/hwmon/Kconfig |9 +
drivers/hwmon/Makefile|1 
drivers/hwmon/superio_locks.c |  235 ++

include/linux/superio-locks.h |  112 
4 files changed, 357 insertions(+)

diff -ruNp -X dontdiff -X exclude-diffs 
hwmon-fan-push-offset/drivers/hwmon/Kconfig 
hwmon-superio.old/drivers/hwmon/Kconfig
--- hwmon-fan-push-offset/drivers/hwmon/Kconfig 2007-10-14 13:00:24.0 
-0600
+++ hwmon-superio.old/drivers/hwmon/Kconfig 2007-10-14 17:22:23.0 
-0600
@@ -750,4 +765,13 @@ config HWMON_DEBUG_CHIP
  a problem with I2C support and want to see more of what is going
  on.

+config SUPERIO_LOCKS
+   tristate Super-IO port sharing
+   default n
+   help
+ This module provides a shared reservation for use by drivers
+ which need to share access to a multi-function device via
+ its superio port, and which register that port.
+
endif # HWMON
+
diff -ruNp -X dontdiff -X exclude-diffs 
hwmon-fan-push-offset/drivers/hwmon/Makefile 
hwmon-superio.old/drivers/hwmon/Makefile
--- hwmon-fan-push-offset/drivers/hwmon/Makefile2007-10-14 
13:00:24.0 -0600
+++ hwmon-superio.old/drivers/hwmon/Makefile2007-10-14 17:22:23.0 
-0600
@@ -72,3 +72,4 @@ ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
endif

+obj-$(CONFIG_SUPERIO_LOCKS)+= superio_locks.o
diff -ruNp -X dontdiff -X exclude-diffs 
hwmon-fan-push-offset/drivers/hwmon/superio_locks.c 
hwmon-superio.old/drivers/hwmon/superio_locks.c
--- hwmon-fan-push-offset/drivers/hwmon/superio_locks.c 1969-12-31 
17:00:00.0 -0700
+++ hwmon-superio.old/drivers/hwmon/superio_locks.c 2007-10-14 
20:27:49.0 -0600
@@ -0,0 +1,235 @@
+
+#define DRVNAME superio_locks
+#define DEBUG 1
+
+#include linux/kernel.h
+#include linux/init.h
+#include linux/module.h
+#include linux/moduleparam.h
+#include linux/mutex.h
+#include linux/ioport.h
+#include linux/superio-locks.h
+
+MODULE_AUTHOR(Jim Cromie [EMAIL PROTECTED]);
+MODULE_LICENSE(GPL);
+
+/*
+ * This module allows multiple driver modules to coordinate their use
+ * of a Super-IO port to control the multiple logical devices behind
+ * it.  Drivers will superio_find() their port, and 2 such modules
+ * will share a slot containing the lock.
+ */
+static int max_locks = 3;  /* 3 is enough for 90% uses */
+module_param(max_locks, int, 0);
+MODULE_PARM_DESC(max_locks,
+ Number of sio-lock clients to serve (default=3));
+
+static int paranoid;
+module_param(paranoid, int, 0);
+MODULE_PARM_DESC(paranoid,
+ when true, fails if superio-port region is claimed);
+
+static struct superio *sio_locks;
+static struct mutex reservation_lock;
+
+#define SIO_DEVID_ADDR_STD 0x20
+#define SIO_LDN_ADDR_STD 0x07
+
+struct superio* superio_probe_reserve(const struct superio_search * const 
where,
+ int cmd_addr, int want_devid)
+{
+   struct superio *gate;
+   u16 devid_addr = where-devid_addr;
+   u16 mydevid;
+   int slot, rc, i;
+
+   if (!devid_addr)
+   devid_addr = SIO_DEVID_ADDR_STD;
+
+
+   /* send superio-enter sequence for devices which need them */
+   for (i = 0; i  SEQ_SZ  where-enter_seq[i]; i++)
+   outb(where-enter_seq[i], cmd_addr);
+
+   outb(devid_addr, cmd_addr);
+
+   /* sanity check that cmd-reg remembers the val just written
+   rc = inb(cmd_addr);
+   if (rc != (devid_addr  0xFF)) {
+   pr_debug(cmd-reg absent at %x, got %x\n, cmd_addr, rc);
+   return NULL;
+   }
+   */
+   /* Read the device-id register(s), using cmd written above */
+   if (!where-devid_word) {
+   mydevid =