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) Cleaned up the module open_asm. Stripped out code for handling direct sector access on alien disks (we'll do this differently to QUBIDE) Changed direct sector access special filename on QDOS volumes to "*D" to avoid confusion with QUBIDE's "*W". Changed the name of the driver binary to Ser_USB_bin. 0.02.019 (OK) In usbdrv_asm: new function driver_find_ex - works like driver_find but also sets a3 to point to DDB. In core_asm: replaced calls to driver_find with driver_find_ex. In core_asm: new function drive_remove can be called instead of drv_rmv if a3 is already set. In core_asm: removed supervisor/user mode switch from enter/exit of drv_rmv. In text_asm: removed surplus leading line feed from "Format complete" message. In format_asm: drive_remove is called to try and remove (unlink) a drive before formatting it. In io_asm: Added a call to drive_select prior to branching to relevant trap servicer. Renamed module setup_asm to SER_USB_asm. 0.02.020 (OK) usbdrv:drive_select, usbdrv:usbwiz_mount and usbdrv:usbwiz_read now only preserve the registers they use, saving some stack. usbdrv:is_ok rewritten; no longer drops through to usbwiz_fetch. Again, saves some stack. iod:get_1sector now sets d0 to the currently selected drive before calling drive_read (a serious bug that never manifested!) core:drv_lnk no longer saves a3 on stack around call to un_drv (as a3 didn't get trashed in the first place!) basics_asm:usb_drive - switched into supervisor mode before calling drv_lnk so that USB_DRIVE n,d,p now works! io_reserved byte in I/O Queue entries renamed io_curr_drive. usbdrv:usbwiz_queue_add - sets the io_curr_drive field of the request to the currently selected media (i.e. value of usbwiz_csm). usbdrv:usbwiz_queue_popregs - loads d7 with the value of the io_curr_drive field. usbdrv:usb_wr_job_cde & usbdrv:usb_rd_job_cde - use the drive number passed in d7 if d0 is zero. This fixes the issue where the drive number was unknown when passing a FAT pointer only. In basics_asm: replaced all calls to driver_find that were followed by a -next_ddlink adjustment with calls to driver_find_ex. Replaced the single value for usb_fix_capacity with a table of 8 values (now called usb_fix_capacities). usbdrv:drive_capacity - now gets the fixed size override from the table entry for the selected drive, instead of one global value. basics:usb_fixsize - S*BASIC command now takes two parameters: Drive and Size. 0.02.021 (BAD) Renamed rdsect_asm to read_asm & wrsect_asm to write_asm. Removed call to drive_nbusy from slaved. Not needed. Replaced call to set_drive/read_block in slaved with selected_drive/drive_read. Reorganised drive_read & drive_write so they both respect the I/O Queue lock and optimised stack usage. This broke everything! 0.02.022 (OK) As 0.02.021 but changes to drive_read & drive_write rolled back. 0.02.023 (OK) Reorganised drive_read & drive_write so they both respect the I/O Queue lock, and optimised stack usage. This time it worked (previous problem related to d2 apparently trashed by mt.susjb when it shouldn't have been). Significantly reduced suspend times: drive_read suspends in 1/25ths of a second, the Queue Manager in 1/50ths. This removes the unintentional throttle on performance that limited throughput to 1 sector every 5 seconds, regardless of the configured baud rate!! Set a1=0 in mt.susjb calls in usbwiz_check_queue and usbwiz_qm. 0.02.024 (OK) Driver now has a standard level 2 config block in the module cfg_asm (thanks to George Gwilt's UCONFIG utility). Configuration items port_def and port_baud moved from usbdrv_asm to cfg_asm, renamed cfg_port_def and cfg_port_baud. Message usbmsg_qm_bad_dev moved from usbdrv_asm to text_asm as unkndev_err. Removed the constant io_pause_checkpipe; usbwiz_checkpipe now uses a fixed I/O delay of 1 frame for better performance. Removed the mt.susjb call from the main loop of the Queue Manager; delay not needed or desirable. 0.02.025 (OK) New function usbwiz_setbaud_cfg: sets the baud rate according to byte short code corresponding to the config block item codes. usbwiz_setbaud no longer tries to set the baud rate if the requested baud rate is already current!! usbwiz_init now respects the config block setting and configures USBWiz for the selected baud rate before first use. Added support for pressing F1 at startup; hook in place to run a driver configuration utility before any comms with USBWiz. Reorganised usbwiz_init so that all variables are cleared right at the start. BUSY flag no longer set during initialisation (nothing reads it until init done anyway!) Functions renamed for consistency: usbwiz_xxx relate to the USBWiz interface, usb_xxx relate to the Ser-USB Driver API: usbwiz_qm -> usb_qm usbwiz_sched -> usb_qm_sched usbwiz_chkpipe -> usb_chkpipe usbwiz_check_queue -> usb_queue_check usbwiz_queue_add -> usb_queue_add usbwiz_queue_status -> usb_queue_status usbwiz_queue_remove -> usb_queue_remove usbwiz_req_size -> usb_queue_req_size usbwiz_queue_popregs -> usb_queue_loadregs clone_buffer -> usb_queue_clone_buffer mk_brc -> usbwiz_mk_br_cmd mk_rws_cmd -> usbwiz_mk_rws_cmd is_ok -> usbwiz_is_ok _______________________________________________ QL-Users Mailing List http://www.q-v-d.demon.co.uk/smsqe.htm
