Adding GPIO support to wbsio(4)

2018-11-03 Thread Matt Dainty
Attached below is a diff that adds GPIO support to wbsio(4) for the Nuvoton
NCT5104D variant which is found on most of the recent PC Engines APU boards,
(I'm personally developing this on an APU4).

I've hit a problem that it causes the kernel to crash when probing for
lm78(4) which can be found on /some/ wbsio(4) chips, but not this particular
variant, so there aren't any to find. If I comment out the "lm* at wbsio?" in
the kernel configuration or comment out the latter `config_found()` call I
added to attach the GPIO bus then the kernel boots fine.

The kernel panic I get is:

...
wbsio0 at isa0 port 0x2e/2: NCT5104D rev 0x53
panic: bus_space_map: bad bus space tag
Stopped at  db_enter+0x12:  popq%r11
TIDPIDUID PRFLAGS PFLAGS  CPU  COMMAND
* 0  0  0 0x1  0x2000K swapper
db_enter(9a1e376995dc152,100,10,81f6aed8,202,8) at db_enter+0x12
panic(200,81f6b168,1a,8,800a3e58,81cb6a60) at 
panic+0x120
bus_space_map(9a45ea3f225ed920,800a3e58,81f6b168,1a,81c93da0,0)
 at bus_space_map+0x62
lm_wbsio_match(b99bd94bc1864cf1,81c93da0,81f6b080,1a,81c93da0,81c8fd76)
 at lm_wbsio_match+0x4d
mapply(9766dee4470b4208,81c93da0,800a3e00,1a,81f6b080,81c93c18)
 at mapply+0xbe
config_search(eef789b22abf,81f6b168,810b7d40,0,800a3e00,81c331f0)
 at config_search+0xc0
config_found_sm(7a3bdef80501ee63,2e,0,800a3e00,814b088e,81f6b110)
 at config_found_sm+0x2e
wbsio_attach(370b5c3cf5b5f4cc,800a3c00,81f6b558,81c73448,800a3e00,800a3e24)
 at wbsio_attach+0x8de
config_attach(d3e35ce7cfd9a5c1,81c93c18,800a3e00,81f6b888,800a3c00,81f6b558)
 at config_attach+0x1ee
isascan(370b5c3cf5b5fae4,8155f110,800a3c00,81c8cc01,81c93c18,81c8fdfc)
 at isascan+0x1fb
config_scan(51e6e319330389e6,80084b00,81f6bc98,81c8ccf8,800a3c00,800a3c24)
 at config_scan+0xb6
config_attach(d3e35ce7cfa11aa1,8008b2c0,8001cf00,81d2ecd8,0,8001cf24)
 at config_attach+0x1ee
pcib_callback(b0d20c41cc678cce,30193439aff14287,0,81c740e8,81c33320,81c331f0)
 at pcib_callback+0x5b
config_process_deferred_children(d810f4a0da8adfd1,80023100,81f6bd90,81c74730,8001cf00,0)
 at config_process_deferred_children+0
x89
end trace frame: 0x81f6bd60, count: 0
https://www.openbsd.org/ddb.html describes the minimum info required in bug
reports.  Insufficient info makes it difficult to find and fix bugs.
ddb{0}> 

So it crashes in lm_wbsio_match() which is in lm78_isa.c. I'm not sure why
bus_space_map() is failing, the GPIO portion doesn't map any I/O space, it's
all driven through the standard chip configuration registers.

Could someone possibly indicate what I've done wrong here? I've based the
GPIO attachment code on the same thing I did when implementing skgpio(4) and
as I mentioned, if I disable lm78(4) then the GPIO driver appears to attach
and function. I suspect I've got some subtlety of autoconf wrong.

Thanks

Matt

diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC
index 9a74efca601..5aaa1f55651 100644
--- a/sys/arch/amd64/conf/GENERIC
+++ b/sys/arch/amd64/conf/GENERIC
@@ -123,6 +123,7 @@ schsio* at isa? port 0x164e
 wbsio* at isa? port 0x2e   # Winbond LPC Super I/O
 wbsio* at isa? port 0x4e
 lm*at wbsio?
+gpio*  at wbsio?
 uguru0 at isa? disable port 0xe0   # ABIT uGuru
 
 aps0   at isa? port 0x1600 # ThinkPad Active Protection System
diff --git a/sys/arch/i386/conf/GENERIC b/sys/arch/i386/conf/GENERIC
index 40dc421cf45..e2349208064 100644
--- a/sys/arch/i386/conf/GENERIC
+++ b/sys/arch/i386/conf/GENERIC
@@ -147,6 +147,7 @@ viasio* at isa? port 0x4e flags 0x
 wbsio* at isa? port 0x2e   # Winbond LPC Super I/O
 wbsio* at isa? port 0x4e
 lm*at wbsio?
+gpio*  at wbsio?
 uguru0 at isa? disable port 0xe0   # ABIT uGuru
 fins0  at isa? port 0x4e   # Fintek F71805 Super I/O
 
diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa
index 65877402ccf..f0fe6fc4e37 100644
--- a/sys/dev/isa/files.isa
+++ b/sys/dev/isa/files.isa
@@ -248,7 +248,7 @@ attach  lpt at isa with lpt_isa
 file   dev/isa/lpt_isa.c   lpt_isa
 
 # Winbond LPC Super I/O
-device wbsio {}
+device wbsio {} : gpiobus
 attach wbsio at isa
 file   dev/isa/wbsio.c wbsio
 
diff --git a/sys/dev/isa/wbsio.c b/sys/dev/isa/wbsio.c
index 7147d481732..31ad1cecec0 100644
--- a/sys/dev/isa/wbsio.c
+++ b/sys/dev/isa/wbsio.c
@@ -23,12 +23,15 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
 #include 
 #include 
 
+#include 
+
 #ifdef WBSIO_DEBUG
 #define DPRINTF(x) printf x
 #else
@@ -40,12 +43,21 @@ struct wbsio_softc {
 

Re: Implement a watchdog

2014-12-11 Thread Matt Dainty
* sven falempin sven.falem...@gmail.com [2014-12-10 12:32:15]:
 On Wed, Dec 10, 2014 at 9:31 AM, Stuart Henderson st...@openbsd.org wrote:
  On 2014/12/10 09:15, sven falempin wrote:
  http://lxr.free-electrons.com/source/drivers/hwmon/nct6775.c
 
  https://github.com/groeck/nct6775
 
  So i guess the first step is to detect the chip
 
  You'll also need somewhere (files) to put the detection. Maybe look at
  the commit from when tcpcib was added as an example.
 
  It might be somewhat similar to the Winbond superio chips (Nuvoton is
  a spin off company).
 
  On Wed, Dec 10, 2014 at 8:32 AM, sven falempin sven.falem...@gmail.com 
  wrote:
   I guess the chip used is obviously this one :
  
   Nuvoton NCT6106D
  
   spec : 
   https://download.nuvoton.com/NuvotonMOSS/DownloadService/Member/DocumentsInfo.aspx?tp_GUID=DA00-NCT6106D
 
  The watchdog part of this appears to use the same registers as NCT5104D
  in the pcengines APU.
 
 Well the sequence to configure is the same in the doc
 
 
 7.1.1 Enter the Extended Function Mode
 To place the chip into the Extended Function Mode, two successive
 writes of 0x87 must be applied to Extended
 Function Enable Registers (EFERs, i.e. 2Eh or 4Eh).
 
 
 I am not sure i understand, is this a pci device or a isa device ?

Have a look at the wbsio(4) driver. There's already a constant defined for
the NCT6776 so you probably just need to add the missing ID(s) and go from
there.

Matt



Re: Soekris net6501 GPIO LED support

2014-12-09 Thread Matt Dainty
* Ted Unangst t...@tedunangst.com [2014-12-08 13:28:36]:
 On Mon, Dec 08, 2014 at 11:52, Matt Dainty wrote:
  * Jonathan Gray j...@jsg.id.au [2014-12-08 08:08:19]:
 
  Well any name that includes gpio that isn't taken should be fine.
  
  I went with soekrisgpio(4) as there are longer driver names in the tree,
  (acpithinkpad(4) seems to hold that record from my quick scan) so rather
  than try and come up with some witty contraction I picked that.
 
 skgpio should be sufficient.

skgpio it is.

Matt

Index: share/man/man4/gpio.4
===
RCS file: /cvs/src/share/man/man4/gpio.4,v
retrieving revision 1.22
diff -u -p -r1.22 gpio.4
--- share/man/man4/gpio.4   21 Jan 2014 11:02:00 -  1.22
+++ share/man/man4/gpio.4   9 Dec 2014 18:05:26 -
@@ -30,6 +30,7 @@
 .Cd gpio* at omgpio? Pq armv7
 .Cd gpio* at pcagpio?
 .Cd gpio* at pcaled?
+.Cd gpio* at skgpio? Pq amd64, i386
 .Cd gpio0 at voyager? Pq loongson
 .Pp
 .Fd #include sys/types.h
Index: share/man/man4/isa.4
===
RCS file: /cvs/src/share/man/man4/isa.4,v
retrieving revision 1.72
diff -u -p -r1.72 isa.4
--- share/man/man4/isa.418 Mar 2014 22:36:31 -  1.72
+++ share/man/man4/isa.49 Dec 2014 18:05:26 -
@@ -222,6 +222,8 @@ PCMCIA controllers
 PC (ISA) keyboard controller driver
 .It Xr pcppi 4
 PC (ISA) control and timer port driver
+.It Xr skgpio 4
+Soekris net6501 GPIO and LEDs driver
 .It Xr vga 4
 VGA graphics driver for wscons
 .El
Index: share/man/man4/man4.amd64/Makefile
===
RCS file: /cvs/src/share/man/man4/man4.amd64/Makefile,v
retrieving revision 1.15
diff -u -p -r1.15 Makefile
--- share/man/man4/man4.amd64/Makefile  27 May 2012 12:24:33 -  1.15
+++ share/man/man4/man4.amd64/Makefile  9 Dec 2014 18:05:26 -
@@ -1,7 +1,7 @@
 #  $OpenBSD: Makefile,v 1.15 2012/05/27 12:24:33 jsg Exp $
 
 MAN=   amdpcib.4 apm.4 autoconf.4 bios.4 cpu.4 intro.4 ioapic.4 \
-   mem.4 mpbios.4 nvram.4 mtrr.4 pctr.4 tcpcib.4
+   mem.4 mpbios.4 nvram.4 mtrr.4 pctr.4 skgpio.4 tcpcib.4
 
 MLINKS+= mem.4 kmem.4
 MANSUBDIR=amd64
Index: share/man/man4/man4.amd64/skgpio.4
===
RCS file: share/man/man4/man4.amd64/skgpio.4
diff -N share/man/man4/man4.amd64/skgpio.4
--- /dev/null   1 Jan 1970 00:00:00 -
+++ share/man/man4/man4.amd64/skgpio.4  9 Dec 2014 18:05:26 -
@@ -0,0 +1,57 @@
+.\ $OpenBSD$
+.\
+.\ Copyright (c) 2014 Matt Dainty m...@bodgit-n-scarper.com
+.\
+.\ Permission to use, copy, modify, and distribute this software for any
+.\ purpose with or without fee is hereby granted, provided that the above
+.\ copyright notice and this permission notice appear in all copies.
+.\
+.\ THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\
+.Dd $Mdocdate$
+.Dt SKGPIO 4 amd64
+.Os
+.Sh NAME
+.Nm skgpio
+.Nd Soekris net6501 GPIO and LEDs
+.Sh SYNOPSIS
+.Cd skgpio0 at isa? port 0x680
+.Cd gpio* at skgpio?
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the GPIO and LEDs as implemented by the Xilinx
+Spartan FGPA integrated into the Soekris net6501 programmed with the default
+bitstream found in the BIOS.
+.Pp
+Two standard
+.Xr gpio 4
+interfaces are provided, one for the 16 real pins which can be configured as
+either inputs or outputs and another with 2 output-only pins that map
+to the error and ready LEDs respectively.
+Both may be used with
+.Xr gpioctl 8 .
+.Sh SEE ALSO
+.Xr intro 4 ,
+.Xr isa 4 ,
+.Xr gpio 4 ,
+.Xr gpioctl 8
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 5.7 .
+.Sh AUTHORS
+The
+.Nm
+driver was written by
+.An Matt Dainty Aq m...@bodgit-n-scarper.com .
+.Sh BUGS
+If the Xilinx FPGA is programmed with a different bistream, the driver will
+likely not function.
Index: share/man/man4/man4.i386/Makefile
===
RCS file: /cvs/src/share/man/man4/man4.i386/Makefile,v
retrieving revision 1.72
diff -u -p -r1.72 Makefile
--- share/man/man4/man4.i386/Makefile   27 May 2012 12:24:33 -  1.72
+++ share/man/man4/man4.i386/Makefile   9 Dec 2014 18:05:26 -
@@ -7,7 +7,7 @@ MAN=amdpcib.4 amdmsr.4 apm.4 autoconf.4
ichpcib.4 intro.4 ioapic.4 \
joy.4 le.4 lms.4 mem.4 mms.4 mpbios.4 mtrr.4 npx.4 nvram.4 \
pas.4 pcibios.4 pctr.4 piixpcib.4 sb.4 \
-   sea.4 tcpcib.4 uha.4 wds.4 wdt.4 wss.4
+   sea

Re: Soekris net6501 GPIO LED support

2014-12-08 Thread Matt Dainty
* Jonathan Gray j...@jsg.id.au [2014-12-08 08:08:19]:
 
 Well any name that includes gpio that isn't taken should be fine.

I went with soekrisgpio(4) as there are longer driver names in the tree,
(acpithinkpad(4) seems to hold that record from my quick scan) so rather
than try and come up with some witty contraction I picked that.

 It doesn't seem that soekris have a particular name for the interface
 (or any actual documentation of it...).

No, I'm struggling to find where I found the programming interface for it,
I can't find it in the manual. It must've come from the mailing list.

Revised patch below.

Matt

Index: share/man/man4/gpio.4
===
RCS file: /cvs/src/share/man/man4/gpio.4,v
retrieving revision 1.22
diff -u -p -r1.22 gpio.4
--- share/man/man4/gpio.4   21 Jan 2014 11:02:00 -  1.22
+++ share/man/man4/gpio.4   8 Dec 2014 16:34:26 -
@@ -30,6 +30,7 @@
 .Cd gpio* at omgpio? Pq armv7
 .Cd gpio* at pcagpio?
 .Cd gpio* at pcaled?
+.Cd gpio* at soekrisgpio? Pq amd64, i386
 .Cd gpio0 at voyager? Pq loongson
 .Pp
 .Fd #include sys/types.h
Index: share/man/man4/isa.4
===
RCS file: /cvs/src/share/man/man4/isa.4,v
retrieving revision 1.72
diff -u -p -r1.72 isa.4
--- share/man/man4/isa.418 Mar 2014 22:36:31 -  1.72
+++ share/man/man4/isa.48 Dec 2014 16:34:26 -
@@ -222,6 +222,8 @@ PCMCIA controllers
 PC (ISA) keyboard controller driver
 .It Xr pcppi 4
 PC (ISA) control and timer port driver
+.It Xr soekrisgpio 4
+Soekris net6501 GPIO and LEDs driver
 .It Xr vga 4
 VGA graphics driver for wscons
 .El
Index: share/man/man4/man4.amd64/Makefile
===
RCS file: /cvs/src/share/man/man4/man4.amd64/Makefile,v
retrieving revision 1.15
diff -u -p -r1.15 Makefile
--- share/man/man4/man4.amd64/Makefile  27 May 2012 12:24:33 -  1.15
+++ share/man/man4/man4.amd64/Makefile  8 Dec 2014 16:34:26 -
@@ -1,7 +1,7 @@
 #  $OpenBSD: Makefile,v 1.15 2012/05/27 12:24:33 jsg Exp $
 
 MAN=   amdpcib.4 apm.4 autoconf.4 bios.4 cpu.4 intro.4 ioapic.4 \
-   mem.4 mpbios.4 nvram.4 mtrr.4 pctr.4 tcpcib.4
+   mem.4 mpbios.4 nvram.4 mtrr.4 pctr.4 soekrisgpio.4 tcpcib.4
 
 MLINKS+= mem.4 kmem.4
 MANSUBDIR=amd64
Index: share/man/man4/man4.amd64/soekrisgpio.4
===
RCS file: share/man/man4/man4.amd64/soekrisgpio.4
diff -N share/man/man4/man4.amd64/soekrisgpio.4
--- /dev/null   1 Jan 1970 00:00:00 -
+++ share/man/man4/man4.amd64/soekrisgpio.4 8 Dec 2014 16:34:26 -
@@ -0,0 +1,57 @@
+.\ $OpenBSD$
+.\
+.\ Copyright (c) 2014 Matt Dainty m...@bodgit-n-scarper.com
+.\
+.\ Permission to use, copy, modify, and distribute this software for any
+.\ purpose with or without fee is hereby granted, provided that the above
+.\ copyright notice and this permission notice appear in all copies.
+.\
+.\ THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\
+.Dd $Mdocdate$
+.Dt SOEKRISGPIO 4 amd64
+.Os
+.Sh NAME
+.Nm soekrisgpio
+.Nd Soekris net6501 GPIO and LEDs
+.Sh SYNOPSIS
+.Cd soekrisgpio0 at isa? port 0x680
+.Cd gpio* at soekrisgpio?
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the GPIO and LEDs as implemented by the Xilinx
+Spartan FGPA integrated into the Soekris net6501 programmed with the default
+bitstream found in the BIOS.
+.Pp
+Two standard
+.Xr gpio 4
+interfaces are provided, one for the 16 real pins which can be configured as
+either inputs or outputs and another with 2 output-only pins that map
+to the error and ready LEDs respectively.
+Both may be used with
+.Xr gpioctl 8 .
+.Sh SEE ALSO
+.Xr intro 4 ,
+.Xr isa 4 ,
+.Xr gpio 4 ,
+.Xr gpioctl 8
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 5.7 .
+.Sh AUTHORS
+The
+.Nm
+driver was written by
+.An Matt Dainty Aq m...@bodgit-n-scarper.com .
+.Sh BUGS
+If the Xilinx FPGA is programmed with a different bistream, the driver will
+likely not function.
Index: share/man/man4/man4.i386/Makefile
===
RCS file: /cvs/src/share/man/man4/man4.i386/Makefile,v
retrieving revision 1.72
diff -u -p -r1.72 Makefile
--- share/man/man4/man4.i386/Makefile   27 May 2012 12:24:33 -  1.72
+++ share/man/man4/man4.i386/Makefile   8 Dec 2014 16:34:26 -
@@ -7,7 +7,7 @@ MAN=amdpcib.4 amdmsr.4 apm.4 autoconf.4
ichpcib.4 intro.4 ioapic.4

Re: Soekris net6501 GPIO LED support

2014-12-05 Thread Matt Dainty
Anyone?

* Matt Dainty m...@bodgit-n-scarper.com [2014-11-21 07:10:24]:
 * Dimitri Sokolyuk de...@dim13.org [2014-11-05 22:05:26]:
  
  I would also like to ask, if there are any plans on reviewing and 
  committing this code into base?
 
 Here's an updated patch with the driver and associated man page changes
 against -current.
 
 Any objections to committing this?
 
 Matt
 
 Index: share/man/man4/gpio.4
 ===
 RCS file: /cvs/src/share/man/man4/gpio.4,v
 retrieving revision 1.22
 diff -u -p -r1.22 gpio.4
 --- share/man/man4/gpio.4 21 Jan 2014 11:02:00 -  1.22
 +++ share/man/man4/gpio.4 21 Nov 2014 11:38:17 -
 @@ -30,6 +30,7 @@
  .Cd gpio* at omgpio? Pq armv7
  .Cd gpio* at pcagpio?
  .Cd gpio* at pcaled?
 +.Cd gpio* at soekris? Pq amd64, i386
  .Cd gpio0 at voyager? Pq loongson
  .Pp
  .Fd #include sys/types.h
 Index: share/man/man4/isa.4
 ===
 RCS file: /cvs/src/share/man/man4/isa.4,v
 retrieving revision 1.72
 diff -u -p -r1.72 isa.4
 --- share/man/man4/isa.4  18 Mar 2014 22:36:31 -  1.72
 +++ share/man/man4/isa.4  21 Nov 2014 11:38:17 -
 @@ -222,6 +222,8 @@ PCMCIA controllers
  PC (ISA) keyboard controller driver
  .It Xr pcppi 4
  PC (ISA) control and timer port driver
 +.It Xr soekris 4
 +Soekris net6501 GPIO and LEDs driver
  .It Xr vga 4
  VGA graphics driver for wscons
  .El
 Index: share/man/man4/man4.amd64/Makefile
 ===
 RCS file: /cvs/src/share/man/man4/man4.amd64/Makefile,v
 retrieving revision 1.15
 diff -u -p -r1.15 Makefile
 --- share/man/man4/man4.amd64/Makefile27 May 2012 12:24:33 -  
 1.15
 +++ share/man/man4/man4.amd64/Makefile21 Nov 2014 11:38:17 -
 @@ -1,7 +1,7 @@
  #$OpenBSD: Makefile,v 1.15 2012/05/27 12:24:33 jsg Exp $
  
  MAN= amdpcib.4 apm.4 autoconf.4 bios.4 cpu.4 intro.4 ioapic.4 \
 - mem.4 mpbios.4 nvram.4 mtrr.4 pctr.4 tcpcib.4
 + mem.4 mpbios.4 nvram.4 mtrr.4 pctr.4 soekris.4 tcpcib.4
  
  MLINKS+= mem.4 kmem.4
  MANSUBDIR=amd64
 Index: share/man/man4/man4.amd64/soekris.4
 ===
 RCS file: share/man/man4/man4.amd64/soekris.4
 diff -N share/man/man4/man4.amd64/soekris.4
 --- /dev/null 1 Jan 1970 00:00:00 -
 +++ share/man/man4/man4.amd64/soekris.4   21 Nov 2014 11:38:17 -
 @@ -0,0 +1,57 @@
 +.\ $OpenBSD$
 +.\
 +.\ Copyright (c) 2014 Matt Dainty m...@bodgit-n-scarper.com
 +.\
 +.\ Permission to use, copy, modify, and distribute this software for any
 +.\ purpose with or without fee is hereby granted, provided that the above
 +.\ copyright notice and this permission notice appear in all copies.
 +.\
 +.\ THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 +.\ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 +.\ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 +.\ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 +.\ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 +.\ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 +.\ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 +.\
 +.Dd $Mdocdate$
 +.Dt SOEKRIS 4 amd64
 +.Os
 +.Sh NAME
 +.Nm soekris
 +.Nd Soekris net6501 GPIO and LEDs
 +.Sh SYNOPSIS
 +.Cd soekris0 at isa? port 0x680
 +.Cd gpio* at soekris?
 +.Sh DESCRIPTION
 +The
 +.Nm
 +driver provides support for the GPIO and LEDs as implemented by the Xilinx
 +Spartan FGPA integrated into the Soekris net6501 programmed with the default
 +bitstream found in the BIOS.
 +.Pp
 +Two standard
 +.Xr gpio 4
 +interfaces are provided, one for the 16 real pins which can be configured as
 +either inputs or outputs and another with 2 output-only pins that map
 +to the error and ready LEDs respectively.
 +Both may be used with
 +.Xr gpioctl 8 .
 +.Sh SEE ALSO
 +.Xr intro 4 ,
 +.Xr isa 4 ,
 +.Xr gpio 4 ,
 +.Xr gpioctl 8
 +.Sh HISTORY
 +The
 +.Nm
 +driver first appeared in
 +.Ox 5.7 .
 +.Sh AUTHORS
 +The
 +.Nm
 +driver was written by
 +.An Matt Dainty Aq m...@bodgit-n-scarper.com .
 +.Sh BUGS
 +If the Xilinx FPGA is programmed with a different bistream, the driver will
 +likely not function.
 Index: share/man/man4/man4.i386/Makefile
 ===
 RCS file: /cvs/src/share/man/man4/man4.i386/Makefile,v
 retrieving revision 1.72
 diff -u -p -r1.72 Makefile
 --- share/man/man4/man4.i386/Makefile 27 May 2012 12:24:33 -  1.72
 +++ share/man/man4/man4.i386/Makefile 21 Nov 2014 11:38:17 -
 @@ -7,7 +7,7 @@ MAN=  amdpcib.4 amdmsr.4 apm.4 autoconf.4
   ichpcib.4 intro.4 ioapic.4 \
   joy.4 le.4 lms.4 mem.4 mms.4 mpbios.4 mtrr.4 npx.4 nvram.4 \
   pas.4 pcibios.4 pctr.4 piixpcib.4 sb.4 \
 - sea.4 tcpcib.4 uha.4 wds.4 wdt.4 wss.4
 + sea.4

Re: Soekris net6501 GPIO LED support

2014-12-05 Thread Matt Dainty
* Jonathan Gray j...@jsg.id.au [2014-12-05 10:16:41]:
 Perhaps a driver name change to reflect that this is to interface to the
 fpga on the soekris?

This is tcpcib(4) all over again ;-)

NetBSD committed this driver as soekrisgpio but I thought that might be a
bit too long. Any opinions or suggestions?

 I wonder if the 16 bit general purpose I/O, 26 pins header, connected
 to FPGA on the net6801 will have the same interface.

I saw this too. Without seeing any details my hunch is it will probably be
very similar.

Matt

 On Fri, Dec 05, 2014 at 10:05:46AM -0500, Matt Dainty wrote:
  Anyone?
 



Re: Soekris net6501 GPIO LED support

2013-03-13 Thread Matt Dainty
* Matt Dainty m...@bodgit-n-scarper.com [2013-01-14 11:13:59]:
 Attached is a patch that adds soekris(4) which provides access to the
 GPIO and LEDs as implemented by the onboard Xilinx FPGA on the Soekris
 net6501. The driver provides two GPIO buses; one for the 16 real GPIO
 pins exposed on the board, and another which has the LEDs coerced into
 the GPIO framework as output-only pins.
 
 I kept them separate to prevent confusion and make the code slightly
 simpler, if it's preferred to have just one GPIO bus let me know.
 
 It's enabled in the kernel config with:
 
 soekris0 at isa? port 0x680
 gpio*at soekris?
 
 The driver cannot be enabled by default as there's no reliable way to
 detect the hardware, it's just a handful of I/O ports at a known
 address, (GPIO isn't enabled by default in GENERIC so a kernel compile
 is required regardless).
 
 This is what is shown at boot:
 
 soekris0 at isa0 port 0x680/32
 gpio0 at soekris0: 16 pins
 gpio1 at soekris0: 2 pins
 
 I then have the following in /etc/rc.securelevel:
 
 gpioctl -q gpio1 0 set out error_led
 gpioctl -q gpio1 1 set out ready_led
 
 If this driver is acceptable I can send a further patch with man pages.
 Tested on a Soekris net6501 running amd64, LEDs work and I've put
 simple LED and pushbutton circuits on the GPIO pins.

Here's an updated patch for the driver, the only change is in the
*_match() function that is now simplified and much more reliable thanks
to the committed Soekris comBIOS patch to bios(4).

I've still left the GENERIC config unchanged as there's no other gpio(4)
drivers enabled, I'm guessing as general policy.

I'll send a separate patch with the various man page changes.

Matt

--- /dev/null   Wed Mar 13 10:27:40 2013
+++ sys/dev/isa/soekris.c   Tue Feb 19 08:31:10 2013
@@ -0,0 +1,239 @@
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2013 Matt Dainty m...@bodgit-n-scarper.com
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Soekris net6501 GPIO and LEDs as implemented by the onboard Xilinx FPGA 
+ */
+
+#include sys/param.h
+#include sys/systm.h
+#include sys/device.h
+#include sys/gpio.h
+
+#include machine/bus.h
+#include machine/intr.h
+
+#include dev/isa/isavar.h
+
+#include dev/gpio/gpiovar.h
+
+#defineSOEKRIS_BASE0x680   /* Base address of FPGA I/O */
+#defineSOEKRIS_IOSIZE  32  /* I/O region size */
+
+#defineSOEKRIS_NPINS   16  /* Number of Pins */
+#defineSOEKRIS_GPIO_INPUT  0x000   /* Current state of pins */
+#defineSOEKRIS_GPIO_OUTPUT 0x004   /* Set state of output pins */
+#defineSOEKRIS_GPIO_RESET  0x008   /* Reset output pins */
+#defineSOEKRIS_GPIO_SET0x00c   /* Set output pins */
+#defineSOEKRIS_GPIO_DIR0x010   /* Direction, set for output */
+
+#defineSOEKRIS_NLEDS   2   /* Number of LEDs */
+#defineSOEKRIS_LED_ERROR   0x01c   /* Offset to error LED */
+#defineSOEKRIS_LED_READY   0x01d   /* Offset to ready LED */
+
+extern char *hw_vendor, *hw_prod;
+
+const u_int soekris_led_offset[SOEKRIS_NLEDS] = {
+   SOEKRIS_LED_ERROR, SOEKRIS_LED_READY
+};
+
+struct soekris_softc {
+   struct devicesc_dev;
+
+   bus_space_tag_t  sc_iot;
+   bus_space_handle_t   sc_ioh;
+
+   struct gpio_chipset_tag  sc_gpio_gc;
+   gpio_pin_t   sc_gpio_pins[SOEKRIS_NPINS];
+
+   /* Fake GPIO device for the LEDs */
+   struct gpio_chipset_tag  sc_led_gc;
+   gpio_pin_t   sc_led_pins[SOEKRIS_NLEDS];
+};
+
+int soekris_match(struct device *, void *, void *);
+voidsoekris_attach(struct device *, struct device *, void *);
+int soekris_gpio_read(void *, int);
+voidsoekris_gpio_write(void *, int, int);
+voidsoekris_gpio_ctl(void *, int, int);
+int soekris_led_read(void *, int);
+voidsoekris_led_write(void *, int, int);
+voidsoekris_led_ctl(void *, int, int);
+
+struct cfattach soekris_ca = {
+   sizeof(struct soekris_softc), soekris_match, soekris_attach
+};
+
+struct cfdriver soekris_cd = {
+   NULL, soekris, DV_DULL
+};
+
+int
+soekris_match(struct device *parent, void *match, void *aux)
+{
+   struct isa_attach_args *ia = aux

Re: Soekris net6501 GPIO LED support

2013-03-13 Thread Matt Dainty
* Matt Dainty m...@bodgit-n-scarper.com [2013-03-13 07:56:14]:
 
 I'll send a separate patch with the various man page changes.

And here's the man page changes.

Matt

--- /dev/null   Wed Mar 13 10:31:11 2013
+++ share/man/man4/man4.amd64/soekris.4 Tue Feb 19 08:34:54 2013
@@ -0,0 +1,57 @@
+.\ $OpenBSD$
+.\
+.\ Copyright (c) 2013 Matt Dainty m...@bodgit-n-scarper.com
+.\
+.\ Permission to use, copy, modify, and distribute this software for any
+.\ purpose with or without fee is hereby granted, provided that the above
+.\ copyright notice and this permission notice appear in all copies.
+.\
+.\ THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\
+.Dd $Mdocdate$
+.Dt SOEKRIS 4 amd64
+.Os
+.Sh NAME
+.Nm soekris
+.Nd Soekris net6501 GPIO and LEDs
+.Sh SYNOPSIS
+.Cd soekris0 at isa? port 0x680
+.Cd gpio* at soekris?
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the GPIO and LEDs as implemented by the Xilinx
+Spartan FGPA integrated into the Soekris net6501 programmed with the default
+bitstream found in the BIOS.
+.Pp
+Two standard
+.Xr gpio 4
+interfaces are provided, one for the 16 real pins which can be configured as
+either inputs or outputs and another with 2 output-only pins that map
+to the error and ready LEDs respectively.
+Both may be used with
+.Xr gpioctl 8 .
+.Sh SEE ALSO
+.Xr intro 4 ,
+.Xr isa 4 ,
+.Xr gpio 4 ,
+.Xr gpioctl 8
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 5.3 .
+.Sh AUTHORS
+The
+.Nm
+driver was written by
+.An Matt Dainty Aq m...@bodgit-n-scarper.com .
+.Sh BUGS
+If the Xilinx FPGA is programmed with a different bistream, the driver will
+likely not function.
--- /dev/null   Wed Mar 13 10:31:27 2013
+++ share/man/man4/man4.i386/soekris.4  Tue Feb 19 08:35:23 2013
@@ -0,0 +1,57 @@
+.\ $OpenBSD$
+.\
+.\ Copyright (c) 2013 Matt Dainty m...@bodgit-n-scarper.com
+.\
+.\ Permission to use, copy, modify, and distribute this software for any
+.\ purpose with or without fee is hereby granted, provided that the above
+.\ copyright notice and this permission notice appear in all copies.
+.\
+.\ THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\
+.Dd $Mdocdate$
+.Dt SOEKRIS 4 i386
+.Os
+.Sh NAME
+.Nm soekris
+.Nd Soekris net6501 GPIO and LEDs
+.Sh SYNOPSIS
+.Cd soekris0 at isa? port 0x680
+.Cd gpio* at soekris?
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the GPIO and LEDs as implemented by the Xilinx
+Spartan FGPA integrated into the Soekris net6501 programmed with the default
+bitstream found in the BIOS.
+.Pp
+Two standard
+.Xr gpio 4
+interfaces are provided, one for the 16 real pins which can be configured as
+either inputs or outputs and another with 2 output-only pins that map
+to the error and ready LEDs respectively.
+Both may be used with
+.Xr gpioctl 8 .
+.Sh SEE ALSO
+.Xr intro 4 ,
+.Xr isa 4 ,
+.Xr gpio 4 ,
+.Xr gpioctl 8
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 5.3 .
+.Sh AUTHORS
+The
+.Nm
+driver was written by
+.An Matt Dainty Aq m...@bodgit-n-scarper.com .
+.Sh BUGS
+If the Xilinx FPGA is programmed with a different bistream, the driver will
+likely not function.
--- share/man/man4/man4.amd64/Makefile.orig Tue Jan  8 15:20:04 2013
+++ share/man/man4/man4.amd64/Makefile  Tue Jan  8 15:21:00 2013
@@ -1,7 +1,7 @@
 #  $OpenBSD: Makefile,v 1.15 2012/05/27 12:24:33 jsg Exp $
 
 MAN=   amdpcib.4 apm.4 autoconf.4 bios.4 cpu.4 intro.4 ioapic.4 \
-   mem.4 mpbios.4 nvram.4 mtrr.4 pctr.4 tcpcib.4
+   mem.4 mpbios.4 nvram.4 mtrr.4 pctr.4 soekris.4 tcpcib.4
 
 MLINKS+= mem.4 kmem.4
 MANSUBDIR=amd64
--- share/man/man4/man4.i386/Makefile.orig  Tue Jan  8 15:19:56 2013
+++ share/man/man4/man4.i386/Makefile   Tue Jan  8 15:20:36 2013
@@ -7,7 +7,7 @@
ichpcib.4 intro.4 ioapic.4 \
joy.4 le.4 lms.4 mem.4 mms.4 mpbios.4 mtrr.4 npx.4 nvram.4 \
pas.4 pcibios.4 pctr.4 piixpcib.4 sb.4 \
-   sea.4 tcpcib.4 uha.4 wds.4 wdt.4 wss.4
+   sea.4 soekris.4 tcpcib.4 uha.4 wds.4 wdt.4 wss.4
 
 MLINKS+= mem.4 kmem.4
 MANSUBDIR=i386
--- share/man/man4/gpio.4.orig  Tue Jan  8 15:22:00 2013
+++ share/man/man4

Re: Add Soekris comBIOS detection to bios(4) on i386/amd64

2013-03-12 Thread Matt Dainty
* Matt Dainty m...@bodgit-n-scarper.com [2013-02-20 19:30:43]:
 Attached are two patches for bios(4) on i386  amd64 that add support
 for detecting the comBIOS on Soekris hardware, which then fills in the
 hw.vendor  hw.product sysctl variables as this hardware lacks any
 SMBIOS to provide them. The idea is then these can be used in the
 GPIO/LED driver for the net6501 I posted a while ago to simplify the
 match logic.

Are there any objections to this being committed? It seems to work on
all Soekris boards. I can send the revised GPIO/LED driver for the
net6501.

Thanks

Matt

 --- sys/arch/amd64/amd64/bios.c.orig  Tue Feb 19 01:56:56 2013
 +++ sys/arch/amd64/amd64/bios.c   Wed Feb 20 08:37:12 2013
 @@ -95,6 +95,7 @@
   vaddr_t va;
   paddr_t pa, end;
   u_int8_t *p;
 + int smbiosrev = 0;
  
   /* see if we have SMBIOS extentions */
   for (p = ISA_HOLE_VADDR(SMBIOS_START);
 @@ -137,6 +138,10 @@
   printf(: SMBIOS rev. %d.%d @ 0x%lx (%d entries),
   hdr-majrev, hdr-minrev, hdr-addr, hdr-count);
  
 + smbiosrev = hdr-majrev * 100 + hdr-minrev;
 + if (hdr-minrev  10)
 + smbiosrev = hdr-majrev * 100 + hdr-minrev * 10;
 +
   bios.cookie = 0;
   if (smbios_find_table(SMBIOS_TYPE_BIOS, bios)) {
   sb = bios.tblhdr;
 @@ -158,6 +163,39 @@
   break;
   }
   printf(\n);
 +
 + /* No SMBIOS extensions, go looking for Soekris comBIOS */
 + if (!smbiosrev) {
 + const char *signature = Soekris Engineering;
 +
 + for (p = ISA_HOLE_VADDR(SMBIOS_START);
 + p = (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END -
 + (strlen(signature) - 1)); p++)
 + if (!memcmp(p, signature, strlen(signature))) {
 + hw_vendor = malloc(strlen(signature) + 1,
 + M_DEVBUF, M_NOWAIT);
 + if (hw_vendor)
 + strlcpy(hw_vendor, signature,
 + strlen(signature) + 1);
 + p += strlen(signature);
 + break;
 + }
 +
 + for (; hw_vendor 
 + p = (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END - 6); p++)
 + /*
 +  * Search only for net6501 in the comBIOS as that's
 +  * the only Soekris platform that can run amd64
 +  */
 + if (!memcmp(p, net6501, 7)) {
 + hw_prod = malloc(8, M_DEVBUF, M_NOWAIT);
 + if (hw_prod) {
 + memcpy(hw_prod, p, 7);
 + hw_prod[7] = '\0';
 + }
 + break;
 + }
 + }
  
  #if NACPI  0
   {
 --- sys/arch/i386/i386/bios.c.origTue Feb 19 06:36:42 2013
 +++ sys/arch/i386/i386/bios.c Wed Feb 20 08:58:17 2013
 @@ -330,6 +330,43 @@
  
   printf(\n);
  
 + /* No SMBIOS extensions, go looking for Soekris comBIOS */
 + if (!(flags  BIOSF_SMBIOS)  !smbiosrev) {
 + const char *signature = Soekris Engineering;
 +
 + for (va = ISA_HOLE_VADDR(SMBIOS_START);
 + va = (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END -
 + (strlen(signature) - 1)); va++)
 + if (!memcmp((u_int8_t *)va, signature,
 + strlen(signature))) {
 + hw_vendor = malloc(strlen(signature) + 1,
 + M_DEVBUF, M_NOWAIT);
 + if (hw_vendor)
 + strlcpy(hw_vendor, signature,
 + strlen(signature) + 1);
 + va += strlen(signature);
 + break;
 + }
 +
 + for (; hw_vendor 
 + va = (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END - 6); va++)
 + /*
 +  * Search for net(4(5xx|801)|[56]501) which matches
 +  * the strings found in the comBIOS images
 +  */
 + if (!memcmp((u_int8_t *)va, net45xx, 7) ||
 + !memcmp((u_int8_t *)va, net4801, 7) ||
 + !memcmp((u_int8_t *)va, net5501, 7) ||
 + !memcmp((u_int8_t *)va, net6501, 7)) {
 + hw_prod = malloc(8, M_DEVBUF, M_NOWAIT);
 + if (hw_prod) {
 + memcpy(hw_prod, (u_int8_t *)va, 7);
 + hw_prod[7] = '\0';
 + }
 + break;
 + }
 + }
 +
  #if NAPM  0

Re: Add Soekris comBIOS detection to bios(4) on i386/amd64

2013-03-12 Thread Matt Dainty
* Kenneth R Westerback kwesterb...@rogers.com [2013-03-12 06:39:02]:
 On Tue, Mar 12, 2013 at 05:13:01AM -0400, Matt Dainty wrote:
  * Matt Dainty m...@bodgit-n-scarper.com [2013-02-20 19:30:43]:
   Attached are two patches for bios(4) on i386  amd64 that add support
   for detecting the comBIOS on Soekris hardware, which then fills in the
   hw.vendor  hw.product sysctl variables as this hardware lacks any
   SMBIOS to provide them. The idea is then these can be used in the
   GPIO/LED driver for the net6501 I posted a while ago to simplify the
   match logic.
  
  Are there any objections to this being committed? It seems to work on
  all Soekris boards. I can send the revised GPIO/LED driver for the
  net6501.
  
  Thanks
  
  Matt
 
 Putting in workarounds for particular vendors always puts my teeth on
 edge. How many other bios weirdos will end up here?
 
  Ken

I was originally using something similar to this code in my GPIO/LED
driver as part of the *_match() function as a means to accurately probe
the hardware. It was suggested to move this code to bios(4) so that it
could provide some value in populating hw.{vendor,product} particularly
if it worked on the older boards, which it seems to. But it has a
purpose rather than purely populating sysctl.

Matt

  
   --- sys/arch/amd64/amd64/bios.c.orig  Tue Feb 19 01:56:56 2013
   +++ sys/arch/amd64/amd64/bios.c   Wed Feb 20 08:37:12 2013
   @@ -95,6 +95,7 @@
 vaddr_t va;
 paddr_t pa, end;
 u_int8_t *p;
   + int smbiosrev = 0;

 /* see if we have SMBIOS extentions */
 for (p = ISA_HOLE_VADDR(SMBIOS_START);
   @@ -137,6 +138,10 @@
 printf(: SMBIOS rev. %d.%d @ 0x%lx (%d entries),
 hdr-majrev, hdr-minrev, hdr-addr, hdr-count);

   + smbiosrev = hdr-majrev * 100 + hdr-minrev;
   + if (hdr-minrev  10)
   + smbiosrev = hdr-majrev * 100 + hdr-minrev * 10;
   +
 bios.cookie = 0;
 if (smbios_find_table(SMBIOS_TYPE_BIOS, bios)) {
 sb = bios.tblhdr;
   @@ -158,6 +163,39 @@
 break;
 }
 printf(\n);
   +
   + /* No SMBIOS extensions, go looking for Soekris comBIOS */
   + if (!smbiosrev) {
   + const char *signature = Soekris Engineering;
   +
   + for (p = ISA_HOLE_VADDR(SMBIOS_START);
   + p = (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END -
   + (strlen(signature) - 1)); p++)
   + if (!memcmp(p, signature, strlen(signature))) {
   + hw_vendor = malloc(strlen(signature) + 1,
   + M_DEVBUF, M_NOWAIT);
   + if (hw_vendor)
   + strlcpy(hw_vendor, signature,
   + strlen(signature) + 1);
   + p += strlen(signature);
   + break;
   + }
   +
   + for (; hw_vendor 
   + p = (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END - 6); p++)
   + /*
   +  * Search only for net6501 in the comBIOS as that's
   +  * the only Soekris platform that can run amd64
   +  */
   + if (!memcmp(p, net6501, 7)) {
   + hw_prod = malloc(8, M_DEVBUF, M_NOWAIT);
   + if (hw_prod) {
   + memcpy(hw_prod, p, 7);
   + hw_prod[7] = '\0';
   + }
   + break;
   + }
   + }

#if NACPI  0
 {
   --- sys/arch/i386/i386/bios.c.origTue Feb 19 06:36:42 2013
   +++ sys/arch/i386/i386/bios.c Wed Feb 20 08:58:17 2013
   @@ -330,6 +330,43 @@

 printf(\n);

   + /* No SMBIOS extensions, go looking for Soekris comBIOS */
   + if (!(flags  BIOSF_SMBIOS)  !smbiosrev) {
   + const char *signature = Soekris Engineering;
   +
   + for (va = ISA_HOLE_VADDR(SMBIOS_START);
   + va = (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END -
   + (strlen(signature) - 1)); va++)
   + if (!memcmp((u_int8_t *)va, signature,
   + strlen(signature))) {
   + hw_vendor = malloc(strlen(signature) + 1,
   + M_DEVBUF, M_NOWAIT);
   + if (hw_vendor)
   + strlcpy(hw_vendor, signature,
   + strlen(signature) + 1);
   + va += strlen(signature);
   + break;
   + }
   +
   + for (; hw_vendor 
   + va = (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END - 6); va++)
   + /*
   +  * Search for net(4(5xx|801)|[56]501) which matches
   +  * the strings found in the comBIOS images

Re: Add Soekris comBIOS detection to bios(4) on i386/amd64

2013-03-04 Thread Matt Dainty
* Matt Dainty m...@bodgit-n-scarper.com [2013-02-20 19:30:43]:
 Attached are two patches for bios(4) on i386  amd64 that add support
 for detecting the comBIOS on Soekris hardware, which then fills in the
 hw.vendor  hw.product sysctl variables as this hardware lacks any
 SMBIOS to provide them. The idea is then these can be used in the
 GPIO/LED driver for the net6501 I posted a while ago to simplify the
 match logic.
 
 I've tested this with a net6501  amd64 so I would appreciate testing
 on any other Soekris hardware under i386; net4501, net4801  net5501.

I'm lacking a test report for a net4801, however as I've had reports
of success for all other Soekris board types, I'd be surprised if it
didn't work.

 Also any other hardware that lacks SMBIOS and in the case of i386
 doesn't need to disable probing of SMBIOS with flags 0x0008.

I would still appreciate some testing on other systems that lack any
SMBIOS, just to make sure it doesn't cause problems there. However as
this code walks over the same area of memory, I would again be
surprised if this caused problems when the SMBIOS probe didn't.

Matt

 --- sys/arch/amd64/amd64/bios.c.orig  Tue Feb 19 01:56:56 2013
 +++ sys/arch/amd64/amd64/bios.c   Wed Feb 20 08:37:12 2013
 @@ -95,6 +95,7 @@
   vaddr_t va;
   paddr_t pa, end;
   u_int8_t *p;
 + int smbiosrev = 0;
  
   /* see if we have SMBIOS extentions */
   for (p = ISA_HOLE_VADDR(SMBIOS_START);
 @@ -137,6 +138,10 @@
   printf(: SMBIOS rev. %d.%d @ 0x%lx (%d entries),
   hdr-majrev, hdr-minrev, hdr-addr, hdr-count);
  
 + smbiosrev = hdr-majrev * 100 + hdr-minrev;
 + if (hdr-minrev  10)
 + smbiosrev = hdr-majrev * 100 + hdr-minrev * 10;
 +
   bios.cookie = 0;
   if (smbios_find_table(SMBIOS_TYPE_BIOS, bios)) {
   sb = bios.tblhdr;
 @@ -158,6 +163,39 @@
   break;
   }
   printf(\n);
 +
 + /* No SMBIOS extensions, go looking for Soekris comBIOS */
 + if (!smbiosrev) {
 + const char *signature = Soekris Engineering;
 +
 + for (p = ISA_HOLE_VADDR(SMBIOS_START);
 + p = (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END -
 + (strlen(signature) - 1)); p++)
 + if (!memcmp(p, signature, strlen(signature))) {
 + hw_vendor = malloc(strlen(signature) + 1,
 + M_DEVBUF, M_NOWAIT);
 + if (hw_vendor)
 + strlcpy(hw_vendor, signature,
 + strlen(signature) + 1);
 + p += strlen(signature);
 + break;
 + }
 +
 + for (; hw_vendor 
 + p = (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END - 6); p++)
 + /*
 +  * Search only for net6501 in the comBIOS as that's
 +  * the only Soekris platform that can run amd64
 +  */
 + if (!memcmp(p, net6501, 7)) {
 + hw_prod = malloc(8, M_DEVBUF, M_NOWAIT);
 + if (hw_prod) {
 + memcpy(hw_prod, p, 7);
 + hw_prod[7] = '\0';
 + }
 + break;
 + }
 + }
  
  #if NACPI  0
   {
 --- sys/arch/i386/i386/bios.c.origTue Feb 19 06:36:42 2013
 +++ sys/arch/i386/i386/bios.c Wed Feb 20 08:58:17 2013
 @@ -330,6 +330,43 @@
  
   printf(\n);
  
 + /* No SMBIOS extensions, go looking for Soekris comBIOS */
 + if (!(flags  BIOSF_SMBIOS)  !smbiosrev) {
 + const char *signature = Soekris Engineering;
 +
 + for (va = ISA_HOLE_VADDR(SMBIOS_START);
 + va = (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END -
 + (strlen(signature) - 1)); va++)
 + if (!memcmp((u_int8_t *)va, signature,
 + strlen(signature))) {
 + hw_vendor = malloc(strlen(signature) + 1,
 + M_DEVBUF, M_NOWAIT);
 + if (hw_vendor)
 + strlcpy(hw_vendor, signature,
 + strlen(signature) + 1);
 + va += strlen(signature);
 + break;
 + }
 +
 + for (; hw_vendor 
 + va = (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END - 6); va++)
 + /*
 +  * Search for net(4(5xx|801)|[56]501) which matches
 +  * the strings found in the comBIOS images
 +  */
 + if (!memcmp((u_int8_t *)va, net45xx, 7) ||
 + !memcmp

Add Soekris comBIOS detection to bios(4) on i386/amd64

2013-02-20 Thread Matt Dainty
Attached are two patches for bios(4) on i386  amd64 that add support
for detecting the comBIOS on Soekris hardware, which then fills in the
hw.vendor  hw.product sysctl variables as this hardware lacks any
SMBIOS to provide them. The idea is then these can be used in the
GPIO/LED driver for the net6501 I posted a while ago to simplify the
match logic.

I've tested this with a net6501  amd64 so I would appreciate testing
on any other Soekris hardware under i386; net4501, net4801  net5501.
You should hopefully get something like the following:

$ sysctl hw
...
hw.vendor=Soekris Engineering
hw.product=net6501

Also any other hardware that lacks SMBIOS and in the case of i386
doesn't need to disable probing of SMBIOS with flags 0x0008.

Thanks

Matt

--- sys/arch/amd64/amd64/bios.c.origTue Feb 19 01:56:56 2013
+++ sys/arch/amd64/amd64/bios.c Wed Feb 20 08:37:12 2013
@@ -95,6 +95,7 @@
vaddr_t va;
paddr_t pa, end;
u_int8_t *p;
+   int smbiosrev = 0;
 
/* see if we have SMBIOS extentions */
for (p = ISA_HOLE_VADDR(SMBIOS_START);
@@ -137,6 +138,10 @@
printf(: SMBIOS rev. %d.%d @ 0x%lx (%d entries),
hdr-majrev, hdr-minrev, hdr-addr, hdr-count);
 
+   smbiosrev = hdr-majrev * 100 + hdr-minrev;
+   if (hdr-minrev  10)
+   smbiosrev = hdr-majrev * 100 + hdr-minrev * 10;
+
bios.cookie = 0;
if (smbios_find_table(SMBIOS_TYPE_BIOS, bios)) {
sb = bios.tblhdr;
@@ -158,6 +163,39 @@
break;
}
printf(\n);
+
+   /* No SMBIOS extensions, go looking for Soekris comBIOS */
+   if (!smbiosrev) {
+   const char *signature = Soekris Engineering;
+
+   for (p = ISA_HOLE_VADDR(SMBIOS_START);
+   p = (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END -
+   (strlen(signature) - 1)); p++)
+   if (!memcmp(p, signature, strlen(signature))) {
+   hw_vendor = malloc(strlen(signature) + 1,
+   M_DEVBUF, M_NOWAIT);
+   if (hw_vendor)
+   strlcpy(hw_vendor, signature,
+   strlen(signature) + 1);
+   p += strlen(signature);
+   break;
+   }
+
+   for (; hw_vendor 
+   p = (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END - 6); p++)
+   /*
+* Search only for net6501 in the comBIOS as that's
+* the only Soekris platform that can run amd64
+*/
+   if (!memcmp(p, net6501, 7)) {
+   hw_prod = malloc(8, M_DEVBUF, M_NOWAIT);
+   if (hw_prod) {
+   memcpy(hw_prod, p, 7);
+   hw_prod[7] = '\0';
+   }
+   break;
+   }
+   }
 
 #if NACPI  0
{
--- sys/arch/i386/i386/bios.c.orig  Tue Feb 19 06:36:42 2013
+++ sys/arch/i386/i386/bios.c   Wed Feb 20 08:58:17 2013
@@ -330,6 +330,43 @@
 
printf(\n);
 
+   /* No SMBIOS extensions, go looking for Soekris comBIOS */
+   if (!(flags  BIOSF_SMBIOS)  !smbiosrev) {
+   const char *signature = Soekris Engineering;
+
+   for (va = ISA_HOLE_VADDR(SMBIOS_START);
+   va = (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END -
+   (strlen(signature) - 1)); va++)
+   if (!memcmp((u_int8_t *)va, signature,
+   strlen(signature))) {
+   hw_vendor = malloc(strlen(signature) + 1,
+   M_DEVBUF, M_NOWAIT);
+   if (hw_vendor)
+   strlcpy(hw_vendor, signature,
+   strlen(signature) + 1);
+   va += strlen(signature);
+   break;
+   }
+
+   for (; hw_vendor 
+   va = (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END - 6); va++)
+   /*
+* Search for net(4(5xx|801)|[56]501) which matches
+* the strings found in the comBIOS images
+*/
+   if (!memcmp((u_int8_t *)va, net45xx, 7) ||
+   !memcmp((u_int8_t *)va, net4801, 7) ||
+   !memcmp((u_int8_t *)va, net5501, 7) ||
+   !memcmp((u_int8_t *)va, net6501, 7)) {
+   hw_prod = malloc(8, M_DEVBUF, M_NOWAIT);
+   if (hw_prod) {
+   

Re: Detect on-die temp sensor for Atom E6xx on amd64

2013-01-30 Thread Matt Dainty
* Mark Kettenis mark.kette...@xs4all.nl [2013-01-30 03:49:45]:
  Date: Tue, 29 Jan 2013 17:35:13 -0500
  From: Matt Dainty m...@bodgit-n-scarper.com
  
  * Christian Weisgerber na...@mips.inka.de [2013-01-24 13:03:43]:
   Matt Dainty m...@bodgit-n-scarper.com wrote:
   
--- sys/arch/amd64/amd64/identcpu.c.orig2013-01-14 
22:23:43.0 +
+++ sys/arch/amd64/amd64/identcpu.c 2013-01-14 22:33:21.0 
+
@@ -506,7 +506,8 @@
if (ci-ci_feature_sefflags  SEFF0EBX_SMAP)
replacesmap();
}
-   if (!strncmp(mycpu_model, Intel, 5)) {
+   if (!strncmp(mycpu_model, Intel, 5) ||
+   !strncmp(mycpu_model, Genuine Intel, 13)) {
u_int32_t cflushsz;
 
CPUID(0x01, dummy, cflushsz, dummy, dummy);

   
   I think it's dubious that we match the CPU brand name for this at
   all.  Shouldn't this be properly handled with CPUID?
  
  Here's a slightly simpler diff that checks the vendor rather than the
  CPU brand.
  
  I'm not sure if it's safe to check CPUID regardless of vendor, plus
  there is the CLFLUSH code in that block as well, I figure that's
  confined to Intel for a reason?
 
 Look at the equivalent i386 code.

It looks like the i386 code ultimately does the same thing, looking
through i386/machdep.c, the CPUID is only checked in
intel686_cpusensors_setup() which is traced back to the big
i386_cpuid_cpus[] struct and intel686_cpu_setup()/intel686_p4_cpu_setup()
which to my eyes only gets called for Intel CPUs.

Matt



Re: Detect on-die temp sensor for Atom E6xx on amd64

2013-01-29 Thread Matt Dainty
* Christian Weisgerber na...@mips.inka.de [2013-01-24 13:03:43]:
 Matt Dainty m...@bodgit-n-scarper.com wrote:
 
  --- sys/arch/amd64/amd64/identcpu.c.orig2013-01-14 22:23:43.0 
  +
  +++ sys/arch/amd64/amd64/identcpu.c 2013-01-14 22:33:21.0 +
  @@ -506,7 +506,8 @@
  if (ci-ci_feature_sefflags  SEFF0EBX_SMAP)
  replacesmap();
  }
  -   if (!strncmp(mycpu_model, Intel, 5)) {
  +   if (!strncmp(mycpu_model, Intel, 5) ||
  +   !strncmp(mycpu_model, Genuine Intel, 13)) {
  u_int32_t cflushsz;
   
  CPUID(0x01, dummy, cflushsz, dummy, dummy);
  
 
 I think it's dubious that we match the CPU brand name for this at
 all.  Shouldn't this be properly handled with CPUID?

Here's a slightly simpler diff that checks the vendor rather than the
CPU brand.

I'm not sure if it's safe to check CPUID regardless of vendor, plus
there is the CLFLUSH code in that block as well, I figure that's
confined to Intel for a reason?

Matt

--- sys/arch/amd64/amd64/identcpu.c.orig2013-01-14 22:23:43.0 
+
+++ sys/arch/amd64/amd64/identcpu.c 2013-01-29 22:17:44.0 +
@@ -506,7 +506,7 @@
if (ci-ci_feature_sefflags  SEFF0EBX_SMAP)
replacesmap();
}
-   if (!strncmp(mycpu_model, Intel, 5)) {
+   if (!strcmp(cpu_vendor, GenuineIntel)) {
u_int32_t cflushsz;
 
CPUID(0x01, dummy, cflushsz, dummy, dummy);



Soekris net6501 GPIO LED support

2013-01-14 Thread Matt Dainty
Attached is a patch that adds soekris(4) which provides access to the
GPIO and LEDs as implemented by the onboard Xilinx FPGA on the Soekris
net6501. The driver provides two GPIO buses; one for the 16 real GPIO
pins exposed on the board, and another which has the LEDs coerced into
the GPIO framework as output-only pins.

I kept them separate to prevent confusion and make the code slightly
simpler, if it's preferred to have just one GPIO bus let me know.

It's enabled in the kernel config with:

soekris0 at isa? port 0x680
gpio*at soekris?

The driver cannot be enabled by default as there's no reliable way to
detect the hardware, it's just a handful of I/O ports at a known
address, (GPIO isn't enabled by default in GENERIC so a kernel compile
is required regardless).

This is what is shown at boot:

soekris0 at isa0 port 0x680/32
gpio0 at soekris0: 16 pins
gpio1 at soekris0: 2 pins

I then have the following in /etc/rc.securelevel:

gpioctl -q gpio1 0 set out error_led
gpioctl -q gpio1 1 set out ready_led

If this driver is acceptable I can send a further patch with man pages.
Tested on a Soekris net6501 running amd64, LEDs work and I've put
simple LED and pushbutton circuits on the GPIO pins.

Comments?

Matt

--- /dev/null   Tue Jan  8 21:22:57 2013
+++ sys/dev/isa/soekris.c   Tue Jan  8 21:17:02 2013
@@ -0,0 +1,235 @@
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2013 Matt Dainty m...@bodgit-n-scarper.com
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Soekris net6501 GPIO and LEDs as implemented by the onboard Xilinx FPGA 
+ */
+
+#include sys/param.h
+#include sys/systm.h
+#include sys/device.h
+#include sys/gpio.h
+
+#include machine/bus.h
+#include machine/intr.h
+
+#include dev/isa/isavar.h
+
+#include dev/gpio/gpiovar.h
+
+#defineSOEKRIS_BASE0x680   /* Base address of FPGA I/O */
+#defineSOEKRIS_IOSIZE  32  /* I/O region size */
+
+#defineSOEKRIS_NPINS   16  /* Number of Pins */
+#defineSOEKRIS_GPIO_INPUT  0x000   /* Current state of pins */
+#defineSOEKRIS_GPIO_OUTPUT 0x004   /* Set state of output pins */
+#defineSOEKRIS_GPIO_RESET  0x008   /* Reset output pins */
+#defineSOEKRIS_GPIO_SET0x00c   /* Set output pins */
+#defineSOEKRIS_GPIO_DIR0x010   /* Direction, set for output */
+
+#defineSOEKRIS_NLEDS   2   /* Number of LEDs */
+#defineSOEKRIS_LED_ERROR   0x01c   /* Offset to error LED */
+#defineSOEKRIS_LED_READY   0x01d   /* Offset to ready LED */
+
+const u_int soekris_led_offset[SOEKRIS_NLEDS] = {
+   SOEKRIS_LED_ERROR, SOEKRIS_LED_READY
+};
+
+struct soekris_softc {
+   struct devicesc_dev;
+
+   bus_space_tag_t  sc_iot;
+   bus_space_handle_t   sc_ioh;
+
+   struct gpio_chipset_tag  sc_gpio_gc;
+   gpio_pin_t   sc_gpio_pins[SOEKRIS_NPINS];
+
+   /* Fake GPIO device for the LEDs */
+   struct gpio_chipset_tag  sc_led_gc;
+   gpio_pin_t   sc_led_pins[SOEKRIS_NLEDS];
+};
+
+int soekris_match(struct device *, void *, void *);
+voidsoekris_attach(struct device *, struct device *, void *);
+int soekris_gpio_read(void *, int);
+voidsoekris_gpio_write(void *, int, int);
+voidsoekris_gpio_ctl(void *, int, int);
+int soekris_led_read(void *, int);
+voidsoekris_led_write(void *, int, int);
+voidsoekris_led_ctl(void *, int, int);
+
+struct cfattach soekris_ca = {
+   sizeof(struct soekris_softc), soekris_match, soekris_attach
+};
+
+struct cfdriver soekris_cd = {
+   NULL, soekris, DV_DULL
+};
+
+int
+soekris_match(struct device *parent, void *match, void *aux)
+{
+   struct isa_attach_args *ia = aux;
+   bus_space_handle_t ioh;
+
+   /* Need some sort of heuristic to match the Soekris net6501 */
+
+   if (ia-ia_iobase != SOEKRIS_BASE || bus_space_map(ia-ia_iot,
+   ia-ia_iobase, SOEKRIS_IOSIZE, 0, ioh) != 0)
+   return (0);
+
+   bus_space_unmap(ia-ia_iot, ioh, SOEKRIS_IOSIZE);
+   ia-ia_iosize = SOEKRIS_IOSIZE;
+   ia-ipa_nio = 1;
+   ia-ipa_nmem = 0;
+   ia-ipa_nirq = 0;
+   ia-ipa_ndrq = 0;
+
+   return (1);
+}
+
+void
+soekris_attach

Detect on-die temp sensor for Atom E6xx on amd64

2013-01-14 Thread Matt Dainty
The following patch fixes the the detection of the on-die temp sensor
for Atom E6xx CPUs (and possibly other Atom CPUs). The code was only
matching processors where the model began with Intel but this Atom
CPU model begins with Genuine Intel so I've updated the logic to
match.

Now I get:

# sysctl hw
hw.machine=amd64
hw.model=Genuine Intel(R) CPU @ 1.60GHz
hw.ncpu=2
hw.byteorder=1234
hw.pagesize=4096
hw.disknames=sd0:937db626fa67a9f0
hw.diskcount=1
hw.sensors.cpu0.temp0=66.00 degC
hw.sensors.cpu1.temp0=66.00 degC
hw.cpuspeed=600
hw.setperf=0
hw.physmem=2146304000
hw.usermem=2146287616
hw.ncpufound=2
hw.allowpowerdown=1

This only seems to affect the amd64 port, I can't find similar logic in
the i386 port.

Matt

--- sys/arch/amd64/amd64/identcpu.c.orig2013-01-14 22:23:43.0 
+
+++ sys/arch/amd64/amd64/identcpu.c 2013-01-14 22:33:21.0 +
@@ -506,7 +506,8 @@
if (ci-ci_feature_sefflags  SEFF0EBX_SMAP)
replacesmap();
}
-   if (!strncmp(mycpu_model, Intel, 5)) {
+   if (!strncmp(mycpu_model, Intel, 5) ||
+   !strncmp(mycpu_model, Genuine Intel, 13)) {
u_int32_t cflushsz;
 
CPUID(0x01, dummy, cflushsz, dummy, dummy);



Re: Add HPET support to tcpcib(4)

2012-06-04 Thread Matt Dainty
* Mark Kettenis mark.kette...@xs4all.nl [2012-06-03 08:51:03]:
  Date: Sat, 2 Jun 2012 15:36:22 -0400
  From: Matt Dainty m...@bodgit-n-scarper.com
  
  As before but with the verbosity of the attach line tuned down a notch
  and not printing extra ':'s as pointed out by Theo. So now it looks
  like this:
  
  ---8---
  tcpcib0 at pci0 dev 31 function 0 Intel E600 LPC rev 0x00: 14318179 Hz 
  timer, watchdog
  ---8---
  
  Matt
 
 I've committed the part to remove the unecessary tcpcib_wdt_unlock()
 calls, since it's better to have that committed as a seperate diff.
 
 I'm looking at the HPET stuff now.  Can you regenerate your diff and
 post it here (after my commit has percolated to your anoncvs mirror)
 for people who want to try it?

Sure, here it is.

Matt

--- sys/dev/pci/tcpcib.c.orig   Thu May 31 14:17:23 2012
+++ sys/dev/pci/tcpcib.cWed May 30 16:21:13 2012
@@ -17,12 +17,13 @@
  */
 
 /*
- * Intel Atom E600 series LPC bridge also containing watchdog
+ * Intel Atom E600 series LPC bridge also containing HPET and watchdog
  */
 
 #include sys/param.h
 #include sys/systm.h
 #include sys/device.h
+#include sys/timetc.h
 
 #include machine/bus.h
 
@@ -52,18 +53,42 @@
 #defineE600_WDT_WDTLR_ENABLE   (1  1)/* Watchdog Timer 
Enable */
 #defineE600_WDT_WDTLR_TIMEOUT  (1  2)/* WDT Timeout 
Configuration */
 
+#defineE600_HPET_BASE  0xfed0  /* HPET register base */
+#defineE600_HPET_SIZE  0x0400  /* HPET register size */
+
+#defineE600_HPET_GCID  0x000   /* Capabilities and ID 
*/
+#defineE600_HPET_GCID_WIDTH(1  13)   /* Counter Size */
+#defineE600_HPET_PERIOD0x004   /* Counter Tick Period 
*/
+#defineE600_HPET_GC0x010   /* General 
Configuration */
+#defineE600_HPET_GC_ENABLE (1  0)/* Overall Enable */
+#defineE600_HPET_GIS   0x020   /* General Interrupt 
Status */
+#defineE600_HPET_MCV   0x0f0   /* Main Counter Value */
+#defineE600_HPET_T0C   0x100   /* Timer 0 Config and 
Capabilities */
+#defineE600_HPET_T0CV  0x108   /* Timer 0 Comparator 
Value */
+#defineE600_HPET_T1C   0x120   /* Timer 1 Config and 
Capabilities */
+#defineE600_HPET_T1CV  0x128   /* Timer 1 Comparator 
Value */
+#defineE600_HPET_T2C   0x140   /* Timer 2 Config and 
Capabilities */
+#defineE600_HPET_T2CV  0x148   /* Timer 2 Comparator 
Value */
+
 struct tcpcib_softc {
struct device sc_dev;
 
/* Keep track of which parts of the hardware are active */
int sc_active;
 #defineE600_WDT_ACTIVE (1  0)
+#defineE600_HPET_ACTIVE(1  1)
 
/* Watchdog interface */
bus_space_tag_t sc_wdt_iot;
bus_space_handle_t sc_wdt_ioh;
 
int sc_wdt_period;
+
+   /* High Precision Event Timer */
+   bus_space_tag_t sc_hpet_iot;
+   bus_space_handle_t sc_hpet_ioh;
+
+   struct timecounter sc_hpet_timecounter;
 };
 
 struct cfdriver tcpcib_cd = {
@@ -79,6 +104,8 @@
 voidtcpcib_wdt_start(struct tcpcib_softc *);
 voidtcpcib_wdt_stop(struct tcpcib_softc *);
 
+u_int   tcpcib_hpet_get_timecount(struct timecounter *tc);
+
 struct cfattach tcpcib_ca = {
sizeof(struct tcpcib_softc), tcpcib_match, tcpcib_attach,
NULL, tcpcib_activate
@@ -157,10 +184,38 @@
 {
struct tcpcib_softc *sc = (struct tcpcib_softc *)self;
struct pci_attach_args *pa = aux;
+   struct timecounter *tc = sc-sc_hpet_timecounter;
u_int32_t reg, wdtbase;
 
sc-sc_active = 0;
 
+   /* High Precision Event Timer */
+   sc-sc_hpet_iot = pa-pa_memt;
+   if (bus_space_map(sc-sc_hpet_iot, E600_HPET_BASE, E600_HPET_SIZE, 0,
+   sc-sc_hpet_ioh) == 0) {
+   tc-tc_get_timecount = tcpcib_hpet_get_timecount;
+   /* XXX 64-bit counter is not supported! */
+   tc-tc_counter_mask = 0x;
+
+   reg = bus_space_read_4(sc-sc_hpet_iot, sc-sc_hpet_ioh,
+   E600_HPET_PERIOD);
+   /* femtosecs - Hz */
+   tc-tc_frequency = 1000ULL / reg;
+
+   tc-tc_name = sc-sc_dev.dv_xname;
+   tc-tc_quality = 1000;
+   tc-tc_priv = sc;
+   tc_init(tc);
+
+   /* Enable counting */
+   bus_space_write_4(sc-sc_hpet_iot, sc-sc_hpet_ioh,
+   E600_HPET_GC, E600_HPET_GC_ENABLE);
+
+   sc-sc_active |= E600_HPET_ACTIVE;
+
+   printf(: %llu Hz timer, tc-tc_frequency);
+   }
+
/* Map Watchdog I/O space */
reg = pci_conf_read(pa-pa_pc, pa-pa_tag, E600_LPC_WDTBA);
wdtbase = reg  0x;
@@ -169,10 +224,11

Add HPET support to tcpcib(4)

2012-06-02 Thread Matt Dainty
Attached are some patches that update the recently added tcpcib(4)
driver with support for using the HPET as a timecounter, based on
amdpcib(4).

Here's the updated dmesg:

---8---
tcpcib0 at pci0 dev 31 function 0 Intel E600 LPC rev 0x00: 64-bit 14318179 Hz 
timer rev 1: watchdog
---8---

Here's the sysctl output from my Soekris net6501:

# sysctl kern.timecounter
kern.timecounter.tick=1
kern.timecounter.timestepwarnings=0
kern.timecounter.hardware=tcpcib0
kern.timecounter.choice=i8254(0) tcpcib0(1000) dummy(-100)

I'm aware there's also acpihpet(4) which might normally take control of
this bit of the hardware however the Soekris net6501 at least lacks any
ACPI support at present so the hardware is currently unused. I presume
on an E600-based system with ACPI, acpihpet(4) will bagsy the hardware
first and so the bus_space_map() call in tcpcib(4) will silently fail.

I also removed a couple of overzealous tcpcib_wdt_unlock()'s that are
not needed before writing to the registers that follow, I re-tested and
the watchdog still triggers as expected.

Matt

--- sys/dev/pci/tcpcib.c.orig   Wed May 30 12:19:41 2012
+++ sys/dev/pci/tcpcib.cWed May 30 12:59:23 2012
@@ -17,12 +17,13 @@
  */
 
 /*
- * Intel Atom E600 series LPC bridge also containing watchdog
+ * Intel Atom E600 series LPC bridge also containing HPET and watchdog
  */
 
 #include sys/param.h
 #include sys/systm.h
 #include sys/device.h
+#include sys/timetc.h
 
 #include machine/bus.h
 
@@ -52,18 +53,42 @@
 #defineE600_WDT_WDTLR_ENABLE   (1  1)/* Watchdog Timer 
Enable */
 #defineE600_WDT_WDTLR_TIMEOUT  (1  2)/* WDT Timeout 
Configuration */
 
+#defineE600_HPET_BASE  0xfed0  /* HPET register base */
+#defineE600_HPET_SIZE  0x0400  /* HPET register size */
+
+#defineE600_HPET_GCID  0x000   /* Capabilities and ID 
*/
+#defineE600_HPET_GCID_WIDTH(1  13)   /* Counter Size */
+#defineE600_HPET_PERIOD0x004   /* Counter Tick Period 
*/
+#defineE600_HPET_GC0x010   /* General 
Configuration */
+#defineE600_HPET_GC_ENABLE (1  0)/* Overall Enable */
+#defineE600_HPET_GIS   0x020   /* General Interrupt 
Status */
+#defineE600_HPET_MCV   0x0f0   /* Main Counter Value */
+#defineE600_HPET_T0C   0x100   /* Timer 0 Config and 
Capabilities */
+#defineE600_HPET_T0CV  0x108   /* Timer 0 Comparator 
Value */
+#defineE600_HPET_T1C   0x120   /* Timer 1 Config and 
Capabilities */
+#defineE600_HPET_T1CV  0x128   /* Timer 1 Comparator 
Value */
+#defineE600_HPET_T2C   0x140   /* Timer 2 Config and 
Capabilities */
+#defineE600_HPET_T2CV  0x148   /* Timer 2 Comparator 
Value */
+
 struct tcpcib_softc {
struct device sc_dev;
 
/* Keep track of which parts of the hardware are active */
int sc_active;
 #defineE600_WDT_ACTIVE (1  0)
+#defineE600_HPET_ACTIVE(1  1)
 
/* Watchdog interface */
bus_space_tag_t sc_wdt_iot;
bus_space_handle_t sc_wdt_ioh;
 
int sc_wdt_period;
+
+   /* High Precision Event Timer */
+   bus_space_tag_t sc_hpet_iot;
+   bus_space_handle_t sc_hpet_ioh;
+
+   struct timecounter sc_hpet_timecounter;
 };
 
 struct cfdriver tcpcib_cd = {
@@ -79,6 +104,8 @@
 voidtcpcib_wdt_start(struct tcpcib_softc *);
 voidtcpcib_wdt_stop(struct tcpcib_softc *);
 
+u_int   tcpcib_hpet_get_timecount(struct timecounter *tc);
+
 struct cfattach tcpcib_ca = {
sizeof(struct tcpcib_softc), tcpcib_match, tcpcib_attach,
NULL, tcpcib_activate
@@ -112,7 +139,6 @@
 * Set watchdog to perform a cold reset toggling the GPIO pin and the
 * prescaler set to 1ms-10m resolution
 */
-   tcpcib_wdt_unlock(sc);
bus_space_write_1(sc-sc_wdt_iot, sc-sc_wdt_ioh, E600_WDT_WDTCR,
E600_WDT_WDTCR_ENABLE);
tcpcib_wdt_unlock(sc);
@@ -129,7 +155,6 @@
 tcpcib_wdt_start(struct tcpcib_softc *sc)
 {
/* Enable watchdog */
-   tcpcib_wdt_unlock(sc);
bus_space_write_1(sc-sc_wdt_iot, sc-sc_wdt_ioh, E600_WDT_WDTLR,
E600_WDT_WDTLR_ENABLE);
 }
@@ -141,7 +166,6 @@
tcpcib_wdt_unlock(sc);
bus_space_write_1(sc-sc_wdt_iot, sc-sc_wdt_ioh, E600_WDT_RR1,
E600_WDT_RR1_RELOAD);
-   tcpcib_wdt_unlock(sc);
bus_space_write_1(sc-sc_wdt_iot, sc-sc_wdt_ioh, E600_WDT_WDTLR, 0);
 }
 
@@ -160,10 +184,43 @@
 {
struct tcpcib_softc *sc = (struct tcpcib_softc *)self;
struct pci_attach_args *pa = aux;
-   u_int32_t reg, wdtbase;
+   struct timecounter *tc = sc-sc_hpet_timecounter;
+   u_int32_t reg, wdtbase, period;
 
sc-sc_active = 0;
 
+   /* High Precision 

Re: Intel Atom E600 watchdog(4) support

2012-05-25 Thread Matt Dainty
* Miod Vallat m...@online.fr [2012-05-24 09:30:37]:
 We typically prefer shorter names.  tcpcib might not be such a bad name.
 
 Come on. It obviously has to be yapcib since it's yet another pcib.

Third time lucky, I've renamed the driver to tcpcib, (as much as I'd
love to call it yapcib ;-).

Theo suggested I add code to handle suspend/resume so I've done that
although I can't test it as my net6501 doesn't suspend, although the
code simply stops the watchdog if it's running at suspend time and
starts it up again come resume time. I presume that's ok?

I also documented the maximum period supported by the watchdog timer
and also made a note of the lack of driver support for any other parts
of the hardware.

Matt

--- /dev/null   Thu May 24 22:49:02 2012
+++ /usr/src/sys/dev/pci/tcpcib.c   Thu May 24 22:48:17 2012
@@ -0,0 +1,264 @@
+/* $OpenBSD$   */
+
+/*
+ * Copyright (c) 2012 Matt Dainty m...@bodgit-n-scarper.com
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Intel Atom E600 series LPC bridge also containing watchdog
+ */
+
+#include sys/param.h
+#include sys/systm.h
+#include sys/device.h
+
+#include machine/bus.h
+
+#include dev/pci/pcireg.h
+#include dev/pci/pcivar.h
+#include dev/pci/pcidevs.h
+
+#defineE600_LPC_SMBA   0x40/* SMBus Base Address */
+#defineE600_LPC_GBA0x44/* GPIO Base Address */
+#defineE600_LPC_WDTBA  0x84/* WDT Base Address */
+
+#defineE600_WDT_SIZE   64  /* I/O region size */
+#defineE600_WDT_PV10x00/* Preload Value 1 
Register */
+#defineE600_WDT_PV20x04/* Preload Value 2 
Register */
+#defineE600_WDT_RR00x0c/* Reload Register 0 */
+#defineE600_WDT_RR10x0d/* Reload Register 1 */
+#defineE600_WDT_RR1_RELOAD (1  0)/* WDT Reload Flag */
+#defineE600_WDT_RR1_TIMEOUT(1  1)/* WDT Timeout Flag */
+#defineE600_WDT_WDTCR  0x10/* WDT Configuration 
Register */
+#defineE600_WDT_WDTCR_PRE  (1  2)/* WDT Prescalar Select 
*/
+#defineE600_WDT_WDTCR_RESET(1  3)/* WDT Reset Select */
+#defineE600_WDT_WDTCR_ENABLE   (1  4)/* WDT Reset Enable */
+#defineE600_WDT_WDTCR_TIMEOUT  (1  5)/* WDT Timeout Output 
Enable */
+#defineE600_WDT_DCR0x14/* Down Counter 
Register */
+#defineE600_WDT_WDTLR  0x18/* WDT Lock Register */
+#defineE600_WDT_WDTLR_LOCK (1  0)/* Watchdog Timer Lock 
*/
+#defineE600_WDT_WDTLR_ENABLE   (1  1)/* Watchdog Timer 
Enable */
+#defineE600_WDT_WDTLR_TIMEOUT  (1  2)/* WDT Timeout 
Configuration */
+
+struct tcpcib_softc {
+   struct device sc_dev;
+
+   /* Keep track of which parts of the hardware are active */
+   int sc_active;
+#defineE600_WDT_ACTIVE (1  0)
+
+   /* Watchdog interface */
+   bus_space_tag_t sc_wdt_iot;
+   bus_space_handle_t sc_wdt_ioh;
+
+   int sc_wdt_period;
+};
+
+struct cfdriver tcpcib_cd = {
+   NULL, tcpcib, DV_DULL
+};
+
+int tcpcib_match(struct device *, void *, void *);
+voidtcpcib_attach(struct device *, struct device *, void *);
+int tcpcib_activate(struct device *, int);
+
+int tcpcib_wdt_cb(void *, int);
+
+struct cfattach tcpcib_ca = {
+   sizeof(struct tcpcib_softc), tcpcib_match, tcpcib_attach,
+   NULL, tcpcib_activate
+};
+
+/* from arch/*/pci/pcib.c */
+void   pcibattach(struct device *parent, struct device *self, void *aux);
+
+const struct pci_matchid tcpcib_devices[] = {
+   { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_E600_LPC }
+};
+
+static __inline void
+tcpcib_wdt_unlock(struct tcpcib_softc *sc)
+{
+   /* Register unlocking sequence */
+   bus_space_write_1(sc-sc_wdt_iot, sc-sc_wdt_ioh, E600_WDT_RR0, 0x80);
+   bus_space_write_1(sc-sc_wdt_iot, sc-sc_wdt_ioh, E600_WDT_RR0, 0x86);
+}
+
+static void
+tcpcib_wdt_init(struct tcpcib_softc *sc, int period)
+{
+   u_int32_t preload;
+
+   /* Set new timeout */
+   preload = (period * 3300)  15

Re: Intel Atom E600 watchdog(4) support

2012-05-24 Thread Matt Dainty
* Jonathan Gray j...@jsg.id.au [2012-05-24 01:23:28]:
 As a general policy drivers do not have numbers in their name,
 so it will have to be renamed.

Yes, I got a couple of private mails stating the same, which explains
why I hadn't seen any others. Anyway, Mike Belopuhov suggested pchpcib
as an alternative name so I've renamed the driver to that along with
the man pages, etc.

Here's the dmesg now:

---8---
pchpcib0 at pci0 dev 31 function 0 Intel E600 LPC rev 0x00: watchdog
isa0 at pchpcib0
---8---

Looks much better to me too.

 I'll have a look into trying it on a net6501 I have here with i386.

Thanks, much appreciated.

Updated patch below.

Matt

--- /dev/null   Thu May 24 00:43:16 2012
+++ sys/dev/pci/pchpcib.c   Thu May 24 00:34:28 2012
@@ -0,0 +1,220 @@
+/* $OpenBSD$   */
+
+/*
+ * Copyright (c) 2012 Matt Dainty m...@bodgit-n-scarper.com
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Intel Atom E600 series LPC bridge also containing watchdog
+ */
+
+#include sys/param.h
+#include sys/systm.h
+#include sys/device.h
+
+#include machine/bus.h
+
+#include dev/pci/pcireg.h
+#include dev/pci/pcivar.h
+#include dev/pci/pcidevs.h
+
+#defineE600_LPC_SMBA   0x40/* SMBus Base Address */
+#defineE600_LPC_GBA0x44/* GPIO Base Address */
+#defineE600_LPC_WDTBA  0x84/* WDT Base Address */
+
+#defineE600_WDT_SIZE   64  /* I/O region size */
+#defineE600_WDT_PV10x00/* Preload Value 1 
Register */
+#defineE600_WDT_PV20x04/* Preload Value 2 
Register */
+#defineE600_WDT_RR00x0c/* Reload Register 0 */
+#defineE600_WDT_RR10x0d/* Reload Register 1 */
+#defineE600_WDT_RR1_RELOAD (1  0)/* WDT Reload Flag */
+#defineE600_WDT_RR1_TIMEOUT(1  1)/* WDT Timeout Flag */
+#defineE600_WDT_WDTCR  0x10/* WDT Configuration 
Register */
+#defineE600_WDT_WDTCR_TIMEOUT  (1  5)/* WDT Timeout Output 
Enable */
+#defineE600_WDT_WDTCR_ENABLE   (1  4)/* WDT Reset Enable */
+#defineE600_WDT_WDTCR_RESET(1  3)/* WDT Reset Select */
+#defineE600_WDT_WDTCR_PRE  (1  2)/* WDT Prescalar Select 
*/
+#defineE600_WDT_DCR0x14/* Down Counter 
Register */
+#defineE600_WDT_WDTLR  0x18/* WDT Lock Register */
+#defineE600_WDT_WDTLR_LOCK (1  0)/* Watchdog Timer Lock 
*/
+#defineE600_WDT_WDTLR_ENABLE   (1  1)/* Watchdog Timer 
Enable */
+#defineE600_WDT_WDTLR_TIMEOUT  (1  2)/* WDT Timeout 
Configuration */
+
+struct pchpcib_softc {
+   struct device sc_dev;
+
+   /* Watchdog interface */
+   bus_space_tag_t sc_wdt_iot;
+   bus_space_handle_t sc_wdt_ioh;
+
+   int sc_wdt_period;
+};
+
+struct cfdriver pchpcib_cd = {
+   NULL, pchpcib, DV_DULL
+};
+
+int pchpcib_match(struct device *, void *, void *);
+voidpchpcib_attach(struct device *, struct device *, void *);
+
+int pchpcib_wdt_cb(void *, int);
+
+struct cfattach pchpcib_ca = {
+   sizeof(struct pchpcib_softc), pchpcib_match, pchpcib_attach
+};
+
+/* from arch/*/pci/pcib.c */
+void   pcibattach(struct device *parent, struct device *self, void *aux);
+
+const struct pci_matchid pchpcib_devices[] = {
+   { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_E600_LPC }
+};
+
+#ifndef SMALL_KERNEL
+static __inline void
+pchpcib_wdt_unlock(struct pchpcib_softc *sc)
+{
+   /* Register unlocking sequence */
+   bus_space_write_1(sc-sc_wdt_iot, sc-sc_wdt_ioh, E600_WDT_RR0, 0x80);
+   bus_space_write_1(sc-sc_wdt_iot, sc-sc_wdt_ioh, E600_WDT_RR0, 0x86);
+}
+#endif /* !SMALL_KERNEL */
+
+int
+pchpcib_match(struct device *parent, void *match, void *aux)
+{
+   if (pci_matchbyid((struct pci_attach_args *)aux, pchpcib_devices,
+   sizeof(pchpcib_devices) / sizeof(pchpcib_devices[0])))
+   return (2);
+
+   return (0);
+}
+
+void
+pchpcib_attach(struct device *parent, struct device *self, void *aux)
+{
+#ifndef SMALL_KERNEL
+   struct pchpcib_softc

Re: Intel Atom E600 watchdog(4) support

2012-05-24 Thread Matt Dainty
* Mitja MuEeniD
 mi...@muzenic.net [2012-05-24 07:23:22]:
 Works for me on net6501 on i386 GENERIC and GENERIC.MP
 
 after a succesfull watchdog fire:
 
 e600pcib0 at pci0 dev 31 function 0 Intel E600 LPC rev 0x00: watchdog,
 reboot on timeout
 
 It did fire a bit too early though, my watchdog period was set to 32 seconds
 and the machine did reset after 26 seconds on my stopwatch. Similarly, with
 a 60 second period it fired after ~50 seconds. Don't know if it really
 matters though

Looking at the watchdog code, it looks like the kernel will refresh the
timer every period / 2, so for a 60 second timeout, it could fire
anywhere between 30-60 seconds after the host hangs.

 Finally, can you mention that the valid period range is 1-600 seconds? The
 code does it right by silently lowering a too-high period to 600, but it
 would be nice to have it mentioned in the manpages too.

Yes, that makes sense.

 P.S. While I was composing this reply some other mails have come through.
 How about esixoopcib ? :)

Better than esixhundredpcib ;-)

Does anyone have any suggestions? e6xxpcib? atompcib? iatcpcib?

Matt



Intel Atom E600 watchdog(4) support

2012-05-23 Thread Matt Dainty
Attached are some patches that add support for the watchdog device on
boards based on the Intel Atom E600 series such as the Soekris net6501.

Based on existing drivers such as amdpcib(4), ichpcib(4) and ichwdt(4)
I've created an e600pcib(4) to override the standard pcib(4) which can
then access the watchdog device.

Here's the original dmesg:

---8---
pcib0 at pci0 dev 31 function 0 Intel E600 LPC rev 0x00
isa0 at pcib0
---8---

Here's with my changes:

---8---
e600pcib0 at pci0 dev 31 function 0 Intel E600 LPC rev 0x00: watchdog
isa0 at e600pcib0
---8---

I tested the watchdog by setting kern.watchdog.period to 60 and then
breaking into ddb and starting a stopwatch and timing until my net6501
resets, it take near enough to 60 seconds that I'm happy it's working.

On a watchdog-triggered reboot, I've done similar to ichwdt(4):

---8---
e600pcib0 at pci0 dev 31 function 0 Intel E600 LPC rev 0x00: watchdog, reboot 
on timeout
isa0 at e600pcib0
---8---

I've included the driver itself, man pages, changes to GENERIC and the
various infrastructure files.

I'm using it with GENERIC.MP on amd64 and I compile tested it on i386.

Any comments?

Matt

--- /dev/null   Wed May 23 21:01:50 2012
+++ sys/dev/pci/e600pcib.c  Wed May 23 21:00:44 2012
@@ -0,0 +1,220 @@
+/* $OpenBSD$   */
+
+/*
+ * Copyright (c) 2012 Matt Dainty m...@bodgit-n-scarper.com
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Intel Atom E600 series LPC bridge also containing watchdog
+ */
+
+#include sys/param.h
+#include sys/systm.h
+#include sys/device.h
+
+#include machine/bus.h
+
+#include dev/pci/pcireg.h
+#include dev/pci/pcivar.h
+#include dev/pci/pcidevs.h
+
+#defineE600_LPC_SMBA   0x40/* SMBus Base Address */
+#defineE600_LPC_GBA0x44/* GPIO Base Address */
+#defineE600_LPC_WDTBA  0x84/* WDT Base Address */
+
+#defineE600_WDT_SIZE   64  /* I/O region size */
+#defineE600_WDT_PV10x00/* Preload Value 1 
Register */
+#defineE600_WDT_PV20x04/* Preload Value 2 
Register */
+#defineE600_WDT_RR00x0c/* Reload Register 0 */
+#defineE600_WDT_RR10x0d/* Reload Register 1 */
+#defineE600_WDT_RR1_RELOAD (1  0)/* WDT Reload Flag */
+#defineE600_WDT_RR1_TIMEOUT(1  1)/* WDT Timeout Flag */
+#defineE600_WDT_WDTCR  0x10/* WDT Configuration 
Register */
+#defineE600_WDT_WDTCR_TIMEOUT  (1  5)/* WDT Timeout Output 
Enable */
+#defineE600_WDT_WDTCR_ENABLE   (1  4)/* WDT Reset Enable */
+#defineE600_WDT_WDTCR_RESET(1  3)/* WDT Reset Select */
+#defineE600_WDT_WDTCR_PRE  (1  2)/* WDT Prescalar Select 
*/
+#defineE600_WDT_DCR0x14/* Down Counter 
Register */
+#defineE600_WDT_WDTLR  0x18/* WDT Lock Register */
+#defineE600_WDT_WDTLR_LOCK (1  0)/* Watchdog Timer Lock 
*/
+#defineE600_WDT_WDTLR_ENABLE   (1  1)/* Watchdog Timer 
Enable */
+#defineE600_WDT_WDTLR_TIMEOUT  (1  2)/* WDT Timeout 
Configuration */
+
+struct e600pcib_softc {
+   struct device sc_dev;
+
+   /* Watchdog interface */
+   bus_space_tag_t sc_wdt_iot;
+   bus_space_handle_t sc_wdt_ioh;
+
+   int sc_wdt_period;
+};
+
+struct cfdriver e600pcib_cd = {
+   NULL, e600pcib, DV_DULL
+};
+
+int e600pcib_match(struct device *, void *, void *);
+voide600pcib_attach(struct device *, struct device *, void *);
+
+int e600pcib_wdt_cb(void *, int);
+
+struct cfattach e600pcib_ca = {
+   sizeof(struct e600pcib_softc), e600pcib_match, e600pcib_attach
+};
+
+/* from arch/*/pci/pcib.c */
+void   pcibattach(struct device *parent, struct device *self, void *aux);
+
+const struct pci_matchid e600pcib_devices[] = {
+   { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_E600_LPC }
+};
+
+#ifndef SMALL_KERNEL
+static __inline void
+e600pcib_wdt_unlock(struct e600pcib_softc *sc)
+{
+   /* Register unlocking sequence */
+   bus_space_write_1(sc-sc_wdt_iot, sc-sc_wdt_ioh, E600_WDT_RR0

Re: RFC 4638 support for pppoe(4)

2012-01-11 Thread Matt Dainty
* Matt Dainty m...@bodgit-n-scarper.com [2012-01-09 20:21:54]:
 * Matt Dainty m...@bodgit-n-scarper.com [2012-01-02 16:30:55]:
  * Stuart Henderson s...@spacehopper.org [2011-12-31 10:12:41]:
   
   If the remote side doesn't echo our tag back, we should restrict ourselves
   to PPPOE_MAXMTU.
   
   Certainly until we are checking this I think we should avoid automatically
   raising pppoe(4)'s MTU based on pppoedev's MTU and require it to be set
   explicitly on the pppoe iface (as well as the parent iface).
  
  Attached is an updated patch for sys/net/if_pppoe.c that now tracks if
  the remote end echoes back the max payload tag that we will have sent.
  
  However I'm not sure how best to set pppoe(4)'s MTU back down to
  PPPOE_MAXMTU (given all the extra logic is keyed off this value). Can I
  just set sc-sc_sppp.pp_if.if_mtu directly or should I bounce it
  through pppoe_ioctl() with SIOCSIFMTU? I can then update the patch and
  replace the FIXME with whatever code is necessary.
 
 So once I stopped pppoe(8) from blindly agreeing to any increased MTU I
 requested, I've now tested the below patches using an em(4) with a 1508
 MTU against a server that doesn't support the larger MTU, pppoe0 will
 now be set back to 1492 and PPP/LCP negotiation continues with the
 correct MRU option. My Huawei/BT modem still negotiates the increased
 size and PPP/LCP negotiation continues with the larger 1500 MRU. All
 verified with some tcpdump captures.
 
 I noticed our if_spppsubr.c compared to NetBSD's (re)sets the MRU
 variables in sppp_lcp_up() so I moved the changes from sppp_lcp_open()
 to there to prevent duplication and also fixed a small amount of
 whitespace formatting (s/^ \t/\t/).

A couple of people pointed out a small tyop lurking in a comment in the
diff context so I've included a correction for it.

Matt

--- sys/net/if_pppoe.c.orig Tue Dec 13 21:52:04 2011
+++ sys/net/if_pppoe.c  Tue Jan 10 01:25:19 2012
@@ -86,9 +86,10 @@
 #definePPPOE_TAG_ACCOOKIE  0x0104  /* AC cookie */
 #definePPPOE_TAG_VENDOR0x0105  /* vendor specific */
 #definePPPOE_TAG_RELAYSID  0x0110  /* relay session id */
+#definePPPOE_TAG_MAX_PAYLOAD   0x0120  /* RFC 4638 max payload 
*/
 #definePPPOE_TAG_SNAME_ERR 0x0201  /* service name error */
 #definePPPOE_TAG_ACSYS_ERR 0x0202  /* AC system error */
-#definePPPOE_TAG_GENERIC_ERR   0x0203  /* gerneric error */
+#definePPPOE_TAG_GENERIC_ERR   0x0203  /* generic error */
 
 #definePPPOE_CODE_PADI 0x09/* Active Discovery 
Initiation */
 #definePPPOE_CODE_PADO 0x07/* Active Discovery 
Offer */
@@ -398,6 +399,7 @@
size_t ac_cookie_len;
size_t relay_sid_len;
int noff, err, errortag;
+   u_int16_t *max_payload;
u_int16_t tag, len;
u_int16_t session, plen;
u_int8_t *ac_cookie;
@@ -424,6 +426,7 @@
ac_cookie_len = 0;
relay_sid = NULL;
relay_sid_len = 0;
+   max_payload = NULL;
 #ifdef PPPOE_SERVER
hunique = NULL;
hunique_len = 0;
@@ -531,6 +534,18 @@
relay_sid_len = len;
}
break;
+   case PPPOE_TAG_MAX_PAYLOAD:
+   if (max_payload == NULL) {
+   n = m_pulldown(m, off, len,
+   noff);
+   if (n == NULL || len != 2) {
+   err_msg = TAG MAX_PAYLOAD ERROR;
+   m = NULL;
+   break;
+   }
+   max_payload = (u_int16_t *)(mtod(n, caddr_t) + 
noff);
+   }
+   break;
case PPPOE_TAG_SNAME_ERR:
err_msg = SERVICE NAME ERROR;
errortag = 1;
@@ -679,6 +694,13 @@
sc-sc_relay_sid_len = relay_sid_len;
memcpy(sc-sc_relay_sid, relay_sid, relay_sid_len);
}
+   if (sc-sc_sppp.pp_if.if_mtu  PPPOE_MAXMTU 
+   (max_payload == NULL ||
+ntohs(*max_payload) != sc-sc_sppp.pp_if.if_mtu)) {
+   printf(%s: No valid PPP-Max-Payload tag received in 
PADO\n,
+   sc-sc_sppp.pp_if.if_xname);
+   sc-sc_sppp.pp_if.if_mtu = PPPOE_MAXMTU;
+   }

memcpy(sc-sc_dest, eh-ether_shost, sizeof(sc-sc_dest));
sc-sc_padr_retried = 0;
@@ -911,7 +933,7 @@
return (ENXIO);
}
 
-   if (sc-sc_sppp.pp_if.if_mtu 
+   if (sc-sc_sppp.pp_if.if_mtu

Re: RFC 4638 support for pppoe(4)

2012-01-09 Thread Matt Dainty
* Matt Dainty m...@bodgit-n-scarper.com [2012-01-02 16:30:55]:
 * Stuart Henderson s...@spacehopper.org [2011-12-31 10:12:41]:
  
  If the remote side doesn't echo our tag back, we should restrict ourselves
  to PPPOE_MAXMTU.
  
  Certainly until we are checking this I think we should avoid automatically
  raising pppoe(4)'s MTU based on pppoedev's MTU and require it to be set
  explicitly on the pppoe iface (as well as the parent iface).
 
 Attached is an updated patch for sys/net/if_pppoe.c that now tracks if
 the remote end echoes back the max payload tag that we will have sent.
 
 However I'm not sure how best to set pppoe(4)'s MTU back down to
 PPPOE_MAXMTU (given all the extra logic is keyed off this value). Can I
 just set sc-sc_sppp.pp_if.if_mtu directly or should I bounce it
 through pppoe_ioctl() with SIOCSIFMTU? I can then update the patch and
 replace the FIXME with whatever code is necessary.

So once I stopped pppoe(8) from blindly agreeing to any increased MTU I
requested, I've now tested the below patches using an em(4) with a 1508
MTU against a server that doesn't support the larger MTU, pppoe0 will
now be set back to 1492 and PPP/LCP negotiation continues with the
correct MRU option. My Huawei/BT modem still negotiates the increased
size and PPP/LCP negotiation continues with the larger 1500 MRU. All
verified with some tcpdump captures.

I noticed our if_spppsubr.c compared to NetBSD's (re)sets the MRU
variables in sppp_lcp_up() so I moved the changes from sppp_lcp_open()
to there to prevent duplication and also fixed a small amount of
whitespace formatting (s/^ \t/\t/).

Comments?

Matt

--- sys/net/if_pppoe.c.orig Tue Dec 13 21:52:04 2011
+++ sys/net/if_pppoe.c  Thu Jan  5 15:03:03 2012
@@ -86,6 +86,7 @@
 #definePPPOE_TAG_ACCOOKIE  0x0104  /* AC cookie */
 #definePPPOE_TAG_VENDOR0x0105  /* vendor specific */
 #definePPPOE_TAG_RELAYSID  0x0110  /* relay session id */
+#definePPPOE_TAG_MAX_PAYLOAD   0x0120  /* RFC 4638 max payload 
*/
 #definePPPOE_TAG_SNAME_ERR 0x0201  /* service name error */
 #definePPPOE_TAG_ACSYS_ERR 0x0202  /* AC system error */
 #definePPPOE_TAG_GENERIC_ERR   0x0203  /* gerneric error */
@@ -398,6 +399,7 @@
size_t ac_cookie_len;
size_t relay_sid_len;
int noff, err, errortag;
+   u_int16_t *max_payload;
u_int16_t tag, len;
u_int16_t session, plen;
u_int8_t *ac_cookie;
@@ -424,6 +426,7 @@
ac_cookie_len = 0;
relay_sid = NULL;
relay_sid_len = 0;
+   max_payload = NULL;
 #ifdef PPPOE_SERVER
hunique = NULL;
hunique_len = 0;
@@ -531,6 +534,18 @@
relay_sid_len = len;
}
break;
+   case PPPOE_TAG_MAX_PAYLOAD:
+   if (max_payload == NULL) {
+   n = m_pulldown(m, off, len,
+   noff);
+   if (n == NULL || len != 2) {
+   err_msg = TAG MAX_PAYLOAD ERROR;
+   m = NULL;
+   break;
+   }
+   max_payload = (u_int16_t *)(mtod(n, caddr_t) + 
noff);
+   }
+   break;
case PPPOE_TAG_SNAME_ERR:
err_msg = SERVICE NAME ERROR;
errortag = 1;
@@ -679,6 +694,13 @@
sc-sc_relay_sid_len = relay_sid_len;
memcpy(sc-sc_relay_sid, relay_sid, relay_sid_len);
}
+   if (sc-sc_sppp.pp_if.if_mtu  PPPOE_MAXMTU 
+   (max_payload == NULL ||
+ntohs(*max_payload) != sc-sc_sppp.pp_if.if_mtu)) {
+   printf(%s: No valid PPP-Max-Payload tag received in 
PADO\n,
+   sc-sc_sppp.pp_if.if_xname);
+   sc-sc_sppp.pp_if.if_mtu = PPPOE_MAXMTU;
+   }

memcpy(sc-sc_dest, eh-ether_shost, sizeof(sc-sc_dest));
sc-sc_padr_retried = 0;
@@ -911,7 +933,7 @@
return (ENXIO);
}
 
-   if (sc-sc_sppp.pp_if.if_mtu 
+   if (sc-sc_sppp.pp_if.if_mtu !=
eth_if-if_mtu - PPPOE_OVERHEAD) {
sc-sc_sppp.pp_if.if_mtu = eth_if-if_mtu -
PPPOE_OVERHEAD;
@@ -1068,6 +1090,8 @@
l2 = strlen(sc-sc_concentrator_name);
len += 2 + 2 + l2;
}
+   if (sc-sc_sppp.pp_if.if_mtu  PPPOE_MAXMTU)
+   len += 2 + 2 + 2;
 
/* allocate a buffer */
m0 = pppoe_get_mbuf(len + PPPOE_HEADERLEN

Stop pppoe(8) server from agreeing to RFC 4638

2012-01-06 Thread Matt Dainty
While trying to test my RFC 4638 changes for pppoe(4) against a PPPoE
server that won't agree to the increased MTU, I found that after setting
up a pppoe(8)-based server I wasn't getting the expected behaviour.

It turns out pppoe(8) returns all of the clients tags in addition to any
tags specific to the PADO or PADS packets so if a client requests an
increased MTU, pppoe(8) blindly agrees to it by echoing the max payload
tag back.

Patch below adds a new function to scrub out any unknown tags that are
not defined in pppoe.h. With this applied I get the correct negotiation.

Matt

--- src/usr.sbin/pppoe/server.c.origWed Jan  4 21:34:58 2012
+++ src/usr.sbin/pppoe/server.c Thu Jan  5 06:49:47 2012
@@ -72,6 +72,8 @@
 static u_int8_t *key_make(u_int8_t *, int, u_int8_t *, int);
 static int key_cmp(u_int8_t *, int, u_int8_t *, int, u_int8_t *, int);
 
+static u_long scrub_pkt(u_long, u_int8_t *);
+
 void
 server_mode(int bpffd, u_int8_t *sysname, u_int8_t *srvname,
 struct ether_addr *ea)
@@ -302,6 +304,7 @@
 struct pppoe_header *ph, u_long pktlen, u_int8_t *pktbuf)
 {
struct pppoe_tag ktag, htag;
+   u_long newlen;
u_int8_t hn[MAXHOSTNAMELEN];
u_int8_t *k = NULL;
struct iovec v[7];
@@ -315,8 +318,14 @@
ph-code = PPPOE_CODE_PADO;
v[idx].iov_base = ph; v[idx].iov_len = sizeof(*ph); idx++;
 
-   v[idx].iov_base = pktbuf; v[idx].iov_len = pktlen; idx++;
+   /* Scrub unknown tags from the packet before returning them */
+   if ((newlen = scrub_pkt(pktlen, pktbuf)) == 0)
+   return;
+   if (newlen != pktlen)
+   ph-len -= pktlen - newlen;
 
+   v[idx].iov_base = pktbuf; v[idx].iov_len = newlen; idx++;
+
if (gethostname((char *)hn, sizeof(hn))  0)
return;
htag.len = strlen((char *)hn);
@@ -383,6 +392,7 @@
 struct ether_header *eh, struct pppoe_header *ph,
 u_long pktlen, u_int8_t *pktbuf)
 {
+   u_long newlen;
u_int8_t hn[MAXHOSTNAMELEN];
struct iovec v[16];
struct pppoe_session *s;
@@ -404,8 +414,14 @@
return;
v[idx].iov_base = ph; v[idx].iov_len = sizeof(*ph); idx++;
 
-   v[idx].iov_base = pktbuf; v[idx].iov_len = pktlen; idx++;
+   /* Scrub unknown tags from the packet before returning them */
+   if ((newlen = scrub_pkt(pktlen, pktbuf)) == 0)
+   return;
+   if (newlen != pktlen)
+   ph-len -= pktlen - newlen;
 
+   v[idx].iov_base = pktbuf; v[idx].iov_len = newlen; idx++;
+
htag.len = strlen((char *)hn);
htag.type = htons(PPPOE_TAG_AC_NAME);
htag.val = hn;
@@ -446,4 +462,57 @@
 
 out:
tag_destroy(tl);
+}
+
+static u_long
+scrub_pkt(u_long pktlen, u_int8_t *pkt)
+{
+   u_long   newlen = 0;
+   u_int16_tttype, tlen;
+   u_int8_t*p = pkt;
+
+   while (pktlen != 0) {
+   if (pktlen  sizeof(u_int16_t))
+   break;
+   ttype = pkt[1] | (pkt[0]  8);
+   pkt += sizeof(u_int16_t);
+   pktlen -= sizeof(u_int16_t);
+
+   if (pktlen  sizeof(u_int16_t))
+   break;
+   tlen = pkt[1] | (pkt[0]  8);
+   pkt += sizeof(u_int16_t);
+   pktlen -= sizeof(u_int16_t);
+
+   if (pktlen  tlen)
+   break;
+
+   pkt += tlen;
+   pktlen -= tlen;
+
+   switch (ttype) {
+   case PPPOE_TAG_END_OF_LIST:
+   case PPPOE_TAG_SERVICE_NAME:
+   case PPPOE_TAG_AC_NAME:
+   case PPPOE_TAG_HOST_UNIQ:
+   case PPPOE_TAG_AC_COOKIE:
+   case PPPOE_TAG_VENDOR_SPEC:
+   case PPPOE_TAG_RELAY_SESSION:
+   case PPPOE_TAG_SERVICE_NAME_ERROR:
+   case PPPOE_TAG_AC_SYSTEM_ERROR:
+   case PPPOE_TAG_GENERIC_ERROR:
+   p = pkt;
+   newlen += sizeof(u_int16_t) + sizeof(u_int16_t) + tlen;
+   break;
+   default:
+   if (pktlen != 0)
+   bcopy(pkt, p, pktlen);
+   pkt = p;
+   break;
+   }
+   }
+
+   if (pktlen != 0)
+   return (0);
+   return (newlen);
 }



RFC 4638 support for pppoe(4)

2011-12-27 Thread Matt Dainty
Attached are three patches for RFC 4638 PPPoE support. The first two are
for pppoe(4) based on similar changes made to NetBSD. The third patch is
to tcpdump(8) so it recognises the additional tag type.

I've been running this on my Soekris net6501 with one of the the built
in em(4) chips hooked up to the BT Openreach-branded Huawei modem. My
/etc/hostname.em0 contains:

mtu 1508
up

and /etc/hostname.pppoe0 is configured as normal. Once up and running
the network interfaces look like this:

em0: flags=28843UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,NOINET6 mtu 1508
lladdr be:ef:be:ef:be:ef
priority: 0
media: Ethernet autoselect (100baseTX full-duplex,rxpause,txpause)
status: active
pppoe0: flags=28851UP,POINTOPOINT,RUNNING,SIMPLEX,MULTICAST,NOINET6 mtu 1500
priority: 0
dev: em0 state: session
sid: 0x903 PADI retries: 3 PADR retries: 0 time: 00:28:27
sppp: phase network authproto chap 
groups: pppoe egress
status: active
inet 1.2.3.4 -- 5.6.7.8 netmask 0x

I'm aware the patch as it currently stands assumes the other end will
JFW and agree to the increased size (as does the NetBSD code). I wasn't
sure how best to handle the case when the remote end doesn't send the
max payload tag back in the PADO/PADS packets.

Matt

--- sys/net/if_pppoe.c.orig Tue Dec 13 21:52:04 2011
+++ sys/net/if_pppoe.c  Sat Dec 17 23:12:43 2011
@@ -86,6 +86,7 @@
 #definePPPOE_TAG_ACCOOKIE  0x0104  /* AC cookie */
 #definePPPOE_TAG_VENDOR0x0105  /* vendor specific */
 #definePPPOE_TAG_RELAYSID  0x0110  /* relay session id */
+#definePPPOE_TAG_MAX_PAYLOAD   0x0120  /* max payload */
 #definePPPOE_TAG_SNAME_ERR 0x0201  /* service name error */
 #definePPPOE_TAG_ACSYS_ERR 0x0202  /* AC system error */
 #definePPPOE_TAG_GENERIC_ERR   0x0203  /* gerneric error */
@@ -531,6 +532,8 @@
relay_sid_len = len;
}
break;
+   case PPPOE_TAG_MAX_PAYLOAD:
+   break;  /* ignored */
case PPPOE_TAG_SNAME_ERR:
err_msg = SERVICE NAME ERROR;
errortag = 1;
@@ -911,7 +914,7 @@
return (ENXIO);
}
 
-   if (sc-sc_sppp.pp_if.if_mtu 
+   if (sc-sc_sppp.pp_if.if_mtu !=
eth_if-if_mtu - PPPOE_OVERHEAD) {
sc-sc_sppp.pp_if.if_mtu = eth_if-if_mtu -
PPPOE_OVERHEAD;
@@ -1068,6 +1071,8 @@
l2 = strlen(sc-sc_concentrator_name);
len += 2 + 2 + l2;
}
+   if (sc-sc_sppp.pp_if.if_mtu  PPPOE_MAXMTU)
+   len += 2 + 2 + 2;
 
/* allocate a buffer */
m0 = pppoe_get_mbuf(len + PPPOE_HEADERLEN); /* header len + payload 
len */
@@ -1094,9 +1099,15 @@
PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
PPPOE_ADD_16(p, sizeof(sc-sc_unique));
memcpy(p, sc-sc_unique, sizeof(sc-sc_unique));
+   p += sizeof(sc-sc_unique);
 
+   if (sc-sc_sppp.pp_if.if_mtu  PPPOE_MAXMTU) {
+   PPPOE_ADD_16(p, PPPOE_TAG_MAX_PAYLOAD);
+   PPPOE_ADD_16(p, 2);
+   PPPOE_ADD_16(p, (u_int16_t)sc-sc_sppp.pp_if.if_mtu);
+   }
+
 #ifdef PPPOE_DEBUG
-   p += sizeof(sc-sc_unique);
if (p - mtod(m0, u_int8_t *) != len + PPPOE_HEADERLEN)
panic(pppoe_send_padi: garbled output len, should be %ld, is 
%ld,
(long)(len + PPPOE_HEADERLEN), (long)(p - mtod(m0, u_int8_t 
*)));
@@ -1298,6 +1309,8 @@
len += 2 + 2 + sc-sc_ac_cookie_len;/* AC cookie */
if (sc-sc_relay_sid_len  0)
len += 2 + 2 + sc-sc_relay_sid_len;/* Relay SID */
+   if (sc-sc_sppp.pp_if.if_mtu  PPPOE_MAXMTU)
+   len += 2 + 2 + 2;
 
m0 = pppoe_get_mbuf(len + PPPOE_HEADERLEN);
if (m0 == NULL)
@@ -1329,9 +1342,15 @@
PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
PPPOE_ADD_16(p, sizeof(sc-sc_unique));
memcpy(p, sc-sc_unique, sizeof(sc-sc_unique));
+   p += sizeof(sc-sc_unique);
 
+   if (sc-sc_sppp.pp_if.if_mtu  PPPOE_MAXMTU) {
+   PPPOE_ADD_16(p, PPPOE_TAG_MAX_PAYLOAD);
+   PPPOE_ADD_16(p, 2);
+   PPPOE_ADD_16(p, (u_int16_t)sc-sc_sppp.pp_if.if_mtu);
+   }
+
 #ifdef PPPOE_DEBUG
-   p += sizeof(sc-sc_unique);
if (p - mtod(m0, u_int8_t *) != len + PPPOE_HEADERLEN)
panic(pppoe_send_padr: garbled output len, should be %ld, is 
%ld,
(long)(len + PPPOE_HEADERLEN), (long)(p - mtod(m0, 
u_int8_t *)));
--- sys/net/if_spppsubr.c.orig  Tue Dec 13 22:16:00 2011
+++ sys/net/if_spppsubr.c   Tue Dec 13 22:26:23 2011
@@ -2027,7