Complete ZTE PL011 device support
Subsystems (3)
v3 cover Complete ZTE PL011 device support
This is a pick-up of Jun's v2 patch which tries to complete ZTE PL011 support.
Commit 7ec758718920 ("tty: amba-pl011: add support for ZTE UART (EXPERIMENTAL)") from Russell had already done part of the work that is needed for ZTE PL011 support. The series adds the missing pieces which includes handling Flag Register bit position oddness and getting ZTE PL011 device probed by amba-pl011 driver.
Thanks to Russell for the "official" pseudo-ID idea.
Changes since v2:
- Split changes into 3 separate patches
- Take Russell's suggestion using helper macro to create pseudo-ID
- Rebase to v4.7-rc6
[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-March/417192.html
Shawn Guo (3):
tty: amba-pl011: define flag register bits for ZTE device
tty: amba-pl011: add .get_fifosize for ZTE device
tty: amba-pl011: probe ZTE device from AMBA bus with a pseudo-ID
drivers/tty/serial/amba-pl011.c | 59 ++++++++++++++++++++++++++++++++--------- include/linux/amba/bus.h | 6 +++++ include/linux/amba/serial.h | 9 +++++++ 3 files changed, 62 insertions(+), 12 deletions(-)
Signature · 1 line
1.9.1
PATCH v3 1/3 tty: amba-pl011: define flag register bits for ZTE device
For some reason we do not really understand, ZTE hardware designers choose to define PL011 Flag Register bit positions differently from standard ones as below.
Bit Standard ZTE ----------------------------------- CTS 0 1 DSR 1 3 BUSY 3 8 RI 8 0
Let's define these bits into vendor data and get ZTE PL011 supported properly.
--- drivers/tty/serial/amba-pl011.c | 45 ++++++++++++++++++++++++++++++++--------- include/linux/amba/serial.h | 9 +++++++++ 2 files changed, 44 insertions(+), 10 deletions(-)
drivers/tty/serial/amba-pl011.c +35 -10
@@ -93,6 +93,10 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {struct vendor_data {const u16 *reg_offset;unsigned int ifls; +unsigned int fr_busy; +unsigned int fr_dsr; +unsigned int fr_cts; +unsigned int fr_ri;bool access_32b;bool oversampling;bool dma_threshold;
@@ -111,6 +115,10 @@ static unsigned int get_fifosize_arm(struct amba_device *dev)static struct vendor_data vendor_arm = { .reg_offset = pl011_std_offsets, .ifls =UART011_IFLS_RX4_8 |UART011_IFLS_TX4_8 , + .fr_busy = UART01x_FR_BUSY, + .fr_dsr = UART01x_FR_DSR, + .fr_cts = UART01x_FR_CTS, + .fr_ri =UART011_FR_RI , .oversampling = false, .dma_threshold = false, .cts_event_workaround = false,
@@ -121,6 +129,10 @@ static struct vendor_data vendor_arm = {static struct vendor_data vendor_sbsa = { .reg_offset = pl011_std_offsets, + .fr_busy = UART01x_FR_BUSY, + .fr_dsr = UART01x_FR_DSR, + .fr_cts = UART01x_FR_CTS, + .fr_ri =UART011_FR_RI , .access_32b = true, .oversampling = false, .dma_threshold = false,
@@ -164,6 +176,10 @@ static unsigned int get_fifosize_st(struct amba_device *dev)static struct vendor_data vendor_st = { .reg_offset = pl011_st_offsets, .ifls =UART011_IFLS_RX_HALF |UART011_IFLS_TX_HALF , + .fr_busy = UART01x_FR_BUSY, + .fr_dsr = UART01x_FR_DSR, + .fr_cts = UART01x_FR_CTS, + .fr_ri =UART011_FR_RI , .oversampling = true, .dma_threshold = true, .cts_event_workaround = true,
@@ -192,6 +208,10 @@ static struct vendor_data vendor_zte __maybe_unused = { .reg_offset = pl011_zte_offsets, .access_32b = true, .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, + .fr_busy = ZX_UART01x_FR_BUSY, + .fr_dsr = ZX_UART01x_FR_DSR, + .fr_cts = ZX_UART01x_FR_CTS, + .fr_ri = ZX_UART011_FR_RI, .get_fifosize = get_fifosize_arm, };
@@ -1167,7 +1187,7 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)return ;/* Disable RX and TX DMA */ -while (pl011_read (uap,REG_FR ) & UART01x_FR_BUSY) +while (pl011_read (uap,REG_FR ) & uap->vendor->fr_busy)cpu_relax ();spin_lock_irq (&uap->port.lock);
@@ -1416,11 +1436,12 @@ static void pl011_modem_status(struct uart_amba_port *uap)if (delta & UART01x_FR_DCD)uart_handle_dcd_change (&uap->port, status & UART01x_FR_DCD); -if (delta & UART01x_FR_DSR) +if (delta & uap->vendor->fr_dsr) uap->port.icount.dsr++; -if (delta & UART01x_FR_CTS) -uart_handle_cts_change (&uap->port, status & UART01x_FR_CTS); +if (delta & uap->vendor->fr_cts) +uart_handle_cts_change (&uap->port, + status & uap->vendor->fr_cts);wake_up_interruptible (&uap->port.state->port.delta_msr_wait); }
@@ -1493,7 +1514,8 @@ static unsigned int pl011_tx_empty(struct uart_port *port)struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port);unsigned int status =pl011_read (uap,REG_FR ); -return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ?0 :TIOCSER_TEMT ; +return status & (uap->vendor->fr_busy | UART01x_FR_TXFF) ? +0 :TIOCSER_TEMT ; }static unsigned int pl011_get_mctrl (struct uart_port *port)
@@ -1508,9 +1530,9 @@ static unsigned int pl011_get_mctrl(struct uart_port *port) result |= tiocmbitTIOCMBIT (UART01x_FR_DCD,TIOCM_CAR ); -TIOCMBIT (UART01x_FR_DSR,TIOCM_DSR ); -TIOCMBIT (UART01x_FR_CTS,TIOCM_CTS ); -TIOCMBIT (UART011_FR_RI ,TIOCM_RNG ); +TIOCMBIT (uap->vendor->fr_dsr,TIOCM_DSR ); +TIOCMBIT (uap->vendor->fr_cts,TIOCM_CTS ); +TIOCMBIT (uap->vendor->fr_ri,TIOCM_RNG );#undef TIOCMBITreturn result; }
@@ -2191,7 +2213,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)* Finally, wait for transmitter to become empty * and restore the TCR */ -while (pl011_read (uap,REG_FR ) & UART01x_FR_BUSY) +while (pl011_read (uap,REG_FR ) & uap->vendor->fr_busy)cpu_relax ();if (!uap->vendor->always_enabled)pl011_write (old_cr, uap,REG_CR );
@@ -2303,13 +2325,16 @@ static struct console amba_console = {static void pl011_putc (struct uart_port *port,int c) { +struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); +while (readl (port->membase + UART01x_FR) & UART01x_FR_TXFF)cpu_relax ();if (port->iotype ==UPIO_MEM32 )writel (c, port->membase + UART01x_DR);else writeb (c, port->membase + UART01x_DR); -while (readl (port->membase + UART01x_FR) & UART01x_FR_BUSY) +while (readl (port->membase + UART01x_FR) & uap->vendor->fr_busy)cpu_relax (); }
include/linux/amba/serial.h +9 -0
@@ -104,6 +104,15 @@#define UART01x_FR_CTS 0x001#define UART01x_FR_TMSK (UART01x_FR_TXFF + UART01x_FR_BUSY) +/* +* Some bits of Flag Register on ZTE device have different position from +* standard ones. +*/ +#define ZX_UART01x_FR_BUSY 0x100 +#define ZX_UART01x_FR_DSR 0x008 +#define ZX_UART01x_FR_CTS 0x002 +#define ZX_UART011_FR_RI 0x001 +#define UART011_CR_CTSEN 0x8000/* CTS hardware flow control */ #define UART011_CR_RTSEN 0x4000/* RTS hardware flow control */ #define UART011_CR_OUT2 0x2000/* OUT2 */
Signature · 1 line
1.9.1
PATCH v3 1/3 tty: amba-pl011: define flag register bits for ZTE device
Hi Shawn, Russell,
I noticed this change is in linux-next and but I happen to hit an issue with this as I tested it with earlycon enabled today for the first time.
Quoted 15 lines · Shawn Guo
For some reason we do not really understand, ZTE hardware designers choose to define PL011 Flag Register bit positions differently from standard ones as below.
Bit Standard ZTE ----------------------------------- CTS 0 1 DSR 1 3 BUSY 3 8 RI 8 0Let's define these bits into vendor data and get ZTE PL011 supported properly.
Signed-off-by Shawn Guo <[email protected]>
[...]
Quoted 7 lines
(quoted diff) +3
-0@@ -2303,13 +2325,16 @@ static struct console amba_console = { static void pl011_putc(struct uart_port *port, int c) { + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); +
Review static struct console amba_console = { · line 2339
Quoted 10 lines
(quoted diff) +1
-1while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF) cpu_relax(); if (port->iotype == UPIO_MEM32) writel(c, port->membase + UART01x_DR); else writeb(c, port->membase + UART01x_DR); - while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY) + while (readl(port->membase + UART01x_FR) & uap->vendor->fr_busy) cpu_relax(); }
The above hunk won't work for early console devices. The earlycon_device just has uart_port and is not uart_amba_port. I don't know how to fix this properly but I thought we could reuse private_data in uart_port for early_con devices. Something like below(incomplete for other vendors, works only for ARM)
Regards,
Sudeep
-->8
(quoted diff) +0 -0
w/drivers/tty/serial/amba-pl011.c
index 0b78b04e895e..abe88223790c 100644
drivers/tty/serial/amba-pl011.c +2 -3
@@ -2330,8 +2330,7 @@ static struct console amba_console = {static void pl011_putc (struct uart_port *port,int c) { -struct uart_amba_port *uap = - container_of(port, struct uart_amba_port, port); +struct vendor_data *vendor = port->private_data;while (readl (port->membase + UART01x_FR) & UART01x_FR_TXFF)cpu_relax ();
@@ -2339,7 +2338,7 @@ static void pl011_putc(struct uart_port *port, int c)writel (c, port->membase + UART01x_DR); else writeb(c, port->membase + UART01x_DR); -while (readl (port->membase + UART01x_FR) & uap->vendor->fr_busy) +while (readl (port->membase + UART01x_FR) & vendor->fr_busy)cpu_relax (); }
@@ -2356,6 +2355,7 @@ static int __init pl011_early_console_setup(struct
earlycon_device *device,
if (!device->port.membase)
return -ENODEV;+ device->port.private_data = &vendor_arm;
device->con->write = pl011_early_write;
return 0;}
Russell King - ARM Linux
maintainerPATCH v3 1/3 tty: amba-pl011: define flag register bits for ZTE device
Quoted 39 lines · Sudeep Holla
Hi Shawn, Russell,
I noticed this change is in linux-next and but I happen to hit an issue with this as I tested it with earlycon enabled today for the first time.
Quoted 15 lines · Shawn Guo
For some reason we do not really understand, ZTE hardware designers choose to define PL011 Flag Register bit positions differently from standard ones as below.
Bit Standard ZTE ----------------------------------- CTS 0 1 DSR 1 3 BUSY 3 8 RI 8 0Let's define these bits into vendor data and get ZTE PL011 supported properly.
Signed-off-by Shawn Guo <[email protected]>[...]
Quoted 15 lines
(quoted diff) +4
-1@@ -2303,13 +2325,16 @@ static struct console amba_console = { static void pl011_putc(struct uart_port *port, int c) { + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); + while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF) cpu_relax(); if (port->iotype == UPIO_MEM32) writel(c, port->membase + UART01x_DR); else writeb(c, port->membase + UART01x_DR); - while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY) + while (readl(port->membase + UART01x_FR) & uap->vendor->fr_busy)
Quoted 8 lines
drivers/tty/serial/amba-pl011.c static void pl011_putc(struct uart_port *port, int c) · line 2343
Quoted 2 lines
drivers/tty/serial/amba-pl011.c +0
-0cpu_relax (); }The above hunk won't work for early console devices. The
earlycon_devicejust hasuart_portand is notuart_amba_port. I don't know how to fix this properly but I thought we could reuseprivate_datainuart_portforearly_condevices. Something likebelow(incomplete for other vendors, works only for ARM)
Unfortunate - I'm getting rather annoyed with the way vendors create these derivatives of ARM hardware which then cause problems for the kernel, springing up all these vendor specific hacks all over the place.
Maybe what we should've done with ZTE is insisted that they implement a complete new driver, rather than trying to shoe-horn it into PL011 even though it is in theory PL011.
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up according to speedtest.net.
PATCH v3 1/3 tty: amba-pl011: define flag register bits for ZTE device
Quoted 3 lines · Russell King - ARM Linux
Maybe what we should've done with ZTE is insisted that they implement a complete new driver, rather than trying to shoe-horn it into PL011 even though it is in theory PL011.
When I suggested that a year ago, I was shot down:
http://www.spinics.net/lists/arm-kernel/msg455888.html
Signature · 3 lines
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc. Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
PATCH v3 1/3 tty: amba-pl011: define flag register bits for ZTE device
Quoted 8 lines · Timur Tabi
Quoted 3 lines · Russell King - ARM Linux
Maybe what we should've done with ZTE is insisted that they implement a complete new driver, rather than trying to shoe-horn it into PL011 even though it is in theory PL011.
When I suggested that a year ago, I was shot down:
I still think that's a bad idea. ZTE is not the first one making such small customization on PL011, and likely won't be the last one. We don't want to clone PL011 driver every time there is a such vendor hardware coming out, do we? Having PL011 driver being able to handle different register layout is very helpful to handle such vendor variants, IMHO.
I still appreciate rmk's insistence to handle ZTE device with PL011 driver, and the effort of adding a little "infrastructure" to handle all such possible variants.
Shawn
Russell King - ARM Linux
maintainerPATCH v3 1/3 tty: amba-pl011: define flag register bits for ZTE device
Quoted 6 lines · Shawn Guo
I still think that's a bad idea. ZTE is not the first one making such small customization on PL011, and likely won't be the last one. We don't want to clone PL011 driver every time there is a such vendor hardware coming out, do we? Having PL011 driver being able to handle different register layout is very helpful to handle such vendor variants, IMHO.
Well, it's turning out that handling ZTE in PL011 is turning into a bad idea as well - we keep getting these breakages each time we try.
I think ZTE is sufficiently different from PL011 with the different register layout _and_ the different bits, _and_ the pain that this is causing, that it should have been a separate driver.
The only way I can think of dealing with the console issue is to replicate the console code, once for the PL011 variant and then again for the ZTE variant. We can't _both_ give them the same names _and_ register them together - we either have to give them different names, which makes it confusing because one name won't match the userspace name for the UART, or we need the driver to detect the port type early. That's made much more difficult because ZTE didn't bother with the ID registers, unlike every other vendor.
Serial drivers are not that complex anymore, compared to how they were back before serial_core happened, so having it as a separate driver isn't that big a deal.
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up according to speedtest.net.
PATCH v3 1/3 tty: amba-pl011: define flag register bits for ZTE device
In reply to Sudeep HollaQuoted 15 lines · Sudeep Holla
Quoted 15 lines
(quoted diff) +4
-1@@ -2303,13 +2325,16 @@ static struct console amba_console = { static void pl011_putc(struct uart_port *port, int c) { + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); + while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF) cpu_relax(); if (port->iotype == UPIO_MEM32) writel(c, port->membase + UART01x_DR); else writeb(c, port->membase + UART01x_DR); - while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY) + while (readl(port->membase + UART01x_FR) & uap->vendor->fr_busy)
Quoted 8 lines
drivers/tty/serial/amba-pl011.c static void pl011_putc(struct uart_port *port, int c) · line 2343
Quoted 2 lines
drivers/tty/serial/amba-pl011.c +0
-0cpu_relax (); }The above hunk won't work for early console devices. The
earlycon_devicejust hasuart_portand is notuart_amba_port. I don't know how to fix this properly but I thought we could reuseprivate_datainuart_portforearly_condevices. Something likebelow(incomplete for other vendors, works only for ARM)
Hi Sudeep,
Thanks much for the report. I think the best way to fix this is that we revert the change for pl011_putc() function, and figure out a correct approach adding earlycon support for ZTE hardware later.
I will send a patch to revert pl011_putc() changes shortly.
Thanks,
Shawn
PATCH v3 2/3 tty: amba-pl011: add .get_fifosize for ZTE device
In reply to Shawn GuoZTE PL011 device has a fixed FIFO size 16. Let's add a .get_fifosize hook for it.
--- drivers/tty/serial/amba-pl011.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/tty/serial/amba-pl011.c +6 -1
@@ -204,6 +204,11 @@ static const u16 pl011_zte_offsets[REG_ARRAY_SIZE] = { [REG_DMACR] = ZX_UART011_DMACR, }; +static unsigned int get_fifosize_zte (struct amba_device *dev) +{ +return 16 ; +} +static struct vendor_data vendor_zte__maybe_unused = { .reg_offset = pl011_zte_offsets, .access_32b = true,
@@ -212,7 +217,7 @@ static struct vendor_data vendor_zte __maybe_unused = { .fr_dsr = ZX_UART01x_FR_DSR, .fr_cts = ZX_UART01x_FR_CTS, .fr_ri = ZX_UART011_FR_RI, - .get_fifosize = get_fifosize_arm, + .get_fifosize = get_fifosize_zte, };/* Deals with DMA transactions */
Signature · 1 line
1.9.1
PATCH v3 3/3 tty: amba-pl011: probe ZTE device from AMBA bus with a pseudo-ID
In reply to Shawn GuoThere is no Peripheral Identification Registers on ZTE PL011 device, so although the driver amba-pl011 is ready to work for ZTE device, the device cannot be probed by the driver at all.
With arm,primecell-periphid DT bindings (bindings/arm/primecell.txt) in place, it should be the cleanest the way to use a pseudo-ID to probe the device from AMBA bus. We create an unofficial vendor number AMBA_VENDOR_LINUX, which will practically never become an official vendor ID, and takes Configuration, Revision number, and Part number as input to compose a pseudo-ID for ZTE device.
Also, since we start using vendor_zte to probe ZTE device, the __maybe_unused for vendor_zte is removed.
--- drivers/tty/serial/amba-pl011.c | 7 ++++++- include/linux/amba/bus.h | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-)
drivers/tty/serial/amba-pl011.c +6 -1
@@ -209,7 +209,7 @@ static unsigned int get_fifosize_zte(struct amba_device *dev)return 16 ; } -static struct vendor_data vendor_zte__maybe_unused = { +static struct vendor_data vendor_zte = { .reg_offset = pl011_zte_offsets, .access_32b = true, .ifls =UART011_IFLS_RX4_8 |UART011_IFLS_TX4_8 ,
@@ -2646,6 +2646,11 @@ static struct amba_id pl011_ids[] = { .mask = 0x00ffffff, .data = &vendor_st, }, + { + .id = AMBA_LINUX_ID(0x00, 0x1, 0xffe), + .mask = 0x00ffffff, + .data = &vendor_zte, + }, { 0, 0 }, };
include/linux/amba/bus.h +6 -0
@@ -53,8 +53,14 @@ enum amba_vendor {AMBA_VENDOR_ST =0x80 ,AMBA_VENDOR_QCOM =0x51 ,AMBA_VENDOR_LSI =0xb6 , + AMBA_VENDOR_LINUX = 0xfe, /* This value is not official */ }; +/* This is used to generate pseudo-ID for AMBA device */ +#define AMBA_LINUX_ID (conf, rev, part) \ + (((conf) & 0xff) << 24 | ((rev) & 0xf) << 20 | \ + AMBA_VENDOR_LINUX << 12 | ((part) & 0xfff)) +extern struct bus_type amba_bustype;#define to_amba_device (d) container_of(d, struct amba_device, dev)
Signature · 1 line
1.9.1
v3 cover Complete ZTE PL011 device support
In reply to Shawn GuoQuoted 16 lines · Shawn Guo
This is a pick-up of Jun's v2 patch which tries to complete ZTE PL011 support.
Commit
7ec758718920("tty: amba-pl011: add support for ZTE UART (EXPERIMENTAL)") from Russell had already done part of the work that is needed for ZTE PL011 support. The series adds the missing pieces which includes handling Flag Register bit position oddness and getting ZTE PL011 device probed by amba-pl011 driver.Thanks to Russell for the "official" pseudo-ID idea.
Changes since v2:
- Split changes into 3 separate patches
- Take Russell's suggestion using helper macro to create pseudo-ID
- Rebase to v4.7-rc6
Quoted 6 lines
[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-March/417192.html
Shawn Guo (3):
tty: amba-pl011: define flag register bits for ZTE device
tty: amba-pl011: add .get_fifosize for ZTE device
tty: amba-pl011: probe ZTE device from AMBA bus with a pseudo-ID
Hi Russell,
Most of the changes of patch #3 are yours, so presumably you are fine with it. What about #1 and #2? May I have your ACK on them, so that I can ask Greg to pick up the series? Thanks.
Shawn
Russell King - ARM Linux
maintainerv3 cover Complete ZTE PL011 device support
Quoted 3 lines · Shawn Guo
Most of the changes of patch #3 are yours, so presumably you are fine with it. What about #1 and #2? May I have your ACK on them, so that I can ask Greg to pick up the series? Thanks.
Yes, the three patches look fine. For the first two:
Thanks.
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up according to speedtest.net.
v3 cover Complete ZTE PL011 device support
Quoted 8 lines · Russell King - ARM Linux
Quoted 3 lines · Shawn Guo
Most of the changes of patch #3 are yours, so presumably you are fine with it. What about #1 and #2? May I have your ACK on them, so that I can ask Greg to pick up the series? Thanks.
Yes, the three patches look fine. For the first two:
Acked-by Russell King <[email protected]>
Hi Greg,
The series missed 4.8 merge window. Since v4.8-rc1 is out there, can you please queue the it up for the next? The series can still apply on v4.8-rc1 cleanly. Thanks.
Shawn
Greg Kroah-Hartman
maintainerv3 cover Complete ZTE PL011 device support
Quoted 8 lines · Shawn Guo
Quoted 7 lines · Russell King - ARM Linux
Quoted 3 lines · Shawn Guo
Most of the changes of patch #3 are yours, so presumably you are fine with it. What about #1 and #2? May I have your ACK on them, so that I can ask Greg to pick up the series? Thanks.
Yes, the three patches look fine. For the first two:
Quoted 7 lines
Quoted 1 line
Acked-by Russell King <[email protected]>Hi Greg,
The series missed 4.8 merge window. Since v4.8-rc1 is out there, can you please queue the it up for the next? The series can still apply on v4.8-rc1 cleanly. Thanks.
Yes, it's in my queue, I will get to it "soon".
thanks,
greg k-h