Adding GPIO support to wbsio(4)
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 { bus
Re: Implement a watchdog
* sven falempin [2014-12-10 12:32:15]: > On Wed, Dec 10, 2014 at 9:31 AM, Stuart Henderson 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 > >> 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
* Ted Unangst [2014-12-08 13:28:36]: > On Mon, Dec 08, 2014 at 11:52, Matt Dainty wrote: > > * Jonathan Gray [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 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 +.\" +.\" 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 i
Re: Soekris net6501 GPIO & LED support
* Jonathan Gray [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 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 +.\" +.\" 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
Re: Soekris net6501 GPIO & LED support
* Jonathan Gray [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
Anyone? * Matt Dainty [2014-11-21 07:10:24]: > * Dimitri Sokolyuk [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 > 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 > +.\" > +.\" 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. >
Re: Soekris net6501 GPIO & LED support
* Dimitri Sokolyuk [2014-11-05 22:05:26]: > I can confirm it working on net6501-70 at least for the LED-part on > 5.6-stable. > It works as expected. > > # dmesg | grep gpio > gpio0 at soekris0: 16 pins > gpio1 at soekris0: 2 pins > > However there is some irregularity in reporting of pin-number too: > > # gpioctl gpio0 > /dev/gpio0: 0 pins That's probably because you haven't set any of the pins prior to raising the securelevel, see gpioctl(8). > # gpioctl gpio1 > /dev/gpio1: 2 pins > > 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 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.421 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/Makefile 27 May 2012 12:24:33 - 1.15 +++ share/man/man4/man4.amd64/Makefile 21 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 +.\" +.\" 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 ===
Re: Soekris net6501 GPIO & LED support
* Matt Dainty [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 +.\" +.\" 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 +.\" +.\" 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
Re: Soekris net6501 GPIO & LED support
* Matt Dainty [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 + * + * 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 +#include +#include +#include + +#include +#include + +#include + +#include + +#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 *au
Re: Add Soekris comBIOS detection to bios(4) on i386/amd64
* Kenneth R Westerback [2013-03-12 06:39:02]: > On Tue, Mar 12, 2013 at 05:13:01AM -0400, Matt Dainty wrote: > > * Matt Dainty [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 *
Re: Add Soekris comBIOS detection to bios(4) on i386/amd64
* Matt Dainty [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 *
Re: Add Soekris comBIOS detection to bios(4) on i386/amd64
* Matt Dainty [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
Add Soekris comBIOS detection to bios(4) on i386/amd64
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); +
Re: Detect on-die temp sensor for Atom E6xx on amd64
* Mark Kettenis [2013-01-30 03:49:45]: > > Date: Tue, 29 Jan 2013 17:35:13 -0500 > > From: Matt Dainty > > > > * Christian Weisgerber [2013-01-24 13:03:43]: > > > Matt Dainty 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
* Christian Weisgerber [2013-01-24 13:03:43]: > Matt Dainty 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);
Detect on-die temp sensor for Atom E6xx on amd64
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);
Soekris net6501 GPIO & LED support
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 + * + * 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 +#include +#include +#include + +#include +#include + +#include + +#include + +#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(struct device *parent, s
Re: Add HPET support to tcpcib(4)
* Mark Kettenis [2012-06-03 08:51:03]: > > Date: Sat, 2 Jun 2012 15:36:22 -0400 > > From: Matt Dainty > > > > 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 #include #include +#include #include @@ -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 time
Re: Add HPET support to tcpcib(4)
* Matt Dainty [2012-06-02 12:52:53]: > 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<--- 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 --- sys/dev/pci/tcpcib.c.orig Wed May 30 12:19:41 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 #include #include +#include #include @@ -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,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; + +
Add HPET support to tcpcib(4)
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 #include #include +#include #include @@ -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 Event Timer */ + sc->sc_hpet_i
Re: Intel Atom E600 watchdog(4) support
* Miod Vallat [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 + * + * 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 +#include +#include + +#include + +#include +#include +#include + +#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; + + /
Re: Intel Atom E600 watchdog(4) support
* Mitja MuE>eniD [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
Re: Intel Atom E600 watchdog(4) support
* Jonathan Gray [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 + * + * 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 +#include +#include + +#include + +#include +#include +#include + +#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 SMAL
Intel Atom E600 watchdog(4) support
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 + * + * 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 +#include +#include + +#include + +#include +#include +#include + +#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
Re: RFC 4638 support for pppoe(4)
* YASUOKA Masahiko [2012-01-12 01:55:44]: > Hello, > > On Wed, 11 Jan 2012 18:31:49 -0500 > Matt Dainty wrote: > > @@ -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; > > MTU for pppoe and ethernet must be configurable respectively. > > In Japan, NTT uses 1452 bytes for MTU of PPPoE service and uses 1500 > bytes for MTU of IPv6 service on same network. That's a very good point, so I scrubbed that hunk of the patch. However, that broke things in that once a pppoe(4) interface is created, you could lower the MTU, but you couldn't increase it beyond 1492 due to the checks in pppoe_ioctl() and sppp_ioctl(), the latter using lcp.their_mru as the upper bound. So what I've done is to default lcp.their_mru to 0 in sppp_lcp_init(), sppp_lcp_up() will set it to the default where it should then be further negotiated if necessary, sppp_lcp_down() sets it back to 0. I've then changed the S{IOCSIF,LIOCSET}MTU calls to only use lcp.their_mru as an upper bound if it's non-zero. This means a pppoe(4) interface can be created and have its MTU upped to 1500 while it's still down. Now PPPOE_MAXMTU doesn't really refer to the maximum I've renamed it and introduced a proper PPPOE_MAXMTU for the aforementioned pppoe_ioctl() checks, currently set to PP_MAX_MRU as I saw reference to it as an upper bound in if_spppsubr.c but equally could be set to as low as ETHERMTU or as high as USHRT_MAX given the PPPoE tag size. So this should mean pppoe(4) interfaces can still be configured with an MTU independent of their parent Ethernet interface, my /etc/hostname.pppoe0 now contains an explicit "mtu 1500" but will still be clamped back to 1492 should the initial nogotiation fail. Matt P.S. Includes a few extra whitespace cleanups found in if_spppsubr.c --- sys/net/if_pppoe.c.orig Tue Dec 13 21:52:04 2011 +++ sys/net/if_pppoe.c Sun Jan 15 17:23:29 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 */ @@ -97,7 +98,8 @@ #definePPPOE_CODE_PADT 0xA7/* Active Discovery Terminate */ /* two byte PPP protocol discriminator, then IP data */ -#definePPPOE_MAXMTU(ETHERMTU - PPPOE_OVERHEAD) +#definePPPOE_MTU (ETHERMTU - PPPOE_OVERHEAD) +#definePPPOE_MAXMTUPP_MAX_MRU /* Add a 16 bit unsigned value to a buffer pointed to by PTR */ #definePPPOE_ADD_16(PTR, VAL) \ @@ -225,7 +227,7 @@ sizeof(sc->sc_sppp.pp_if.if_xname), "pppoe%d", unit); sc->sc_sppp.pp_if.if_softc = sc; - sc->sc_sppp.pp_if.if_mtu = PPPOE_MAXMTU; + sc->sc_sppp.pp_if.if_mtu = PPPOE_MTU; sc->sc_sppp.pp_if.if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST; sc->sc_sppp.pp_if.if_type = IFT_PPP; sc->sc_sppp.pp_if.if_hdrlen = sizeof(struct ether_header) + PPPOE_HEADERLEN; @@ -398,6 +400,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 +427,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 +535,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 |
Re: RFC 4638 support for pppoe(4)
* Matt Dainty [2012-01-09 20:21:54]: > * Matt Dainty [2012-01-02 16:30:55]: > > * Stuart Henderson [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->
Re: RFC 4638 support for pppoe(4)
* Matt Dainty [2012-01-02 16:30:55]: > * Stuart Henderson [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
Stop pppoe(8) server from agreeing to RFC 4638
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); }
Re: RFC 4638 support for pppoe(4)
* Stuart Henderson [2011-12-31 10:12:41]: > On 2011/12/27 21:12, Matt Dainty wrote: > > 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'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. > > 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. Matt --- sys/net/if_pppoe.c.orig Tue Dec 13 21:52:04 2011 +++ sys/net/if_pppoe.c Tue Dec 20 14:24:24 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 /* 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,12 @@ 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("pppoe: No valid PPP-Max-Payload tag received in PADO\n"); + /* FIXME: Magic happens here */ + } memcpy(&sc->sc_dest, eh->ether_shost, sizeof(sc->sc_dest)); sc->sc_padr_retried = 0; @@ -911,7 +932,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 +1089,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 +1117,15 @@ PPPO
RFC 4638 support for pppoe(4)
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=28843 mtu 1508 lladdr be:ef:be:ef:be:ef priority: 0 media: Ethernet autoselect (100baseTX full-duplex,rxpause,txpause) status: active pppoe0: flags=28851 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 +2027,6 @@ sp->state[IDX_LCP] = STATE_INITIAL;