[Ql-Users] Ser-USB Driver Update

2011-02-22 Thread Adrian Ives
Current version is 0.04 Build 002.

 

Development is now frozen while I finish testing so that I'm satisfied it's
good enough to put out as a beta.

 

The INPUT bug reported last time is fixed (slave block issue).

Problematic initial handshaking under JM QDOS is fixed (yet again!) with a
better retry and timeout mechanism.

Calls down to the SER driver are now all made with zero timeout when in
supervisor mode (as they should have been!).

USB_RESTART command allows the driver to be restarted if it didn't detect
the Ser-USB, or if you forgot to connect it.

S*BASIC USB_PUTCMD, USB_GETCMD and USB_GETCMD$ interface to the driver layer
is working.

Implemented an auxiliary stack to get around QDOS's dreadfully small
supervisor stack allocation when calling into the driver (even the original
QUBIDE code had managed to exceed the 64 byte limit at one point).

Driver is now layered to enable the hardware interface to be replaced.

Default I/O mode is synchronous to preserve memory on low-end systems;
asynchronous I/O functions are still available through the API for user
programs.

 

I would appreciate it if anyone who wants to help with the beta-testing
could get in touch with me off-list.

 

And now I'm having a few driver-free days ;)

 

 

Adrian

___
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm


Re: [Ql-Users] Ser-USB Driver Update: External Command Interface (and Progress Update)

2011-02-13 Thread gdgqler

On 13 Feb 2011, at 14:02, Adrian Ives wrote:

> 
> Hn.
> 
> Well, I'm using SMSQ and I get this ...
> 
> 65537 DIV 65536 = 1
> 65537 MOD 65536 = 1
> 
> 128000 DIV 65536 = 1
> 128000 MOD 65536 = 62464

Yes. SMSQ/E allows larger numbers than integers for DIV and MOD. However, Turbo 
does not allow this.

George
___
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm


Re: [Ql-Users] Ser-USB Driver Update: External Command Interface (and Progress Update)

2011-02-13 Thread Adrian Ives
Bob,

Hn.

Well, I'm using SMSQ and I get this ...

65537 DIV 65536 = 1
65537 MOD 65536 = 1

128000 DIV 65536 = 1
128000 MOD 65536 = 62464

It's academic, anyway.  This is just an example to show how you _could_ use
these facilities.  Thanks for pointing it out, though.


Adrian

-Original Message-
From: ql-users-boun...@lists.q-v-d.com
[mailto:ql-users-boun...@lists.q-v-d.com] On Behalf Of Bob Spelten
Sent: 13 February 2011 13:44
To: ql-us...@q-v-d.com
Subject: Re: [Ql-Users] Ser-USB Driver Update: External Command Interface
(and Progress Update)

Op Sun, 13 Feb 2011 13:10:41 +0100 schreef Adrian Ives
:

> 250 REMark ===
> 260 REMark :
> 270 DEFine FuNction GetDWordResponse$(Cmd%)
> 280 LOCal Response, High%, Low%
> 290 USB_PUTCMD Cmd%
> 300 Response= USB_GETCMD
> 310 High%= Response DIV 65536
> 320 Low%= Response MOD 65536
> 330 RETurn High% & '/' & Low%
> 340 END DEFine GetDWordResponse$
> 350 REMark :
> 360 REMark ===
> 370 REMark :
> 380 DEFine FuNction Get32BitResponse$(Cmd%)
> 390 LOCal Response, High%, Low%
> 400 USB_PUTCMD Cmd%
> 410 Response= USB_GETCMD
> 420 High%= Response DIV 65536
> 430 Low%= Response MOD 65536
> 440 RETurn BIN$(High%,16) & "/" & BIN$(Low%,16)
> 450 END DEFine Get32BitResponse$
>
I think these functions need a little adjustment.
The DIV & MOD functions in S'Basic work on signed Integers and not on Longs.
Value DIV 65536 will always produce zero.
Value MOD 65536 will always produce value.
There probably are Long DIV/MOD functions in some toolkit out there, I just
happened to find one in an old Machine Code book.
Otherwise just use '/' and INT to extract the high% and low% parts.
high%=INT(response / 65536): low%=response -(high% * 65536)

Bob

--
The BSJR QL software site at: http://members.chello.nl/b.spelten/ql/
___
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm

___
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm


Re: [Ql-Users] Ser-USB Driver Update: External Command Interface (and Progress Update)

2011-02-13 Thread Bob Spelten

Op Sun, 13 Feb 2011 13:10:41 +0100 schreef Adrian Ives
:


250 REMark ===
260 REMark :
270 DEFine FuNction GetDWordResponse$(Cmd%)
280 LOCal Response, High%, Low%
290 USB_PUTCMD Cmd%
300 Response= USB_GETCMD
310 High%= Response DIV 65536
320 Low%= Response MOD 65536
330 RETurn High% & '/' & Low%
340 END DEFine GetDWordResponse$
350 REMark :
360 REMark ===
370 REMark :
380 DEFine FuNction Get32BitResponse$(Cmd%)
390 LOCal Response, High%, Low%
400 USB_PUTCMD Cmd%
410 Response= USB_GETCMD
420 High%= Response DIV 65536
430 Low%= Response MOD 65536
440 RETurn BIN$(High%,16) & "/" & BIN$(Low%,16)
450 END DEFine Get32BitResponse$


I think these functions need a little adjustment.
The DIV & MOD functions in S'Basic work on signed Integers and not on
Longs.
Value DIV 65536 will always produce zero.
Value MOD 65536 will always produce value.
There probably are Long DIV/MOD functions in some toolkit out there, I
just happened to find one in an old Machine Code book.
Otherwise just use '/' and INT to extract the high% and low% parts.
high%=INT(response / 65536): low%=response -(high% * 65536)

Bob

--
The BSJR QL software site at: http://members.chello.nl/b.spelten/ql/
___
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm


Re: [Ql-Users] Ser-USB Driver Update: External Command Interface (and Progress Update)

2011-02-13 Thread Adrian Ives
Well, in that version it was because of the NUL device (although there are
ways around that - any channel could be used as the target of a Turbo
Toolkit SET_CHANNEL).

However, I have now implemented three new commands which remove the need for
all that mucking about ...

USB_PUTCMD Byte [,Byte]: Put a command in the driver's command pipe.

USB_GETCMD(): Get a long word command response from the driver's command
pipe.

USB_GETCMD$(): Get a long word command response from the driver's command
pipe and return it as a string to S*BASIC.

... which makes the S*BASIC example look like this (also much faster):

100 PRINT "The Response to Command $01 (Get Driver Version) was: " &
GetResponse$(1)
110 PRINT "The Response to Command $02 (Get Hardware Version) was: " &
GetResponse$(2)
120 PRINT "The Response to Command $03 (Get Hardware Type) was: " &
GetResponse$(3)
130 PRINT "The Response to Command $04 (Get I/O Queue Status) was: " &
GetDWordResponse$(4)
140 PRINT "The Response to Command $05 (Get I/O State) was: " &
GetDWordResponse$(5)
150 PRINT "The Response to Command $06 (Get Flags) was: " &
Get32BitResponse$(6)
160 PRINT "The Response to Command $11 (Get Mapped Physical Drive 1) was: "
& GetDWordResponse$(HEX("11"))
170 REMark :
180 REMark ===
190 REMark :
200 DEFine FuNction GetResponse$(Cmd%)
210 USB_PUTCMD Cmd%
220 RETurn USB_GETCMD$
230 END DEFine GetResponse$
240 REMark :
250 REMark ===
260 REMark :
270 DEFine FuNction GetDWordResponse$(Cmd%)
280 LOCal Response, High%, Low%
290 USB_PUTCMD Cmd%
300 Response= USB_GETCMD
310 High%= Response DIV 65536
320 Low%= Response MOD 65536
330 RETurn High% & '/' & Low%
340 END DEFine GetDWordResponse$
350 REMark :
360 REMark ===
370 REMark :
380 DEFine FuNction Get32BitResponse$(Cmd%)
390 LOCal Response, High%, Low%
400 USB_PUTCMD Cmd%
410 Response= USB_GETCMD
420 High%= Response DIV 65536
430 Low%= Response MOD 65536
440 RETurn BIN$(High%,16) & "/" & BIN$(Low%,16)
450 END DEFine Get32BitResponse$

-Original Message-
From: ql-users-boun...@lists.q-v-d.com
[mailto:ql-users-boun...@lists.q-v-d.com] On Behalf Of Plastic
Sent: 13 February 2011 11:16
To: ql-us...@q-v-d.com
Subject: Re: [Ql-Users] Ser-USB Driver Update: External Command Interface
(and Progress Update)

On Sun, Feb 13, 2011 at 1:09 AM, Adrian Ives  wrote:

> [SNIP]
> Here is a tidier version of the example S*BASIC program that I posted 
> in my last mail. It shows how to use the interface in its current 
> form. Requires SMSQ & Turbo Toolkit (and the Ser-USB Driver).
> [SNIP]


Is the SMSQ requirement permanent, or just for development purposes?

Dave
___
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm

___
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm


Re: [Ql-Users] Ser-USB Driver Update: External Command Interface (and Progress Update)

2011-02-13 Thread Plastic
On Sun, Feb 13, 2011 at 1:09 AM, Adrian Ives  wrote:

> [SNIP]
> Here is a tidier version of the example S*BASIC program that I posted in my
> last mail. It shows how to use the interface in its current form. Requires
> SMSQ & Turbo Toolkit (and the Ser-USB Driver).
> [SNIP]


Is the SMSQ requirement permanent, or just for development purposes?

Dave
___
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm


[Ql-Users] Ser-USB Driver Update: External Command Interface (and Progress Update)

2011-02-12 Thread Adrian Ives
Here is a list of the commands that the current version of the Ser-USB
Driver can execute through its command pipe interface. This interface
supports run-time interrogation and configuration of the driver and is
intended to enable the development of utility software that does not require
detailed knowledge of the underlying hardware. When the necessary code
support is completed there will also be commands for mounting/unmounting
partitions.

This interface has primarily come about as a result of including run-time
debugging so I would be very interested to hear any views on its usefulness,
or what other features might be desirable.

usbcmd_get_dr_ver
$01 Get Driver Version
Command Size: Byte
Response Size: Long
Returns the Ser-USB Driver version as four characters.

usbcmd_get_hw_ver
$02 Get Hardware Version
Command Size: Byte
Response Size: Long
Returns the hardware (USBWiz) version as four characters.

usbcmd_get_hw_type
$03 Get Hardware Type
Command Size: Byte
Response Size: Long
Returns the hardware type as four characters.
USBWiz returns "USBW".
Other hardware types are supported as per the original QUBIDE defines
(though these are unlikely to be encountered).

usbcmd_get_q_stats
$04 Get I/O Queue Stats
Command Size: Byte
Response Size: Long
Returns statistics about the I/O Queue as a long word.
High word contains the maximum I/O Queue size in requests.
Low word contains the current number of entries in the queue.

usbcmd_get_io_state
$05 Get I/O State
Command Size: Byte
Response Size: Long
Returns information about the currently executing I/O operation.
High word contains the op code of the current operation (ip_op_read=1 or
io_op_write=2).
Low word contains the stage number in the operation.

usbcmd_get_flags
$06 Get Flags
Command Size: Byte
Response Size: Long
Returns all flag bytes as one long word.
High word contains the debug flags in the top 8 bits, the USBWiz flags in
the bottom 8.
Low word contains 0 in the top 8 bits, the Ser-USB Driver flags in the
bottom 8.

usbcmd_get_mphys_drv
$10 Get Mapped Physical Drive
Command Size: Byte with operand in low nibble ($11..$18)
Response Size: Long
Returns the physical drive/partition that is currently mapped to a USB drive
number.
High word contains the Logical Unit Number (LUN).
Low word contains the partition number.
The low nibble of command $10 is a logical drive number in the range 1..8;
other values always return 0.

usbcmd_clr_flag
$e0 Clear Flag
Command Size: Byte with operand in low nibble ($e0..$ef)
Response Size: Long
Clear a Ser-USB Driver or USBWiz flag.
Returns the previous state of the flag as 0 or 1.
The low nibble of command $e0 is broken down as follows:
  Bits 0..2 = Flag number (0..7).
  Bit  3 = 0 for Ser-USB Flags, or 1 for USBWiz Flags.


usbcmd_set_flag
$f0 Set Flag
Command Size: Byte with operand in low nibble ($f0..$ff)
Response Size: Long
Set a Ser-USB Driver or USBWiz flag.
Returns the previous state of the flag as 0 or 1.
The low nibble of command $f0 is broken down as follows:
  Bits 0..2 = Flag number (0..7).
  Bit  3 = 0 for Ser-USB Flags, or 1 for USBWiz Flags.

Here is a tidier version of the example S*BASIC program that I posted in my
last mail. It shows how to use the interface in its current form. Requires
SMSQ & Turbo Toolkit (and the Ser-USB Driver).

100 OPEN #4,"NUL"
110 OPEN #5,"NUL"
120 SET_CHANNEL #4,USB_PIPE_W
130 SET_CHANNEL #5,USB_PIPE_R
140 PRINT "The Response to Command $01 (Get Driver Version) was: " &
GetResponse$(1)
150 PRINT "The Response to Command $02 (Get Hardware Version) was: " &
GetResponse$(2)
160 PRINT "The Response to Command $03 (Get Hardware Type) was: " &
GetResponse$(3)
170 PRINT "The Response to Command $04 (Get I/O Queue Status) was: " &
GetDWordResponse$(4)
180 PRINT "The Response to Command $05 (Get I/O State) was: " &
GetDWordResponse$(5)
190 PRINT "The Response to Command $06 (Get Flags) was: " &
Get32BitResponse$(6)
200 PRINT "The Response to Command $11 (Get Mapped Physical Drive 1) was: "
& GetDWordResponse$(HEX("11"))
210 REMark ===
220 DEFine FuNction GetResponse$(Cmd%)
230 LOCal Response$, This$, Bytes%
240 PRINT #4;CHR$(Cmd%);
250 Response$= ""
260 Bytes%= 0
270 REPeat GetResponse
280   This$= INKEY$(#5)
290   IF This$ = "" THEN NEXT GetResponse
300   Response$= Response$ & This$
310   Bytes%= Bytes% + 1
320   IF Bytes% = 4 THEN EXIT GetResponse
330 END REPeat GetResponse
340 RETurn Response$
350 END DEFine GetResponse$
360 REMark ===
370 DEFine FuNction GetDWordResponse$(Cmd%)
380 LOCal Response$, High%, Low%
390 Response$= GetResponse$(Cmd%)
400 High%= CODE(Response$(1))*256 + CODE(Response$(2))
410 Low%= CODE(Response$(3))*256 + CODE(Response$(4))
420 RETurn High% & '/' & Low%
430 END DEFine GetDWordResponse$
440 REMark ===
450 DEFine FuNction Get32BitResponse$(Cmd%)
460 LOCal Response$, High%, Low%
470 Response$= GetRe

Re: [Ql-Users] Ser-USB Driver Update w/e 11-FEB-2011

2011-02-11 Thread Adrian Ives
Thanks.  I will be looking for anybody who already has a USBWiz unit lying
around (and who would be capable of connecting it to the QL) to volunteer to
test the driver.

I'm not there yet, but hopefully we're not talking months away.


Adrian

-Original Message-
From: ql-users-boun...@lists.q-v-d.com
[mailto:ql-users-boun...@lists.q-v-d.com] On Behalf Of
tobias.froesc...@t-online.de
Sent: 11 February 2011 15:11
To: ql-us...@q-v-d.com
Subject: Re: [Ql-Users] Ser-USB Driver Update w/e 11-FEB-2011

Adrian,
add me as second entry on that list.

Also, I would like to offer help - should you need it. You seem to be making
very good progress.

Regards,
Tobias

-Original-Nachricht-
Subject: Re: [Ql-Users] Ser-USB Driver Update w/e 11-FEB-2011
Date: Fri, 11 Feb 2011 14:53:41 +0100
From: "Urs Koenig (QL)" 
To: 

Adrian Ives wrote:
> As of today there is a Ser-USB driver that's around 85% complete.  The 
> current version can mount, read, write and format SD cards/USB storage 
> with a "QLW1" partition, but it doesn't yet support multiple 
> partitions on the same drive.
> All traps are implemented and some optimisation has been started, 
> delivering a perceived performance at 56K that feels like a floppy 
> disk - but even the default 9600 baud is useable, albeit somewhat 
> pedestrian
Sounds very promising. Please Go on!

You can put me on the preorder-list for at least the driver.

Urs

___
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm



___
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm

___
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm


Re: [Ql-Users] Ser-USB Driver Update w/e 11-FEB-2011

2011-02-11 Thread tobias.froesc...@t-online.de
Adrian,
add me as second entry on that list.

Also, I would like to offer help - should you need it. You seem to be making 
very good progress.

Regards,
Tobias

-Original-Nachricht-
Subject: Re: [Ql-Users] Ser-USB Driver Update w/e 11-FEB-2011
Date: Fri, 11 Feb 2011 14:53:41 +0100
From: "Urs Koenig (QL)" 
To: 

Adrian Ives wrote:
> As of today there is a Ser-USB driver that's around 85% 
> complete.  The current version can mount, read, write and 
> format SD cards/USB storage with a "QLW1" partition, but it 
> doesn't yet support multiple partitions on the same drive.  
> All traps are implemented and some optimisation has been 
> started, delivering a perceived performance at 56K that feels 
> like a floppy disk - but even the default 9600 baud is 
> useable, albeit somewhat pedestrian
Sounds very promising. Please Go on!

You can put me on the preorder-list for at least the driver.

Urs

___
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm



___
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm


Re: [Ql-Users] Ser-USB Driver Update w/e 11-FEB-2011

2011-02-11 Thread Urs Koenig (QL)
Adrian Ives wrote:
> As of today there is a Ser-USB driver that's around 85% 
> complete.  The current version can mount, read, write and 
> format SD cards/USB storage with a "QLW1" partition, but it 
> doesn't yet support multiple partitions on the same drive.  
> All traps are implemented and some optimisation has been 
> started, delivering a perceived performance at 56K that feels 
> like a floppy disk - but even the default 9600 baud is 
> useable, albeit somewhat pedestrian
Sounds very promising. Please Go on!

You can put me on the preorder-list for at least the driver.

Urs

___
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm


[Ql-Users] Ser-USB Driver Update w/e 11-FEB-2011

2011-02-11 Thread Adrian Ives
As of today there is a Ser-USB driver that's around 85% complete.  The
current version can mount, read, write and format SD cards/USB storage with
a "QLW1" partition, but it doesn't yet support multiple partitions on the
same drive.  All traps are implemented and some optimisation has been
started, delivering a perceived performance at 56K that feels like a floppy
disk - but even the default 9600 baud is useable, albeit somewhat pedestrian
;)

 

The latest build has a standard level 2 config block allowing the default
port name and baud rate to be configured. The hooks are also in place for
load-time configuration upon hitting the F1 key after the banner is
displayed.

 

Now the bad news.  I've started some application testing and I've already
discovered a couple of incompatibilities.  For instance, QD can load a file
directly from a USBn_ device, but the MasterSpy editor locks up! The QPAC2
Files thing shows the device, but can't list the files unless the root
directory is already in the slave blocks . that kind of thing.  I'm hopeful
that most of these issues can be resolved now that the core driver is
working.  I suspect that the main area of difficulty is the pitiful amount
of stack that QDOS allocates when handing over to the device driver code!
The Ser-USB API gets a little deep in places.

 

Just for fun, here is an example of communicating with the driver through
its command pipe (this example needs SMSQ/Turbo Toolkit):

 

100 OPEN #4,"NUL"

110 OPEN #5,"NUL"

120 SET_CHANNEL #4,USB_PIPE_W

130 SET_CHANNEL #5,USB_PIPE_R

140 PRINT #4;CHR$(1);

150 Response$= ""

160 Bytes%= 0

170 REPeat GetResponse1

180   This$= INKEY$(#5)

190   IF This$ = "" THEN NEXT GetResponse1

200   Response$= Response$ & This$

210   Bytes%= Bytes% + 1

220   IF Bytes% = 4 THEN EXIT GetResponse1

230 END REPeat GetResponse1

240 PRINT "The Response to Command 01 (Get Driver Version) was: " &
Response$

250 PRINT #4;CHR$(2);

260 Response$= ""

270 Bytes%= 0

280 REPeat GetResponse2

290   This$= INKEY$(#5)

300   IF This$ = "" THEN NEXT GetResponse2

310   Response$= Response$ & This$

320   Bytes%= Bytes% + 1

330   IF Bytes% = 4 THEN EXIT GetResponse2

340 END REPeat GetResponse2

350 PRINT "The Response to Command 02 (Get Hardware Version) was: " &
Response$

 

The driver interface will be somewhat sleeker than this in the final build
of course ;)

 

 

 

Adrian

 

 

In the interests of being open, and as I intend that this driver will
ultimately become open source, here is this week's change log:

 

0.02.011 (OK)

Unused messages removed.

Optimised core:drv_inst.

Removed usbdrv:usbwiz_link, core:set_d7, core:read_params.

Fixed wrong register error in usbdrv:drive_select.

USB_RD & USB_WR now attempt to select correct physical drive if not current
at start of process.

 

0.02.012 (OK)

usbdrv:drive_capacity no longer returns a hard coded result, but instead
establishes the size of the drive through iterative RS commands (USBWiz MS
command won't work with direct sector access on non-FAT).

usbdrv:usbwiz_fetch now able to exit faster on detection of an error return.

New S*BASIC function USB_SIZE() returns the capacity of the selected drive.

 

0.02.013 (OK)

Fixed bad error exits in usbdrv:usbwiz_fetch

Added new debug messages in usbdrv:usbwiz_send and usbdrv:usbwiz_fetch.

 

0.02.014 (OK)

Implemented new variable usb_fix_capacity to override calls to
drive_capacity.

New S*BASIC command USB_FIXSIZE to set usb_fix_capacity.

 

0.02.015 (OK)

In usbdrv:usbwiz_queue_status, if an entry has a status of failed it will be
set to complete so that it will automatically be purged when its retention
count reaches zero.

Map write delay now configurable at run-time.

New function core:selected_drive to eventually replace the deprecated
core:set_drive.

In open:do_open, legacy calls to set_drive/write_block replaced with
selected_drive/drive_write.

Check at startup, just after driver version banner, for F5 pressed. If so,
debug flag is set.

 

0.02.016 (OK)

New constant io_queue_safe_limit determines how full the I/O Queue is
allowed to get before I/O write operations are blocked.

Implemented bit 29 of I/O request flag to indicate request came from forced
slaving.

forced:do_forced optimised; deprecated calls to drive_nbusy removed, legacy
call to write_block replaced with drive_write.

Documentation headers on read/write functions updated to reflect changes.

 

0.02.017 (OK)

Incorporated the queue safe limit test into drive_read, so neither call can
exhaust queue space (Bit 29 of d6 treated the same).

Greatly simplified and cleaned up the project make file, removing the module
boot entirely.

Stripped out code to support ROM version (Ser-USB was never intended to be
loaded from ROM - at least not conventionally).

Simplied initialisation code and swapped order so that driver is initialised
before S*BASIC PROCs & FNs installed.

Removed obsolete pointer hard_add from startup_asm.

 

0.02.018 (OK)

Cleane

[Ql-Users] Ser-USB Driver Update

2011-02-08 Thread Adrian Ives
Heh . talk about bad luck.  Build 13 and the completion of the
drive_capacity call, which establishes the true physical size of a drive
(this was previously hard coded, as the USBWiz module cannot return media
size information unless it has mounted a FAT file system).  And that's when
my old 256MB Bytestor SD card decided that it would no longer be able to
read blocks beyond $fff!

 

I think this is actually the first time that an SD card has failed on me and
was a sober reminder that when they go bad - they really go BAD!

 

 

Adrian

___
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm