Browse Source

Merge pull request #592 from dinoboards/dean-ch376-usb-native-8

CH376 Native USB Driver
pull/596/head
Wayne Warthen 6 months ago
committed by GitHub
parent
commit
a29c6f35c7
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 3
      .github/workflows/commit.yml
  2. 3
      .github/workflows/release.yml
  3. 18
      .gitignore
  4. 36
      .vscode/settings.json
  5. 12
      Dockerfile
  6. 7
      Makefile
  7. 6
      Source/CBIOS/cbios.asm
  8. 1
      Source/Doc/SystemGuide.md
  9. 12
      Source/HBIOS/Config/RCEZ80_std.asm
  10. 6
      Source/HBIOS/Config/RCZ80_std.asm
  11. 2
      Source/HBIOS/ansi.asm
  12. 10
      Source/HBIOS/cfg_MASTER.asm
  13. 8
      Source/HBIOS/cfg_RCEZ80.asm
  14. 107
      Source/HBIOS/ch376-native/Makefile
  15. 106
      Source/HBIOS/ch376-native/base-drv.asm
  16. 39
      Source/HBIOS/ch376-native/base-drv.s
  17. 1
      Source/HBIOS/ch376-native/base-drv/.gitignore
  18. 769
      Source/HBIOS/ch376-native/base-drv/ch376.c.s
  19. 293
      Source/HBIOS/ch376-native/base-drv/ch376_init.c.s
  20. 85
      Source/HBIOS/ch376-native/base-drv/class_hub.c.s
  21. 67
      Source/HBIOS/ch376-native/base-drv/critical-section.c.s
  22. 449
      Source/HBIOS/ch376-native/base-drv/dev_transfers.c.s
  23. 1085
      Source/HBIOS/ch376-native/base-drv/enumerate.c.s
  24. 457
      Source/HBIOS/ch376-native/base-drv/enumerate_hub.c.s
  25. 142
      Source/HBIOS/ch376-native/base-drv/enumerate_storage.c.s
  26. 97
      Source/HBIOS/ch376-native/base-drv/hbios-driver-storage.c.s
  27. 482
      Source/HBIOS/ch376-native/base-drv/protocol.c.s
  28. 311
      Source/HBIOS/ch376-native/base-drv/transfers.c.s
  29. 224
      Source/HBIOS/ch376-native/base-drv/usb-base-drv.c.s
  30. 258
      Source/HBIOS/ch376-native/base-drv/usb_state.c.s
  31. 149
      Source/HBIOS/ch376-native/base-drv/work-area.c.s
  32. 133
      Source/HBIOS/ch376-native/cruntime.asm
  33. 143
      Source/HBIOS/ch376-native/ez80-firmware.asm
  34. 11
      Source/HBIOS/ch376-native/keyboard.s
  35. 1
      Source/HBIOS/ch376-native/keyboard/.gitignore
  36. 169
      Source/HBIOS/ch376-native/keyboard/class_hid.c.s
  37. 440
      Source/HBIOS/ch376-native/keyboard/class_hid_keyboard.c.s
  38. 122
      Source/HBIOS/ch376-native/keyboard/kyb-init.c.s
  39. 406
      Source/HBIOS/ch376-native/keyboard/kyb_driver.c.s
  40. 39
      Source/HBIOS/ch376-native/print.asm
  41. 125
      Source/HBIOS/ch376-native/readme.md
  42. 8
      Source/HBIOS/ch376-native/scsi-drv.s
  43. 1
      Source/HBIOS/ch376-native/scsi-drv/.gitignore
  44. 446
      Source/HBIOS/ch376-native/scsi-drv/class_scsi.c.s
  45. 148
      Source/HBIOS/ch376-native/scsi-drv/scsi-init.c.s
  46. 470
      Source/HBIOS/ch376-native/scsi-drv/scsi_driver.c.s
  47. 13
      Source/HBIOS/ch376-native/source-doc/.clang-format
  48. 242
      Source/HBIOS/ch376-native/source-doc/base-drv/ch376.c
  49. 176
      Source/HBIOS/ch376-native/source-doc/base-drv/ch376.h
  50. 76
      Source/HBIOS/ch376-native/source-doc/base-drv/ch376_init.c
  51. 1323
      Source/HBIOS/ch376-native/source-doc/base-drv/ch376inc.h
  52. 9
      Source/HBIOS/ch376-native/source-doc/base-drv/class_hub.c
  53. 62
      Source/HBIOS/ch376-native/source-doc/base-drv/class_hub.h
  54. 8
      Source/HBIOS/ch376-native/source-doc/base-drv/critical-section.c
  55. 13
      Source/HBIOS/ch376-native/source-doc/base-drv/critical-section.h
  56. 11
      Source/HBIOS/ch376-native/source-doc/base-drv/delay.h
  57. 106
      Source/HBIOS/ch376-native/source-doc/base-drv/dev_transfers.c
  58. 66
      Source/HBIOS/ch376-native/source-doc/base-drv/dev_transfers.h
  59. 262
      Source/HBIOS/ch376-native/source-doc/base-drv/enumerate.c
  60. 39
      Source/HBIOS/ch376-native/source-doc/base-drv/enumerate.h
  61. 82
      Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_hub.c
  62. 10
      Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_hub.h
  63. 27
      Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_storage.c
  64. 9
      Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_storage.h
  65. 1
      Source/HBIOS/ch376-native/source-doc/base-drv/ez80-helpers.h
  66. 11
      Source/HBIOS/ch376-native/source-doc/base-drv/hbios-driver-storage.c
  67. 15
      Source/HBIOS/ch376-native/source-doc/base-drv/hbios-driver-storage.h
  68. 6
      Source/HBIOS/ch376-native/source-doc/base-drv/hbios.h
  69. 11
      Source/HBIOS/ch376-native/source-doc/base-drv/print.h
  70. 159
      Source/HBIOS/ch376-native/source-doc/base-drv/protocol.c
  71. 98
      Source/HBIOS/ch376-native/source-doc/base-drv/protocol.h
  72. 152
      Source/HBIOS/ch376-native/source-doc/base-drv/transfers.c
  73. 103
      Source/HBIOS/ch376-native/source-doc/base-drv/transfers.h
  74. 76
      Source/HBIOS/ch376-native/source-doc/base-drv/usb-base-drv.c
  75. 14
      Source/HBIOS/ch376-native/source-doc/base-drv/usb-base-drv.h
  76. 97
      Source/HBIOS/ch376-native/source-doc/base-drv/usb_state.c
  77. 26
      Source/HBIOS/ch376-native/source-doc/base-drv/usb_state.h
  78. 3
      Source/HBIOS/ch376-native/source-doc/base-drv/work-area.c
  79. 54
      Source/HBIOS/ch376-native/source-doc/base-drv/work-area.h
  80. 54
      Source/HBIOS/ch376-native/source-doc/convert-for-uz80as.sh
  81. 24
      Source/HBIOS/ch376-native/source-doc/keyboard/class_hid.c
  82. 21
      Source/HBIOS/ch376-native/source-doc/keyboard/class_hid.h
  83. 377
      Source/HBIOS/ch376-native/source-doc/keyboard/class_hid_keyboard.c
  84. 27
      Source/HBIOS/ch376-native/source-doc/keyboard/class_hid_keyboard.h
  85. 25
      Source/HBIOS/ch376-native/source-doc/keyboard/kyb-init.c
  86. 136
      Source/HBIOS/ch376-native/source-doc/keyboard/kyb_driver.c
  87. 12
      Source/HBIOS/ch376-native/source-doc/keyboard/kyb_driver.h
  88. 77
      Source/HBIOS/ch376-native/source-doc/scsi-drv/class_scsi.c
  89. 196
      Source/HBIOS/ch376-native/source-doc/scsi-drv/class_scsi.h
  90. 30
      Source/HBIOS/ch376-native/source-doc/scsi-drv/scsi-init.c
  91. 123
      Source/HBIOS/ch376-native/source-doc/scsi-drv/scsi_driver.c
  92. 14
      Source/HBIOS/ch376-native/source-doc/scsi-drv/scsi_driver.h
  93. 179
      Source/HBIOS/ch376-native/source-doc/ufi-drv/class_ufi.c
  94. 186
      Source/HBIOS/ch376-native/source-doc/ufi-drv/class_ufi.h
  95. 29
      Source/HBIOS/ch376-native/source-doc/ufi-drv/ufi-init.c
  96. 85
      Source/HBIOS/ch376-native/source-doc/ufi-drv/ufi_driver.c
  97. 11
      Source/HBIOS/ch376-native/source-doc/ufi-drv/ufi_driver.h
  98. 69
      Source/HBIOS/ch376-native/source-doc/ufi-drv/usb_cbi.c
  99. 14
      Source/HBIOS/ch376-native/source-doc/ufi-drv/usb_cbi.h
  100. 11
      Source/HBIOS/ch376-native/ufi-drv.s

3
.github/workflows/commit.yml

@ -26,7 +26,8 @@ jobs:
run: |
export TZ='America/Los_Angeles'
sudo apt-get install srecord
make distlog
make transpile-c-code
make distlog --trace
rm -rf .git*
- name: List Output

3
.github/workflows/release.yml

@ -19,7 +19,8 @@ jobs:
export TZ='America/Los_Angeles'
sudo apt-get install libncurses-dev
sudo apt-get install srecord
make distlog
make transpile-c-code
make distlog --trace
rm -rf .git*
- name: Create Package Archive

18
.gitignore

@ -114,20 +114,24 @@ Source/ZPM3/genbnk.dat
Source/ZSDOS/zsdos.err
# Lets explicit list all generate untracked binary files
Binary/*.upd
Binary/Apps/bbcbasic.txt
Binary/Apps/copysl.doc
Binary/Apps/copysl.doc
Binary/Apps/fdu.doc
Binary/Apps/fdu.doc
Binary/Apps/Tunes/bgm.vgm
Binary/Apps/Tunes/ending.vgm
Binary/Apps/Tunes/inchina.vgm
Binary/Apps/Tunes/shirakaw.vgm
Binary/Apps/Tunes/startdem.vgm
Binary/Apps/Tunes/wonder01.vgm
Binary/Apps/copysl.doc
Binary/Apps/fdu.doc
Binary/Apps/zmconfig.ovr
Binary/Apps/zminit.ovr
Binary/Apps/zmp.doc
Binary/Apps/zmp.hlp
Binary/Apps/zmp.cfg
Binary/Apps/zmp.doc
Binary/Apps/zmp.fon
Binary/Apps/zmp.hlp
Binary/Apps/zmterm.ovr
Binary/Apps/zmxfer.ovr
Binary/CPM3/bdos3.spr
@ -146,13 +150,12 @@ Binary/CPNET/cpn12ser.lbr
Binary/CPNET/cpn3duo.lbr
Binary/CPNET/cpn3mt.lbr
Binary/CPNET/cpn3ser.lbr
Binary/*.upd
Binary/hd1k_prefix.dat
Binary/ZPM3/bnkbdos3.spr
Binary/ZPM3/bnkbios3.spr
Binary/ZPM3/gencpm.dat
Binary/ZPM3/resbdos3.spr
Binary/ZPM3/zinstal.zpm
Binary/hd1k_prefix.dat
Source/BPBIOS/def-ww.lib
Source/CPNET/cpn12duo.lbr
Source/CPNET/cpn12mt.lbr
@ -180,6 +183,8 @@ Source/Fonts/fontvgarcc.bin
Source/Fonts/fontvgarcu.asm
Source/HBIOS/*.upd
Source/HBIOS/build_env.cmd
Source/HBIOS/build_env.cmd
Source/HBIOS/hbios_env.sh
Source/HBIOS/hbios_env.sh
Source/HBIOS/netboot.mod
Source/Images/*.cat
@ -197,4 +202,3 @@ Source/ZPM3/setz3.com
Tools/unix/OpenSpin/build/
Tools/unix/zxcc/config.h
Tools/unix/zxcc/zxcc
Binary/Apps/bbcbasic.txt

36
.vscode/settings.json

@ -1,4 +1,38 @@
{
"z80-macroasm.format.enabled": true,
"z80-macroasm.format.baseIndent": 1,
"z80-macroasm.format.whitespaceAfterInstruction": "tab",
"z80-macroasm.format.uppercaseKeywords": true,
"z80-macroasm.format.spaceAfterArgument": true,
"z80-macroasm.format.hexaNumberStyle": "motorola",
"z80-macroasm.format.hexaNumberCase": true,
"files.trimTrailingWhitespace": false,
"files.eol": "\r\n"
"files.eol": "\r\n",
"files.associations": {
"*.inc": "z80-macroasm",
"*.asm": "z80-macroasm",
"*.180": "z80-macroasm",
"*.asm.m4": "z80-macroasm",
"*.inc.m4": "z80-macroasm",
"*.mac": "z80-macroasm",
"*.asmpp": "z80-macroasm",
"*.zdsproj": "xml",
"*.Z80": "z80-macroasm",
"ch376.h": "c",
"protocol.h": "c",
"usb_state.h": "c",
"functional": "c",
"class_scsi.h": "c",
"z80.h": "c",
"dev_transfers.h": "c",
"usb-base-drv.h": "c",
"critical-section.h": "c",
"enumerate.h": "c",
"ch376inc.h": "c",
"enumerate_storage.h": "c",
"work-area.h": "c",
"hbios-driver-storage.h": "c",
"class_hid_keyboard.h": "c",
"print.h": "c"
}
}

12
Dockerfile

@ -1,4 +1,4 @@
FROM ubuntu:jammy-20240111 as basebuilder
FROM ubuntu:jammy-20240111 AS basebuilder
# This docker file can be used to build a tool chain docker image for building RomWBW images.
@ -10,7 +10,7 @@ FROM ubuntu:jammy-20240111 as basebuilder
# After you have built the above image (called romwbw-chain), you can use it to compile and build the RomWBW images
# as per the standard make scripts within RomWBW.
# Start a new terminal, cd to where you have clone RomWBW, and then run this command:
# docker run --rm -v ${PWD}:/src/ --privileged=true -u $(id -u ${USER}):$(id -g ${USER}) -it romwbw-chain:latest
# docker run --rm -v ${PWD}:/src/ --privileged=true -u $(id -u ${USER}):$(id -g ${USER}) -it romwbw-chain
# you can now compile and build the required images:
@ -21,13 +21,11 @@ FROM ubuntu:jammy-20240111 as basebuilder
# when finish, type 'exit' to return to back to your standard terminal session
LABEL Maintainer="Dean Netherton" \
Description="spike to use clang for ez80 target"
Description="RomWBW builder platform"
ENV DEBIAN_FRONTEND=noninteractive
RUN dpkg --add-architecture i386
RUN sed -i 's/http:\/\/archive\.ubuntu\.com\/ubuntu/http:\/\/au.archive.ubuntu.com\/ubuntu/g' /etc/apt/sources.list
RUN apt update -y
RUN apt dist-upgrade -y
RUN apt install -y --no-install-recommends cmake lzip ca-certificates mtools build-essential dos2unix libboost-all-dev texinfo texi2html libxml2-dev subversion bison flex zlib1g-dev m4 git wget dosfstools curl
@ -35,10 +33,10 @@ RUN apt install -y --no-install-recommends cmake lzip ca-certificates mtools bui
RUN mkdir work
WORKDIR /work
FROM basebuilder as main
FROM basebuilder AS main
LABEL Maintainer="Dean Netherton" \
Description="spike to build RomWBW"
Description="RomWBW builder platform"
RUN mkdir /src
WORKDIR /src/

7
Makefile

@ -1,7 +1,7 @@
.PHONY: tools source clean clobber diff dist
.ONESHELL:
.SHELLFLAGS = -cex
.SHELLFLAGS = -ce
all: tools source
@ -22,6 +22,11 @@ clobber: clean
diff:
$(MAKE) --directory Source diff
# Convert c code to assembly code
transpile-c-code:
@cd Source/HBIOS/ch376-native
$(MAKE) -j
dist:
$(MAKE) ROM_PLATFORM=dist
$(MAKE) --directory Tools clean

6
Source/CBIOS/cbios.asm

@ -3381,7 +3381,7 @@ DEVUNK .DB "UNK$"
RST 08 ; CALL HBIOS
LD A,D ; RESULTANT DEVICE TYPE
PUSH DE ; NEED TO SAVE UNIT NUMBER (IN E)
AND $0F ; ISOLATE DEVICE BITS
AND $1F ; ISOLATE DEVICE BITS
ADD A,A ; MULTIPLY BY TWO FOR WORD TABLE
LD HL,DEVTBL ; POINT TO START OF DEVICE NAME TABLE
CALL ADDHLA ; ADD A TO HL TO POINT TO TABLE ENTRY
@ -3407,6 +3407,7 @@ DEVTBL: ; DEVICE TABLE
.DW DEV04, DEV05, DEV06, DEV07
.DW DEV08, DEV09, DEV10, DEV11
.DW DEV12, DEV13, DEV14, DEV15
.DW DEV16
;
DEVUNK .DB "???$"
DEV00 .DB "MD$"
@ -3424,7 +3425,8 @@ DEV11 .DB "IMM$"
DEV12 .DB "SYQ$"
DEV13 .DB "CHUSB$"
DEV14 .DB "CHSD$"
DEV15 .EQU DEVUNK
DEV15 .DB "USB$"
DEV16 .EQU DEVUNK
;
#ENDIF
;

1
Source/Doc/SystemGuide.md

@ -1088,6 +1088,7 @@ below enumerates their values.
| DIODEV_SYQ | 0x0C | Syquest Sparq Disk | syq.asm |
| DIODEV_CHUSB | 0x0D | CH375/376 USB Disk | ch.asm |
| DIODEV_CHSD | 0x0E | CH375/376 SD Card | ch.asm |
| DIODEV_USB | 0x0F | CH376 Native USB Device | ch376.asm |
A fixed set of media types are defined. The currently defined media
types identifiers are listed below. Each driver will support one or

12
Source/HBIOS/Config/RCEZ80_std.asm

@ -55,7 +55,7 @@ CRTACT .SET FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
VDAEMU_SERKBD .SET $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
;;
TMSENABLE .SET FALSE ; TMS: ENABLE TMS9918 VIDEO/KBD DRIVER (TMS.ASM)
TMSMODE .SET TMSMODE_MSX ; TMS: DRIVER MODE: TMSMODE_[SCG|N8|MSX|MSXKBD|MSXMKY|MBC|COLECO|DUO|NABU]
TMSMODE .SET TMSMODE_MSX ; TMS: DRIVER MODE: TMSMODE_[SCG|N8|MSX|MSXKBD|MSXMKY|MBC|COLECO|DUO|NABU|MSXUKY]
TMS80COLS .SET FALSE ; TMS: ENABLE 80 COLUMN SCREEN, REQUIRES V9958
TMSTIMENABLE .SET FALSE ; TMS: ENABLE TIMER INTERRUPTS (REQUIRES IM1)
VRCENABLE .SET FALSE ; VRC: ENABLE VGARC VIDEO/KBD DRIVER (VRC.ASM)
@ -71,6 +71,14 @@ PPIDEENABLE .SET TRUE ; PPIDE: ENABLE PARALLEL PORT IDE DISK DRIVER (PPIDE.ASM)
SDENABLE .SET FALSE ; SD: ENABLE SD CARD DISK DRIVER (SD.ASM)
SDMODE .SET SDMODE_PIO ; SD: DRIVER MODE: SDMODE_[JUHA|N8|CSIO|PPI|UART|DSD|MK4|SC|MT|USR|PIO|Z80R|EPITX|FZ80|GM|EZ512|K80W]
SDCNT .SET 1 ; SD: NUMBER OF SD CARD DEVICES (1-2), FOR DSD/SC/MT ONLY
;
CHENABLE .SET TRUE ; CH: ENABLE CH375/376 USB SUPPORT
CHNATIVEENABLE .SET FALSE ; CH376: ENABLE CH376 NATIVE USB DRIVER
CHSCSIENABLE .SET FALSE ; CH376: ENABLE CH376 NATIVE MASS STORAGE DEVICES (REQUIRES CHNATIVEENABLE)
CHUFIENABLE .SET FALSE ; CH376: ENABLE CH376 NATIVE UFI FLOPPY DISK DEVICES (REQUIRES CHNATIVEENABLE)
CHNATIVEEZ80 .SET TRUE ; CH376: DELEGATE USB DRIVERS TO EZ80'S FIRMWARE
CHNATIVEFORCE .SET FALSE ; CH376: DISABLE AUTO-DETECTION OF MODULE - ASSUME ITS INSTALLED
;
PRPENABLE .SET FALSE ; PRP: ENABLE ECB PROPELLER IO BOARD DRIVER (PRP.ASM)
;
LPTENABLE .SET FALSE ; LPT: ENABLE CENTRONICS PRINTER DRIVER (LPT.ASM)
@ -82,3 +90,5 @@ SN76489ENABLE .SET FALSE ; SN: ENABLE SN76489 SOUND DRIVER
AY38910ENABLE .SET FALSE ; AY: ENABLE AY-3-8910 / YM2149 SOUND DRIVER
AYMODE .SET AYMODE_RCZ80 ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC|MBC|DUO|NABU]
AY_FORCE .SET FALSE ; AY: BYPASS AUTO-DETECT, FORCED PRESENT
EZ80TIMER .SET EZ80TMR_FIRM ; EZ80: TIMER TICK MODEL: EZ80TMR_[INT|FIRM]

6
Source/HBIOS/Config/RCZ80_std.asm

@ -72,7 +72,7 @@ ACIAENABLE .SET TRUE ; ACIA: ENABLE MOTOROLA 6850 ACIA DRIVER (ACIA.ASM)
SIOENABLE .SET TRUE ; SIO: ENABLE ZILOG SIO SERIAL DRIVER (SIO.ASM)
;
TMSENABLE .SET FALSE ; TMS: ENABLE TMS9918 VIDEO/KBD DRIVER (TMS.ASM)
TMSMODE .SET TMSMODE_MSX ; TMS: DRIVER MODE: TMSMODE_[SCG|N8|MSX|MSXKBD|MSXMKY|MBC|COLECO|DUO|NABU]
TMSMODE .SET TMSMODE_MSX ; TMS: DRIVER MODE: TMSMODE_[SCG|N8|MSX|MSXKBD|MSXMKY|MBC|COLECO|DUO|NABU|MSXUKY]
TMS80COLS .SET FALSE ; TMS: ENABLE 80 COLUMN SCREEN, REQUIRES V9958
TMSTIMENABLE .SET FALSE ; TMS: ENABLE TIMER INTERRUPTS (REQUIRES IM1)
VRCENABLE .SET FALSE ; VRC: ENABLE VGARC VIDEO/KBD DRIVER (VRC.ASM)
@ -92,6 +92,10 @@ SDMODE .SET SDMODE_PIO ; SD: DRIVER MODE: SDMODE_[JUHA|N8|CSIO|PPI|UART|DSD|MK4
SDCNT .SET 1 ; SD: NUMBER OF SD CARD DEVICES (1-2), FOR DSD/SC/MT ONLY
;
CHENABLE .SET TRUE ; CH: ENABLE CH375/376 USB SUPPORT
CHNATIVEENABLE .SET FALSE ; CH376: ENABLE CH376 NATIVE USB DRIVER
CHSCSIENABLE .SET FALSE ; CH376: ENABLE CH376 NATIVE MASS STORAGE DEVICES (REQUIRES CHNATIVEENABLE)
CHUFIENABLE .SET FALSE ; CH376: ENABLE CH376 NATIVE UFI FLOPPY DISK DEVICES (REQUIRES CHNATIVEENABLE)
CHNATIVEFORCE .SET FALSE ; CH376: DISABLE AUTO-DETECTION OF MODULE - ASSUME ITS INSTALLED
;
PRPENABLE .SET FALSE ; PRP: ENABLE ECB PROPELLER IO BOARD DRIVER (PRP.ASM)
;

2
Source/HBIOS/ansi.asm

@ -1554,4 +1554,4 @@ ANSI_DEVNUM .DB $FF ; TERMINAL DEVICE NUMBER
; E Light Cyan
; F Bright White
;=============================================================
;
;

10
Source/HBIOS/cfg_MASTER.asm

@ -503,3 +503,13 @@ EZ80_WSMD_TYP .EQU EZ80WSMD_CALC ; BUS WAIT STATE CONFIG: EZ80WSMD_[CALC|CYCLES]
EZ80_FLSH_WS .EQU 1 ; WAIT STATES FOR ON CHIP FLASH (0-7)
EZ80_FLSH_MIN_NS .EQU 60 ; MINIMUM WAIT STATES TO APPLY TO ON-CHIP FLASH, IF EZ80_WSMD_TYP = EZ80WSMD_CALC
EZ80_FWSMD_TYP .EQU EZ80WSMD_CALC ; WAIT STATE TYPE: EZ80RMMD_[CALC|WAIT] (CYCLES NOT ALLOWED)
CHNATIVEENABLE .EQU FALSE ; CH376: ENABLE CH376 NATIVE USB DRIVER
CHSCSIENABLE .EQU FALSE ; CH376: ENABLE CH376 NATIVE MASS STORAGE DEVICES (REQUIRES CHNATIVEENABLE)
CHUFIENABLE .EQU FALSE ; CH376: ENABLE CH376 NATIVE UFI FLOPPY DISK DEVICES (REQUIRES CHNATIVEENABLE)
CHNATIVEFORCE .EQU FALSE ; CH376: DISABLE AUTO-DETECTION OF MODULE - ASSUME ITS INSTALLED (REQUIRES CHNATIVEENABLE)
CHNATIVEEZ80 .EQU FALSE ; CH376: DELEGATE USB DRIVERS TO EZ80'S FIRMWARE
_CH376_DATA_PORT .EQU $FF88 ; CH376: DATA PORT
_CH376_COMMAND_PORT .EQU $FF89 ; CH376: COMMAND PORT
_USB_MODULE_LEDS .EQU $FF8A ; CH376: LED CONTROL PORT

8
Source/HBIOS/cfg_RCEZ80.asm

@ -250,7 +250,7 @@ VDUENABLE .SET FALSE ; VDU: ENABLE VDU VIDEO/KBD DRIVER (VDU.ASM)
CVDUENABLE .SET FALSE ; CVDU: ENABLE CVDU VIDEO/KBD DRIVER (CVDU.ASM)
GDCENABLE .SET FALSE ; GDC: ENABLE 7220 GDC VIDEO/KBD DRIVER (GDC.ASM)
TMSENABLE .SET FALSE ; TMS: ENABLE TMS9918 VIDEO/KBD DRIVER (TMS.ASM)
TMSMODE .SET TMSMODE_MSX ; TMS: DRIVER MODE: TMSMODE_[SCG|N8|MSX|MSXKBD|MSXMKY|MBC|COLECO|DUO|NABU]
TMSMODE .SET TMSMODE_MSX ; TMS: DRIVER MODE: TMSMODE_[SCG|N8|MSX|MSXKBD|MSXMKY|MBC|COLECO|DUO|NABU|MSXUKY]
TMS80COLS .SET FALSE ; TMS: ENABLE 80 COLUMN SCREEN, REQUIRES V9958
TMSTIMENABLE .SET FALSE ; TMS: ENABLE TIMER INTERRUPTS (REQUIRES IM1)
VGAENABLE .SET FALSE ; VGA: ENABLE VGA VIDEO/KBD DRIVER (VGA.ASM)
@ -406,6 +406,12 @@ EZ80TMR_NONE .SET 0 ; DO NOT USE ON-BOARD TIMER TO GENERATE TICKS
EZ80TMR_INT .SET 1 ; MARSHALL TIMER TICK INTERRUPTS FROM EZ80 TO HBIOS
EZ80TMR_FIRM .SET 2 ; DELEGATE SYS TIMER HBIOS CALL TO EZ80 FIRMWARE (TIMER TICK INTS DISABLED)
;
CHNATIVEENABLE .EQU FALSE ; CH376: ENABLE CH376 NATIVE USB DRIVER
CHSCSIENABLE .EQU FALSE ; CH376: ENABLE CH376 NATIVE MASS STORAGE DEVICES (REQUIRES CHNATIVEENABLE)
CHUFIENABLE .EQU FALSE ; CH376: ENABLE CH376 NATIVE UFI FLOPPY DISK DEVICES (REQUIRES CHNATIVEENABLE)
CHNATIVEFORCE .EQU FALSE ; CH376: DISABLE AUTO-DETECTION OF MODULE - ASSUME ITS INSTALLED (REQUIRES CHNATIVEENABLE)
CHNATIVEEZ80 .EQU TRUE ; CH376: DELEGATE USB DRIVERS TO EZ80'S FIRMWARE
EZ80UARTENABLE .SET TRUE ; EZ80 UART: ENABLE EZ80 UART0 DRIVER (EZ80UART.ASM)
EZ80RTCENABLE .SET TRUE ; EZ80 ON CHIP RTC
EZ80TIMER .SET EZ80TMR_FIRM ; EZ80: TIMER TICK MODEL: EZ80TMR_[INT|FIRM]

107
Source/HBIOS/ch376-native/Makefile

@ -0,0 +1,107 @@
SHELL := /bin/sh
SHELLFLAGS := -c -e -x
.ONESHELL:
MAKEFLAGS += --warn-undefined-variables
MAKEFLAGS += --no-builtin-rules
MAKEFLAGS += --always-make
ZCCRELFLAGS := -SO3 --max-allocs-per-node600000 --allow-unsafe-read --opt-code-speed
SRC := ./source-doc/
LIBS := -I./$(SRC)base-drv/
ZCCFLAGS := +z80 -vn -startup=0 -clib=sdcc_iy -compiler=sdcc -Cs--std=c23 -Cs--Werror $(ZCCRELFLAGS) $(LIBS)
ZCC_PATH := $(shell command -v zcc)
DOCKER_PATH := $(shell command -v docker)
ZCC := $(shell command -v zcc >/dev/null 2>&1 && echo zcc || echo 'docker run -w /host/${PWD} -v /:/host/ -u $(shell id -u ${USER}):$(shell id -g ${USER}) -t z88dk/z88dk:20250224 zcc')
ifeq ($(ZCC_PATH),)
ifeq ($(DOCKER_PATH),)
.DEFAULT_GOAL := skip
else
$(info ZCC is set to use Docker to run zcc)
endif
else
$(info ZCC is set to $(ZCC_PATH))
endif
ASSDIR := ./
all: $(ASSDIR)base-drv.s $(ASSDIR)scsi-drv.s $(ASSDIR)ufi-drv.s $(ASSDIR)keyboard.s
skip:
@echo "Unable to compile ch376 native to assembly. Install docker or z88dk."
exit 0
clean:
@rm -rf base-drv/*.s
rm -rf base-drv/*.asm
rm -rf scsi-drv/*.s
rm -rf scsi-drv/*.asm
rm -rf ufi-drv/*.s
rm -rf ufi-drv/*.asm
rm -rf keyboard/*.s
rm -rf keyboard/*.asm
rm ufi-drv.s
rm scsi-drv.s
rm base-drv.s
rm keyboard.s
.PRECIOUS: $(ASSDIR)%.c.asm
$(ASSDIR)%.c.s: $(ASSDIR)%.c.asm
@mkdir -p $(dir $@)
echo "Converting $< to $@"
${SRC}convert-for-uz80as.sh $< $@
define compile
@set -e
mkdir -p $(dir $@)
$(ZCC) $(ZCCFLAGS) --c-code-in-asm --assemble-only $< -o $@
echo "Compiled $(notdir $@) from $(notdir $<)"
endef
FIRMWARE_ALT = kyb-init ch376_init scsi-init ufi-init hbios-driver-storage
define build_subsystem =
$$(ASSDIR)$(1).s:
@echo "Creating $(1).s"
echo "; Generated File -- not to be modify directly" > $$(ASSDIR)$(1).s
for dep in $$^; do
dep=$$$${dep#*/}
dep=$$$${dep#*/}
filename=$$$${dep##*/}
basename=$$$${filename%.*.*}
if echo "$(FIRMWARE_ALT)" | grep -w -q "$$$${basename}"; then
if [ -n "$$$${dep%%*.asm}" ]; then
echo '#include "'ch376-native/$(1)/$$$${dep}'"' >> $$(ASSDIR)$(1).s
else
echo '#include "'ch376-native/source-doc/$(1)/$$$${dep}'"' >> $$(ASSDIR)$(1).s
fi
else
echo '#IF (!CHNATIVEEZ80)' >> $$(ASSDIR)$(1).s
if [ -n "$$$${dep%%*.asm}" ]; then
echo '#include "'ch376-native/$(1)/$$$${dep}'"' >> $$(ASSDIR)$(1).s
else
echo '#include "'ch376-native/source-doc/$(1)/$$$${dep}'"' >> $$(ASSDIR)$(1).s
fi
echo '#ENDIF' >> $$(ASSDIR)$(1).s
fi
done
$$(ASSDIR)$(1)/%.c.asm: $$(SRC)$(1)/%.c; $$(compile)
# $$(ASSDIR)$(1)/%.asm: $$(SRC)$(1)/%.asm; echo $$@ $$<
$(1)_C_FILES := $$(wildcard $$(SRC)$(1)/*.c)
$(1)_ASM_FILES := $$(wildcard $$(SRC)$(1)/*.asm)
$(1)_C_S_FILES := $$(patsubst ./source-doc/%, ./%, $$($(1)_C_FILES:.c=.c.s))
./$(1).s: $$($(1)_C_S_FILES) $$($(1)_ASM_FILES)
endef
$(eval $(call build_subsystem,base-drv))
$(eval $(call build_subsystem,scsi-drv))
$(eval $(call build_subsystem,keyboard))
$(eval $(call build_subsystem,ufi-drv))
.PHONY: format
format: SHELL:=/bin/bash
format:
@find \( -name "*.c" -o -name "*.h" \) -exec echo "formating {}" \; -exec clang-format -i {} \;

106
Source/HBIOS/ch376-native/base-drv.asm

@ -0,0 +1,106 @@
DELAY_FACTOR .EQU 640
CMD01_RD_USB_DATA0 .EQU $27 ; Read data block from current USB interrupt endpoint buffer or host endpoint receive buffer
; output: length, data stream
CMD10_WR_HOST_DATA .EQU $2C ; Write a data block to the send buffer of the USB host endpoint
; input: length, data stream
CH_CMD_RD_USB_DATA0 .EQU CMD01_RD_USB_DATA0
CH_CMD_WR_HOST_DATA .EQU CMD10_WR_HOST_DATA
; HL -> timeout
; returns
; L -> error code
; ---------------------------------
; Function ch_wait_int_and_get_status
; ---------------------------------
_ch_wait_int_and_get_status:
ld bc, DELAY_FACTOR
keep_waiting:
ld a, $FF
in a, (_CH376_COMMAND_PORT & 0xFF)
rlca
jp nc, _ch_get_status
dec bc
ld a, b
or c
jr nz, keep_waiting
dec hl
ld a, h
or l
jr nz, _ch_wait_int_and_get_status
call _delay
ld a, $FF
in a, (_CH376_COMMAND_PORT & $FF)
bit 4, a ; _CH376_COMMAND_PORT & PARA_STATE_BUSY
ld l, $0C ; USB_ERR_CH376_BLOCKED;
ret nz
ld l, $0D ; USB_ERR_CH376_TIMEOUT
ret
; uint8_t ch_read_data(uint8_t *buffer) __sdcccall(1);
_ch_read_data:
push hl
ld l, CH_CMD_RD_USB_DATA0
call _ch_command
pop hl
call _delay
ld bc, _CH376_DATA_PORT
in a, (c)
or a
ret z
ld e, a
push af
read_block:
call _delay
in a, (c)
ld (hl), a
inc hl
dec e
jr nz, read_block
pop af
ret
;const uint8_t *ch_write_data(const uint8_t *buffer, uint8_t length)
_ch_write_data:
ld l, CH_CMD_WR_HOST_DATA
call _ch_command
ld iy, 2
add iy, sp
ld l, (iy+0)
ld h, (iy+1)
ld a, (iy+2)
ld bc, _CH376_DATA_PORT
; _CH376_DATA_PORT = length;
call _delay
out (c), a
or a
ret z
ld d, a
write_block:
call _delay
ld a, (hl)
out (c), a
inc hl
dec d
jr nz, write_block
ret

39
Source/HBIOS/ch376-native/base-drv.s

@ -0,0 +1,39 @@
; Generated File -- not to be modify directly
#IF (!CHNATIVEEZ80)
#include "ch376-native/base-drv/ch376.c.s"
#ENDIF
#include "ch376-native/base-drv/ch376_init.c.s"
#IF (!CHNATIVEEZ80)
#include "ch376-native/base-drv/class_hub.c.s"
#ENDIF
#IF (!CHNATIVEEZ80)
#include "ch376-native/base-drv/critical-section.c.s"
#ENDIF
#IF (!CHNATIVEEZ80)
#include "ch376-native/base-drv/dev_transfers.c.s"
#ENDIF
#IF (!CHNATIVEEZ80)
#include "ch376-native/base-drv/enumerate.c.s"
#ENDIF
#IF (!CHNATIVEEZ80)
#include "ch376-native/base-drv/enumerate_hub.c.s"
#ENDIF
#IF (!CHNATIVEEZ80)
#include "ch376-native/base-drv/enumerate_storage.c.s"
#ENDIF
#include "ch376-native/base-drv/hbios-driver-storage.c.s"
#IF (!CHNATIVEEZ80)
#include "ch376-native/base-drv/protocol.c.s"
#ENDIF
#IF (!CHNATIVEEZ80)
#include "ch376-native/base-drv/transfers.c.s"
#ENDIF
#IF (!CHNATIVEEZ80)
#include "ch376-native/base-drv/usb-base-drv.c.s"
#ENDIF
#IF (!CHNATIVEEZ80)
#include "ch376-native/base-drv/usb_state.c.s"
#ENDIF
#IF (!CHNATIVEEZ80)
#include "ch376-native/base-drv/work-area.c.s"
#ENDIF

1
Source/HBIOS/ch376-native/base-drv/.gitignore

@ -0,0 +1 @@
*.asm

769
Source/HBIOS/ch376-native/base-drv/ch376.c.s

@ -0,0 +1,769 @@
;
; Generated from source-doc/base-drv/ch376.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/base-drv/ch376.c:6: void ch_command(const uint8_t command) __z88dk_fastcall {
; ---------------------------------
; Function ch_command
; ---------------------------------
_ch_command:
;source-doc/base-drv/ch376.c:8: while ((CH376_COMMAND_PORT & PARA_STATE_BUSY) && --counter != 0)
ld b,0xff
l_ch_command_00102:
ld a, +((_CH376_COMMAND_PORT) / 256)
in a, (((_CH376_COMMAND_PORT) & 0xFF))
bit 4, a
jr Z,l_ch_command_00104
djnz l_ch_command_00102
l_ch_command_00104:
;source-doc/base-drv/ch376.c:19: CH376_COMMAND_PORT = command;
ld a, l
ld bc,_CH376_COMMAND_PORT
out (c), a
;source-doc/base-drv/ch376.c:20: }
ret
;source-doc/base-drv/ch376.c:24: usb_error ch_long_wait_int_and_get_status(void) { return ch_wait_int_and_get_status(5000); }
; ---------------------------------
; Function ch_long_wait_int_and_get_status
; ---------------------------------
_ch_long_wait_int_and_get_statu:
ld hl,0x1388
jp _ch_wait_int_and_get_status
;source-doc/base-drv/ch376.c:26: usb_error ch_short_wait_int_and_get_statu(void) { return ch_wait_int_and_get_status(100); }
; ---------------------------------
; Function ch_short_wait_int_and_get_statu
; ---------------------------------
_ch_short_wait_int_and_get_stat:
ld hl,0x0064
jp _ch_wait_int_and_get_status
;source-doc/base-drv/ch376.c:28: usb_error ch_very_short_wait_int_and_get_(void) { return ch_wait_int_and_get_status(10); }
; ---------------------------------
; Function ch_very_short_wait_int_and_get_
; ---------------------------------
_ch_very_short_wait_int_and_get:
ld hl,0x000a
jp _ch_wait_int_and_get_status
;source-doc/base-drv/ch376.c:30: usb_error ch_get_status(void) {
; ---------------------------------
; Function ch_get_status
; ---------------------------------
_ch_get_status:
;source-doc/base-drv/ch376.c:31: ch_command(CH_CMD_GET_STATUS);
ld l,0x22
call _ch_command
;source-doc/base-drv/ch376.c:32: uint8_t ch_status = CH376_DATA_PORT;
ld a, +((_CH376_DATA_PORT) / 256)
in a, (((_CH376_DATA_PORT) & 0xFF))
;source-doc/base-drv/ch376.c:34: if (ch_status >= USB_FILERR_MIN && ch_status <= USB_FILERR_MAX)
cp 0x41
jr C,l_ch_get_status_00102
cp 0xb5
jr NC,l_ch_get_status_00102
;source-doc/base-drv/ch376.c:35: return ch_status;
ld l, a
jr l_ch_get_status_00126
l_ch_get_status_00102:
;source-doc/base-drv/ch376.c:37: if (ch_status == CH_CMD_RET_SUCCESS)
cp 0x51
jr NZ,l_ch_get_status_00105
;source-doc/base-drv/ch376.c:38: return USB_ERR_OK;
ld l,0x00
jr l_ch_get_status_00126
l_ch_get_status_00105:
;source-doc/base-drv/ch376.c:40: if (ch_status == CH_USB_INT_SUCCESS)
cp 0x14
jr NZ,l_ch_get_status_00107
;source-doc/base-drv/ch376.c:41: return USB_ERR_OK;
ld l,0x00
jr l_ch_get_status_00126
l_ch_get_status_00107:
;source-doc/base-drv/ch376.c:43: if (ch_status == CH_USB_INT_CONNECT)
cp 0x15
jr NZ,l_ch_get_status_00109
;source-doc/base-drv/ch376.c:44: return USB_INT_CONNECT;
ld l,0x81
jr l_ch_get_status_00126
l_ch_get_status_00109:
;source-doc/base-drv/ch376.c:46: if (ch_status == CH_USB_INT_DISK_READ)
cp 0x1d
jr NZ,l_ch_get_status_00111
;source-doc/base-drv/ch376.c:47: return USB_ERR_DISK_READ;
ld l,0x1d
jr l_ch_get_status_00126
l_ch_get_status_00111:
;source-doc/base-drv/ch376.c:49: if (ch_status == CH_USB_INT_DISK_WRITE)
cp 0x1e
jr NZ,l_ch_get_status_00113
;source-doc/base-drv/ch376.c:50: return USB_ERR_DISK_WRITE;
ld l,0x1e
jr l_ch_get_status_00126
l_ch_get_status_00113:
;source-doc/base-drv/ch376.c:52: if (ch_status == CH_USB_INT_DISCONNECT) {
cp 0x16
jr NZ,l_ch_get_status_00115
;source-doc/base-drv/ch376.c:53: ch_cmd_set_usb_mode(5);
ld l,0x05
call _ch_cmd_set_usb_mode
;source-doc/base-drv/ch376.c:54: return USB_ERR_NO_DEVICE;
ld l,0x05
jr l_ch_get_status_00126
l_ch_get_status_00115:
;source-doc/base-drv/ch376.c:57: if (ch_status == CH_USB_INT_BUF_OVER)
cp 0x17
jr NZ,l_ch_get_status_00117
;source-doc/base-drv/ch376.c:58: return USB_ERR_DATA_ERROR;
ld l,0x04
jr l_ch_get_status_00126
l_ch_get_status_00117:
;source-doc/base-drv/ch376.c:60: ch_status &= 0x2F;
and 0x2f
;source-doc/base-drv/ch376.c:62: if (ch_status == 0x2A)
cp 0x2a
jr NZ,l_ch_get_status_00119
;source-doc/base-drv/ch376.c:63: return USB_ERR_NAK;
ld l,0x01
jr l_ch_get_status_00126
l_ch_get_status_00119:
;source-doc/base-drv/ch376.c:65: if (ch_status == 0x2E)
cp 0x2e
jr NZ,l_ch_get_status_00121
;source-doc/base-drv/ch376.c:66: return USB_ERR_STALL;
ld l,0x02
jr l_ch_get_status_00126
l_ch_get_status_00121:
;source-doc/base-drv/ch376.c:68: ch_status &= 0x23;
and 0x23
;source-doc/base-drv/ch376.c:70: if (ch_status == 0x20)
cp 0x20
jr NZ,l_ch_get_status_00123
;source-doc/base-drv/ch376.c:71: return USB_ERR_TIMEOUT;
ld l,0x03
jr l_ch_get_status_00126
l_ch_get_status_00123:
;source-doc/base-drv/ch376.c:73: if (ch_status == 0x23)
sub 0x23
jr NZ,l_ch_get_status_00125
;source-doc/base-drv/ch376.c:74: return USB_TOKEN_OUT_OF_SYNC;
ld l,0x07
jr l_ch_get_status_00126
l_ch_get_status_00125:
;source-doc/base-drv/ch376.c:76: return USB_ERR_UNEXPECTED_STATUS_FROM_;
ld l,0x08
l_ch_get_status_00126:
;source-doc/base-drv/ch376.c:77: }
ret
;source-doc/base-drv/ch376.c:79: void ch_cmd_reset_all(void) { ch_command(CH_CMD_RESET_ALL); }
; ---------------------------------
; Function ch_cmd_reset_all
; ---------------------------------
_ch_cmd_reset_all:
ld l,0x05
jp _ch_command
;source-doc/base-drv/ch376.c:98: uint8_t ch_probe(void) {
; ---------------------------------
; Function ch_probe
; ---------------------------------
_ch_probe:
push ix
ld ix,0
add ix,sp
dec sp
;source-doc/base-drv/ch376.c:100: do {
ld (ix-1),0x05
l_ch_probe_00103:
;source-doc/base-drv/ch376.c:83: ch_command(CH_CMD_CHECK_EXIST);
ld l,0x06
call _ch_command
;source-doc/base-drv/ch376.c:84: CH376_DATA_PORT = (uint8_t)~0x55;
ld a,0xaa
ld bc,_CH376_DATA_PORT
out (c), a
;source-doc/base-drv/ch376.c:85: delay();
call _delay
;source-doc/base-drv/ch376.c:86: complement = CH376_DATA_PORT;
ld a, +((_CH376_DATA_PORT) / 256)
in a, (((_CH376_DATA_PORT) & 0xFF))
;source-doc/base-drv/ch376.c:87: return complement == 0x55;
sub 0x55
jr NZ,l_ch_probe_00102
;source-doc/base-drv/ch376.c:101: if (ch_cmd_check_exist())
;source-doc/base-drv/ch376.c:102: return true;
ld l,0x01
jr l_ch_probe_00107
l_ch_probe_00102:
;source-doc/base-drv/ch376.c:104: delay_medium();
call _delay_medium
;source-doc/base-drv/ch376.c:105: } while (--i != 0);
dec (ix-1)
jr NZ,l_ch_probe_00103
;source-doc/base-drv/ch376.c:107: return false;
ld l,0x00
l_ch_probe_00107:
;source-doc/base-drv/ch376.c:108: }
inc sp
pop ix
ret
;source-doc/base-drv/ch376.c:110: usb_error ch_cmd_set_usb_mode(const uint8_t mode) __z88dk_fastcall {
; ---------------------------------
; Function ch_cmd_set_usb_mode
; ---------------------------------
_ch_cmd_set_usb_mode:
ld c, l
;source-doc/base-drv/ch376.c:111: uint8_t result = 0;
ld b,0x00
;source-doc/base-drv/ch376.c:113: CH376_COMMAND_PORT = CH_CMD_SET_USB_MODE;
ld a,0x15
push bc
ld bc,_CH376_COMMAND_PORT
out (c), a
;source-doc/base-drv/ch376.c:114: delay();
call _delay
pop bc
;source-doc/base-drv/ch376.c:115: CH376_DATA_PORT = mode;
ld a, c
push bc
ld bc,_CH376_DATA_PORT
out (c), a
;source-doc/base-drv/ch376.c:116: delay();
call _delay
pop bc
;source-doc/base-drv/ch376.c:120: while (result != CH_CMD_RET_SUCCESS && result != CH_CMD_RET_ABORT && --count != 0) {
ld c,0x7f
l_ch_cmd_set_usb_mode_00103:
ld a, b
sub 0x51
jr NZ,l_ch_cmd_set_usb_mode_00146
ld a,0x01
jr l_ch_cmd_set_usb_mode_00147
l_ch_cmd_set_usb_mode_00146:
xor a
l_ch_cmd_set_usb_mode_00147:
ld e,a
bit 0,a
jr NZ,l_ch_cmd_set_usb_mode_00105
ld a, b
sub 0x5f
jr Z,l_ch_cmd_set_usb_mode_00105
dec c
jr Z,l_ch_cmd_set_usb_mode_00105
;source-doc/base-drv/ch376.c:121: result = CH376_DATA_PORT;
ld a, +((_CH376_DATA_PORT) / 256)
in a, (((_CH376_DATA_PORT) & 0xFF))
ld b, a
;source-doc/base-drv/ch376.c:122: delay();
push bc
call _delay
pop bc
jr l_ch_cmd_set_usb_mode_00103
l_ch_cmd_set_usb_mode_00105:
;source-doc/base-drv/ch376.c:125: return (result == CH_CMD_RET_SUCCESS) ? USB_ERR_OK : USB_ERR_FAIL;
ld a, e
or a
jr Z,l_ch_cmd_set_usb_mode_00108
ld l,0x00
jr l_ch_cmd_set_usb_mode_00109
l_ch_cmd_set_usb_mode_00108:
ld l,0x0e
l_ch_cmd_set_usb_mode_00109:
;source-doc/base-drv/ch376.c:126: }
ret
;source-doc/base-drv/ch376.c:128: uint8_t ch_cmd_get_ic_version(void) {
; ---------------------------------
; Function ch_cmd_get_ic_version
; ---------------------------------
_ch_cmd_get_ic_version:
;source-doc/base-drv/ch376.c:129: ch_command(CH_CMD_GET_IC_VER);
ld l,0x01
call _ch_command
;source-doc/base-drv/ch376.c:130: return CH376_DATA_PORT & 0x1f;
ld a, +((_CH376_DATA_PORT) / 256)
in a, (((_CH376_DATA_PORT) & 0xFF))
and 0x1f
ld l, a
;source-doc/base-drv/ch376.c:131: }
ret
;source-doc/base-drv/ch376.c:133: void ch_issue_token(const uint8_t toggle_bit, const uint8_t endpoint, const ch376_pid pid) {
; ---------------------------------
; Function ch_issue_token
; ---------------------------------
_ch_issue_token:
push ix
ld ix,0
add ix,sp
;source-doc/base-drv/ch376.c:134: ch_command(CH_CMD_ISSUE_TKN_X);
ld l,0x4e
call _ch_command
;source-doc/base-drv/ch376.c:135: CH376_DATA_PORT = toggle_bit;
ld a,(ix+4)
ld bc,_CH376_DATA_PORT
out (c), a
;source-doc/base-drv/ch376.c:136: CH376_DATA_PORT = endpoint << 4 | pid;
ld a,(ix+5)
add a, a
add a, a
add a, a
add a, a
or (ix+6)
ld bc,_CH376_DATA_PORT
out (c), a
;source-doc/base-drv/ch376.c:137: }
pop ix
ret
;source-doc/base-drv/ch376.c:139: void ch_issue_token_in(const endpoint_param *const endpoint) __z88dk_fastcall {
; ---------------------------------
; Function ch_issue_token_in
; ---------------------------------
_ch_issue_token_in:
;source-doc/base-drv/ch376.c:140: ch_issue_token(endpoint->toggle ? 0x80 : 0x00, endpoint->number, CH_PID_IN);
ld e,l
ld d,h
ld a, (hl)
rrca
and 0x07
ld b, a
ex de, hl
ld a, (hl)
and 0x01
jr Z,l_ch_issue_token_in_00103
ld a,0x80
jr l_ch_issue_token_in_00104
l_ch_issue_token_in_00103:
xor a
l_ch_issue_token_in_00104:
ld h,0x09
ld l,b
push hl
push af
inc sp
call _ch_issue_token
pop af
inc sp
;source-doc/base-drv/ch376.c:141: }
ret
;source-doc/base-drv/ch376.c:143: void ch_issue_token_out(const endpoint_param *const endpoint) __z88dk_fastcall {
; ---------------------------------
; Function ch_issue_token_out
; ---------------------------------
_ch_issue_token_out:
;source-doc/base-drv/ch376.c:144: ch_issue_token(endpoint->toggle ? 0x40 : 0x00, endpoint->number, CH_PID_OUT);
ld e,l
ld d,h
ld a, (hl)
rrca
and 0x07
ld b, a
ex de, hl
ld a, (hl)
and 0x01
jr Z,l_ch_issue_token_out_00103
ld a,0x40
jr l_ch_issue_token_out_00104
l_ch_issue_token_out_00103:
xor a
l_ch_issue_token_out_00104:
ld h,0x01
ld l,b
push hl
push af
inc sp
call _ch_issue_token
pop af
inc sp
;source-doc/base-drv/ch376.c:145: }
ret
;source-doc/base-drv/ch376.c:147: void ch_issue_token_out_ep0(void) { ch_issue_token(0x40, 0, CH_PID_OUT); }
; ---------------------------------
; Function ch_issue_token_out_ep0
; ---------------------------------
_ch_issue_token_out_ep0:
ld a,0x01
push af
inc sp
xor a
ld d,a
ld e,0x40
push de
call _ch_issue_token
pop af
inc sp
ret
;source-doc/base-drv/ch376.c:149: void ch_issue_token_in_ep0(void) { ch_issue_token(0x80, 0, CH_PID_IN); }
; ---------------------------------
; Function ch_issue_token_in_ep0
; ---------------------------------
_ch_issue_token_in_ep0:
ld a,0x09
push af
inc sp
xor a
ld d,a
ld e,0x80
push de
call _ch_issue_token
pop af
inc sp
ret
;source-doc/base-drv/ch376.c:151: void ch_issue_token_setup(void) { ch_issue_token(0, 0, CH_PID_SETUP); }
; ---------------------------------
; Function ch_issue_token_setup
; ---------------------------------
_ch_issue_token_setup:
ld a,0x0d
push af
inc sp
xor a
push af
inc sp
xor a
push af
inc sp
call _ch_issue_token
pop af
inc sp
ret
;source-doc/base-drv/ch376.c:153: usb_error ch_data_in_transfer(uint8_t *buffer, int16_t buffer_size, endpoint_param *const endpoint) {
; ---------------------------------
; Function ch_data_in_transfer
; ---------------------------------
_ch_data_in_transfer:
push ix
ld ix,0
add ix,sp
;source-doc/base-drv/ch376.c:157: if (buffer_size == 0)
ld a,(ix+7)
or (ix+6)
jr NZ,l_ch_data_in_transfer_00102
;source-doc/base-drv/ch376.c:158: return USB_ERR_OK;
ld l,0x00
jp l_ch_data_in_transfer_00111
l_ch_data_in_transfer_00102:
;source-doc/base-drv/ch376.c:160: USB_MODULE_LEDS = 0x01;
ld a,0x01
ld bc,_USB_MODULE_LEDS
out (c), a
;source-doc/base-drv/ch376.c:161: do {
ld c,(ix+8)
ld b,(ix+9)
l_ch_data_in_transfer_00107:
;source-doc/base-drv/ch376.c:162: ch_issue_token_in(endpoint);
ld l,c
ld h,b
push hl
call _ch_issue_token_in
;source-doc/base-drv/ch376.c:164: result = ch_long_wait_int_and_get_status();
call _ch_long_wait_int_and_get_statu
ld a, l
pop bc
ld l, a
;source-doc/base-drv/ch376.c:165: CHECK(result);
or a
jr NZ,l_ch_data_in_transfer_00110
;source-doc/base-drv/ch376.c:167: endpoint->toggle = !endpoint->toggle;
ld e, c
ld d, b
ld l, e
ld h, d
ld a, (hl)
and 0x01
xor 0x01
and 0x01
ld l, a
ld a, (de)
and 0xfe
or l
ld (de), a
;source-doc/base-drv/ch376.c:169: count = ch_read_data(buffer);
push bc
ld l,(ix+4)
ld h,(ix+5)
call _ch_read_data
ld e, a
pop bc
;source-doc/base-drv/ch376.c:171: if (count == 0) {
ld a, e
;source-doc/base-drv/ch376.c:172: USB_MODULE_LEDS = 0x00;
or a
jr NZ,l_ch_data_in_transfer_00106
ld bc,_USB_MODULE_LEDS
out (c), a
;source-doc/base-drv/ch376.c:173: return USB_ERR_DATA_ERROR;
ld l,0x04
jr l_ch_data_in_transfer_00111
l_ch_data_in_transfer_00106:
;source-doc/base-drv/ch376.c:176: buffer += count;
ld a,(ix+4)
add a, e
ld (ix+4),a
jr NC,l_ch_data_in_transfer_00148
inc (ix+5)
l_ch_data_in_transfer_00148:
;source-doc/base-drv/ch376.c:177: buffer_size -= count;
ld d,0x00
ld a,(ix+6)
sub e
ld (ix+6),a
ld a,(ix+7)
sbc a, d
ld (ix+7),a
;source-doc/base-drv/ch376.c:178: } while (buffer_size > 0);
xor a
cp (ix+6)
sbc a,(ix+7)
jp PO, l_ch_data_in_transfer_00149
xor 0x80
l_ch_data_in_transfer_00149:
jp M, l_ch_data_in_transfer_00107
;source-doc/base-drv/ch376.c:180: USB_MODULE_LEDS = 0x00;
ld a,0x00
ld bc,_USB_MODULE_LEDS
out (c), a
;source-doc/base-drv/ch376.c:181: return USB_ERR_OK;
ld l,0x00
jr l_ch_data_in_transfer_00111
;source-doc/base-drv/ch376.c:183: done:
l_ch_data_in_transfer_00110:
;source-doc/base-drv/ch376.c:184: USB_MODULE_LEDS = 0x00;
ld a,0x00
ld bc,_USB_MODULE_LEDS
out (c), a
;source-doc/base-drv/ch376.c:185: return result;
l_ch_data_in_transfer_00111:
;source-doc/base-drv/ch376.c:186: }
pop ix
ret
;source-doc/base-drv/ch376.c:189: usb_error ch_data_in_transfer_n(uint8_t *const buffer, uint8_t *const buffer_size, endpoint_param *const endpoint) {
; ---------------------------------
; Function ch_data_in_transfer_n
; ---------------------------------
_ch_data_in_transfer_n:
push ix
ld ix,0
add ix,sp
;source-doc/base-drv/ch376.c:193: USB_MODULE_LEDS = 0x01;
ld a,0x01
ld bc,_USB_MODULE_LEDS
out (c), a
;source-doc/base-drv/ch376.c:195: ch_issue_token_in(endpoint);
ld l,(ix+8)
ld h,(ix+9)
call _ch_issue_token_in
;source-doc/base-drv/ch376.c:197: CHECK(ch_long_wait_int_and_get_status());
call _ch_long_wait_int_and_get_statu
ld a,l
or a
jr NZ,l_ch_data_in_transfer_n_00103
;source-doc/base-drv/ch376.c:199: endpoint->toggle = !endpoint->toggle;
ld l,(ix+8)
ld h,(ix+9)
ld a, (hl)
and 0x01
xor 0x01
and 0x01
ld c, a
ld a, (hl)
and 0xfe
or c
ld (hl), a
;source-doc/base-drv/ch376.c:201: count = ch_read_data(buffer);
ld l,(ix+4)
ld h,(ix+5)
call _ch_read_data
;source-doc/base-drv/ch376.c:203: *buffer_size = count;
ld c,(ix+6)
ld b,(ix+7)
ld (bc), a
;source-doc/base-drv/ch376.c:205: USB_MODULE_LEDS = 0x00;
ld a,0x00
ld bc,_USB_MODULE_LEDS
out (c), a
;source-doc/base-drv/ch376.c:207: return USB_ERR_OK;
ld l,0x00
jr l_ch_data_in_transfer_n_00104
;source-doc/base-drv/ch376.c:208: done:
l_ch_data_in_transfer_n_00103:
;source-doc/base-drv/ch376.c:209: USB_MODULE_LEDS = 0x00;
ld a,0x00
ld bc,_USB_MODULE_LEDS
out (c), a
;source-doc/base-drv/ch376.c:210: return result;
l_ch_data_in_transfer_n_00104:
;source-doc/base-drv/ch376.c:211: }
pop ix
ret
;source-doc/base-drv/ch376.c:213: usb_error ch_data_out_transfer(const uint8_t *buffer, int16_t buffer_length, endpoint_param *const endpoint) {
; ---------------------------------
; Function ch_data_out_transfer
; ---------------------------------
_ch_data_out_transfer:
push ix
ld ix,0
add ix,sp
dec sp
;source-doc/base-drv/ch376.c:216: const uint8_t max_packet_size = calc_max_packet_size(endpoint->max_packet_sizex);
ld c,(ix+8)
ld b,(ix+9)
ld e, c
ld d, b
inc de
ld a, (de)
ld (ix-1),a
;source-doc/base-drv/ch376.c:218: USB_MODULE_LEDS = 0x02;
ld a,0x02
push bc
ld bc,_USB_MODULE_LEDS
out (c), a
pop bc
;source-doc/base-drv/ch376.c:220: while (buffer_length > 0) {
l_ch_data_out_transfer_00103:
xor a
cp (ix+6)
sbc a,(ix+7)
jp PO, l_ch_data_out_transfer_00139
xor 0x80
l_ch_data_out_transfer_00139:
jp P, l_ch_data_out_transfer_00105
;source-doc/base-drv/ch376.c:221: const uint8_t size = max_packet_size < buffer_length ? max_packet_size : buffer_length;
ld d,(ix-1)
ld e,0x00
ld a, d
sub (ix+6)
ld a, e
sbc a,(ix+7)
jp PO, l_ch_data_out_transfer_00140
xor 0x80
l_ch_data_out_transfer_00140:
jp P, l_ch_data_out_transfer_00109
jr l_ch_data_out_transfer_00110
l_ch_data_out_transfer_00109:
ld d,(ix+6)
ld e,(ix+7)
l_ch_data_out_transfer_00110:
;source-doc/base-drv/ch376.c:222: buffer = ch_write_data(buffer, size);
push bc
push de
push de
inc sp
ld l,(ix+4)
ld h,(ix+5)
push hl
call _ch_write_data
pop af
inc sp
pop de
pop bc
ld (ix+4),l
ld (ix+5),h
;source-doc/base-drv/ch376.c:223: buffer_length -= size;
ld e,0x00
ld a,(ix+6)
sub d
ld (ix+6),a
ld a,(ix+7)
sbc a, e
ld (ix+7),a
;source-doc/base-drv/ch376.c:224: ch_issue_token_out(endpoint);
ld l,c
ld h,b
push hl
call _ch_issue_token_out
;source-doc/base-drv/ch376.c:226: CHECK(ch_long_wait_int_and_get_status());
call _ch_long_wait_int_and_get_statu
ld a, l
pop bc
ld l, a
or a
jr NZ,l_ch_data_out_transfer_00106
;source-doc/base-drv/ch376.c:228: endpoint->toggle = !endpoint->toggle;
ld e, c
ld d, b
ld l, e
ld h, d
ld a, (hl)
and 0x01
xor 0x01
and 0x01
ld l, a
ld a, (de)
and 0xfe
or l
ld (de), a
jr l_ch_data_out_transfer_00103
l_ch_data_out_transfer_00105:
;source-doc/base-drv/ch376.c:231: USB_MODULE_LEDS = 0x00;
ld a,0x00
ld bc,_USB_MODULE_LEDS
out (c), a
;source-doc/base-drv/ch376.c:232: return USB_ERR_OK;
ld l,0x00
jr l_ch_data_out_transfer_00107
;source-doc/base-drv/ch376.c:234: done:
l_ch_data_out_transfer_00106:
;source-doc/base-drv/ch376.c:235: USB_MODULE_LEDS = 0x00;
ld a,0x00
ld bc,_USB_MODULE_LEDS
out (c), a
;source-doc/base-drv/ch376.c:236: return result;
l_ch_data_out_transfer_00107:
;source-doc/base-drv/ch376.c:237: }
inc sp
pop ix
ret
;source-doc/base-drv/ch376.c:239: void ch_set_usb_address(const uint8_t device_address) __z88dk_fastcall {
; ---------------------------------
; Function ch_set_usb_address
; ---------------------------------
_ch_set_usb_address:
;source-doc/base-drv/ch376.c:240: ch_command(CH_CMD_SET_USB_ADDR);
push hl
ld l,0x13
call _ch_command
pop hl
;source-doc/base-drv/ch376.c:241: CH376_DATA_PORT = device_address;
ld a, l
ld bc,_CH376_DATA_PORT
out (c), a
;source-doc/base-drv/ch376.c:242: }
ret

293
Source/HBIOS/ch376-native/base-drv/ch376_init.c.s

@ -0,0 +1,293 @@
;
; Generated from source-doc/base-drv/ch376_init.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/base-drv/ch376_init.c:4: static uint16_t wait_for_state(const uint8_t loop_counter, uint8_t state, const uint8_t desired_state) __sdcccall(1) {
; ---------------------------------
; Function wait_for_state
; ---------------------------------
_wait_for_state:
push ix
ld ix,0
add ix,sp
dec sp
ld (ix-1),a
;source-doc/base-drv/ch376_init.c:5: uint16_t r = state;
ld c,l
ld e,l
;source-doc/base-drv/ch376_init.c:7: for (uint8_t i = 0; i < loop_counter; i++) {
ld d,0x00
ld b,d
l_wait_for_state_00108:
ld a, b
sub (ix-1)
jr NC,l_wait_for_state_00106
;source-doc/base-drv/ch376_init.c:8: if (state == desired_state)
ld a,(ix+4)
sub c
jr Z,l_wait_for_state_00106
;source-doc/base-drv/ch376_init.c:11: if (i & 1)
bit 0, b
jr Z,l_wait_for_state_00104
;source-doc/base-drv/ch376_init.c:12: print_string("\b $");
push bc
ld hl,ch376_init_str_0
call _print_string
pop bc
jr l_wait_for_state_00105
l_wait_for_state_00104:
;source-doc/base-drv/ch376_init.c:14: print_string("\b*$");
push bc
ld hl,ch376_init_str_1
call _print_string
pop bc
l_wait_for_state_00105:
;source-doc/base-drv/ch376_init.c:16: r = usb_init(state);
push bc
ld l, c
call _usb_init
ex de, hl
pop bc
;source-doc/base-drv/ch376_init.c:17: state = r & 255;
ld c, e
;source-doc/base-drv/ch376_init.c:7: for (uint8_t i = 0; i < loop_counter; i++) {
inc b
jr l_wait_for_state_00108
l_wait_for_state_00106:
;source-doc/base-drv/ch376_init.c:20: return r;
;source-doc/base-drv/ch376_init.c:21: }
inc sp
pop ix
pop hl
inc sp
jp (hl)
ch376_init_str_0:
DEFB 0x08
DEFM " $"
DEFB 0x00
ch376_init_str_1:
DEFB 0x08
DEFM "*$"
DEFB 0x00
;source-doc/base-drv/ch376_init.c:25: static void _chnative_init(bool forced) {
; ---------------------------------
; Function _chnative_init
; ---------------------------------
__chnative_init:
push ix
ld ix,0
add ix,sp
dec sp
;source-doc/base-drv/ch376_init.c:28: const uint8_t loop_counter = forced ? 40 : 5;
bit 0,(ix+4)
jr Z,l__chnative_init_00113
ld a,0x28
jr l__chnative_init_00114
l__chnative_init_00113:
ld a,0x05
l__chnative_init_00114:
ld (ix-1),a
;source-doc/base-drv/ch376_init.c:30: print_string("\r\nCH376: *$");
ld hl,ch376_init_str_2
call _print_string
;source-doc/base-drv/ch376_init.c:32: r = wait_for_state(loop_counter, state, 1);
ld a,0x01
push af
inc sp
ld l,0x00
ld a,(ix-1)
call _wait_for_state
;source-doc/base-drv/ch376_init.c:33: state = r & 255;
;source-doc/base-drv/ch376_init.c:35: print_string("\bPRESENT (VER $");
push de
ld hl,ch376_init_str_3
call _print_string
pop de
;source-doc/base-drv/ch376_init.c:37: r = usb_init(state);
ld l, e
call _usb_init
ex de, hl
;source-doc/base-drv/ch376_init.c:38: state = r & 255;
ld c, e
;source-doc/base-drv/ch376_init.c:39: if (state != 2) {
ld a, c
sub 0x02
jr Z,l__chnative_init_00102
;source-doc/base-drv/ch376_init.c:40: print_string("\rCH376: $");
ld hl,ch376_init_str_4
call _print_string
;source-doc/base-drv/ch376_init.c:41: print_string("VERSION FAILURE\r\n$");
ld hl,ch376_init_str_5
call _print_string
;source-doc/base-drv/ch376_init.c:42: return;
jr l__chnative_init_00111
l__chnative_init_00102:
;source-doc/base-drv/ch376_init.c:45: print_hex(r >> 8);
push bc
ld l, d
call _print_hex
;source-doc/base-drv/ch376_init.c:46: print_string(ch376_driver_version);
ld hl,_ch376_driver_version
call _print_string
;source-doc/base-drv/ch376_init.c:48: print_string("USB: *$");
ld hl,ch376_init_str_6
call _print_string
pop bc
;source-doc/base-drv/ch376_init.c:50: r = wait_for_state(loop_counter, state, 3);
ld a,0x03
push af
inc sp
ld l, c
ld a,(ix-1)
call _wait_for_state
;source-doc/base-drv/ch376_init.c:51: state = r & 255;
;source-doc/base-drv/ch376_init.c:53: if (state == 2) {
ld a, e
sub 0x02
jr NZ,l__chnative_init_00104
;source-doc/base-drv/ch376_init.c:54: print_string("\bDISCONNECTED$");
ld hl,ch376_init_str_7
call _print_string
;source-doc/base-drv/ch376_init.c:55: return;
jr l__chnative_init_00111
l__chnative_init_00104:
;source-doc/base-drv/ch376_init.c:58: print_string("\bCONNECTED$");
push de
ld hl,ch376_init_str_8
call _print_string
pop de
;source-doc/base-drv/ch376_init.c:61: r = usb_init(state);
ld l, e
call _usb_init
ex de, hl
;source-doc/base-drv/ch376_init.c:62: state = r & 255;
ld c, e
;source-doc/base-drv/ch376_init.c:64: for (uint8_t i = 0; i < loop_counter; i++) {
ld b,0x00
l__chnative_init_00109:
ld a, b
sub (ix-1)
jr NC,l__chnative_init_00111
;source-doc/base-drv/ch376_init.c:65: if (r >> 8 != 0)
ld a,0x00
or d
jr NZ,l__chnative_init_00111
;source-doc/base-drv/ch376_init.c:68: print_string(".$");
push bc
ld hl,ch376_init_str_9
call _print_string
pop bc
;source-doc/base-drv/ch376_init.c:69: r = usb_init(state);
push bc
ld l, c
call _usb_init
ex de, hl
pop bc
;source-doc/base-drv/ch376_init.c:70: state = r & 255;
ld c, e
;source-doc/base-drv/ch376_init.c:64: for (uint8_t i = 0; i < loop_counter; i++) {
inc b
jr l__chnative_init_00109
l__chnative_init_00111:
;source-doc/base-drv/ch376_init.c:72: }
inc sp
pop ix
ret
ch376_init_str_2:
DEFB 0x0d
DEFB 0x0a
DEFM "CH376: *$"
DEFB 0x00
ch376_init_str_3:
DEFB 0x08
DEFM "PRESENT (VER $"
DEFB 0x00
ch376_init_str_4:
DEFB 0x0d
DEFM "CH376: $"
DEFB 0x00
ch376_init_str_5:
DEFM "VERSION FAILURE"
DEFB 0x0d
DEFB 0x0a
DEFM "$"
DEFB 0x00
ch376_init_str_6:
DEFM "USB: *$"
DEFB 0x00
ch376_init_str_7:
DEFB 0x08
DEFM "DISCONNECTED$"
DEFB 0x00
ch376_init_str_8:
DEFB 0x08
DEFM "CONNECTED$"
DEFB 0x00
ch376_init_str_9:
DEFM ".$"
DEFB 0x00
;source-doc/base-drv/ch376_init.c:74: void chnative_init_force(void) { _chnative_init(true); }
; ---------------------------------
; Function chnative_init_force
; ---------------------------------
_chnative_init_force:
ld a,0x01
push af
inc sp
call __chnative_init
inc sp
ret
;source-doc/base-drv/ch376_init.c:76: void chnative_init(void) { _chnative_init(false); }
; ---------------------------------
; Function chnative_init
; ---------------------------------
_chnative_init:
xor a
push af
inc sp
call __chnative_init
inc sp
ret

85
Source/HBIOS/ch376-native/base-drv/class_hub.c.s

@ -0,0 +1,85 @@
;
; Generated from source-doc/base-drv/class_hub.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/base-drv/class_hub.c:7: usb_error hub_get_descriptor(const device_config_hub *const hub_config, hub_descriptor *const hub_description) __sdcccall(1) {
; ---------------------------------
; Function hub_get_descriptor
; ---------------------------------
_hub_get_descriptor:
;source-doc/base-drv/class_hub.c:8: return usb_control_transfer(&cmd_get_hub_descriptor, hub_description, hub_config->address, hub_config->max_packet_size);
ld a,l
ld c,h
inc hl
ld b, (hl)
ld l, a
ld h, c
ld a, (hl)
rlca
rlca
rlca
rlca
and 0x0f
ld c, a
push bc
push de
ld hl,_cmd_get_hub_descriptor
push hl
call _usb_control_transfer
pop af
pop af
pop af
ld a, l
;source-doc/base-drv/class_hub.c:9: }
ret
_cmd_get_hub_descriptor:
DEFB +0xa0
DEFB +0x06
DEFB +0x00
DEFB +0x29
DEFB +0x00
DEFB +0x00
DEFW +0x0008

67
Source/HBIOS/ch376-native/base-drv/critical-section.c.s

@ -0,0 +1,67 @@
;
; Generated from source-doc/base-drv/critical-section.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
_in_critical_usb_section:
DEFS 1
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/base-drv/critical-section.c:6: void critical_begin() { in_critical_usb_section++; }
; ---------------------------------
; Function critical_begin
; ---------------------------------
_critical_begin:
ld hl,_in_critical_usb_section
inc (hl)
ret
;source-doc/base-drv/critical-section.c:8: void critical_end() { in_critical_usb_section--; }
; ---------------------------------
; Function critical_end
; ---------------------------------
_critical_end:
ld hl,_in_critical_usb_section
dec (hl)
ret
_in_critical_usb_section:
DEFB +0x00

449
Source/HBIOS/ch376-native/base-drv/dev_transfers.c.s

@ -0,0 +1,449 @@
;
; Generated from source-doc/base-drv/dev_transfers.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/base-drv/dev_transfers.c:23: * See https://www.beyondlogic.org/usbnutshell/usb4.shtml for a description of the USB control transfer
; ---------------------------------
; Function usbdev_control_transfer
; ---------------------------------
_usbdev_control_transfer:
push ix
ld ix,0
add ix,sp
;source-doc/base-drv/dev_transfers.c:24: *
ld l,(ix+4)
ld h,(ix+5)
ld e,l
ld d,h
inc hl
ld b, (hl)
ex de, hl
ld a, (hl)
rlca
rlca
rlca
rlca
and 0x0f
ld e,(ix+8)
ld d,(ix+9)
ld c,a
push bc
push de
ld l,(ix+6)
ld h,(ix+7)
push hl
call _usb_control_transfer
pop af
pop af
pop af
;source-doc/base-drv/dev_transfers.c:25: * @param device the usb device
pop ix
ret
;source-doc/base-drv/dev_transfers.c:27: * @param buffer Pointer of data to send or receive into
; ---------------------------------
; Function usbdev_blk_out_trnsfer
; ---------------------------------
_usbdev_blk_out_trnsfer:
push ix
ld ix,0
add ix,sp
push af
;source-doc/base-drv/dev_transfers.c:30: usb_error usbdev_control_transfer(device_config *const device, const setup_packet *const cmd_packet, uint8_t *const buffer) {
ld c,(ix+4)
ld b,(ix+5)
ld e, c
ld d, b
inc de
inc de
inc de
;source-doc/base-drv/dev_transfers.c:32: }
pop hl
ld l,c
ld h,b
ld a,(hl)
push hl
rlca
rlca
rlca
rlca
and 0x0f
push bc
push de
push de
push af
inc sp
ld l,(ix+8)
ld h,(ix+9)
push hl
ld l,(ix+6)
ld h,(ix+7)
push hl
call _usb_data_out_transfer
pop af
pop af
pop af
inc sp
pop de
pop bc
;source-doc/base-drv/dev_transfers.c:34: usb_error usbdev_blk_out_trnsfer(device_config *const dev, const uint8_t *const buffer, const uint16_t buffer_size) {
ld a, l
sub 0x02
jr NZ,l_usbdev_blk_out_trnsfer_00102
;source-doc/base-drv/dev_transfers.c:35: usb_error result;
inc bc
ld a, (bc)
ld b, a
pop hl
ld a,(hl)
push hl
rlca
rlca
rlca
rlca
and 0x0f
ld c, a
ld l, e
ld h, d
ld a, (hl)
rrca
and 0x07
push de
push bc
inc sp
ld h, c
ld l,a
push hl
call _usbtrn_clear_endpoint_halt
pop af
inc sp
pop de
;source-doc/base-drv/dev_transfers.c:36:
ex de, hl
res 0, (hl)
;source-doc/base-drv/dev_transfers.c:37: endpoint_param *const endpoint = &dev->endpoints[ENDPOINT_BULK_OUT];
ld l,0x02
;source-doc/base-drv/dev_transfers.c:43: endpoint->toggle = 0;
l_usbdev_blk_out_trnsfer_00102:
;source-doc/base-drv/dev_transfers.c:44: return USB_ERR_STALL;
ld sp, ix
pop ix
ret
;source-doc/base-drv/dev_transfers.c:46:
; ---------------------------------
; Function usbdev_bulk_in_transfer
; ---------------------------------
_usbdev_bulk_in_transfer:
push ix
ld ix,0
add ix,sp
push af
;source-doc/base-drv/dev_transfers.c:49: done:
ld c,(ix+4)
ld b,(ix+5)
ld hl,0x0006
add hl, bc
;source-doc/base-drv/dev_transfers.c:51: }
pop de
ld e,c
ld d,b
ex de,hl
ld a,(hl)
push hl
rlca
rlca
rlca
rlca
and 0x0f
push bc
push de
push de
push af
inc sp
ld l,(ix+8)
ld h,(ix+9)
push hl
ld l,(ix+6)
ld h,(ix+7)
push hl
call _usb_data_in_transfer_n
pop af
pop af
pop af
inc sp
pop de
pop bc
;source-doc/base-drv/dev_transfers.c:53: usb_error usbdev_bulk_in_transfer(device_config *const dev, uint8_t *const buffer, uint8_t *const buffer_size) {
ld a, l
sub 0x02
jr NZ,l_usbdev_bulk_in_transfer_00102
;source-doc/base-drv/dev_transfers.c:54: usb_error result;
inc bc
ld a, (bc)
ld b, a
pop hl
ld a,(hl)
push hl
rlca
rlca
rlca
rlca
and 0x0f
ld c, a
ld l, e
ld h, d
ld a, (hl)
rrca
and 0x07
push de
push bc
inc sp
ld h, c
ld l,a
push hl
call _usbtrn_clear_endpoint_halt
pop af
inc sp
pop de
;source-doc/base-drv/dev_transfers.c:55:
ex de, hl
res 0, (hl)
;source-doc/base-drv/dev_transfers.c:56: endpoint_param *const endpoint = &dev->endpoints[ENDPOINT_BULK_IN];
ld l,0x02
;source-doc/base-drv/dev_transfers.c:61: usbtrn_clear_endpoint_halt(endpoint->number, dev->address, dev->max_packet_size);
l_usbdev_bulk_in_transfer_00102:
;source-doc/base-drv/dev_transfers.c:62: endpoint->toggle = 0;
ld sp, ix
pop ix
ret
;source-doc/base-drv/dev_transfers.c:64: }
; ---------------------------------
; Function usbdev_dat_in_trnsfer
; ---------------------------------
_usbdev_dat_in_trnsfer:
push ix
ld ix,0
add ix,sp
push af
;source-doc/base-drv/dev_transfers.c:70:
ld c,(ix+4)
ld b,(ix+5)
ld e, c
ld d, b
inc de
inc de
inc de
push de
ld a,(ix+10)
ld e, a
add a, a
add a, e
pop de
add a, e
ld e, a
ld a,0x00
adc a, d
ld d, a
;source-doc/base-drv/dev_transfers.c:72: uint8_t *const buffer,
pop hl
ld l,c
ld h,b
ld a,(hl)
push hl
rlca
rlca
rlca
rlca
and 0x0f
push bc
push de
push de
push af
inc sp
ld l,(ix+8)
ld h,(ix+9)
push hl
ld l,(ix+6)
ld h,(ix+7)
push hl
call _usb_data_in_transfer
pop af
pop af
pop af
inc sp
pop de
pop bc
;source-doc/base-drv/dev_transfers.c:74: const usb_endpoint_type endpoint_type) {
ld a, l
sub 0x02
jr NZ,l_usbdev_dat_in_trnsfer_00102
;source-doc/base-drv/dev_transfers.c:75: usb_error result;
inc bc
ld a, (bc)
ld b, a
pop hl
ld a,(hl)
push hl
rlca
rlca
rlca
rlca
and 0x0f
ld c, a
ld l, e
ld h, d
ld a, (hl)
rrca
and 0x07
push de
push bc
inc sp
ld h, c
ld l,a
push hl
call _usbtrn_clear_endpoint_halt
pop af
inc sp
pop de
;source-doc/base-drv/dev_transfers.c:76:
ex de, hl
res 0, (hl)
;source-doc/base-drv/dev_transfers.c:77: endpoint_param *const endpoint = &device->endpoints[endpoint_type];
ld l,0x02
;source-doc/base-drv/dev_transfers.c:82: usbtrn_clear_endpoint_halt(endpoint->number, device->address, device->max_packet_size);
l_usbdev_dat_in_trnsfer_00102:
;source-doc/base-drv/dev_transfers.c:83: endpoint->toggle = 0;
ld sp, ix
pop ix
ret
;source-doc/base-drv/dev_transfers.c:85: }
; ---------------------------------
; Function usbdev_dat_in_trnsfer_0
; ---------------------------------
_usbdev_dat_in_trnsfer_0:
push ix
ld ix,0
add ix,sp
push af
;source-doc/base-drv/dev_transfers.c:88: done:
ld c,(ix+4)
ld b,(ix+5)
ld e, c
ld d, b
inc de
inc de
inc de
;source-doc/base-drv/dev_transfers.c:90: }
pop hl
ld l,c
ld h,b
ld a,(hl)
push hl
rlca
rlca
rlca
rlca
and 0x0f
ld l,(ix+8)
ld h,0x00
push bc
push de
push de
push af
inc sp
push hl
ld l,(ix+6)
ld h,(ix+7)
push hl
call _usb_data_in_transfer
pop af
pop af
pop af
inc sp
pop de
pop bc
;source-doc/base-drv/dev_transfers.c:92: usb_error usbdev_dat_in_trnsfer_0(device_config *const device, uint8_t *const buffer, const uint8_t buffer_size) {
ld a, l
sub 0x02
jr NZ,l_usbdev_dat_in_trnsfer_0_00102
;source-doc/base-drv/dev_transfers.c:93: usb_error result;
inc bc
ld a, (bc)
ld b, a
pop hl
ld a,(hl)
push hl
rlca
rlca
rlca
rlca
and 0x0f
ld c, a
ld l, e
ld h, d
ld a, (hl)
rrca
and 0x07
push de
push bc
inc sp
ld h, c
ld l,a
push hl
call _usbtrn_clear_endpoint_halt
pop af
inc sp
pop de
;source-doc/base-drv/dev_transfers.c:94:
ex de, hl
res 0, (hl)
;source-doc/base-drv/dev_transfers.c:95: endpoint_param *const endpoint = &device->endpoints[0];
ld l,0x02
;source-doc/base-drv/dev_transfers.c:98:
l_usbdev_dat_in_trnsfer_0_00102:
;source-doc/base-drv/dev_transfers.c:99: if (result == USB_ERR_STALL) {
ld sp, ix
pop ix
ret

1085
Source/HBIOS/ch376-native/base-drv/enumerate.c.s

File diff suppressed because it is too large

457
Source/HBIOS/ch376-native/base-drv/enumerate_hub.c.s

@ -0,0 +1,457 @@
;
; Generated from source-doc/base-drv/enumerate_hub.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/base-drv/enumerate_hub.c:13: usb_error hub_set_feature(const device_config_hub *const hub_config, const uint8_t feature, const uint8_t index) {
; ---------------------------------
; Function hub_set_feature
; ---------------------------------
_hub_set_feature:
push ix
ld ix,0
add ix,sp
ld hl, -8
add hl, sp
ld sp, hl
;source-doc/base-drv/enumerate_hub.c:15: set_feature = cmd_set_feature;
ld hl,0
add hl, sp
ld e,l
ld d,h
push hl
ld bc,0x0008
ld hl,_cmd_set_feature
ldir
pop bc
;source-doc/base-drv/enumerate_hub.c:17: set_feature.bValue[0] = feature;
ld a,(ix+6)
ld (ix-6),a
;source-doc/base-drv/enumerate_hub.c:18: set_feature.bIndex[0] = index;
ld a,(ix+7)
ld (ix-4),a
;source-doc/base-drv/enumerate_hub.c:19: return usb_control_transfer(&set_feature, 0, hub_config->address, hub_config->max_packet_size);
ld e,(ix+5)
ld a,(ix+4)
ld l, a
ld h, e
inc hl
ld d, (hl)
ld l, a
ld h, e
ld a, (hl)
rlca
rlca
rlca
rlca
and 0x0f
ld e,a
push de
ld hl,0x0000
push hl
push bc
call _usb_control_transfer
;source-doc/base-drv/enumerate_hub.c:20: }
ld sp,ix
pop ix
ret
_cmd_set_feature:
DEFB +0x23
DEFB +0x03
DEFB +0x08
DEFB +0x00
DEFB +0x01
DEFB +0x00
DEFW +0x0000
_cmd_clear_feature:
DEFB +0x23
DEFB +0x01
DEFB +0x08
DEFB +0x00
DEFB +0x01
DEFB +0x00
DEFW +0x0000
_cmd_get_status_port:
DEFB +0xa3
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x01
DEFB +0x00
DEFW +0x0004
;source-doc/base-drv/enumerate_hub.c:22: usb_error hub_clear_feature(const device_config_hub *const hub_config, const uint8_t feature, const uint8_t index) {
; ---------------------------------
; Function hub_clear_feature
; ---------------------------------
_hub_clear_feature:
push ix
ld ix,0
add ix,sp
ld hl, -8
add hl, sp
ld sp, hl
;source-doc/base-drv/enumerate_hub.c:24: clear_feature = cmd_clear_feature;
ld hl,0
add hl, sp
ld e,l
ld d,h
push hl
ld bc,0x0008
ld hl,_cmd_clear_feature
ldir
pop bc
;source-doc/base-drv/enumerate_hub.c:26: clear_feature.bValue[0] = feature;
ld a,(ix+6)
ld (ix-6),a
;source-doc/base-drv/enumerate_hub.c:27: clear_feature.bIndex[0] = index;
ld a,(ix+7)
ld (ix-4),a
;source-doc/base-drv/enumerate_hub.c:28: return usb_control_transfer(&clear_feature, 0, hub_config->address, hub_config->max_packet_size);
ld e,(ix+5)
ld a,(ix+4)
ld l, a
ld h, e
inc hl
ld d, (hl)
ld l, a
ld h, e
ld a, (hl)
rlca
rlca
rlca
rlca
and 0x0f
ld e,a
push de
ld hl,0x0000
push hl
push bc
call _usb_control_transfer
;source-doc/base-drv/enumerate_hub.c:29: }
ld sp,ix
pop ix
ret
;source-doc/base-drv/enumerate_hub.c:31: usb_error hub_get_status_port(const device_config_hub *const hub_config, const uint8_t index, hub_port_status *const port_status) {
; ---------------------------------
; Function hub_get_status_port
; ---------------------------------
_hub_get_status_port:
push ix
ld ix,0
add ix,sp
ld hl, -8
add hl, sp
ld sp, hl
;source-doc/base-drv/enumerate_hub.c:33: get_status_port = cmd_get_status_port;
ld hl,0
add hl, sp
ld e,l
ld d,h
push hl
ld bc,0x0008
ld hl,_cmd_get_status_port
ldir
pop bc
;source-doc/base-drv/enumerate_hub.c:35: get_status_port.bIndex[0] = index;
ld a,(ix+6)
ld (ix-4),a
;source-doc/base-drv/enumerate_hub.c:36: return usb_control_transfer(&get_status_port, port_status, hub_config->address, hub_config->max_packet_size);
ld e,(ix+5)
ld a,(ix+4)
ld l, a
ld h, e
inc hl
ld d, (hl)
ld l, a
ld h, e
ld a, (hl)
rlca
rlca
rlca
rlca
and 0x0f
ld l,(ix+7)
ld h,(ix+8)
ld e,a
push de
push hl
push bc
call _usb_control_transfer
;source-doc/base-drv/enumerate_hub.c:37: }
ld sp,ix
pop ix
ret
;source-doc/base-drv/enumerate_hub.c:39: usb_error configure_usb_hub(_working *const working) __z88dk_fastcall {
; ---------------------------------
; Function configure_usb_hub
; ---------------------------------
_configure_usb_hub:
push ix
ld ix,0
add ix,sp
ld c, l
ld b, h
ld hl, -14
add hl, sp
ld sp, hl
;source-doc/base-drv/enumerate_hub.c:45: const device_config_hub *const hub_config = working->hub_config;
ld (ix-2),c
ld (ix-1),b
ld hl,25
add hl, bc
ld c, (hl)
inc hl
ld b, (hl)
;source-doc/base-drv/enumerate_hub.c:47: CHECK(hub_get_descriptor(hub_config, &hub_description));
push bc
ld hl,2
add hl, sp
ld e,c
ld d,b
ex de,hl
call _hub_get_descriptor
pop bc
or a
jp NZ, l_configure_usb_hub_00129
;source-doc/base-drv/enumerate_hub.c:49: uint8_t i = hub_description.bNbrPorts;
ld d,(ix-12)
;source-doc/base-drv/enumerate_hub.c:50: do {
l_configure_usb_hub_00126:
;source-doc/base-drv/enumerate_hub.c:51: CHECK(hub_clear_feature(hub_config, FEAT_PORT_POWER, i));
push bc
push de
ld e,0x08
push de
push bc
call _hub_clear_feature
pop af
pop af
ld a, l
pop de
pop bc
or a
jp NZ, l_configure_usb_hub_00129
;source-doc/base-drv/enumerate_hub.c:53: CHECK(hub_set_feature(hub_config, FEAT_PORT_POWER, i));
push bc
push de
ld e,0x08
push de
push bc
call _hub_set_feature
pop af
pop af
ld a, l
pop de
pop bc
or a
jp NZ, l_configure_usb_hub_00129
;source-doc/base-drv/enumerate_hub.c:55: hub_clear_feature(hub_config, FEAT_PORT_RESET, i);
push bc
push de
ld e,0x04
push de
push bc
call _hub_clear_feature
pop af
pop af
pop de
pop bc
;source-doc/base-drv/enumerate_hub.c:57: CHECK(hub_set_feature(hub_config, FEAT_PORT_RESET, i));
push bc
push de
ld e,0x04
push de
push bc
call _hub_set_feature
pop af
pop af
ld a, l
pop de
pop bc
or a
jp NZ, l_configure_usb_hub_00129
;source-doc/base-drv/enumerate_hub.c:59: CHECK(hub_get_status_port(hub_config, i, &port_status));
push bc
push de
ld hl,12
add hl, sp
push hl
push de
inc sp
push bc
call _hub_get_status_port
pop af
pop af
inc sp
ld a, l
pop de
pop bc
or a
jp NZ, l_configure_usb_hub_00129
;source-doc/base-drv/enumerate_hub.c:61: if (port_status.wPortStatus & PORT_STAT_CONNECTION) {
ld e,(ix-6)
bit 0, e
jr Z,l_configure_usb_hub_00124
;source-doc/base-drv/enumerate_hub.c:62: CHECK(hub_clear_feature(hub_config, HUB_FEATURE_PORT_CONNECTION_CHA, i));
push bc
push de
ld e,0x10
push de
push bc
call _hub_clear_feature
pop af
pop af
ld a, l
pop de
pop bc
or a
jr NZ,l_configure_usb_hub_00129
;source-doc/base-drv/enumerate_hub.c:64: CHECK(hub_clear_feature(hub_config, FEAT_PORT_ENABLE_CHANGE, i));
push bc
push de
ld e,0x11
push de
push bc
call _hub_clear_feature
pop af
pop af
ld a, l
pop de
pop bc
or a
jr NZ,l_configure_usb_hub_00129
;source-doc/base-drv/enumerate_hub.c:66: CHECK(hub_clear_feature(hub_config, FEAT_PORT_RESET_CHANGE, i));
push bc
push de
ld e,0x14
push de
push bc
call _hub_clear_feature
pop af
pop af
ld a, l
pop de
pop bc
or a
jr NZ,l_configure_usb_hub_00129
;source-doc/base-drv/enumerate_hub.c:67: delay_short();
push bc
push de
call _delay_short
pop de
pop bc
;source-doc/base-drv/enumerate_hub.c:69: CHECK(hub_get_status_port(hub_config, i, &port_status));
push bc
push de
ld hl,12
add hl, sp
push hl
push de
inc sp
push bc
call _hub_get_status_port
pop af
pop af
inc sp
ld a, l
pop de
pop bc
or a
jr NZ,l_configure_usb_hub_00129
;source-doc/base-drv/enumerate_hub.c:70: delay_short();
push bc
push de
call _delay_short
pop de
pop bc
;source-doc/base-drv/enumerate_hub.c:72: CHECK(read_all_configs(working->state));
ld l,(ix-2)
ld h,(ix-1)
ld a, (hl)
inc hl
ld h, (hl)
ld l, a
push bc
push de
push hl
call _read_all_configs
pop af
ld a, l
pop de
pop bc
or a
jr Z,l_configure_usb_hub_00127
jr l_configure_usb_hub_00129
l_configure_usb_hub_00124:
;source-doc/base-drv/enumerate_hub.c:75: CHECK(hub_clear_feature(hub_config, FEAT_PORT_POWER, i));
push bc
push de
ld e,0x08
push de
push bc
call _hub_clear_feature
pop af
pop af
ld a, l
pop de
pop bc
or a
jr NZ,l_configure_usb_hub_00129
l_configure_usb_hub_00127:
;source-doc/base-drv/enumerate_hub.c:77: } while (--i != 0);
dec d
jp NZ, l_configure_usb_hub_00126
;source-doc/base-drv/enumerate_hub.c:79: return USB_ERR_OK;
ld l,0x00
jr l_configure_usb_hub_00130
;source-doc/base-drv/enumerate_hub.c:80: done:
l_configure_usb_hub_00129:
;source-doc/base-drv/enumerate_hub.c:81: return result;
ld l, a
l_configure_usb_hub_00130:
;source-doc/base-drv/enumerate_hub.c:82: }
ld sp, ix
pop ix
ret

142
Source/HBIOS/ch376-native/base-drv/enumerate_storage.c.s

@ -0,0 +1,142 @@
;
; Generated from source-doc/base-drv/enumerate_storage.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/base-drv/enumerate_storage.c:5: void parse_endpoints(device_config_storage *const storage_dev, const endpoint_descriptor const *pEndpoint) {
; ---------------------------------
; Function parse_endpoints
; ---------------------------------
_parse_endpoints:
push ix
ld ix,0
add ix,sp
push af
;source-doc/base-drv/enumerate_storage.c:7: if (!(pEndpoint->bmAttributes & 0x02))
ld l,(ix+6)
ld h,(ix+7)
ld c,l
ld b,h
inc hl
inc hl
inc hl
ld a, (hl)
ld (ix-2),a
bit 1,a
;source-doc/base-drv/enumerate_storage.c:8: return;
jr Z,l_parse_endpoints_00108
;source-doc/base-drv/enumerate_storage.c:10: const uint8_t x = calc_max_packet_sizex(pEndpoint->wMaxPacketSize);
ld hl,4
add hl,bc
ld a, (hl)
ld (ix-1),a
;source-doc/base-drv/enumerate_storage.c:11: endpoint_param *const eps = storage_dev->endpoints;
ld e,(ix+4)
ld d,(ix+5)
inc de
inc de
inc de
;source-doc/base-drv/enumerate_storage.c:15: if (!(pEndpoint->bEndpointAddress & 0x80))
inc bc
inc bc
ld a, (bc)
ld c,a
and 0x80
ld b,0x00
;source-doc/base-drv/enumerate_storage.c:14: if (pEndpoint->bmAttributes & 0x01) { // 3 -> Interrupt
bit 0,(ix-2)
jr Z,l_parse_endpoints_00106
;source-doc/base-drv/enumerate_storage.c:15: if (!(pEndpoint->bEndpointAddress & 0x80))
or b
;source-doc/base-drv/enumerate_storage.c:16: return;
jr Z,l_parse_endpoints_00108
;source-doc/base-drv/enumerate_storage.c:18: ep = &eps[ENDPOINT_INTERRUPT_IN];
ld hl,0x0006
add hl, de
ex de, hl
jr l_parse_endpoints_00107
l_parse_endpoints_00106:
;source-doc/base-drv/enumerate_storage.c:21: ep = (pEndpoint->bEndpointAddress & 0x80) ? &eps[ENDPOINT_BULK_IN] : &eps[ENDPOINT_BULK_OUT];
or b
jr Z,l_parse_endpoints_00110
inc de
inc de
inc de
l_parse_endpoints_00110:
l_parse_endpoints_00107:
;source-doc/base-drv/enumerate_storage.c:24: ep->number = pEndpoint->bEndpointAddress & 0x07;
ld l, e
ld h, d
ld a, c
and 0x07
rlca
and 0x0e
ld c, a
ld a, (hl)
and 0xf1
or c
ld (hl), a
;source-doc/base-drv/enumerate_storage.c:25: ep->toggle = 0;
ld l, e
ld h, d
res 0, (hl)
;source-doc/base-drv/enumerate_storage.c:26: ep->max_packet_sizex = x;
inc de
ld a,(ix-1)
ld b,0x00
ld (de), a
inc de
ld a, b
and 0x03
ld l, a
ld a, (de)
and 0xfc
or l
ld (de), a
l_parse_endpoints_00108:
;source-doc/base-drv/enumerate_storage.c:27: }
ld sp, ix
pop ix
ret

97
Source/HBIOS/ch376-native/base-drv/hbios-driver-storage.c.s

@ -0,0 +1,97 @@
;
; Generated from source-doc/base-drv/hbios-driver-storage.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
_hbios_usb_storage_devices:
DEFS 12
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/base-drv/hbios-driver-storage.c:5: uint8_t find_storage_dev(void) {
; ---------------------------------
; Function find_storage_dev
; ---------------------------------
_find_storage_dev:
;source-doc/base-drv/hbios-driver-storage.c:6: for (uint8_t i = 0; i < MAX_NUMBER_OF_DEVICES; i++)
ld c,0x00
ld de,_hbios_usb_storage_devices+0
ld b,c
l_find_storage_dev_00105:
ld a, b
sub 0x06
jr NC,l_find_storage_dev_00103
;source-doc/base-drv/hbios-driver-storage.c:7: if (hbios_usb_storage_devices[i].drive_index == 0)
ld l, b
ld h,0x00
add hl, hl
add hl, de
ld a, (hl)
or a
jr NZ,l_find_storage_dev_00106
;source-doc/base-drv/hbios-driver-storage.c:8: return i;
ld l, c
jr l_find_storage_dev_00107
l_find_storage_dev_00106:
;source-doc/base-drv/hbios-driver-storage.c:6: for (uint8_t i = 0; i < MAX_NUMBER_OF_DEVICES; i++)
inc b
ld c, b
jr l_find_storage_dev_00105
l_find_storage_dev_00103:
;source-doc/base-drv/hbios-driver-storage.c:10: return -1;
ld l,0xff
l_find_storage_dev_00107:
;source-doc/base-drv/hbios-driver-storage.c:11: }
ret
_hbios_usb_storage_devices:
DEFB +0x00
DEFB +0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00

482
Source/HBIOS/ch376-native/base-drv/protocol.c.s

@ -0,0 +1,482 @@
;
; Generated from source-doc/base-drv/protocol.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/base-drv/protocol.c:25: *
; ---------------------------------
; Function usbtrn_get_descriptor
; ---------------------------------
_usbtrn_get_descriptor:
push ix
ld ix,0
add ix,sp
ld hl, -8
add hl, sp
ld sp, hl
;source-doc/base-drv/protocol.c:28: */
ld hl,0
add hl, sp
ex de, hl
ld bc,0x0008
ld hl,_cmd_get_device_descriptor
ldir
;source-doc/base-drv/protocol.c:29: usb_error usbtrn_get_descriptor(device_descriptor *const buffer) {
ld (ix-2),0x08
xor a
ld (ix-1),a
;source-doc/base-drv/protocol.c:31: setup_packet cmd;
ld c,(ix+4)
ld b,(ix+5)
push bc
push bc
ld e,c
ld d,b
ld a,0x08
push af
inc sp
xor a
push af
inc sp
push de
ld hl,8
add hl, sp
push hl
call _usb_control_transfer
pop af
pop af
pop af
ld a, l
pop de
pop bc
ld l, a
;source-doc/base-drv/protocol.c:33: cmd.wLength = 8;
or a
jr NZ,l_usbtrn_get_descriptor_00103
;source-doc/base-drv/protocol.c:35: result = usb_control_transfer(&cmd, (uint8_t *)buffer, 0, 8);
push de
push bc
ld hl,4
add hl, sp
ex de, hl
ld bc,0x0008
ld hl,_cmd_get_device_descriptor
ldir
pop bc
pop de
;source-doc/base-drv/protocol.c:36:
ld (ix-2),0x12
xor a
ld (ix-1),a
;source-doc/base-drv/protocol.c:37: CHECK(result);
ld hl,7
add hl, bc
ld a, (hl)
push af
inc sp
xor a
push af
inc sp
push de
ld hl,4
add hl, sp
push hl
call _usb_control_transfer
pop af
pop af
pop af
;source-doc/base-drv/protocol.c:41: result = usb_control_transfer(&cmd, (uint8_t *)buffer, 0, buffer->bMaxPacketSize0);
l_usbtrn_get_descriptor_00103:
;source-doc/base-drv/protocol.c:42:
;source-doc/base-drv/protocol.c:43: RETURN_CHECK(result);
ld sp, ix
pop ix
ret
_cmd_get_device_descriptor:
DEFB +0x80
DEFB +0x06
DEFB +0x00
DEFB +0x01
DEFB +0x00
DEFB +0x00
DEFW +0x0008
;source-doc/base-drv/protocol.c:47: }
; ---------------------------------
; Function usbtrn_get_descriptor2
; ---------------------------------
_usbtrn_get_descriptor2:
push ix
ld ix,0
add ix,sp
ld hl, -8
add hl, sp
ld sp, hl
;source-doc/base-drv/protocol.c:51: *
ld hl,0
add hl, sp
ex de, hl
ld bc,0x0008
ld hl,_cmd_get_device_descriptor
ldir
;source-doc/base-drv/protocol.c:52: * @param buffer the buffer to store the device descriptor in
ld (ix-2),0x08
xor a
ld (ix-1),a
;source-doc/base-drv/protocol.c:54: */
ld c,(ix+4)
ld b,(ix+5)
push bc
push bc
ld e,c
ld d,b
ld h,0x08
ld l,(ix+6)
push hl
push de
ld hl,8
add hl, sp
push hl
call _usb_control_transfer
pop af
pop af
pop af
ld a, l
pop de
pop bc
ld l, a
;source-doc/base-drv/protocol.c:56: usb_error result;
or a
jr NZ,l_usbtrn_get_descriptor2_00103
;source-doc/base-drv/protocol.c:58: setup_packet cmd;
push de
push bc
ld hl,4
add hl, sp
ex de, hl
ld bc,0x0008
ld hl,_cmd_get_device_descriptor
ldir
pop bc
pop de
;source-doc/base-drv/protocol.c:59: cmd = cmd_get_device_descriptor;
ld (ix-2),0x12
xor a
ld (ix-1),a
;source-doc/base-drv/protocol.c:60: cmd.wLength = 8;
ld hl,7
add hl, bc
ld h,(hl)
ld l,(ix+6)
push hl
push de
ld hl,4
add hl, sp
push hl
call _usb_control_transfer
pop af
pop af
pop af
;source-doc/base-drv/protocol.c:61:
l_usbtrn_get_descriptor2_00103:
;source-doc/base-drv/protocol.c:62: result = usb_control_transfer(&cmd, (uint8_t *)buffer, device_address, 8);
;source-doc/base-drv/protocol.c:63:
ld sp, ix
pop ix
ret
;source-doc/base-drv/protocol.c:69: done:
; ---------------------------------
; Function usbtrn_set_address
; ---------------------------------
_usbtrn_set_address:
push ix
ld ix,0
add ix,sp
push af
push af
push af
push af
ld c, l
;source-doc/base-drv/protocol.c:71: }
push bc
ld hl,2
add hl, sp
ex de, hl
ld bc,0x0008
ld hl,_cmd_set_device_address
ldir
pop bc
;source-doc/base-drv/protocol.c:72:
ld (ix-6),c
;source-doc/base-drv/protocol.c:74:
xor a
push af
inc sp
xor a
push af
inc sp
ld hl,0x0000
push hl
ld hl,4
add hl, sp
push hl
call _usb_control_transfer
;source-doc/base-drv/protocol.c:75: /**
ld sp,ix
pop ix
ret
_cmd_set_device_address:
DEFB +0x00
DEFB +0x05
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFW +0x0000
;source-doc/base-drv/protocol.c:81: usb_error usbtrn_set_address(const uint8_t device_address) __z88dk_fastcall {
; ---------------------------------
; Function usbtrn_set_configuration
; ---------------------------------
_usbtrn_set_configuration:
push ix
ld ix,0
add ix,sp
ld hl, -8
add hl, sp
ld sp, hl
;source-doc/base-drv/protocol.c:83: cmd = cmd_set_device_address;
ld hl,0
add hl, sp
ld e,l
ld d,h
push hl
ld bc,0x0008
ld hl,_cmd_set_configuration
ldir
pop bc
;source-doc/base-drv/protocol.c:84: cmd.bValue[0] = device_address;
ld a,(ix+6)
ld (ix-6),a
;source-doc/base-drv/protocol.c:86: return usb_control_transfer(&cmd, 0, 0, 0);
ld h,(ix+5)
ld l,(ix+4)
push hl
ld hl,0x0000
push hl
push bc
call _usb_control_transfer
;source-doc/base-drv/protocol.c:87: }
ld sp,ix
pop ix
ret
_cmd_set_configuration:
DEFB +0x00
DEFB +0x09
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFW +0x0000
;source-doc/base-drv/protocol.c:93: *
; ---------------------------------
; Function usbtrn_get_config_descriptor
; ---------------------------------
_usbtrn_get_config_descriptor:
push ix
ld ix,0
add ix,sp
ld hl, -8
add hl, sp
ld sp, hl
;source-doc/base-drv/protocol.c:99: cmd = cmd_set_configuration;
ld hl,0
add hl, sp
ld e,l
ld d,h
push hl
ld bc,0x0008
ld hl,_cmd_get_config_descriptor
ldir
pop bc
;source-doc/base-drv/protocol.c:100: cmd.bValue[0] = configuration;
ld a,(ix+6)
ld (ix-6),a
;source-doc/base-drv/protocol.c:101:
ld hl,0x0006
add hl, bc
ld e,(ix+7)
xor a
ld (hl), e
inc hl
ld (hl), a
;source-doc/base-drv/protocol.c:103: }
ld e,(ix+4)
ld d,(ix+5)
ld h,(ix+9)
ld l,(ix+8)
push hl
push de
push bc
call _usb_control_transfer
;source-doc/base-drv/protocol.c:104:
ld sp,ix
pop ix
ret
_cmd_get_config_descriptor:
DEFB +0x80
DEFB +0x06
DEFB +0x00
DEFB +0x02
DEFB +0x00
DEFB +0x00
DEFW +0x0000
;source-doc/base-drv/protocol.c:106:
; ---------------------------------
; Function usbtrn_gfull_cfg_desc
; ---------------------------------
_usbtrn_gfull_cfg_desc:
push ix
ld ix,0
add ix,sp
;source-doc/base-drv/protocol.c:114: * @param max_packet_size the max packet size for control transfers (endpoint 0)
ld c,(ix+8)
ld b,(ix+9)
push bc
ld a,(ix+6)
push af
inc sp
ld d,(ix+5)
ld e,0x09
push de
ld a,(ix+4)
push af
inc sp
push bc
call _usbtrn_get_config_descriptor
pop af
pop af
pop af
pop bc
ld a, l
or a
jr NZ,l_usbtrn_gfull_cfg_desc_00107
;source-doc/base-drv/protocol.c:116: */
ld l,(ix+8)
ld h,(ix+9)
inc hl
inc hl
ld d, (hl)
;source-doc/base-drv/protocol.c:117: usb_error usbtrn_get_config_descriptor(config_descriptor *const buffer,
ld a,(ix+7)
sub d
jr NC,l_usbtrn_gfull_cfg_desc_00104
;source-doc/base-drv/protocol.c:118: const uint8_t config_index,
ld d,(ix+7)
l_usbtrn_gfull_cfg_desc_00104:
;source-doc/base-drv/protocol.c:120: const uint8_t device_address,
ld h,(ix+6)
ld l,(ix+5)
push hl
ld e,(ix+4)
push de
push bc
call _usbtrn_get_config_descriptor
pop af
pop af
pop af
ld a, l
;source-doc/base-drv/protocol.c:122: setup_packet cmd;
or a
jr NZ,l_usbtrn_gfull_cfg_desc_00107
ld l,a
;source-doc/base-drv/protocol.c:123: cmd = cmd_get_config_descriptor;
;source-doc/base-drv/protocol.c:124: cmd.bValue[0] = config_index;
l_usbtrn_gfull_cfg_desc_00107:
;source-doc/base-drv/protocol.c:125: cmd.wLength = (uint16_t)buffer_size;
pop ix
ret
;source-doc/base-drv/protocol.c:129:
; ---------------------------------
; Function usbtrn_clear_endpoint_halt
; ---------------------------------
_usbtrn_clear_endpoint_halt:
push ix
ld ix,0
add ix,sp
ld hl, -8
add hl, sp
ld sp, hl
;source-doc/base-drv/protocol.c:131: const uint8_t device_address,
ld hl,0
add hl, sp
ld e,l
ld d,h
push hl
ld bc,0x0008
ld hl,_usb_cmd_clear_endpoint_halt
ldir
pop bc
;source-doc/base-drv/protocol.c:132: const uint8_t max_packet_size,
ld a,(ix+4)
ld (ix-4),a
;source-doc/base-drv/protocol.c:134: uint8_t *const buffer) {
ld h,(ix+6)
ld l,(ix+5)
push hl
ld hl,0x0000
push hl
push bc
call _usb_control_transfer
;source-doc/base-drv/protocol.c:135: usb_error result;
ld sp,ix
pop ix
ret
_usb_cmd_clear_endpoint_halt:
DEFB +0x02
DEFB +0x01
DEFB +0x00
DEFB +0x00
DEFB +0xff
DEFB +0x00
DEFW +0x0000

311
Source/HBIOS/ch376-native/base-drv/transfers.c.s

@ -0,0 +1,311 @@
;
; Generated from source-doc/base-drv/transfers.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/base-drv/transfers.c:23: * See https://www.beyondlogic.org/usbnutshell/usb4.shtml for a description of the USB control transfer
; ---------------------------------
; Function usb_control_transfer
; ---------------------------------
_usb_control_transfer:
push ix
ld ix,0
add ix,sp
push af
push af
;source-doc/base-drv/transfers.c:28: * @param max_packet_size Maximum packet size for endpoint
ld hl,0
add hl, sp
set 0, (hl)
ld hl,0
add hl, sp
ld a, (hl)
and 0xf1
ld (hl), a
ld c,(ix+9)
ld b,0x00
ld hl,1
add hl, sp
ld (hl), c
inc hl
ld a, b
and 0x03
ld e, a
ld a, (hl)
and 0xfc
or e
ld (hl), a
;source-doc/base-drv/transfers.c:30: */
ld c,(ix+4)
ld b,(ix+5)
ld a, (bc)
and 0x80
;source-doc/base-drv/transfers.c:32: void *const buffer,
ld (ix-1),a
or a
jr Z,l_usb_control_transfer_00102
ld a,(ix+7)
or (ix+6)
jr NZ,l_usb_control_transfer_00102
;source-doc/base-drv/transfers.c:33: const uint8_t device_address,
ld l,0x0f
jp l_usb_control_transfer_00114
l_usb_control_transfer_00102:
;source-doc/base-drv/transfers.c:35: usb_error result;
push bc
call _critical_begin
;source-doc/base-drv/transfers.c:37:
ld l,(ix+8)
call _ch_set_usb_address
pop bc
;source-doc/base-drv/transfers.c:39:
ld e,(ix+4)
ld d,(ix+5)
push bc
ld a,0x08
push af
inc sp
push de
call _ch_write_data
pop af
inc sp
;source-doc/base-drv/transfers.c:40: if (transferIn && buffer == 0)
call _ch_issue_token_setup
;source-doc/base-drv/transfers.c:41: return USB_ERR_OTHER;
call _ch_short_wait_int_and_get_stat
pop bc
;source-doc/base-drv/transfers.c:42:
ld a, l
or a
jr NZ,l_usb_control_transfer_00113
;source-doc/base-drv/transfers.c:44:
ld hl,6
add hl, bc
ld c, (hl)
inc hl
;source-doc/base-drv/transfers.c:47: ch_write_data((const uint8_t *)cmd_packet, sizeof(setup_packet));
ld a,(hl)
ld b,a
or c
jr Z,l_usb_control_transfer_00116
ld hl,0
add hl, sp
ld e,(ix+6)
ld d,(ix+7)
ld a,(ix-1)
or a
jr Z,l_usb_control_transfer_00118
push hl
push bc
push de
call _ch_data_in_transfer
pop af
pop af
pop af
jr l_usb_control_transfer_00119
l_usb_control_transfer_00118:
push hl
push bc
push de
call _ch_data_out_transfer
pop af
pop af
pop af
l_usb_control_transfer_00119:
jr l_usb_control_transfer_00117
l_usb_control_transfer_00116:
;source-doc/base-drv/transfers.c:48: ch_issue_token_setup();
ld l,0x00
l_usb_control_transfer_00117:
;source-doc/base-drv/transfers.c:50: CHECK(result);
ld a, l
or a
jr NZ,l_usb_control_transfer_00113
;source-doc/base-drv/transfers.c:52: const uint16_t length = cmd_packet->wLength;
ld a,(ix-1)
or a
jr Z,l_usb_control_transfer_00112
;source-doc/base-drv/transfers.c:53:
ld l,0x2c
call _ch_command
;source-doc/base-drv/transfers.c:54: result = length != 0
ld a,0x00
ld bc,_CH376_DATA_PORT
out (c), a
;source-doc/base-drv/transfers.c:55: ? (transferIn ? ch_data_in_transfer(buffer, length, &endpoint) : ch_data_out_transfer(buffer, length, &endpoint))
call _ch_issue_token_out_ep0
;source-doc/base-drv/transfers.c:56: : USB_ERR_OK;
call _ch_long_wait_int_and_get_statu
;source-doc/base-drv/transfers.c:58: CHECK(result)
ld a,l
or a
jr Z,l_usb_control_transfer_00108
sub 0x02
jr NZ,l_usb_control_transfer_00113
l_usb_control_transfer_00108:
;source-doc/base-drv/transfers.c:59:
ld l,0x00
;source-doc/base-drv/transfers.c:60: if (transferIn) {
jr l_usb_control_transfer_00113
;source-doc/base-drv/transfers.c:63: ch_issue_token_out_ep0();
l_usb_control_transfer_00112:
;source-doc/base-drv/transfers.c:66: if (result == USB_ERR_OK || result == USB_ERR_STALL) {
call _ch_issue_token_in_ep0
;source-doc/base-drv/transfers.c:67: result = USB_ERR_OK;
call _ch_long_wait_int_and_get_statu
;source-doc/base-drv/transfers.c:71: RETURN_CHECK(result);
l_usb_control_transfer_00113:
;source-doc/base-drv/transfers.c:72: }
push hl
call _critical_end
pop hl
;source-doc/base-drv/transfers.c:73:
l_usb_control_transfer_00114:
;source-doc/base-drv/transfers.c:74: ch_issue_token_in_ep0();
ld sp, ix
pop ix
ret
;source-doc/base-drv/transfers.c:79: done:
; ---------------------------------
; Function usb_data_in_transfer
; ---------------------------------
_usb_data_in_transfer:
push ix
ld ix,0
add ix,sp
;source-doc/base-drv/transfers.c:81: return result;
call _critical_begin
;source-doc/base-drv/transfers.c:83:
ld l,(ix+8)
call _ch_set_usb_address
;source-doc/base-drv/transfers.c:85: * @brief Perform a USB data in on the specified endpoint
ld l,(ix+9)
ld h,(ix+10)
push hl
ld l,(ix+6)
ld h,(ix+7)
push hl
ld l,(ix+4)
ld h,(ix+5)
push hl
call _ch_data_in_transfer
pop af
pop af
;source-doc/base-drv/transfers.c:87: * @param buffer the buffer to receive the data
ex (sp),hl
call _critical_end
pop hl
;source-doc/base-drv/transfers.c:89: * @param device_address the usb address of the device
;source-doc/base-drv/transfers.c:90: * @param endpoint the usb endpoint to receive from (toggle of endpoint is updated)
pop ix
ret
;source-doc/base-drv/transfers.c:95: usb_error result;
; ---------------------------------
; Function usb_data_in_transfer_n
; ---------------------------------
_usb_data_in_transfer_n:
push ix
ld ix,0
add ix,sp
;source-doc/base-drv/transfers.c:98: ch_set_usb_address(device_address);
call _critical_begin
;source-doc/base-drv/transfers.c:100: result = ch_data_in_transfer(buffer, buffer_size, endpoint);
ld l,(ix+8)
call _ch_set_usb_address
;source-doc/base-drv/transfers.c:102: critical_end();
ld l,(ix+9)
ld h,(ix+10)
push hl
ld l,(ix+6)
ld h,(ix+7)
push hl
ld l,(ix+4)
ld h,(ix+5)
push hl
call _ch_data_in_transfer_n
pop af
pop af
;source-doc/base-drv/transfers.c:104: return result;
ex (sp),hl
call _critical_end
pop hl
;source-doc/base-drv/transfers.c:106:
;source-doc/base-drv/transfers.c:107: /**
pop ix
ret
;source-doc/base-drv/transfers.c:112: * @param device_address the usb address of the device
; ---------------------------------
; Function usb_data_out_transfer
; ---------------------------------
_usb_data_out_transfer:
push ix
ld ix,0
add ix,sp
;source-doc/base-drv/transfers.c:114: * @return usb_error USB_ERR_OK if all good, otherwise specific error code
call _critical_begin
;source-doc/base-drv/transfers.c:116: usb_error
ld l,(ix+8)
call _ch_set_usb_address
;source-doc/base-drv/transfers.c:118: usb_error result;
ld l,(ix+9)
ld h,(ix+10)
push hl
ld l,(ix+6)
ld h,(ix+7)
push hl
ld l,(ix+4)
ld h,(ix+5)
push hl
call _ch_data_out_transfer
pop af
pop af
;source-doc/base-drv/transfers.c:120: critical_begin();
ex (sp),hl
call _critical_end
pop hl
;source-doc/base-drv/transfers.c:122: ch_set_usb_address(device_address);
;source-doc/base-drv/transfers.c:123:
pop ix
ret

224
Source/HBIOS/ch376-native/base-drv/usb-base-drv.c.s

@ -0,0 +1,224 @@
;
; Generated from source-doc/base-drv/usb-base-drv.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/base-drv/usb-base-drv.c:7: static usb_error usb_host_bus_reset(void) {
; ---------------------------------
; Function usb_host_bus_reset
; ---------------------------------
_usb_host_bus_reset:
;source-doc/base-drv/usb-base-drv.c:8: ch_cmd_set_usb_mode(CH_MODE_HOST);
ld l,0x06
call _ch_cmd_set_usb_mode
;source-doc/base-drv/usb-base-drv.c:9: delay_20ms();
call _delay_20ms
;source-doc/base-drv/usb-base-drv.c:11: ch_cmd_set_usb_mode(CH_MODE_HOST_RESET);
ld l,0x07
call _ch_cmd_set_usb_mode
;source-doc/base-drv/usb-base-drv.c:12: delay_20ms();
call _delay_20ms
;source-doc/base-drv/usb-base-drv.c:14: ch_cmd_set_usb_mode(CH_MODE_HOST);
ld l,0x06
call _ch_cmd_set_usb_mode
;source-doc/base-drv/usb-base-drv.c:15: delay_20ms();
call _delay_20ms
;source-doc/base-drv/ch376.h:108: #define TRACE_USB_ERROR(result)
ld l,0x0b
call _ch_command
;source-doc/base-drv/ch376.h:109:
ld a,0x25
ld bc,_CH376_DATA_PORT
out (c), a
;source-doc/base-drv/ch376.h:110: #endif
ld a,0xdf
ld bc,_CH376_DATA_PORT
out (c), a
;source-doc/base-drv/usb-base-drv.c:19: return USB_ERR_OK;
ld l,0x00
;source-doc/base-drv/usb-base-drv.c:20: }
ret
;source-doc/base-drv/usb-base-drv.c:24: uint16_t usb_init(uint8_t state) __z88dk_fastcall {
; ---------------------------------
; Function usb_init
; ---------------------------------
_usb_init:
;source-doc/base-drv/usb-base-drv.c:27: USB_MODULE_LEDS = 0x03;
ld a,0x03
ld bc,_USB_MODULE_LEDS
out (c), a
;source-doc/base-drv/usb-base-drv.c:29: if (state == 0) {
ld a, l
or a
jr NZ,l_usb_init_00104
;source-doc/base-drv/usb-base-drv.c:30: ch_cmd_reset_all();
call _ch_cmd_reset_all
;source-doc/base-drv/usb-base-drv.c:31: delay_medium();
call _delay_medium
;source-doc/base-drv/usb-base-drv.c:33: if (!ch_probe()) {
call _ch_probe
ld a, l
;source-doc/base-drv/usb-base-drv.c:34: USB_MODULE_LEDS = 0x00;
or a
jr NZ,l_usb_init_00102
ld bc,_USB_MODULE_LEDS
out (c), a
;source-doc/base-drv/usb-base-drv.c:35: return 0xFF00;
ld hl,0xff00
jp l_usb_init_00113
l_usb_init_00102:
;source-doc/base-drv/usb-base-drv.c:37: USB_MODULE_LEDS = 0x00;
ld a,0x00
ld bc,_USB_MODULE_LEDS
out (c), a
;source-doc/base-drv/usb-base-drv.c:38: return 1;
ld hl,0x0001
jr l_usb_init_00113
l_usb_init_00104:
;source-doc/base-drv/usb-base-drv.c:41: if (state == 1) {
ld a, l
dec a
jr NZ,l_usb_init_00106
;source-doc/base-drv/usb-base-drv.c:42: r = ch_cmd_get_ic_version();
call _ch_cmd_get_ic_version
;source-doc/base-drv/usb-base-drv.c:44: USB_MODULE_LEDS = 0x00;
ld a,0x00
ld bc,_USB_MODULE_LEDS
out (c), a
;source-doc/base-drv/usb-base-drv.c:45: return (uint16_t)r << 8 | 2;
xor a
ld h, l
ld l,0x02
jr l_usb_init_00113
l_usb_init_00106:
;source-doc/base-drv/usb-base-drv.c:48: if (state == 2) {
ld a, l
sub 0x02
jr NZ,l_usb_init_00159
ld a,0x01
jr l_usb_init_00160
l_usb_init_00159:
xor a
l_usb_init_00160:
ld c,a
or a
jr Z,l_usb_init_00110
;source-doc/base-drv/usb-base-drv.c:49: usb_host_bus_reset();
call _usb_host_bus_reset
;source-doc/base-drv/usb-base-drv.c:51: r = ch_very_short_wait_int_and_get_();
call _ch_very_short_wait_int_and_get
ld a, l
;source-doc/base-drv/usb-base-drv.c:53: if (r != USB_INT_CONNECT) {
sub 0x81
jr Z,l_usb_init_00108
;source-doc/base-drv/usb-base-drv.c:54: USB_MODULE_LEDS = 0x00;
ld a,0x00
ld bc,_USB_MODULE_LEDS
out (c), a
;source-doc/base-drv/usb-base-drv.c:55: return 2;
ld hl,0x0002
jr l_usb_init_00113
l_usb_init_00108:
;source-doc/base-drv/usb-base-drv.c:58: return 3;
ld hl,0x0003
jr l_usb_init_00113
l_usb_init_00110:
;source-doc/base-drv/usb-base-drv.c:61: memset(get_usb_work_area(), 0, sizeof(_usb_state));
ld b,0x32
ld hl,_x
jr l_usb_init_00163
l_usb_init_00162:
ld (hl),0x00
inc hl
l_usb_init_00163:
ld (hl),0x00
inc hl
djnz l_usb_init_00162
;source-doc/base-drv/usb-base-drv.c:62: if (state != 2) {
bit 0, c
jr NZ,l_usb_init_00112
;source-doc/base-drv/usb-base-drv.c:63: usb_host_bus_reset();
call _usb_host_bus_reset
;source-doc/base-drv/usb-base-drv.c:64: delay_medium();
call _delay_medium
l_usb_init_00112:
;source-doc/base-drv/usb-base-drv.c:66: enumerate_all_devices();
call _enumerate_all_devices
;source-doc/base-drv/usb-base-drv.c:67: USB_MODULE_LEDS = 0x00;
ld a,0x00
ld bc,_USB_MODULE_LEDS
out (c), a
;source-doc/base-drv/usb-base-drv.c:68: return (uint16_t)count_of_devices() << 8 | 4;
call _count_of_devices
ld h, a
xor a
ld l,0x04
l_usb_init_00113:
;source-doc/base-drv/usb-base-drv.c:69: }
ret
;source-doc/base-drv/usb-base-drv.c:71: usb_error usb_scsi_seek(const uint16_t dev_index, const uint32_t lba) {
; ---------------------------------
; Function usb_scsi_seek
; ---------------------------------
_usb_scsi_seek:
push ix
ld ix,0
add ix,sp
;source-doc/base-drv/usb-base-drv.c:72: device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index);
ld a,(ix+4)
call _get_usb_device_config
;source-doc/base-drv/usb-base-drv.c:74: dev->current_lba = lba;
ld hl,0x000c
add hl, de
ex de, hl
ld hl,6
add hl, sp
ld bc,0x0004
ldir
;source-doc/base-drv/usb-base-drv.c:75: return USB_ERR_OK;
ld l,0x00
;source-doc/base-drv/usb-base-drv.c:76: }
pop ix
ret

258
Source/HBIOS/ch376-native/base-drv/usb_state.c.s

@ -0,0 +1,258 @@
;
; Generated from source-doc/base-drv/usb_state.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/base-drv/usb_state.c:17: uint8_t count_of_devices(void) __sdcccall(1) {
; ---------------------------------
; Function count_of_devices
; ---------------------------------
_count_of_devices:
;source-doc/base-drv/usb_state.c:18: _usb_state *const p = get_usb_work_area();
;source-doc/base-drv/usb_state.c:22: const device_config *p_config = first_device_config(p);
ld hl,_x
call _first_device_config
;source-doc/base-drv/usb_state.c:23: while (p_config) {
ld c,0x00
l_count_of_devices_00104:
ld a, d
or e
jr Z,l_count_of_devices_00106
;source-doc/base-drv/usb_state.c:24: const uint8_t type = p_config->type;
ld l, e
ld h, d
ld a, (hl)
and 0x0f
;source-doc/base-drv/usb_state.c:26: if (type != USB_IS_HUB && type)
cp 0x0f
jr Z,l_count_of_devices_00102
or a
jr Z,l_count_of_devices_00102
;source-doc/base-drv/usb_state.c:27: count++;
inc c
l_count_of_devices_00102:
;source-doc/base-drv/usb_state.c:30: p_config = next_device_config(p, p_config);
push bc
ld hl,_x
call _next_device_config
pop bc
jr l_count_of_devices_00104
l_count_of_devices_00106:
;source-doc/base-drv/usb_state.c:33: return count;
ld a, c
;source-doc/base-drv/usb_state.c:34: }
ret
_device_config_sizes:
DEFB +0x00
DEFB +0x10
DEFB +0x10
DEFB +0x0c
DEFB +0x06
DEFB 0x00
DEFB 0x00
;source-doc/base-drv/usb_state.c:37: device_config *find_first_free(void) {
; ---------------------------------
; Function find_first_free
; ---------------------------------
_find_first_free:
;source-doc/base-drv/usb_state.c:38: _usb_state *const boot_state = get_usb_work_area();
;source-doc/base-drv/usb_state.c:41: device_config *p = first_device_config(boot_state);
ld hl,_x
call _first_device_config
;source-doc/base-drv/usb_state.c:42: while (p) {
l_find_first_free_00103:
ld a, d
or e
jr Z,l_find_first_free_00105
;source-doc/base-drv/usb_state.c:43: if (p->type == 0)
ld l, e
ld h, d
ld a, (hl)
and 0x0f
jr NZ,l_find_first_free_00102
;source-doc/base-drv/usb_state.c:44: return p;
ex de, hl
jr l_find_first_free_00106
l_find_first_free_00102:
;source-doc/base-drv/usb_state.c:46: p = next_device_config(boot_state, p);
ld hl,_x
call _next_device_config
jr l_find_first_free_00103
l_find_first_free_00105:
;source-doc/base-drv/usb_state.c:49: return NULL;
ld hl,0x0000
l_find_first_free_00106:
;source-doc/base-drv/usb_state.c:50: }
ret
;source-doc/base-drv/usb_state.c:52: device_config *first_device_config(const _usb_state *const p) __sdcccall(1) { return (device_config *)&p->device_configs[0]; }
; ---------------------------------
; Function first_device_config
; ---------------------------------
_first_device_config:
ex de, hl
inc de
inc de
ret
;source-doc/base-drv/usb_state.c:54: device_config *next_device_config(const _usb_state *const usb_state, const device_config *const p) __sdcccall(1) {
; ---------------------------------
; Function next_device_config
; ---------------------------------
_next_device_config:
ld c, l
ld b, h
;source-doc/base-drv/usb_state.c:55: if (p->type == 0)
ld l, e
ld h, d
ld a, (hl)
and 0x0f
jr NZ,l_next_device_config_00102
;source-doc/base-drv/usb_state.c:56: return NULL;
ld de,0x0000
jr l_next_device_config_00105
l_next_device_config_00102:
;source-doc/base-drv/usb_state.c:58: const uint8_t size = device_config_sizes[p->type];
ld l, e
ld h, d
ld a, (hl)
and 0x0f
add a, +((_device_config_sizes) & 0xFF)
ld l, a
ld a,0x00
adc a, +((_device_config_sizes) / 256)
ld h, a
ld a, (hl)
;source-doc/base-drv/usb_state.c:65: const uint8_t *_p = (uint8_t *)p;
;source-doc/base-drv/usb_state.c:66: device_config *const result = (device_config *)(_p + size);
add a, e
ld e, a
ld a,0x00
adc a, d
ld d, a
;source-doc/base-drv/usb_state.c:68: if (result >= (device_config *)&usb_state->device_configs_end)
ld hl,0x0062
add hl, bc
ld a, e
sub l
ld a, d
sbc a, h
ret C
;source-doc/base-drv/usb_state.c:69: return NULL;
ld de,0x0000
;source-doc/base-drv/usb_state.c:71: return result;
l_next_device_config_00105:
;source-doc/base-drv/usb_state.c:72: }
ret
;source-doc/base-drv/usb_state.c:74: device_config *get_usb_device_config(const uint8_t device_index) __sdcccall(1) {
; ---------------------------------
; Function get_usb_device_config
; ---------------------------------
_get_usb_device_config:
ld c, a
;source-doc/base-drv/usb_state.c:75: const _usb_state *const usb_state = get_usb_work_area();
;source-doc/base-drv/usb_state.c:79: for (device_config *p = first_device_config(usb_state); p; p = next_device_config(usb_state, p)) {
push bc
ld hl,_x
call _first_device_config
pop bc
ld b,0x01
l_get_usb_device_config_00107:
ld a, d
or e
jr Z,l_get_usb_device_config_00105
;source-doc/base-drv/usb_state.c:80: if (p->type != USB_NOT_SUPPORTED) {
ld l, e
ld h, d
ld a, (hl)
and 0x0f
jr Z,l_get_usb_device_config_00108
;source-doc/base-drv/usb_state.c:81: if (counter == device_index)
ld a, c
sub b
;source-doc/base-drv/usb_state.c:82: return p;
jr Z,l_get_usb_device_config_00109
;source-doc/base-drv/usb_state.c:83: counter++;
inc b
l_get_usb_device_config_00108:
;source-doc/base-drv/usb_state.c:79: for (device_config *p = first_device_config(usb_state); p; p = next_device_config(usb_state, p)) {
push bc
ld hl,_x
call _next_device_config
pop bc
jr l_get_usb_device_config_00107
l_get_usb_device_config_00105:
;source-doc/base-drv/usb_state.c:87: return NULL; // is not a usb device
ld de,0x0000
l_get_usb_device_config_00109:
;source-doc/base-drv/usb_state.c:88: }
ret
;source-doc/base-drv/usb_state.c:90: usb_device_type usb_get_device_type(const uint16_t dev_index) {
; ---------------------------------
; Function usb_get_device_type
; ---------------------------------
_usb_get_device_type:
push ix
ld ix,0
add ix,sp
;source-doc/base-drv/usb_state.c:91: const device_config *dev = get_usb_device_config(dev_index);
ld a,(ix+4)
call _get_usb_device_config
ld l, e
;source-doc/base-drv/usb_state.c:93: if (dev == NULL)
ld a,d
ld h,a
or e
jr NZ,l_usb_get_device_type_00102
;source-doc/base-drv/usb_state.c:94: return -1;
ld l,0xff
jr l_usb_get_device_type_00103
l_usb_get_device_type_00102:
;source-doc/base-drv/usb_state.c:96: return dev->type;
ld a, (hl)
and 0x0f
ld l, a
l_usb_get_device_type_00103:
;source-doc/base-drv/usb_state.c:97: }
pop ix
ret

149
Source/HBIOS/ch376-native/base-drv/work-area.c.s

@ -0,0 +1,149 @@
;
; Generated from source-doc/base-drv/work-area.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
_x:
DEFS 99
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
_x:
DEFB 0x00
DEFB +0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB +0x00

133
Source/HBIOS/ch376-native/cruntime.asm

@ -0,0 +1,133 @@
_memset_callee:
pop af ; return address
pop bc ; address to be set
pop de ; value to be set
pop hl ; number of bytes to set
push af ; restore return address
ld a, b
or c
ret z
ld a, e
push hl
pop de
ret z
ld (hl), a
inc de
dec bc
ld a, b
or c
ret z
push hl
ldir
pop hl
ret
_memcpy_callee:
pop af
pop bc
pop hl
pop de
push af
; enter : bc = size_t n
; hl = void *s2 = src
; de = void *s1 = dst
;
; exit : hl = void *s1 = dst
; de = ptr in s1 to one byte past last byte copied
; bc = 0
; carry reset
;
; uses : af, bc, de, hl
ld a, b
or c
jr z, zero_n
asm0_memcpy:
push de
ldir
pop hl
or a
ret
zero_n:
push de
pop hl
ret
.if 0
; required if --optimise-for-size is targetted
; but there appears to be a regression that stop the driver from working
; if optimised for size is selected
___sdcc_enter_ix:
ex (sp), ix
push ix
ld ix, 2
add ix, sp
ret
____sdcc_lib_setmem_hl:
l_setmem_hl:
ret
____sdcc_load_debc_mhl:
ld c, (hl)
inc hl
ld b, (hl)
inc hl
ld e, (hl)
inc hl
ld d, (hl)
ret
____sdcc_4_push_hlix:
pop af
push af
push af
push af
push de
push ix
pop de
add hl, de
ex de, hl
ld hl, 2+2
add hl, sp
ex de, hl
ldi
ldi
ldi
ld a, (hl)
ld (de), a
inc bc
inc bc
inc bc
pop de
ret
____sdcc_store_debc_mhl:
ld (hl), c
inc hl
ld (hl), b
inc hl
ld (hl), e
inc hl
ld (hl), d
ret
.endif

143
Source/HBIOS/ch376-native/ez80-firmware.asm

@ -0,0 +1,143 @@
; delegate usb function to firmware of ez80 module
; extern uint16_t usb_init(uint8_t state) __z88dk_fastcall;
_usb_init:
EZ80_EX_USB_INIT
RET
; usb_error usb_scsi_seek(const uint16_t dev_index, const uint32_t lba)
_usb_scsi_seek:
; iy+2 : dev_index
; iy+4:5:6:7 : lba
LD IY, 0
ADD IY, SP
EZ80_EXTN_IY_TO_MB_IY
LD C, (IY+2)
LD_DE_IY_P_.L(4) ; LD.L DE, (IY+4)
LD L, (IY+7)
EZ80_EX_USB_STORAGE_SEEK
LD L, A
RET
; usb_error usb_scsi_init(const uint16_t dev_index)
_usb_scsi_init:
LD IY, 0
ADD IY, SP
LD C, (IY+2)
EZ80_EX_USB_SCSI_INIT
LD L, A
RET
; usb_error usb_scsi_read(const uint16_t dev_index, uint8_t *const buffer);
_usb_scsi_read:
LD IY, 0
ADD IY, SP
LD C, (IY+2)
LD E, (IY+4)
LD D, (IY+5)
EZ80_EXTN_DE_TO_MB_DE
EZ80_EX_USB_SCSI_READ
LD L, A
RET
; usb_error usb_scsi_write(const uint16_t dev_index, uint8_t *const buffer)
_usb_scsi_write:
LD IY, 0
ADD IY, SP
LD C, (IY+2)
LD E, (IY+4)
LD D, (IY+5)
EZ80_EXTN_DE_TO_MB_DE
EZ80_EX_USB_SCSI_WRITE
LD L, A
RET
; usb_error usb_scsi_read_capacity(const uint16_t dev_index, scsi_read_capacity_result *cap_result)
_usb_scsi_read_capacity:
LD IY, 0
ADD IY, SP
LD C, (IY+2)
LD E, (IY+4)
LD D, (IY+5)
EZ80_EXTN_DE_TO_MB_DE
EZ80_EX_USB_SCSI_READ_CAP
LD L, A
RET
; extern uint8_t usb_ufi_read(const uint16_t dev_index, uint8_t *const buffer)
_usb_ufi_read:
LD IY, 0
ADD IY, SP
LD C, (IY+2)
LD E, (IY+4)
LD D, (IY+5)
EZ80_EXTN_DE_TO_MB_DE
EZ80_EX_USB_UFI_READ
LD L, A
RET
;extern usb_error usb_ufi_write(const uint16_t dev_index, uint8_t *const buffer);
_usb_ufi_write:
LD IY, 0
ADD IY, SP
LD C, (IY+2)
LD E, (IY+4)
LD D, (IY+5)
EZ80_EXTN_DE_TO_MB_DE
EZ80_EX_USB_UFI_WRITE
LD L, A
RET
; extern uint32_t usb_ufi_get_cap(const uint16_t dev_index)
_usb_ufi_get_cap:
LD IY, 0
ADD IY, SP
LD C, (IY+2)
EZ80_EXTN_DE_TO_MB_DE
EZ80_EX_USB_UFI_GET_CAP ;
LD D, E ; convert E:uHL to DE:HL
EZ80_CPY_UHL_TO_EHL
RET
; extern void usb_kyb_init(const uint8_t dev_index) __sdcccall(1);
_usb_kyb_init:
LD C, A
EZ80_EX_USB_KYB_INIT
RET
; extern uint8_t usb_kyb_flush() __sdcccall(1);
_usb_kyb_flush:
EZ80_EX_USB_KYB_FLUSH
RET
; extern uint8_t usb_kyb_status() __sdcccall(1);
_usb_kyb_status:
EZ80_EX_USB_KYB_STATUS
RET
; extern uint16_t usb_kyb_read();
; H = 0/1 set if char, L=>code
_usb_kyb_read:
EZ80_EX_USB_KYB_READ
LD H, A
RET
;usb_device_type usb_get_device_type(const uint16_t dev_index)
_usb_get_device_type:
LD IY, 0
ADD IY, SP
LD C, (IY+2)
EZ80_EX_USB_GET_DEV_TYPE
LD L, A
RET

11
Source/HBIOS/ch376-native/keyboard.s

@ -0,0 +1,11 @@
; Generated File -- not to be modify directly
#IF (!CHNATIVEEZ80)
#include "ch376-native/keyboard/class_hid.c.s"
#ENDIF
#IF (!CHNATIVEEZ80)
#include "ch376-native/keyboard/class_hid_keyboard.c.s"
#ENDIF
#IF (!CHNATIVEEZ80)
#include "ch376-native/keyboard/kyb_driver.c.s"
#ENDIF
#include "ch376-native/keyboard/kyb-init.c.s"

1
Source/HBIOS/ch376-native/keyboard/.gitignore

@ -0,0 +1 @@
*.asm

169
Source/HBIOS/ch376-native/keyboard/class_hid.c.s

@ -0,0 +1,169 @@
;
; Generated from source-doc/keyboard/class_hid.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/keyboard/class_hid.c:6: usb_error hid_set_protocol(const device_config_keyboard *const dev, const uint8_t protocol) __sdcccall(1) {
; ---------------------------------
; Function hid_set_protocol
; ---------------------------------
_hid_set_protocol:
push ix
ld ix,0
add ix,sp
push af
push af
push af
push af
;source-doc/keyboard/class_hid.c:8: cmd = cmd_hid_set;
push hl
ex de,hl
ld hl,2
add hl, sp
ex de, hl
ld bc,0x0008
ld hl,_cmd_hid_set
ldir
pop de
;source-doc/keyboard/class_hid.c:10: cmd.bRequest = HID_SET_PROTOCOL;
ld (ix-7),0x0b
;source-doc/keyboard/class_hid.c:11: cmd.bValue[0] = protocol;
ld a,(ix+4)
ld (ix-6),a
;source-doc/keyboard/class_hid.c:13: return usb_control_transfer(&cmd, NULL, dev->address, dev->max_packet_size);
ld l, e
ld h, d
inc hl
ld b, (hl)
ex de, hl
ld a, (hl)
rlca
rlca
rlca
rlca
and 0x0f
ld c,a
push bc
ld hl,0x0000
push hl
ld hl,4
add hl, sp
push hl
call _usb_control_transfer
pop af
pop af
pop af
ld a, l
;source-doc/keyboard/class_hid.c:14: }
ld sp, ix
pop ix
pop hl
inc sp
jp (hl)
_cmd_hid_set:
DEFB +0x21
DEFB +0x0b
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFW +0x0000
;source-doc/keyboard/class_hid.c:16: usb_error hid_set_idle(const device_config_keyboard *const dev, const uint8_t duration) __sdcccall(1) {
; ---------------------------------
; Function hid_set_idle
; ---------------------------------
_hid_set_idle:
push ix
ld ix,0
add ix,sp
push af
push af
push af
push af
;source-doc/keyboard/class_hid.c:18: cmd = cmd_hid_set;
push hl
ex de,hl
ld hl,2
add hl, sp
ex de, hl
ld bc,0x0008
ld hl,_cmd_hid_set
ldir
pop de
;source-doc/keyboard/class_hid.c:20: cmd.bRequest = HID_SET_IDLE;
ld (ix-7),0x0a
;source-doc/keyboard/class_hid.c:21: cmd.bValue[0] = duration;
ld a,(ix+4)
ld (ix-6),a
;source-doc/keyboard/class_hid.c:23: return usb_control_transfer(&cmd, NULL, dev->address, dev->max_packet_size);
ld l, e
ld h, d
inc hl
ld b, (hl)
ex de, hl
ld a, (hl)
rlca
rlca
rlca
rlca
and 0x0f
ld c,a
push bc
ld hl,0x0000
push hl
ld hl,4
add hl, sp
push hl
call _usb_control_transfer
pop af
pop af
pop af
ld a, l
;source-doc/keyboard/class_hid.c:24: }
ld sp, ix
pop ix
pop hl
inc sp
jp (hl)

440
Source/HBIOS/ch376-native/keyboard/class_hid_keyboard.c.s

@ -0,0 +1,440 @@
;
; Generated from source-doc/keyboard/class_hid_keyboard.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
_scancodes_shift_table:
DEFS 128
_scancodes_table:
DEFS 128
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/keyboard/class_hid_keyboard.c:334: };
; ---------------------------------
; Function char_with_caps_lock
; ---------------------------------
_char_with_caps_lock:
;source-doc/keyboard/class_hid_keyboard.c:335:
bit 0, l
;source-doc/keyboard/class_hid_keyboard.c:336: static char char_with_caps_lock(const char c, const bool caps_lock_engaged) __sdcccall(1) {
jr Z,l_char_with_caps_lock_00109
;source-doc/keyboard/class_hid_keyboard.c:338: return c;
cp 0x41
jr C,l_char_with_caps_lock_00104
cp 0x5b
jr NC,l_char_with_caps_lock_00104
;source-doc/keyboard/class_hid_keyboard.c:339:
add a,0x20
jr l_char_with_caps_lock_00109
l_char_with_caps_lock_00104:
;source-doc/keyboard/class_hid_keyboard.c:341: return c - 'A' + 'a';
cp 0x61
ret C
cp 0x7b
ret NC
;source-doc/keyboard/class_hid_keyboard.c:342:
add a,0xe0
;source-doc/keyboard/class_hid_keyboard.c:344: return c - 'a' + 'A';
l_char_with_caps_lock_00109:
;source-doc/keyboard/class_hid_keyboard.c:345:
ret
;source-doc/keyboard/class_hid_keyboard.c:347: }
; ---------------------------------
; Function scancode_to_char
; ---------------------------------
_scancode_to_char:
push ix
ld ix,0
add ix,sp
;source-doc/keyboard/class_hid_keyboard.c:348:
ld c,a
ld e,l
and 0x11
jr Z,l_scancode_to_char_00118
;source-doc/keyboard/class_hid_keyboard.c:349: char scancode_to_char(const uint8_t modifier_keys, const uint8_t code, const bool caps_lock_engaged) __sdcccall(1) {
ld a, e
sub 0x04
jr C,l_scancode_to_char_00102
ld a,0x1d
sub e
jr C,l_scancode_to_char_00102
;source-doc/keyboard/class_hid_keyboard.c:350: if ((modifier_keys & (KEY_MOD_LCTRL | KEY_MOD_RCTRL))) {
ld a, e
add a,0xfd
jr l_scancode_to_char_00121
l_scancode_to_char_00102:
;source-doc/keyboard/class_hid_keyboard.c:352: return code - 3;
ld a,e
cp 0x1f
jr Z,l_scancode_to_char_00104
sub 0x2c
jr NZ,l_scancode_to_char_00105
l_scancode_to_char_00104:
;source-doc/keyboard/class_hid_keyboard.c:353:
xor a
jr l_scancode_to_char_00121
l_scancode_to_char_00105:
;source-doc/keyboard/class_hid_keyboard.c:355: return 0;
ld a, e
sub 0x2f
jr NZ,l_scancode_to_char_00108
;source-doc/keyboard/class_hid_keyboard.c:356:
ld a,0x1b
jr l_scancode_to_char_00121
l_scancode_to_char_00108:
;source-doc/keyboard/class_hid_keyboard.c:358: return 27;
ld a, e
sub 0x31
jr NZ,l_scancode_to_char_00110
;source-doc/keyboard/class_hid_keyboard.c:359:
ld a,0x1c
jr l_scancode_to_char_00121
l_scancode_to_char_00110:
;source-doc/keyboard/class_hid_keyboard.c:361: return 28;
ld a, e
sub 0x30
jr NZ,l_scancode_to_char_00112
;source-doc/keyboard/class_hid_keyboard.c:362:
ld a,0x1d
jr l_scancode_to_char_00121
l_scancode_to_char_00112:
;source-doc/keyboard/class_hid_keyboard.c:364: return 29;
ld a, e
sub 0x23
jr NZ,l_scancode_to_char_00114
;source-doc/keyboard/class_hid_keyboard.c:365:
ld a,0x1e
jr l_scancode_to_char_00121
l_scancode_to_char_00114:
;source-doc/keyboard/class_hid_keyboard.c:367: return 30;
ld a, e
sub 0x2d
jr NZ,l_scancode_to_char_00118
;source-doc/keyboard/class_hid_keyboard.c:368:
ld a,0x1f
jr l_scancode_to_char_00121
l_scancode_to_char_00118:
;source-doc/keyboard/class_hid_keyboard.c:371: }
ld a, c
and 0x22
jr Z,l_scancode_to_char_00120
;source-doc/keyboard/class_hid_keyboard.c:372:
ld d,0x00
ld hl,_scancodes_shift_table
add hl, de
ld a, (hl)
ld l,(ix+4)
call _char_with_caps_lock
jr l_scancode_to_char_00121
l_scancode_to_char_00120:
;source-doc/keyboard/class_hid_keyboard.c:374: return char_with_caps_lock(scancodes_shift_table[code], caps_lock_engaged);
ld d,0x00
ld hl,_scancodes_table
add hl, de
ld a, (hl)
ld l,(ix+4)
call _char_with_caps_lock
l_scancode_to_char_00121:
;source-doc/keyboard/class_hid_keyboard.c:375:
pop ix
pop hl
inc sp
jp (hl)
_scancodes_shift_table:
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x41
DEFB +0x42
DEFB +0x43
DEFB +0x44
DEFB +0x45
DEFB +0x46
DEFB +0x47
DEFB +0x48
DEFB +0x49
DEFB +0x4a
DEFB +0x4b
DEFB +0x4c
DEFB +0x4d
DEFB +0x4e
DEFB +0x4f
DEFB +0x50
DEFB +0x51
DEFB +0x52
DEFB +0x53
DEFB +0x54
DEFB +0x55
DEFB +0x56
DEFB +0x57
DEFB +0x58
DEFB +0x59
DEFB +0x5a
DEFB +0x21
DEFB +0x40
DEFB +0x23
DEFB +0x24
DEFB +0x25
DEFB +0x5e
DEFB +0x26
DEFB +0x2a
DEFB +0x28
DEFB +0x29
DEFB +0x0d
DEFB +0x1b
DEFB +0x08
DEFB +0x09
DEFB +0x20
DEFB +0x5f
DEFB +0x2b
DEFB +0x7b
DEFB +0x7d
DEFB +0x7c
DEFB +0x7e
DEFB +0x3a
DEFB +0x22
DEFB +0x7e
DEFB +0x3c
DEFB +0x3e
DEFB +0x3f
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x2f
DEFB +0x2a
DEFB +0x2d
DEFB +0x2b
DEFB +0x0d
DEFB +0x31
DEFB +0x32
DEFB +0x33
DEFB +0x34
DEFB +0x35
DEFB +0x36
DEFB +0x37
DEFB +0x38
DEFB +0x39
DEFB +0x30
DEFB +0x2e
DEFB +0x5c
DEFB +0x00
DEFB +0x00
DEFB +0x3d
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
_scancodes_table:
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x61
DEFB +0x62
DEFB +0x63
DEFB +0x64
DEFB +0x65
DEFB +0x66
DEFB +0x67
DEFB +0x68
DEFB +0x69
DEFB +0x6a
DEFB +0x6b
DEFB +0x6c
DEFB +0x6d
DEFB +0x6e
DEFB +0x6f
DEFB +0x70
DEFB +0x71
DEFB +0x72
DEFB +0x73
DEFB +0x74
DEFB +0x75
DEFB +0x76
DEFB +0x77
DEFB +0x78
DEFB +0x79
DEFB +0x7a
DEFB +0x31
DEFB +0x32
DEFB +0x33
DEFB +0x34
DEFB +0x35
DEFB +0x36
DEFB +0x37
DEFB +0x38
DEFB +0x39
DEFB +0x30
DEFB +0x0d
DEFB +0x1b
DEFB +0x08
DEFB +0x09
DEFB +0x20
DEFB +0x2d
DEFB +0x3d
DEFB +0x5b
DEFB +0x5d
DEFB +0x5c
DEFB +0x23
DEFB +0x3b
DEFB +0x27
DEFB +0x60
DEFB +0x2c
DEFB +0x2e
DEFB +0x2f
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x2f
DEFB +0x2a
DEFB +0x2d
DEFB +0x2b
DEFB +0x0d
DEFB +0x31
DEFB +0x32
DEFB +0x33
DEFB +0x34
DEFB +0x35
DEFB +0x36
DEFB +0x37
DEFB +0x38
DEFB +0x39
DEFB +0x30
DEFB +0x2e
DEFB +0x5c
DEFB +0x00
DEFB +0x00
DEFB +0x3d
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00

122
Source/HBIOS/ch376-native/keyboard/kyb-init.c.s

@ -0,0 +1,122 @@
;
; Generated from source-doc/keyboard/kyb-init.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/keyboard/kyb-init.c:6: uint8_t keyboard_init(void) __sdcccall(1) {
; ---------------------------------
; Function keyboard_init
; ---------------------------------
_keyboard_init:
push ix
ld ix,0
add ix,sp
dec sp
;source-doc/keyboard/kyb-init.c:7: uint8_t index = 1;
;source-doc/keyboard/kyb-init.c:9: do {
ld c,0x01
ld (ix-1),c
l_keyboard_init_00103:
;source-doc/keyboard/kyb-init.c:10: usb_device_type t = usb_get_device_type(index);
ld e, c
ld d,0x00
push bc
push de
push de
call _usb_get_device_type
pop af
ld a, l
pop de
pop bc
;source-doc/keyboard/kyb-init.c:12: if (t == USB_IS_KEYBOARD) {
sub 0x04
jr NZ,l_keyboard_init_00104
;source-doc/keyboard/kyb-init.c:13: print_string("\r\nUSB: KEYBOARD @ $");
push de
ld hl,kyb_init_str_0
call _print_string
pop de
;source-doc/keyboard/kyb-init.c:14: print_uint16(index);
ex de, hl
call _print_uint16
;source-doc/keyboard/kyb-init.c:15: print_string(" $");
ld hl,kyb_init_str_1
call _print_string
;source-doc/keyboard/kyb-init.c:17: usb_kyb_init(index);
ld a,(ix-1)
call _usb_kyb_init
;source-doc/keyboard/kyb-init.c:18: return 1;
ld a,0x01
jr l_keyboard_init_00106
l_keyboard_init_00104:
;source-doc/keyboard/kyb-init.c:20: } while (++index != MAX_NUMBER_OF_DEVICES + 1);
inc c
ld (ix-1),c
ld a, c
sub 0x07
jr NZ,l_keyboard_init_00103
;source-doc/keyboard/kyb-init.c:22: print_string("\r\nUSB: KEYBOARD: NOT FOUND$");
ld hl,kyb_init_str_2
call _print_string
;source-doc/keyboard/kyb-init.c:24: return 0;
xor a
l_keyboard_init_00106:
;source-doc/keyboard/kyb-init.c:25: }
inc sp
pop ix
ret
kyb_init_str_0:
DEFB 0x0d
DEFB 0x0a
DEFM "USB: KEYBOARD @ $"
DEFB 0x00
kyb_init_str_1:
DEFM " $"
DEFB 0x00
kyb_init_str_2:
DEFB 0x0d
DEFB 0x0a
DEFM "USB: KEYBOARD: NOT FOUND$"
DEFB 0x00

406
Source/HBIOS/ch376-native/keyboard/kyb_driver.c.s

@ -0,0 +1,406 @@
;
; Generated from source-doc/keyboard/kyb_driver.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
_caps_lock_engaged:
DEFS 1
_keyboard_config:
DEFS 2
_buffer:
DEFS 8
_write_index:
DEFS 1
_read_index:
DEFS 1
_report:
DEFS 8
_previous:
DEFS 8
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/keyboard/kyb_driver.c:23: #define EI __asm__("EI")
; ---------------------------------
; Function report_diff
; ---------------------------------
_report_diff:
;source-doc/keyboard/kyb_driver.c:24:
ld de,_report+0
;source-doc/keyboard/kyb_driver.c:25: static uint8_t report_diff() __sdcccall(1) {
;source-doc/keyboard/kyb_driver.c:28:
ld b,0x08
ld hl,_previous
l_report_diff_00103:
;source-doc/keyboard/kyb_driver.c:29: uint8_t i = sizeof(report);
ld a, (de)
inc de
ld c, (hl)
inc hl
sub c
jr Z,l_report_diff_00104
;source-doc/keyboard/kyb_driver.c:30: do {
ld a,0x01
jr l_report_diff_00106
l_report_diff_00104:
;source-doc/keyboard/kyb_driver.c:31: if (*a++ != *b++)
djnz l_report_diff_00103
;source-doc/keyboard/kyb_driver.c:33: } while (--i != 0);
xor a
l_report_diff_00106:
;source-doc/keyboard/kyb_driver.c:34:
ret
;source-doc/keyboard/kyb_driver.c:36: }
; ---------------------------------
; Function keyboard_buf_put
; ---------------------------------
_keyboard_buf_put:
ld c, a
;source-doc/keyboard/kyb_driver.c:37:
ld b,0x00
ld hl,+(_report + 2)
add hl, bc
;source-doc/keyboard/kyb_driver.c:38: static void keyboard_buf_put(const uint8_t indx) __sdcccall(1) {
ld a,(hl)
ld e,a
sub 0x80
jr NC,l_keyboard_buf_put_00112
ld a, e
or a
;source-doc/keyboard/kyb_driver.c:39: const uint8_t key_code = report.keyCode[indx];
jr Z,l_keyboard_buf_put_00112
;source-doc/keyboard/kyb_driver.c:42:
ld b,0x00
ld hl,+(_previous + 2)
add hl, bc
ld a, (hl)
sub e
;source-doc/keyboard/kyb_driver.c:43: // if already reported, just skip it
jr Z,l_keyboard_buf_put_00112
;source-doc/keyboard/kyb_driver.c:45: return;
ld a, e
sub 0x39
jr NZ,l_keyboard_buf_put_00107
;source-doc/keyboard/kyb_driver.c:46:
ld hl,_caps_lock_engaged
ld a, (hl)
xor 0x01
ld (hl), a
;source-doc/keyboard/kyb_driver.c:47: if (key_code == KEY_CODE_CAPS_LOCK) {
jr l_keyboard_buf_put_00112
l_keyboard_buf_put_00107:
;source-doc/keyboard/kyb_driver.c:50: }
ld a,(_report)
ld hl,_caps_lock_engaged
ld h, (hl)
push hl
inc sp
ld l, e
call _scancode_to_char
ld b, a
;source-doc/keyboard/kyb_driver.c:52: const unsigned char c = scancode_to_char(report.bModifierKeys, key_code, caps_lock_engaged);
or a
;source-doc/keyboard/kyb_driver.c:53:
ret Z
;source-doc/keyboard/kyb_driver.c:55: return;
ld a, (_write_index)
inc a
and 0x07
ld c, a
;source-doc/keyboard/kyb_driver.c:56:
ld hl,_read_index
ld a, (hl)
sub c
ret Z
;source-doc/keyboard/kyb_driver.c:57: uint8_t next_write_index = (write_index + 1) & KEYBOARD_BUFFER_SIZE_MASK;
ld hl,(_write_index)
ld h,0x00
ld de,_buffer
add hl,de
ld a,b
ld (hl),a
ld hl,_write_index
;source-doc/keyboard/kyb_driver.c:58: if (next_write_index != read_index) { // Check if buffer is not full
ld (hl), c
l_keyboard_buf_put_00112:
;source-doc/keyboard/kyb_driver.c:60: write_index = next_write_index;
ret
;source-doc/keyboard/kyb_driver.c:62: }
; ---------------------------------
; Function usb_kyb_status
; ---------------------------------
_usb_kyb_status:
;source-doc/keyboard/kyb_driver.c:63:
DI
;source-doc/keyboard/kyb_driver.c:67: uint8_t size;
ld a,(_write_index)
ld hl,_read_index
sub (hl)
jr C,l_usb_kyb_status_00102
;source-doc/keyboard/kyb_driver.c:68:
ld a,(_write_index)
ld hl,_read_index
sub (hl)
jr l_usb_kyb_status_00103
l_usb_kyb_status_00102:
;source-doc/keyboard/kyb_driver.c:70: size = write_index - read_index;
ld hl, (_read_index)
ld a,0x08
sub l
ld hl, (_write_index)
add a, l
l_usb_kyb_status_00103:
;source-doc/keyboard/kyb_driver.c:72: size = KEYBOARD_BUFFER_SIZE - read_index + write_index;
EI
;source-doc/keyboard/kyb_driver.c:73:
;source-doc/keyboard/kyb_driver.c:74: EI;
ret
;source-doc/keyboard/kyb_driver.c:76: }
; ---------------------------------
; Function usb_kyb_read
; ---------------------------------
_usb_kyb_read:
;source-doc/keyboard/kyb_driver.c:77:
ld a,(_write_index)
ld hl,_read_index
sub (hl)
jr NZ,l_usb_kyb_read_00102
;source-doc/keyboard/kyb_driver.c:78: uint16_t usb_kyb_read() {
ld hl,0xff00
jr l_usb_kyb_read_00103
l_usb_kyb_read_00102:
;source-doc/keyboard/kyb_driver.c:80: return 0xFF00; // H = -1, L = 0
DI
;source-doc/keyboard/kyb_driver.c:81:
ld hl,(_read_index)
ld h,0x00
ld bc,_buffer
add hl,bc
ld a,(hl)
ld c,l
ld b,h
ld hl,_read_index
ld l, a
;source-doc/keyboard/kyb_driver.c:82: DI;
ld a, (_read_index)
inc a
and 0x07
ld (_read_index), a
;source-doc/keyboard/kyb_driver.c:83: const uint8_t c = buffer[read_index];
EI
;source-doc/keyboard/kyb_driver.c:86:
ld h,0x00
l_usb_kyb_read_00103:
;source-doc/keyboard/kyb_driver.c:87: /* H = 0, L = ascii char */
ret
;source-doc/keyboard/kyb_driver.c:89: }
; ---------------------------------
; Function usb_kyb_flush
; ---------------------------------
_usb_kyb_flush:
;source-doc/keyboard/kyb_driver.c:90:
DI
;source-doc/keyboard/kyb_driver.c:91: uint8_t usb_kyb_flush() __sdcccall(1) {
xor a
ld (_read_index),a
ld (_write_index),a
;source-doc/keyboard/kyb_driver.c:94:
ld de,_previous+0
;source-doc/keyboard/kyb_driver.c:95: uint8_t i = sizeof(previous);
;source-doc/keyboard/kyb_driver.c:96: uint8_t *a = (uint8_t *)previous;
ld b,0x08
ld hl,_report
l_usb_kyb_flush_00101:
;source-doc/keyboard/kyb_driver.c:97: uint8_t *b = (uint8_t *)report;
xor a
ld (de), a
inc de
;source-doc/keyboard/kyb_driver.c:98: do {
ld (hl),0x00
inc hl
;source-doc/keyboard/kyb_driver.c:99: *a++ = 0;
djnz l_usb_kyb_flush_00101
;source-doc/keyboard/kyb_driver.c:101: } while (--i != 0);
EI
;source-doc/keyboard/kyb_driver.c:103: EI;
xor a
;source-doc/keyboard/kyb_driver.c:104:
ret
;source-doc/keyboard/kyb_driver.c:106: }
; ---------------------------------
; Function usb_kyb_tick
; ---------------------------------
_usb_kyb_tick:
;source-doc/keyboard/kyb_driver.c:109: usb_error result;
ld hl,_in_critical_usb_section
ld a, (hl)
or a
;source-doc/keyboard/kyb_driver.c:110:
jr NZ,l_usb_kyb_tick_00112
;././source-doc/base-drv//ch376.h:108: #define TRACE_USB_ERROR(result)
ld l,0x0b
call _ch_command
;././source-doc/base-drv//ch376.h:109:
ld a,0x25
ld bc,_CH376_DATA_PORT
out (c), a
;././source-doc/base-drv//ch376.h:110: #endif
ld a,0x1f
ld bc,_CH376_DATA_PORT
out (c), a
;source-doc/keyboard/kyb_driver.c:113:
ld bc,_report+0
ld hl, (_keyboard_config)
ld a,0x08
push af
inc sp
push bc
push hl
call _usbdev_dat_in_trnsfer_0
pop af
pop af
inc sp
;././source-doc/base-drv//ch376.h:108: #define TRACE_USB_ERROR(result)
push hl
ld l,0x0b
call _ch_command
pop hl
;././source-doc/base-drv//ch376.h:109:
ld a,0x25
ld bc,_CH376_DATA_PORT
out (c), a
;././source-doc/base-drv//ch376.h:110: #endif
ld a,0xdf
ld bc,_CH376_DATA_PORT
out (c), a
;source-doc/keyboard/kyb_driver.c:115: result = usbdev_dat_in_trnsfer_0((device_config *)keyboard_config, (uint8_t *)&report, 8);
ld a, l
or a
jr NZ,l_usb_kyb_tick_00112
;source-doc/keyboard/kyb_driver.c:116: ch_configure_nak_retry_3s();
call _report_diff
or a
jr Z,l_usb_kyb_tick_00112
;source-doc/keyboard/kyb_driver.c:118: if (report_diff()) {
ld b,0x06
l_usb_kyb_tick_00103:
;source-doc/keyboard/kyb_driver.c:119: uint8_t i = 6;
ld a, b
dec a
push bc
call _keyboard_buf_put
pop bc
;source-doc/keyboard/kyb_driver.c:120: do {
djnz l_usb_kyb_tick_00103
;source-doc/keyboard/kyb_driver.c:121: keyboard_buf_put(i - 1);
ld de,_previous
ld bc,0x0008
ld hl,_report
ldir
l_usb_kyb_tick_00112:
;source-doc/keyboard/kyb_driver.c:124: }
ret
;source-doc/keyboard/kyb_driver.c:126: }
; ---------------------------------
; Function usb_kyb_init
; ---------------------------------
_usb_kyb_init:
;source-doc/keyboard/kyb_driver.c:127:
call _get_usb_device_config
ex de, hl
ld (_keyboard_config), hl
;source-doc/keyboard/kyb_driver.c:129: keyboard_config = (device_config_keyboard *)get_usb_device_config(dev_index);
ld hl,_keyboard_config + 1
ld a, (hl)
dec hl
or (hl)
;source-doc/keyboard/kyb_driver.c:130:
ret Z
;source-doc/keyboard/kyb_driver.c:132: return;
ld a,0x01
push af
inc sp
ld hl, (_keyboard_config)
call _hid_set_protocol
;source-doc/keyboard/kyb_driver.c:133:
ld a,0x80
push af
inc sp
ld hl, (_keyboard_config)
call _hid_set_idle
;source-doc/keyboard/kyb_driver.c:134: hid_set_protocol(keyboard_config, 1);
ret
_caps_lock_engaged:
DEFB +0x01
_keyboard_config:
DEFW +0x0000
_buffer:
DEFB +0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
_write_index:
DEFB +0x00
_read_index:
DEFB +0x00
_report:
DEFB +0x00
DEFB +0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
_previous:
DEFB +0x00
DEFB +0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00

39
Source/HBIOS/ch376-native/print.asm

@ -0,0 +1,39 @@
; HL = unsigned 16 bit number to write out
; call CHPUT to write a single ascii character (in A)
_print_uint16:
ld a, h
or l
jr z, print_zero
ld e, 0
ld bc, -10000
call num1
ld bc, -1000
call num1
ld bc, -100
call num1
ld c, -10
call num1
ld c, b
num1: ld a, '0'-1
num2: inc a
add hl, bc
jr c, num2
sbc hl, bc
cp '0'
jr nz, num3
ld a, e
cp 1
ret nz
ld a, '0'
num3:
ld e, 1
jp COUT
print_zero
ld a, '0'
jp COUT

125
Source/HBIOS/ch376-native/readme.md

@ -0,0 +1,125 @@
# Native CH376 Driver
The native CH376 HBIOS driver is written in c, using z88dk's zcc compiler.
The build process, is a 3 stage process.
1. Compile all the C code to assembly files (.asm)
2. Translate the produced .asm files syntax to compile with the RomWBW assembler (.s)
3. Assemble the driver .s files as per the standard HBIOS build process
The original C code and produced/translated .s files are all committed units in the repo. But it is
expected, that only the c files are to be modified/updated.
The .s files are checked in, so builders do not require the C compiler tool chain (z88dk) to be installed.
The c compiling/translating process is only supported on linux, as the script to translate the .asm files
to .s files is a linux bash script. (Although the script can be easily run within Windows's Sub-system for linux)
## Compiling the C code
> Requires linux with docker installed.
> The C code only needs to be recompiled if and when you change any of the `.c` source files.
To compile the `.c` code to generate updated `.s` files:
Within the `Source/HBIOS/ch376-native` directory:
```
make
```
The make script will search for z88dk's `zcc` compiler, if not found, will attempt to use a docker wrapper.
It will not work if z88dk or docker is not installed.
## USB Native Driver systems
The default builds of RomWBW do not enable the CH376 native usb drivers. These drivers take a reasonable chunk of ROM space. As such you
will need to build a new HBIOS image customised for your platform. Please familiarise yourself with the HBIOS/RomWBW build and configuration process.
The usb driver is divided into a few sub-system, which can be individually enabled within the standard HBIOS config files.
For activating the full native USB support, the non native CH365 drivers need to be disabled and the relevant `CHNATIVE` drivers enabled
Example:
```
CHENABLE .SET FALSE ; CH: ENABLE CH375/376 USB SUPPORT
CH0USBENABLE .SET FALSE ; CH375: ENABLE CH375 USB DRIVER
CH1USBENABLE .SET FALSE ; CH376: ENABLE CH376 USB DRIVER
CHNATIVEENABLE .SET TRUE ; CH376: ENABLE CH376 NATIVE USB DRIVER
CHSCSIENABLE .SET TRUE ; CH376: ENABLE CH376 NATIVE MASS STORAGE DEVICES (REQUIRES CHNATIVEENABLE)
CHUFIENABLE .SET TRUE ; CH376: ENABLE CH376 NATIVE UFI FLOPPY DISK DEVICES (REQUIRES CHNATIVEENABLE)
CHNATIVEEZ80 .SET FALSE ; CH376: DELEGATE USB DRIVERS TO EZ80'S FIRMWARE
CHNATIVEFORCE .SET TRUE ; CH376: DISABLE AUTO-DETECTION OF MODULE - ASSUME ITS INSTALLED
```
As the USB driver is a fairly large, you may need to disable other HBIOS drivers in your configuration. As such, it is
recommend to only enable drivers for your platform's hardware configuration - for example, enable only the serial driver
required for your system.
```
DUARTENABLE .SET FALSE ; DUART: ENABLE 2681/2692 SERIAL DRIVER (DUART.ASM)
UARTENABLE .SET FALSE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM)
ACIAENABLE .SET FALSE ; ACIA: ENABLE MOTOROLA 6850 ACIA DRIVER (ACIA.ASM)
SIOENABLE .SET TRUE ; SIO: ENABLE ZILOG SIO SERIAL DRIVER (SIO.ASM)
```
You may also need to disable other storage drivers:
```
FDENABLE .SET FALSE ; FD: ENABLE FLOPPY DISK DRIVER (FD.ASM)
IDEENABLE .SET FALSE ; IDE: ENABLE IDE DISK DRIVER (IDE.ASM)
PPIDEENABLE .SET FALSE ; PPIDE: ENABLE PARALLEL PORT IDE DISK DRIVER (PPIDE.ASM)
```
### base-drv `CHNATIVEENABLE`
The `base-drv` system contains the core code to discover, enumerate, and communicate with USB devices.
It also includes the driver code to enumerate and operating USB devices through a USB hub.
### scsi-drv `CHSCSIENABLE`
The `scsi-drv` system can be enabled with the HBIOS config `CHSCSIENABLE`
When activated, access to most USB mass storage devices (thumb drives, magnetic usb drives) is enabled.
### ufi-drv `CHUFIENABLE`
The `ufi-drv` system can be enabled with the HBIOS config `CHUFIENABLE`
When activated, access to 3.5" Floppy USB devices will be enabled.
### keyboard `TMSMODE_MSXUKY`
The `keyboard` system can be enabled with the inferred config entry `USBKYBENABLE`
This config item is not to be directly set, but is activated via the TMS keyboard driver
Example configuration, combined with the TMS VDP module driver.
```
TMSENABLE .SET TRUE ; TMS: ENABLE TMS9918 VIDEO/KBD DRIVER (TMS.ASM)
TMSMODE .SET TMSMODE_MSXUKY ; TMS: DRIVER MODE: TMSMODE_[SCG|N8|MSX|MSXKBD|MSXMKY|MBC|COLECO|DUO|NABU|MSXUKY]
TMS80COLS .SET FALSE ; TMS: ENABLE 80 COLUMN SCREEN, REQUIRES V9958
TMSTIMENABLE .SET TRUE ; TMS: ENABLE TIMER INTERRUPTS (REQUIRES IM1)
```
When activated, usb keyboards can be used as input devices.
### Force activation `CHNATIVEFORCE`
The CH376 module, during a cold power on boot, can take many seconds before it will
respond to the CPU. As such, the CPU may fail to detect the presence of the module.
A manual reset (without power cycling) generally enables detection. The config entry
`CHNATIVEFORCE` can be enabled to force the CPU to always wait for the module to come online.
### eZ80 support `CHNATIVEEZ80`
If you have the eZ80 CPU installed with onboard USB firmware support, you
can gain performance by delegating HBIOS to the firmware implementation. To enable
delegation, enable the config entry `CHNATIVEEZ80`

8
Source/HBIOS/ch376-native/scsi-drv.s

@ -0,0 +1,8 @@
; Generated File -- not to be modify directly
#IF (!CHNATIVEEZ80)
#include "ch376-native/scsi-drv/class_scsi.c.s"
#ENDIF
#IF (!CHNATIVEEZ80)
#include "ch376-native/scsi-drv/scsi_driver.c.s"
#ENDIF
#include "ch376-native/scsi-drv/scsi-init.c.s"

1
Source/HBIOS/ch376-native/scsi-drv/.gitignore

@ -0,0 +1 @@
*.asm

446
Source/HBIOS/ch376-native/scsi-drv/class_scsi.c.s

@ -0,0 +1,446 @@
;
; Generated from source-doc/scsi-drv/class_scsi.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
_scsi_command_block_wrapper:
DEFS 15
_next_tag:
DEFS 2
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/scsi-drv/class_scsi.c:11: usb_error do_scsi_cmd(device_config_storage *const dev,
; ---------------------------------
; Function do_scsi_cmd
; ---------------------------------
_do_scsi_cmd:
push ix
ld ix,0
add ix,sp
ld hl, -21
add hl, sp
ld sp, hl
;source-doc/scsi-drv/class_scsi.c:17: _scsi_command_status_wrapper csw = {{{0}}};
ld a,0x00
ld (ix-21),a
ld (ix-20),a
ld (ix-19),a
ld (ix-18),a
xor a
ld (ix-17),a
ld (ix-16),a
xor a
ld (ix-15),a
ld (ix-14),a
ld a,0x00
ld (ix-13),a
ld (ix-12),a
ld (ix-11),a
ld (ix-10),a
ld (ix-9),0x00
;source-doc/scsi-drv/class_scsi.c:19: cbw->dCBWTag[0] = next_tag++;
ld c,(ix+6)
ld b,(ix+7)
ld hl,0x0004
add hl, bc
ld (ix-8),l
ld (ix-7),h
ld a, (_next_tag)
ld e, a
ld hl,_next_tag + 1
ld d, (hl)
ld hl, (_next_tag)
inc hl
ld (_next_tag), hl
ld l,(ix-8)
ld h,(ix-7)
ld (hl), e
inc hl
ld (hl), d
;source-doc/scsi-drv/class_scsi.c:21: if (!send)
bit 0,(ix+10)
jr NZ,l_do_scsi_cmd_00102
;source-doc/scsi-drv/class_scsi.c:22: cbw->bmCBWFlags = 0x80;
ld hl,0x000c
add hl, bc
ld (hl),0x80
l_do_scsi_cmd_00102:
;source-doc/scsi-drv/class_scsi.c:24: critical_begin();
push bc
call _critical_begin
pop bc
;source-doc/scsi-drv/class_scsi.c:27: &dev->endpoints[ENDPOINT_BULK_OUT]));
ld a,(ix+4)
ld (ix-6),a
ld e, a
ld a,(ix+5)
ld (ix-5),a
ld d,a
inc de
inc de
inc de
ld a,(ix-6)
ld (ix-4),a
ld l, a
ld a,(ix-5)
ld (ix-3),a
ld h,a
ld a, (hl)
rlca
rlca
rlca
rlca
and 0x0f
ld l,(ix+6)
ld h,(ix+7)
push bc
push de
push de
push af
inc sp
push hl
ld hl,0x001f
ex (sp), hl
push hl
call _usb_data_out_transfer
pop af
pop af
pop af
inc sp
pop de
pop bc
ld a, l
or a
jp NZ, l_do_scsi_cmd_00120
;source-doc/scsi-drv/class_scsi.c:29: if (cbw->dCBWDataTransferLength != 0) {
ld hl,8
add hl, bc
ld c, (hl)
inc hl
ld b, (hl)
inc hl
inc hl
ld a, (hl)
dec hl
ld l, (hl)
or l
or b
or c
jr Z,l_do_scsi_cmd_00113
;source-doc/scsi-drv/class_scsi.c:32: &dev->endpoints[ENDPOINT_BULK_IN]));
ld (ix-2),c
ld (ix-1),b
ld c,(ix+8)
ld b,(ix+9)
;source-doc/scsi-drv/class_scsi.c:30: if (!send) {
bit 0,(ix+10)
jr NZ,l_do_scsi_cmd_00110
;source-doc/scsi-drv/class_scsi.c:32: &dev->endpoints[ENDPOINT_BULK_IN]));
ld a,(ix-6)
add a,0x06
ld e, a
ld a,(ix-5)
adc a,0x00
ld d, a
ld l,(ix-4)
ld h,(ix-3)
ld a, (hl)
rlca
rlca
rlca
rlca
and 0x0f
push de
push af
inc sp
ld l,(ix-2)
ld h,(ix-1)
push hl
push bc
call _usb_data_in_transfer
pop af
pop af
pop af
inc sp
ld a, l
or a
jr Z,l_do_scsi_cmd_00113
jr l_do_scsi_cmd_00120
l_do_scsi_cmd_00110:
;source-doc/scsi-drv/class_scsi.c:36: &dev->endpoints[ENDPOINT_BULK_OUT]));
ld l,(ix-4)
ld h,(ix-3)
ld a, (hl)
rlca
rlca
rlca
rlca
and 0x0f
push de
push af
inc sp
ld l,(ix-2)
ld h,(ix-1)
push hl
push bc
call _usb_data_out_transfer
pop af
pop af
pop af
inc sp
ld a, l
or a
jr NZ,l_do_scsi_cmd_00120
l_do_scsi_cmd_00113:
;source-doc/scsi-drv/class_scsi.c:41: usb_data_in_transfer((uint8_t *)&csw, sizeof(_scsi_command_status_wrapper), dev->address, &dev->endpoints[ENDPOINT_BULK_IN]));
ld a,(ix-6)
add a,0x06
ld c, a
ld a,(ix-5)
adc a,0x00
ld b, a
ld l,(ix-4)
ld h,(ix-3)
ld a, (hl)
rlca
rlca
rlca
rlca
and 0x0f
ld d, a
push bc
push de
inc sp
ld hl,0x000d
push hl
ld hl,5
add hl, sp
push hl
call _usb_data_in_transfer
pop af
pop af
pop af
inc sp
ld a, l
or a
jr NZ,l_do_scsi_cmd_00120
;source-doc/scsi-drv/class_scsi.c:43: if (csw.bCSWStatus != 0 || csw.dCSWTag[0] != cbw->dCBWTag[0])
ld a,(ix-9)
or a
jr NZ,l_do_scsi_cmd_00116
ld c,(ix-17)
ld b,(ix-16)
ld l,(ix-8)
ld h,(ix-7)
ld a, (hl)
inc hl
ld h, (hl)
ld l, a
xor a
sbc hl,bc
jr Z,l_do_scsi_cmd_00117
l_do_scsi_cmd_00116:
;source-doc/scsi-drv/class_scsi.c:44: result = USB_ERR_FAIL;
ld l,0x0e
jr l_do_scsi_cmd_00120
l_do_scsi_cmd_00117:
;source-doc/scsi-drv/class_scsi.c:46: result = USB_ERR_OK;
ld l,0x00
;source-doc/scsi-drv/class_scsi.c:48: done:
l_do_scsi_cmd_00120:
;source-doc/scsi-drv/class_scsi.c:49: critical_end();
push hl
call _critical_end
pop hl
;source-doc/scsi-drv/class_scsi.c:50: return result;
;source-doc/scsi-drv/class_scsi.c:51: }
ld sp, ix
pop ix
ret
;source-doc/scsi-drv/class_scsi.c:53: usb_error scsi_test(device_config_storage *const dev) {
; ---------------------------------
; Function scsi_test
; ---------------------------------
_scsi_test:
push ix
ld ix,0
add ix,sp
ld hl, -27
add hl, sp
ld sp, hl
;source-doc/scsi-drv/class_scsi.c:55: cbw_scsi.cbw = scsi_command_block_wrapper;
ld hl,0
add hl, sp
ld e,l
ld d,h
push hl
ld bc,0x000f
ld hl,_scsi_command_block_wrapper
ldir
;source-doc/scsi-drv/class_scsi.c:56: memset(&cbw_scsi.test, 0, sizeof(_scsi_packet_test));
ld hl,17
add hl, sp
ld b,0x06
l_scsi_test_00103:
xor a
ld (hl), a
inc hl
ld (hl), a
inc hl
djnz l_scsi_test_00103
pop bc
;source-doc/scsi-drv/class_scsi.c:58: cbw_scsi.cbw.bCBWLUN = 0;
ld (ix-14),0x00
;source-doc/scsi-drv/class_scsi.c:59: cbw_scsi.cbw.bCBWCBLength = sizeof(_scsi_packet_test);
ld (ix-13),0x0c
;source-doc/scsi-drv/class_scsi.c:60: cbw_scsi.cbw.dCBWDataTransferLength = 0;
ld hl,0x0008
add hl, bc
xor a
ld (hl), a
inc hl
ld (hl), a
inc hl
ld (hl), a
inc hl
ld (hl), a
;source-doc/scsi-drv/class_scsi.c:62: return do_scsi_cmd(dev, &cbw_scsi.cbw, 0, false);
xor a
push af
inc sp
ld hl,0x0000
push hl
push bc
ld l,(ix+4)
ld h,(ix+5)
push hl
call _do_scsi_cmd
;source-doc/scsi-drv/class_scsi.c:63: }
ld sp,ix
pop ix
ret
;source-doc/scsi-drv/class_scsi.c:67: usb_error scsi_request_sense(device_config_storage *const dev, scsi_sense_result *const sens_result) {
; ---------------------------------
; Function scsi_request_sense
; ---------------------------------
_scsi_request_sense:
push ix
ld ix,0
add ix,sp
ld hl, -27
add hl, sp
ld sp, hl
;source-doc/scsi-drv/class_scsi.c:69: cbw_scsi.cbw = scsi_command_block_wrapper;
ld hl,0
add hl, sp
ld e,l
ld d,h
push hl
ld bc,0x000f
ld hl,_scsi_command_block_wrapper
ldir
;source-doc/scsi-drv/class_scsi.c:70: cbw_scsi.request_sense = scsi_packet_request_sense;
ld hl,17
add hl, sp
ex de, hl
ld bc,0x000c
ld hl,_scsi_packet_request_sense
ldir
pop bc
;source-doc/scsi-drv/class_scsi.c:72: cbw_scsi.cbw.bCBWLUN = 0;
ld (ix-14),0x00
;source-doc/scsi-drv/class_scsi.c:73: cbw_scsi.cbw.bCBWCBLength = sizeof(_scsi_packet_request_sense);
ld (ix-13),0x0c
;source-doc/scsi-drv/class_scsi.c:74: cbw_scsi.cbw.dCBWDataTransferLength = sizeof(scsi_sense_result);
ld hl,0x0008
add hl, bc
ld (hl),0x12
inc hl
xor a
ld (hl), a
inc hl
ld (hl), a
inc hl
ld (hl), a
;source-doc/scsi-drv/class_scsi.c:76: return do_scsi_cmd(dev, &cbw_scsi.cbw, sens_result, false);
ld e,(ix+6)
ld d,(ix+7)
xor a
push af
inc sp
push de
push bc
ld l,(ix+4)
ld h,(ix+5)
push hl
call _do_scsi_cmd
;source-doc/scsi-drv/class_scsi.c:77: }
ld sp,ix
pop ix
ret
_scsi_packet_request_sense:
DEFB +0x03
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x12
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
_scsi_command_block_wrapper:
DEFB +0x55
DEFB +0x53
DEFB +0x42
DEFB +0x43
DEFW +0x0000
DEFW +0x0000
DEFB +0x00,0x00, +0x00, +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
_next_tag:
DEFW +0x0000

148
Source/HBIOS/ch376-native/scsi-drv/scsi-init.c.s

@ -0,0 +1,148 @@
;
; Generated from source-doc/scsi-drv/scsi-init.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/scsi-drv/scsi-init.c:9: void chscsi_init(void) {
; ---------------------------------
; Function chscsi_init
; ---------------------------------
_chscsi_init:
push ix
ld ix,0
add ix,sp
push af
dec sp
;source-doc/scsi-drv/scsi-init.c:11: do {
ld (ix-1),0x01
l_chscsi_init_00103:
;source-doc/scsi-drv/scsi-init.c:12: usb_device_type t = usb_get_device_type(index);
ld a,(ix-1)
ld (ix-3),a
ld (ix-2),0x00
pop hl
push hl
push hl
call _usb_get_device_type
pop af
ld a, l
;source-doc/scsi-drv/scsi-init.c:14: if (t == USB_IS_MASS_STORAGE) {
sub 0x02
jr NZ,l_chscsi_init_00104
;source-doc/scsi-drv/scsi-init.c:15: const uint8_t dev_index = find_storage_dev(); // index == -1 (no more left) should never happen
call _find_storage_dev
;source-doc/scsi-drv/scsi-init.c:17: hbios_usb_storage_devices[dev_index].drive_index = dev_index + 1;
ld a, l
ld c,0x00
add a, a
rl c
add a, +((_hbios_usb_storage_devices) & 0xFF)
ld e, a
ld a, c
adc a, +((_hbios_usb_storage_devices) / 256)
ld d, a
ld c, e
ld b, d
ld a, l
inc a
ld (bc), a
;source-doc/scsi-drv/scsi-init.c:18: hbios_usb_storage_devices[dev_index].usb_device = index;
ld c, e
ld b, d
inc bc
ld a,(ix-1)
ld (bc), a
;source-doc/scsi-drv/scsi-init.c:20: print_string("\r\nUSB: MASS STORAGE @ $");
push hl
push de
ld hl,scsi_init_str_0
call _print_string
;source-doc/scsi-drv/scsi-init.c:21: print_uint16(index);
ld l,(ix-3)
ld h,0x00
call _print_uint16
;source-doc/scsi-drv/scsi-init.c:22: print_string(":$");
ld hl,scsi_init_str_1
call _print_string
pop de
pop hl
;source-doc/scsi-drv/scsi-init.c:23: print_uint16(dev_index);
ld h,0x00
push de
call _print_uint16
;source-doc/scsi-drv/scsi-init.c:24: print_string(" $");
ld hl,scsi_init_str_2
call _print_string
;source-doc/scsi-drv/scsi-init.c:25: usb_scsi_init(index);
ld l,(ix-3)
ld h,0x00
push hl
call _usb_scsi_init
pop af
pop de
;source-doc/scsi-drv/scsi-init.c:26: dio_add_entry(ch_scsi_fntbl, &hbios_usb_storage_devices[dev_index]);
ld hl,_ch_scsi_fntbl
call _dio_add_entry
l_chscsi_init_00104:
;source-doc/scsi-drv/scsi-init.c:29: } while (++index != MAX_NUMBER_OF_DEVICES + 1);
inc (ix-1)
ld a,(ix-1)
sub 0x07
jr NZ,l_chscsi_init_00103
;source-doc/scsi-drv/scsi-init.c:30: }
ld sp, ix
pop ix
ret
scsi_init_str_0:
DEFB 0x0d
DEFB 0x0a
DEFM "USB: MASS STORAGE @ $"
DEFB 0x00
scsi_init_str_1:
DEFM ":$"
DEFB 0x00
scsi_init_str_2:
DEFM " $"
DEFB 0x00

470
Source/HBIOS/ch376-native/scsi-drv/scsi_driver.c.s

@ -0,0 +1,470 @@
;
; Generated from source-doc/scsi-drv/scsi_driver.c.asm -- not to be modify directly
;
;
;--------------------------------------------------------
; File Created by SDCC : free open source ISO C Compiler
; Version 4.5.0 #15248 (Linux)
;--------------------------------------------------------
; Processed by Z88DK
;--------------------------------------------------------
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
;--------------------------------------------------------
; Externals used
;--------------------------------------------------------
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
#IF 0
; .area _INITIALIZED removed by z88dk
_scsi_packet_read_capacity:
DEFS 12
_cbw:
DEFS 27
#ENDIF
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;--------------------------------------------------------
; Home
;--------------------------------------------------------
;--------------------------------------------------------
; code
;--------------------------------------------------------
;source-doc/scsi-drv/scsi_driver.c:8: usb_error usb_scsi_init(const uint16_t dev_index) {
; ---------------------------------
; Function usb_scsi_init
; ---------------------------------
_usb_scsi_init:
push ix
ld ix,0
add ix,sp
ld hl, -18
add hl, sp
ld sp, hl
;source-doc/scsi-drv/scsi_driver.c:11: device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index);
ld a,(ix+4)
call _get_usb_device_config
;source-doc/scsi-drv/scsi_driver.c:16: critical_begin();
push de
call _critical_begin
pop de
;source-doc/scsi-drv/scsi_driver.c:17: while ((result = scsi_test(dev)) && --counter > 0)
ld c,0x03
l_usb_scsi_init_00102:
push bc
push de
push de
call _scsi_test
pop af
ld a, l
pop de
pop bc
ld l, a
or a
jr Z,l_usb_scsi_init_00104
dec c
jr Z,l_usb_scsi_init_00104
;source-doc/scsi-drv/scsi_driver.c:18: scsi_request_sense(dev, &response);
push bc
push de
ld hl,4
add hl, sp
push hl
push de
call _scsi_request_sense
pop af
pop af
pop de
pop bc
jr l_usb_scsi_init_00102
l_usb_scsi_init_00104:
;source-doc/scsi-drv/scsi_driver.c:19: critical_end();
push hl
call _critical_end
pop hl
;source-doc/scsi-drv/scsi_driver.c:21: return result;
;source-doc/scsi-drv/scsi_driver.c:22: }
ld sp, ix
pop ix
ret
;source-doc/scsi-drv/scsi_driver.c:26: usb_error usb_scsi_read_capacity(const uint16_t dev_index, scsi_read_capacity_result *cap_result) {
; ---------------------------------
; Function usb_scsi_read_capacity
; ---------------------------------
_usb_scsi_read_capacity:
push ix
ld ix,0
add ix,sp
ld hl, -27
add hl, sp
ld sp, hl
;source-doc/scsi-drv/scsi_driver.c:27: device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index);
ld a,(ix+4)
call _get_usb_device_config
;source-doc/scsi-drv/scsi_driver.c:30: cbw_scsi.cbw = scsi_command_block_wrapper;
push de
ld hl,2
add hl, sp
ex de, hl
ld bc,0x000f
ld hl,_scsi_command_block_wrapper
ldir
pop de
;source-doc/scsi-drv/scsi_driver.c:31: cbw_scsi.read_capacity = scsi_packet_read_capacity;
push de
ld hl,17
add hl, sp
ex de, hl
ld bc,0x000c
ld hl,_scsi_packet_read_capacity
ldir
pop de
;source-doc/scsi-drv/scsi_driver.c:33: cbw_scsi.cbw.bCBWLUN = 0;
ld (ix-14),0x00
;source-doc/scsi-drv/scsi_driver.c:34: cbw_scsi.cbw.bCBWCBLength = sizeof(_scsi_read_capacity);
ld (ix-13),0x0c
;source-doc/scsi-drv/scsi_driver.c:35: cbw_scsi.cbw.dCBWDataTransferLength = sizeof(scsi_read_capacity_result);
ld (ix-19),0x08
xor a
ld (ix-18),a
ld (ix-17),a
ld (ix-16),a
;source-doc/scsi-drv/scsi_driver.c:37: return do_scsi_cmd(dev, &cbw_scsi.cbw, cap_result, false);
ld c,(ix+6)
ld b,(ix+7)
xor a
push af
inc sp
push bc
ld hl,3
add hl, sp
push hl
push de
call _do_scsi_cmd
pop af
pop af
pop af
inc sp
;source-doc/scsi-drv/scsi_driver.c:38: }
ld sp, ix
pop ix
ret
;source-doc/scsi-drv/scsi_driver.c:58: usb_error usb_scsi_read(const uint16_t dev_index, uint8_t *const buffer) {
; ---------------------------------
; Function usb_scsi_read
; ---------------------------------
_usb_scsi_read:
push ix
ld ix,0
add ix,sp
push af
;source-doc/scsi-drv/scsi_driver.c:61: device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index);
ld a,(ix+4)
call _get_usb_device_config
pop bc
push de
;source-doc/scsi-drv/scsi_driver.c:63: memset(&cbw, 0, sizeof(cbw_scsi_read_write));
ld de,_cbw
ld l, e
ld h, d
ld b,0x0e
jr l_usb_scsi_read_00113
l_usb_scsi_read_00112:
ld (hl),0x00
inc hl
l_usb_scsi_read_00113:
ld (hl),0x00
inc hl
djnz l_usb_scsi_read_00112
;source-doc/scsi-drv/scsi_driver.c:64: cbw.cbw = scsi_command_block_wrapper;
ld bc,0x000f
ld hl,_scsi_command_block_wrapper
ldir
;source-doc/scsi-drv/scsi_driver.c:66: cbw.cbw.bCBWLUN = 0;
ld hl,_cbw + 13
ld (hl),0x00
;source-doc/scsi-drv/scsi_driver.c:67: cbw.cbw.bCBWCBLength = sizeof(_scsi_packet_read_write);
ld hl,_cbw + 14
ld (hl),0x0c
;source-doc/scsi-drv/scsi_driver.c:68: cbw.cbw.dCBWDataTransferLength = 512;
ld hl,0x0200
ld (_cbw + 8),hl
ld h, l
ld (_cbw + 8 + 2),hl
;source-doc/scsi-drv/scsi_driver.c:70: cbw.scsi_cmd.operation_code = 0x28; // read operation
ld hl,_cbw + 15
ld (hl),0x28
;source-doc/scsi-drv/scsi_driver.c:71: cbw.scsi_cmd.transfer_len[1] = 1;
ld hl,_cbw + 23
ld (hl),0x01
;source-doc/scsi-drv/scsi_driver.c:72: cbw.scsi_cmd.lba[0] = dev->current_lba >> 24;
pop hl
push hl
ld de,0x000c
add hl, de
push hl
inc hl
inc hl
inc hl
ld a, (hl)
ld ((_cbw + 17)),a
pop hl
;source-doc/scsi-drv/scsi_driver.c:73: cbw.scsi_cmd.lba[1] = dev->current_lba >> 16;
push hl
inc hl
inc hl
ld a, (hl)
ld ((_cbw + 18)),a
pop hl
;source-doc/scsi-drv/scsi_driver.c:74: cbw.scsi_cmd.lba[2] = dev->current_lba >> 8;
push hl
inc hl
ld a, (hl)
ld ((_cbw + 19)),a
pop hl
;source-doc/scsi-drv/scsi_driver.c:75: cbw.scsi_cmd.lba[3] = dev->current_lba;
ld bc,_cbw + 20
ld a, (hl)
ld (bc), a
;source-doc/scsi-drv/scsi_driver.c:77: result = do_scsi_cmd(dev, &cbw.cbw, buffer, false);
ld c,(ix+6)
ld b,(ix+7)
push hl
xor a
push af
inc sp
push bc
ld de,_cbw
push de
ld e,(ix-2)
ld d,(ix-1)
push de
call _do_scsi_cmd
pop af
pop af
pop af
inc sp
ld a, l
pop hl
ld (ix-1),a
;source-doc/scsi-drv/scsi_driver.c:79: if (result == USB_ERR_OK)
or a
jr NZ,l_usb_scsi_read_00102
;source-doc/scsi-drv/scsi_driver.c:80: dev->current_lba++;
ld c,(hl)
push hl
inc hl
ld b, (hl)
inc hl
ld e, (hl)
inc hl
ld d, (hl)
pop hl
inc c
jr NZ,l_usb_scsi_read_00114
inc b
jr NZ,l_usb_scsi_read_00114
inc de
l_usb_scsi_read_00114:
ld (hl), c
inc hl
ld (hl), b
inc hl
ld (hl), e
inc hl
ld (hl), d
l_usb_scsi_read_00102:
;source-doc/scsi-drv/scsi_driver.c:81: return result;
ld l,(ix-1)
;source-doc/scsi-drv/scsi_driver.c:82: }
ld sp, ix
pop ix
ret
;source-doc/scsi-drv/scsi_driver.c:84: usb_error usb_scsi_write(const uint16_t dev_index, uint8_t *const buffer) {
; ---------------------------------
; Function usb_scsi_write
; ---------------------------------
_usb_scsi_write:
push ix
ld ix,0
add ix,sp
push af
;source-doc/scsi-drv/scsi_driver.c:86: device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index);
ld a,(ix+4)
call _get_usb_device_config
pop bc
push de
;source-doc/scsi-drv/scsi_driver.c:88: memset(&cbw, 0, sizeof(cbw_scsi_read_write));
ld de,_cbw
ld l, e
ld h, d
ld b,0x0e
jr l_usb_scsi_write_00113
l_usb_scsi_write_00112:
ld (hl),0x00
inc hl
l_usb_scsi_write_00113:
ld (hl),0x00
inc hl
djnz l_usb_scsi_write_00112
;source-doc/scsi-drv/scsi_driver.c:89: cbw.cbw = scsi_command_block_wrapper;
ld bc,0x000f
ld hl,_scsi_command_block_wrapper
ldir
;source-doc/scsi-drv/scsi_driver.c:91: cbw.cbw.bCBWLUN = 0;
ld hl,_cbw + 13
ld (hl),0x00
;source-doc/scsi-drv/scsi_driver.c:92: cbw.cbw.bCBWCBLength = sizeof(_scsi_packet_read_write);
ld hl,_cbw + 14
ld (hl),0x0c
;source-doc/scsi-drv/scsi_driver.c:93: cbw.cbw.dCBWDataTransferLength = 512;
ld hl,0x0200
ld (_cbw + 8),hl
ld h, l
ld (_cbw + 8 + 2),hl
;source-doc/scsi-drv/scsi_driver.c:95: cbw.scsi_cmd.operation_code = 0x2A; // write operation
ld hl,_cbw + 15
ld (hl),0x2a
;source-doc/scsi-drv/scsi_driver.c:96: cbw.scsi_cmd.transfer_len[1] = 1;
ld hl,_cbw + 23
ld (hl),0x01
;source-doc/scsi-drv/scsi_driver.c:97: cbw.scsi_cmd.lba[0] = dev->current_lba >> 24;
pop hl
push hl
ld de,0x000c
add hl, de
push hl
inc hl
inc hl
inc hl
ld a, (hl)
ld ((_cbw + 17)),a
pop hl
;source-doc/scsi-drv/scsi_driver.c:98: cbw.scsi_cmd.lba[1] = dev->current_lba >> 16;
push hl
inc hl
inc hl
ld a, (hl)
ld ((_cbw + 18)),a
pop hl
;source-doc/scsi-drv/scsi_driver.c:99: cbw.scsi_cmd.lba[2] = dev->current_lba >> 8;
push hl
inc hl
ld a, (hl)
ld ((_cbw + 19)),a
pop hl
;source-doc/scsi-drv/scsi_driver.c:100: cbw.scsi_cmd.lba[3] = dev->current_lba;
ld bc,_cbw + 20
ld a, (hl)
ld (bc), a
;source-doc/scsi-drv/scsi_driver.c:102: result = do_scsi_cmd(dev, &cbw.cbw, buffer, true);
ld c,(ix+6)
ld b,(ix+7)
push hl
ld a,0x01
push af
inc sp
push bc
ld de,_cbw
push de
ld e,(ix-2)
ld d,(ix-1)
push de
call _do_scsi_cmd
pop af
pop af
pop af
inc sp
ld a, l
pop hl
ld (ix-1),a
;source-doc/scsi-drv/scsi_driver.c:104: if (result == USB_ERR_OK)
or a
jr NZ,l_usb_scsi_write_00102
;source-doc/scsi-drv/scsi_driver.c:105: dev->current_lba++;
ld c,(hl)
push hl
inc hl
ld b, (hl)
inc hl
ld e, (hl)
inc hl
ld d, (hl)
pop hl
inc c
jr NZ,l_usb_scsi_write_00114
inc b
jr NZ,l_usb_scsi_write_00114
inc de
l_usb_scsi_write_00114:
ld (hl), c
inc hl
ld (hl), b
inc hl
ld (hl), e
inc hl
ld (hl), d
l_usb_scsi_write_00102:
;source-doc/scsi-drv/scsi_driver.c:106: return result;
ld l,(ix-1)
;source-doc/scsi-drv/scsi_driver.c:107: }
ld sp, ix
pop ix
ret
_scsi_packet_read_capacity:
DEFB +0x25
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
_cbw:
DEFB +0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB +0x00,0x00, +0x00, +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB +0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB 0x00
DEFB +0x00
DEFB 0x00
DEFB 0x00
DEFB +0x00
DEFB 0x00
DEFB 0x00

13
Source/HBIOS/ch376-native/source-doc/.clang-format

@ -0,0 +1,13 @@
BasedOnStyle: LLVM
IndentWidth: 2
AlignConsecutiveMacros: true
ColumnLimit: 132
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true
AlignEscapedNewlines: true
AlignConsecutiveMacros: true
AlignEscapedNewlines: Right
BinPackArguments: true
BinPackParameters: false
IncludeBlocks: Preserve
SortIncludes: CaseInsensitive

242
Source/HBIOS/ch376-native/source-doc/base-drv/ch376.c

@ -0,0 +1,242 @@
#include "ch376.h"
#include "ez80-helpers.h"
#include "print.h"
void ch_command(const uint8_t command) __z88dk_fastcall {
uint8_t counter = 255;
while ((CH376_COMMAND_PORT & PARA_STATE_BUSY) && --counter != 0)
;
// if (counter == 0) {
// It appears that the Ch376 has become blocked
// command will fail and timeout will eventually be returned by the ch_xxx_wait_int_and_get_status
// todo consider a return value to allow callers to respond appropriately
// Experimentation would indicate that USB_RESET_ALL will still work to reset chip
// return;
// }
CH376_COMMAND_PORT = command;
}
extern usb_error ch_wait_int_and_get_status(const int16_t timeout) __z88dk_fastcall;
usb_error ch_long_wait_int_and_get_status(void) { return ch_wait_int_and_get_status(5000); }
usb_error ch_short_wait_int_and_get_status(void) { return ch_wait_int_and_get_status(100); }
usb_error ch_very_short_wait_int_and_get_status(void) { return ch_wait_int_and_get_status(10); }
usb_error ch_get_status(void) {
ch_command(CH_CMD_GET_STATUS);
uint8_t ch_status = CH376_DATA_PORT;
if (ch_status >= USB_FILERR_MIN && ch_status <= USB_FILERR_MAX)
return ch_status;
if (ch_status == CH_CMD_RET_SUCCESS)
return USB_ERR_OK;
if (ch_status == CH_USB_INT_SUCCESS)
return USB_ERR_OK;
if (ch_status == CH_USB_INT_CONNECT)
return USB_INT_CONNECT;
if (ch_status == CH_USB_INT_DISK_READ)
return USB_ERR_DISK_READ;
if (ch_status == CH_USB_INT_DISK_WRITE)
return USB_ERR_DISK_WRITE;
if (ch_status == CH_USB_INT_DISCONNECT) {
ch_cmd_set_usb_mode(5);
return USB_ERR_NO_DEVICE;
}
if (ch_status == CH_USB_INT_BUF_OVER)
return USB_ERR_DATA_ERROR;
ch_status &= 0x2F;
if (ch_status == 0x2A)
return USB_ERR_NAK;
if (ch_status == 0x2E)
return USB_ERR_STALL;
ch_status &= 0x23;
if (ch_status == 0x20)
return USB_ERR_TIMEOUT;
if (ch_status == 0x23)
return USB_TOKEN_OUT_OF_SYNC;
return USB_ERR_UNEXPECTED_STATUS_FROM_HOST;
}
void ch_cmd_reset_all(void) { ch_command(CH_CMD_RESET_ALL); }
inline uint8_t ch_cmd_check_exist(void) {
uint8_t complement;
ch_command(CH_CMD_CHECK_EXIST);
CH376_DATA_PORT = (uint8_t)~0x55;
delay();
complement = CH376_DATA_PORT;
return complement == 0x55;
// if (complement != 0x55)
// return false;
// ch_command(CH_CMD_CHECK_EXIST);
// CH376_DATA_PORT = (uint8_t)~0x89;
// delay();
// complement = CH376_DATA_PORT;
// return complement == 0x89;
}
uint8_t ch_probe(void) {
uint8_t i = 5;
do {
if (ch_cmd_check_exist())
return true;
delay_medium();
} while (--i != 0);
return false;
}
usb_error ch_cmd_set_usb_mode(const uint8_t mode) __z88dk_fastcall {
uint8_t result = 0;
CH376_COMMAND_PORT = CH_CMD_SET_USB_MODE;
delay();
CH376_DATA_PORT = mode;
delay();
uint8_t count = 127;
while (result != CH_CMD_RET_SUCCESS && result != CH_CMD_RET_ABORT && --count != 0) {
result = CH376_DATA_PORT;
delay();
}
return (result == CH_CMD_RET_SUCCESS) ? USB_ERR_OK : USB_ERR_FAIL;
}
uint8_t ch_cmd_get_ic_version(void) {
ch_command(CH_CMD_GET_IC_VER);
return CH376_DATA_PORT & 0x1f;
}
void ch_issue_token(const uint8_t toggle_bit, const uint8_t endpoint, const ch376_pid pid) {
ch_command(CH_CMD_ISSUE_TKN_X);
CH376_DATA_PORT = toggle_bit;
CH376_DATA_PORT = endpoint << 4 | pid;
}
void ch_issue_token_in(const endpoint_param *const endpoint) __z88dk_fastcall {
ch_issue_token(endpoint->toggle ? 0x80 : 0x00, endpoint->number, CH_PID_IN);
}
void ch_issue_token_out(const endpoint_param *const endpoint) __z88dk_fastcall {
ch_issue_token(endpoint->toggle ? 0x40 : 0x00, endpoint->number, CH_PID_OUT);
}
void ch_issue_token_out_ep0(void) { ch_issue_token(0x40, 0, CH_PID_OUT); }
void ch_issue_token_in_ep0(void) { ch_issue_token(0x80, 0, CH_PID_IN); }
void ch_issue_token_setup(void) { ch_issue_token(0, 0, CH_PID_SETUP); }
usb_error ch_data_in_transfer(uint8_t *buffer, int16_t buffer_size, endpoint_param *const endpoint) {
uint8_t count;
usb_error result;
if (buffer_size == 0)
return USB_ERR_OK;
USB_MODULE_LEDS = 0x01;
do {
ch_issue_token_in(endpoint);
result = ch_long_wait_int_and_get_status();
CHECK(result);
endpoint->toggle = !endpoint->toggle;
count = ch_read_data(buffer);
if (count == 0) {
USB_MODULE_LEDS = 0x00;
return USB_ERR_DATA_ERROR;
}
buffer += count;
buffer_size -= count;
} while (buffer_size > 0);
USB_MODULE_LEDS = 0x00;
return USB_ERR_OK;
done:
USB_MODULE_LEDS = 0x00;
return result;
}
// TODO: review: does buffer_size need to be signed?
usb_error ch_data_in_transfer_n(uint8_t *const buffer, uint8_t *const buffer_size, endpoint_param *const endpoint) {
uint8_t count;
usb_error result;
USB_MODULE_LEDS = 0x01;
ch_issue_token_in(endpoint);
CHECK(ch_long_wait_int_and_get_status());
endpoint->toggle = !endpoint->toggle;
count = ch_read_data(buffer);
*buffer_size = count;
USB_MODULE_LEDS = 0x00;
return USB_ERR_OK;
done:
USB_MODULE_LEDS = 0x00;
return result;
}
usb_error ch_data_out_transfer(const uint8_t *buffer, int16_t buffer_length, endpoint_param *const endpoint) {
usb_error result;
const uint8_t number = endpoint->number;
const uint8_t max_packet_size = calc_max_packet_size(endpoint->max_packet_sizex);
USB_MODULE_LEDS = 0x02;
while (buffer_length > 0) {
const uint8_t size = max_packet_size < buffer_length ? max_packet_size : buffer_length;
buffer = ch_write_data(buffer, size);
buffer_length -= size;
ch_issue_token_out(endpoint);
CHECK(ch_long_wait_int_and_get_status());
endpoint->toggle = !endpoint->toggle;
}
USB_MODULE_LEDS = 0x00;
return USB_ERR_OK;
done:
USB_MODULE_LEDS = 0x00;
return result;
}
void ch_set_usb_address(const uint8_t device_address) __z88dk_fastcall {
ch_command(CH_CMD_SET_USB_ADDR);
CH376_DATA_PORT = device_address;
}

176
Source/HBIOS/ch376-native/source-doc/base-drv/ch376.h

@ -0,0 +1,176 @@
#ifndef __CH376
#define __CH376
#include "ch376inc.h"
#include "delay.h"
#include <stdint.h>
#include <stdlib.h>
typedef enum {
USB_ERR_OK = 0,
USB_ERR_NAK = 1,
USB_ERR_STALL = 2,
USB_ERR_TIMEOUT = 3,
USB_ERR_DATA_ERROR = 4,
USB_ERR_NO_DEVICE = 5,
USB_ERR_PANIC_BUTTON_PRESSED = 6,
USB_TOKEN_OUT_OF_SYNC = 7,
USB_ERR_UNEXPECTED_STATUS_FROM_HOST = 8,
USB_ERR_CODE_EXCEPTION = 9,
USB_ERR_MEDIA_CHANGED = 10,
USB_ERR_MEDIA_NOT_PRESENT = 11,
USB_ERR_CH376_BLOCKED = 12,
USB_ERR_CH376_TIMEOUT = 13,
USB_ERR_FAIL = 14,
USB_ERR_MAX = 14,
USB_ERR_OTHER = 15,
USB_ERR_DISK_READ = 0x1D,
USB_ERR_DISK_WRITE = 0x1E,
USB_FILERR_MIN = 0x41,
USB_ERR_OPEN_DIR = 0x41,
USB_ERR_MISS_FILE = 0x42,
USB_FILERR_MAX = 0xB4,
USB_INT_CONNECT = 0x81,
USB_BAD_ADDRESS = 0x82,
USB_ERR_OUT_OF_MEMORY = 0x83,
USB_ERR_BUFF_TO_LARGE = 0x84,
USB_ERROR_DEVICE_NOT_FOUND = 0x85,
} usb_error;
typedef enum { CH_NAK_RETRY_DONT = 0b00, CH_NAK_RETRY_INDEFINITE = 0b10, CH_NAK_RETRY_3S = 0b11 } ch_nak_retry_type;
typedef enum {
USB_NOT_SUPPORTED = 0,
USB_IS_FLOPPY = 1,
USB_IS_MASS_STORAGE = 2,
USB_IS_CDC = 3,
USB_IS_KEYBOARD = 4,
USB_IS_UNKNOWN = 6,
_USB_LAST_DEVICE_TYPE,
USB_IS_HUB = 15
} usb_device_type; // 4 bits only
typedef enum { ENDPOINT_BULK_OUT = 0, ENDPOINT_BULK_IN = 1, ENDPOINT_INTERRUPT_IN = 2 } usb_endpoint_type;
extern int printf(const char *msg, ...);
#if STACK_TRACE_ENABLED
#define trace_printf printf
#define CHECK(fn) \
{ \
result = fn; \
if (result != USB_ERR_OK && result != USB_ERR_STALL) { \
if (result != USB_TOKEN_OUT_OF_SYNC) \
printf("Error: %s:%d %d\r\n", __FILE__, __LINE__, result); \
return result; \
} \
}
#define RETURN_CHECK(fn) \
{ \
result = fn; \
if (result != USB_ERR_OK && result != USB_ERR_STALL) { \
if (result != USB_TOKEN_OUT_OF_SYNC) \
printf("Error: %s:%d %d\r\n", __FILE__, __LINE__, result); \
return result; \
} \
return result; \
}
#define TRACE_USB_ERROR(result) \
{ \
if (result != USB_ERR_OK) { \
printf("USB: %s:%d %d\r\n", __FILE__, __LINE__, result); \
} \
}
#else
#define trace_printf(...)
#define CHECK(fn) \
{ \
result = fn; \
if (result != USB_ERR_OK) \
goto done; \
}
#define RETURN_CHECK(fn) \
{ \
result = fn; \
goto done; \
}
#define TRACE_USB_ERROR(result)
#endif
#define calc_max_packet_sizex(packet_size) (packet_size & 0x3FF)
#define calc_max_packet_size(packet_sizex) packet_sizex
typedef struct {
uint8_t toggle : 1;
uint8_t number : 3;
uint16_t max_packet_sizex : 10;
} endpoint_param;
#define CH_SPEED_FULL \
0 /* 12Mbps full speed FullSpeed ​​(default value) \
*/
#define CH_SPEED_LOW_FREQ 1 /* 1.5Mbps (modify frequency only) */
#define CH_SPEED_LOW 2 /* 1.5Mbps low speed LowSpeed */
#define CH_MODE_HOST_RESET 7
#define CH_MODE_HOST 6
typedef enum _ch376_pid { CH_PID_SETUP = DEF_USB_PID_SETUP, CH_PID_IN = DEF_USB_PID_IN, CH_PID_OUT = DEF_USB_PID_OUT } ch376_pid;
extern __sfr __banked CH376_DATA_PORT;
extern __sfr __banked CH376_COMMAND_PORT;
extern __sfr __banked USB_MODULE_LEDS;
extern void delay_20ms(void);
extern void delay_short(void);
extern void delay_medium(void);
extern void ch_command(const uint8_t command) __z88dk_fastcall;
extern usb_error ch_get_status(void);
extern usb_error ch_long_wait_int_and_get_status(void);
extern usb_error ch_short_wait_int_and_get_status(void);
extern usb_error ch_very_short_wait_int_and_get_status(void);
extern uint8_t ch_read_data(uint8_t *buffer) __sdcccall(1);
extern void ch_cmd_reset_all(void);
extern uint8_t ch_probe(void);
extern usb_error ch_cmd_set_usb_mode(const uint8_t mode) __z88dk_fastcall;
extern uint8_t ch_cmd_get_ic_version(void);
extern const uint8_t *ch_write_data(const uint8_t *buffer, uint8_t length);
extern void ch_set_usb_address(const uint8_t device_address) __z88dk_fastcall;
extern usb_error ch_control_transfer_request_descriptor(const uint8_t descriptor_type) __z88dk_fastcall;
extern usb_error ch_control_transfer_set_address(const uint8_t device_address) __z88dk_fastcall;
extern usb_error ch_control_transfer_set_config(const uint8_t config_value) __z88dk_fastcall;
extern usb_error ch_data_in_transfer(uint8_t *buffer, int16_t data_length, endpoint_param *const endpoint);
extern usb_error ch_data_in_transfer_n(uint8_t *buffer, uint8_t *const buffer_size, endpoint_param *const endpoint);
extern usb_error ch_data_out_transfer(const uint8_t *buffer, int16_t buffer_length, endpoint_param *const endpoint);
inline void ch_configure_nak_retry(const ch_nak_retry_type retry, const uint8_t number_of_retries) {
ch_command(CH_CMD_WRITE_VAR8);
CH376_DATA_PORT = CH_VAR_RETRY_TIMES;
CH376_DATA_PORT = retry << 6 | (number_of_retries & 0x1F);
}
#define ch_configure_nak_retry_indefinite() ch_configure_nak_retry(CH_NAK_RETRY_INDEFINITE, 0x1F)
#define ch_configure_nak_retry_disable() ch_configure_nak_retry(CH_NAK_RETRY_DONT, 0x1F)
#define ch_configure_nak_retry_3s() ch_configure_nak_retry(CH_NAK_RETRY_3S, 0x1F)
extern void ch_issue_token_setup(void);
extern void ch_issue_token_out_ep0(void);
extern void ch_issue_token_in_ep0(void);
#endif

76
Source/HBIOS/ch376-native/source-doc/base-drv/ch376_init.c

@ -0,0 +1,76 @@
#include "print.h"
#include "usb-base-drv.h"
static uint16_t wait_for_state(const uint8_t loop_counter, uint8_t state, const uint8_t desired_state) __sdcccall(1) {
uint16_t r = state;
for (uint8_t i = 0; i < loop_counter; i++) {
if (state == desired_state)
break;
if (i & 1)
print_string("\b $");
else
print_string("\b*$");
r = usb_init(state);
state = r & 255;
}
return r;
}
extern const char ch376_driver_version[];
static void _chnative_init(bool forced) {
uint8_t state = 0;
uint16_t r;
const uint8_t loop_counter = forced ? 40 : 5;
print_string("\r\nCH376: *$");
r = wait_for_state(loop_counter, state, 1);
state = r & 255;
print_string("\bPRESENT (VER $");
r = usb_init(state);
state = r & 255;
if (state != 2) {
print_string("\rCH376: $");
print_string("VERSION FAILURE\r\n$");
return;
}
print_hex(r >> 8);
print_string(ch376_driver_version);
print_string("USB: *$");
r = wait_for_state(loop_counter, state, 3);
state = r & 255;
if (state == 2) {
print_string("\bDISCONNECTED$");
return;
}
print_string("\bCONNECTED$");
// enumerate....
r = usb_init(state);
state = r & 255;
for (uint8_t i = 0; i < loop_counter; i++) {
if (r >> 8 != 0)
break;
print_string(".$");
r = usb_init(state);
state = r & 255;
}
}
void chnative_init_force(void) { _chnative_init(true); }
void chnative_init(void) { _chnative_init(false); }

1323
Source/HBIOS/ch376-native/source-doc/base-drv/ch376inc.h

File diff suppressed because it is too large

9
Source/HBIOS/ch376-native/source-doc/base-drv/class_hub.c

@ -0,0 +1,9 @@
#include "class_hub.h"
#include "protocol.h"
#include "usb_state.h"
const setup_packet cmd_get_hub_descriptor = {RT_DEVICE_TO_HOST | RT_CLASS | RT_DEVICE, 6, {0, 0x29}, {0, 0}, 8};
usb_error hub_get_descriptor(const device_config_hub *const hub_config, hub_descriptor *const hub_description) __sdcccall(1) {
return usb_control_transfer(&cmd_get_hub_descriptor, hub_description, hub_config->address, hub_config->max_packet_size);
}

62
Source/HBIOS/ch376-native/source-doc/base-drv/class_hub.h

@ -0,0 +1,62 @@
#ifndef __CLASS_HUB
#define __CLASS_HUB
#include "ch376.h"
#include "protocol.h"
#include <stdlib.h>
/*
wHubCharacteristics:
D1...D0: Logical Power Switching Mode
00: Ganged power switching (all ports power at once)
01: Individual port power switching
1X: Reserved. Used only on 1.0 compliant hubs that implement no power switching
D2: Identifies a Compound Device
0: Hub is not part of a compound device.
1: Hub is part of a compound device.
D4...D3: Logical Power Switching Mode
00: Global Over-current Protection. The hub reports over-current as a summation
of all ports current draw, without a breakdown of individual port
over-current status.
01: Individual Port Over-current Protection. The hub reports over-current on a
per-port basis. Each port has an over-current status.
1X: No Over-current Protection. This option is allowed only for bus-powered
*/
typedef struct {
uint8_t bDescLength;
uint8_t bDescriptorType; /* HUB Descriptor Type 0x29 */
uint8_t bNbrPorts; /* Number of ports */
uint16_t wHubCharacteristics; /* Bitmap Hub Characteristics (see above) */
uint8_t bPwrOn2PwrGood; /* Time (*2 ms) from port power on to power good */
uint8_t bHubContrCurrent; /* Maximum current used by hub controller (mA).*/
uint8_t DeviceRemovable[1]; /* bits indicating deviceRemovable and portPwrCtrlMask */
} hub_descriptor;
typedef struct {
uint16_t wPortStatus;
uint16_t wPortChange;
} hub_port_status;
#define PORT_STAT_CONNECTION 0x0001
#define PORT_STAT_ENABLE 0x0002
#define PORT_STAT_SUSPEND 0x0004
#define PORT_STAT_OVERCURRENT 0x0008
#define PORT_STAT_RESET 0x0010
#define PORT_STAT_POWER 0x0100
#define PORT_STAT_LOW_SPEED 0x0200
#define PORT_STAT_HIGH_SPEED 0x0400
#define PORT_STAT_TEST 0x0800
#define PORT_STAT_INDICATOR 0x1000
#define PORT_STAT_C_CONNECTION 0x0001
#define PORT_STAT_C_ENABLE 0x0002
#define PORT_STAT_C_SUSPEND 0x0004
#define PORT_STAT_C_OVERCURRENT 0x0008
#define PORT_STAT_C_RESET 0x0010
usb_error hub_get_descriptor(const device_config_hub *const hub_config, hub_descriptor *const hub_description) __sdcccall(1);
#endif

8
Source/HBIOS/ch376-native/source-doc/base-drv/critical-section.c

@ -0,0 +1,8 @@
#include "critical-section.h"
#include <stdint.h>
uint8_t in_critical_usb_section = 0;
void critical_begin() { in_critical_usb_section++; }
void critical_end() { in_critical_usb_section--; }

13
Source/HBIOS/ch376-native/source-doc/base-drv/critical-section.h

@ -0,0 +1,13 @@
#ifndef __CRITICAL_BLOCKS_H__
#define __CRITICAL_BLOCKS_H__
#include <stdint.h>
extern uint8_t in_critical_usb_section;
void critical_begin();
void critical_end();
#define is_in_critical_section() (in_critical_usb_section != 0)
#endif

11
Source/HBIOS/ch376-native/source-doc/base-drv/delay.h

@ -0,0 +1,11 @@
#ifndef __DELAY
#define __DELAY
#include <stdlib.h>
extern void delay(void);
extern void delay_20ms(void);
extern void delay_short(void);
extern void delay_medium(void);
#endif

106
Source/HBIOS/ch376-native/source-doc/base-drv/dev_transfers.c

@ -0,0 +1,106 @@
/**
* @file transfers.c
* @author Dean Netherton
* @brief A simplest implementation of common usb transfer functions, based on the CH376S chip
* @details For a basic walkthrough of the usb protocol see https://www.beyondlogic.org/usbnutshell/usb1.shtml
* @version 1.0
* @date 2023-09-22
*
* @copyright Copyright (c) 2023
*
*/
#include "dev_transfers.h"
#include "ch376.h"
#include "critical-section.h"
#include "delay.h"
#include "ez80-helpers.h"
#include "protocol.h"
#include <stdlib.h>
/**
* @brief Perform a USB control transfer (in or out)
* See https://www.beyondlogic.org/usbnutshell/usb4.shtml for a description of the USB control transfer
*
* @param device the usb device
* @param cmd_packet Pointer to the setup packet - top bit of bmRequestType indicate data direction
* @param buffer Pointer of data to send or receive into
* @return usb_error USB_ERR_OK if all good, otherwise specific error code
*/
usb_error usbdev_control_transfer(device_config *const device, const setup_packet *const cmd_packet, uint8_t *const buffer) {
return usb_control_transfer(cmd_packet, buffer, device->address, device->max_packet_size);
}
usb_error usbdev_blk_out_trnsfer(device_config *const dev, const uint8_t *const buffer, const uint16_t buffer_size) {
usb_error result;
endpoint_param *const endpoint = &dev->endpoints[ENDPOINT_BULK_OUT];
result = usb_data_out_transfer(buffer, buffer_size, dev->address, endpoint);
if (result == USB_ERR_STALL) {
usbtrn_clear_endpoint_halt(endpoint->number, dev->address, dev->max_packet_size);
endpoint->toggle = 0;
return USB_ERR_STALL;
}
RETURN_CHECK(result);
done:
return result;
}
usb_error usbdev_bulk_in_transfer(device_config *const dev, uint8_t *const buffer, uint8_t *const buffer_size) {
usb_error result;
endpoint_param *const endpoint = &dev->endpoints[ENDPOINT_BULK_IN];
result = usb_data_in_transfer_n(buffer, buffer_size, dev->address, endpoint);
if (result == USB_ERR_STALL) {
usbtrn_clear_endpoint_halt(endpoint->number, dev->address, dev->max_packet_size);
endpoint->toggle = 0;
return USB_ERR_STALL;
}
RETURN_CHECK(result);
done:
return result;
}
usb_error usbdev_dat_in_trnsfer(device_config *const device,
uint8_t *const buffer,
const uint16_t buffer_size,
const usb_endpoint_type endpoint_type) {
usb_error result;
endpoint_param *const endpoint = &device->endpoints[endpoint_type];
result = usb_data_in_transfer(buffer, buffer_size, device->address, endpoint);
if (result == USB_ERR_STALL) {
usbtrn_clear_endpoint_halt(endpoint->number, device->address, device->max_packet_size);
endpoint->toggle = 0;
return USB_ERR_STALL;
}
RETURN_CHECK(result);
done:
return result;
}
usb_error usbdev_dat_in_trnsfer_0(device_config *const device, uint8_t *const buffer, const uint8_t buffer_size) {
usb_error result;
endpoint_param *const endpoint = &device->endpoints[0];
result = usb_data_in_transfer(buffer, buffer_size, device->address, endpoint);
if (result == USB_ERR_STALL) {
usbtrn_clear_endpoint_halt(endpoint->number, device->address, device->max_packet_size);
endpoint->toggle = 0;
return USB_ERR_STALL;
}
return result;
}

66
Source/HBIOS/ch376-native/source-doc/base-drv/dev_transfers.h

@ -0,0 +1,66 @@
/**
* @file transfer.h
* @author Dean Netherton
* @brief A simplest implementation of common usb transfer functions, based on the CH376S chip
* @details For a basic walkthrough of the usb protocol see https://www.beyondlogic.org/usbnutshell/usb1.shtml
* @version 1.0
* @date 2023-09-22
*
* @copyright Copyright (c) 2023
*
*/
#ifndef __USBDEV_TRANSFERS
#define __USBDEV_TRANSFERS
#include "ch376.h"
#include "transfers.h"
#include <stdlib.h>
typedef struct {
uint8_t number : 3;
uint16_t max_packet_sizex : 10;
} endpoint;
// 3 bytes
#define COMMON_DEVICE_CONFIG \
usb_device_type type : 4; \
uint8_t address : 4; \
uint8_t max_packet_size; \
uint8_t interface_number;
typedef struct {
COMMON_DEVICE_CONFIG
endpoint_param endpoints[3]; // bulk in/out and interrupt
} device_config;
typedef struct {
COMMON_DEVICE_CONFIG // bytes: 0-2
endpoint_param endpoints[3]; // bytes: 3-5, 6-8, 9-11 bulk in/out and interrupt
uint32_t current_lba; // bytes 12-15
} device_config_storage;
typedef struct {
COMMON_DEVICE_CONFIG
} device_config_hub;
typedef struct {
COMMON_DEVICE_CONFIG
endpoint_param endpoints[1]; // Isochronous
} device_config_keyboard;
extern usb_error usbdev_control_transfer(device_config *const device, const setup_packet *const cmd, uint8_t *const buffer);
extern usb_error usbdev_blk_out_trnsfer(device_config *const device, const uint8_t *const buffer, const uint16_t buffer_size);
extern usb_error usbdev_bulk_in_transfer(device_config *const dev, uint8_t *const buffer, uint8_t *const buffer_size);
extern usb_error usbdev_dat_in_trnsfer(device_config *const device,
uint8_t *const buffer,
const uint16_t buffer_size,
const usb_endpoint_type endpoint_type);
extern usb_error usbdev_dat_in_trnsfer_0(device_config *const device, uint8_t *const buffer, const uint8_t buffer_size);
#endif

262
Source/HBIOS/ch376-native/source-doc/base-drv/enumerate.c

@ -0,0 +1,262 @@
#include "enumerate.h"
#include "enumerate_hub.h"
#include "enumerate_storage.h"
#include "protocol.h"
#include "work-area.h"
#include <string.h>
#include "print.h"
usb_error op_id_class_drv(_working *const working) __sdcccall(1);
usb_error op_parse_endpoint(_working *const working) __sdcccall(1);
static usb_error adv_to_next_desc(_working *const working, const uint8_t descriptor_type) __sdcccall(1) {
usb_descriptor_t *d;
const uint8_t *buffer_end = working->config.buffer + MAX_CONFIG_SIZE;
if (working->ptr >= buffer_end)
return USB_ERR_BUFF_TO_LARGE;
d = (usb_descriptor_t *)working->ptr;
do {
working->ptr += d->bLength;
if (working->ptr >= buffer_end)
return USB_ERR_BUFF_TO_LARGE;
d = (usb_descriptor_t *)working->ptr;
} while (d->bDescriptorType != descriptor_type);
if (working->ptr + d->bLength >= buffer_end)
return USB_ERR_BUFF_TO_LARGE;
return USB_ERR_OK;
}
void parse_endpoint_keyboard(device_config_keyboard *const keyboard_config, const endpoint_descriptor const *pEndpoint)
__sdcccall(1) {
endpoint_param *const ep = &keyboard_config->endpoints[0];
ep->number = pEndpoint->bEndpointAddress;
ep->toggle = 0;
ep->max_packet_sizex = calc_max_packet_sizex(pEndpoint->wMaxPacketSize);
}
usb_device_type identify_class_driver(_working *const working) {
const interface_descriptor *const p = (const interface_descriptor *)working->ptr;
if (p->bInterfaceClass == 2)
return USB_IS_CDC;
if (p->bInterfaceClass == 8 && (p->bInterfaceSubClass == 6 || p->bInterfaceSubClass == 5) && p->bInterfaceProtocol == 80)
return USB_IS_MASS_STORAGE;
if (p->bInterfaceClass == 8 && p->bInterfaceSubClass == 4 && p->bInterfaceProtocol == 0)
return USB_IS_FLOPPY;
if (p->bInterfaceClass == 9 && p->bInterfaceSubClass == 0 && p->bInterfaceProtocol == 0)
return USB_IS_HUB;
if (p->bInterfaceClass == 3)
return USB_IS_KEYBOARD;
return USB_IS_UNKNOWN;
}
usb_error op_interface_next(_working *const working) __z88dk_fastcall {
uint8_t result;
if (--working->interface_count == 0)
return USB_ERR_OK;
CHECK(adv_to_next_desc(working, USB_DESCR_INTERFACE));
return op_id_class_drv(working);
done:
return result;
}
usb_error op_endpoint_next(_working *const working) __sdcccall(1) {
usb_error result;
if (working->endpoint_count != 0 && --working->endpoint_count > 0) {
CHECK(adv_to_next_desc(working, USB_DESCR_ENDPOINT));
return op_parse_endpoint(working);
}
return op_interface_next(working);
done:
return result;
}
usb_error op_parse_endpoint(_working *const working) __sdcccall(1) {
const endpoint_descriptor *endpoint = (endpoint_descriptor *)working->ptr;
device_config *const device = working->p_current_device;
switch (working->usb_device) {
case USB_IS_FLOPPY:
case USB_IS_MASS_STORAGE: {
parse_endpoints((device_config_storage *)device, endpoint);
break;
}
case USB_IS_KEYBOARD: {
parse_endpoint_keyboard((device_config_keyboard *)device, endpoint);
break;
}
}
return op_endpoint_next(working);
}
usb_error
configure_device(const _working *const working, const interface_descriptor *const interface, device_config *const dev_cfg) {
dev_cfg->interface_number = interface->bInterfaceNumber;
dev_cfg->max_packet_size = working->desc.bMaxPacketSize0;
dev_cfg->address = working->current_device_address;
dev_cfg->type = working->usb_device;
return usbtrn_set_configuration(dev_cfg->address, dev_cfg->max_packet_size, working->config.desc.bConfigurationvalue);
}
usb_error op_capture_hub_driver_interface(_working *const working) __sdcccall(1) {
const interface_descriptor *const interface = (interface_descriptor *)working->ptr;
usb_error result;
device_config_hub hub_config;
working->hub_config = &hub_config;
hub_config.type = USB_IS_HUB;
CHECK(configure_device(working, interface, (device_config *const)&hub_config));
RETURN_CHECK(configure_usb_hub(working));
done:
return result;
}
usb_error op_cap_drv_intf(_working *const working) __z88dk_fastcall {
usb_error result;
_usb_state *const work_area = get_usb_work_area();
const interface_descriptor *const interface = (interface_descriptor *)working->ptr;
working->endpoint_count = interface->bNumEndpoints;
if (working->endpoint_count > 0)
CHECK(adv_to_next_desc(working, USB_DESCR_ENDPOINT));
working->p_current_device = NULL;
switch (working->usb_device) {
case USB_IS_HUB: {
CHECK(op_capture_hub_driver_interface(working))
break;
}
case USB_IS_UNKNOWN: {
device_config unkown_dev_cfg;
memset(&unkown_dev_cfg, 0, sizeof(device_config));
working->p_current_device = &unkown_dev_cfg;
CHECK(configure_device(working, interface, &unkown_dev_cfg));
break;
}
default: {
device_config *dev_cfg = find_first_free();
if (dev_cfg == NULL)
return USB_ERR_OUT_OF_MEMORY;
working->p_current_device = dev_cfg;
CHECK(configure_device(working, interface, dev_cfg));
break;
}
}
return op_parse_endpoint(working);
done:
return result;
}
usb_error op_id_class_drv(_working *const working) __sdcccall(1) {
const interface_descriptor *const ptr = (const interface_descriptor *)working->ptr;
if (ptr->bDescriptorType != USB_DESCR_INTERFACE)
return USB_ERR_FAIL;
working->usb_device = identify_class_driver(working);
return op_cap_drv_intf(working);
}
usb_error op_get_cfg_desc(_working *const working) __sdcccall(1) {
usb_error result;
const uint8_t max_packet_size = working->desc.bMaxPacketSize0;
memset(working->config.buffer, 0, MAX_CONFIG_SIZE);
working->ptr = working->config.buffer;
CHECK(usbtrn_gfull_cfg_desc(working->config_index, working->current_device_address, max_packet_size, MAX_CONFIG_SIZE,
working->config.buffer));
CHECK(adv_to_next_desc(working, USB_DESCR_INTERFACE));
working->interface_count = working->config.desc.bNumInterfaces;
return op_id_class_drv(working);
done:
return result;
}
usb_error read_all_configs(enumeration_state *const state) {
uint8_t result;
_usb_state *const work_area = get_usb_work_area();
_working working;
memset(&working, 0, sizeof(_working));
working.state = state;
CHECK(usbtrn_get_descriptor(&working.desc));
state->next_device_address++;
working.current_device_address = state->next_device_address;
CHECK(usbtrn_set_address(working.current_device_address));
for (uint8_t config_index = 0; config_index < working.desc.bNumConfigurations; config_index++) {
working.config_index = config_index;
CHECK(op_get_cfg_desc(&working));
}
return USB_ERR_OK;
done:
return result;
}
usb_error enumerate_all_devices(void) {
_usb_state *const work_area = get_usb_work_area();
enumeration_state state;
memset(&state, 0, sizeof(enumeration_state));
usb_error result = read_all_configs(&state);
work_area->count_of_detected_usb_devices = state.next_device_address;
done:
return result;
}
/*
enumerate_all_devices
-> read_all_configs
-> parse_config
-> op_get_cfg_desc
-> op_id_class_drv
-> op_cap_drv_intf (increment index)
-> op_parse_endpoint
-> parse_endpoints
-> parse_endpoint_hub
-> op_endpoint_next
-> op_parse_endpoint -^ (install driver endpoint)
-> op_interface_next
-> return
-> op_id_class_drv -^
*/

39
Source/HBIOS/ch376-native/source-doc/base-drv/enumerate.h

@ -0,0 +1,39 @@
#ifndef __USB_ENUMERATE
#define __USB_ENUMERATE
#include "ch376.h"
#include "protocol.h"
#include "usb_state.h"
#define MAX_CONFIG_SIZE 140
typedef struct {
uint8_t next_device_address; /* Track the count of installed usb devices*/
uint8_t storage_count; /* Track the count of storage devices (scsi, ufi) */
} enumeration_state;
typedef struct __working {
enumeration_state *state;
usb_device_type usb_device;
device_descriptor desc;
uint8_t config_index;
uint8_t interface_count;
uint8_t endpoint_count;
uint8_t current_device_address;
device_config_hub *hub_config;
uint8_t *ptr;
device_config *p_current_device;
union {
uint8_t buffer[MAX_CONFIG_SIZE];
config_descriptor desc;
} config;
} _working;
extern usb_error read_all_configs(enumeration_state *const state);
extern usb_error enumerate_all_devices(void);
#endif

82
Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_hub.c

@ -0,0 +1,82 @@
#include "enumerate_hub.h"
#include "class_hub.h"
#include "delay.h"
#include "protocol.h"
#include "work-area.h"
#include <string.h>
const setup_packet cmd_set_feature = {RT_HOST_TO_DEVICE | RT_CLASS | RT_OTHER, SET_FEATURE, {FEAT_PORT_POWER, 0}, {1, 0}, 0};
const setup_packet cmd_clear_feature = {RT_HOST_TO_DEVICE | RT_CLASS | RT_OTHER, CLEAR_FEATURE, {FEAT_PORT_POWER, 0}, {1, 0}, 0};
const setup_packet cmd_get_status_port = {
RT_DEVICE_TO_HOST | RT_CLASS | RT_OTHER, GET_STATUS, {0, 0}, {1, 0}, sizeof(hub_port_status)};
usb_error hub_set_feature(const device_config_hub *const hub_config, const uint8_t feature, const uint8_t index) {
setup_packet set_feature;
set_feature = cmd_set_feature;
set_feature.bValue[0] = feature;
set_feature.bIndex[0] = index;
return usb_control_transfer(&set_feature, 0, hub_config->address, hub_config->max_packet_size);
}
usb_error hub_clear_feature(const device_config_hub *const hub_config, const uint8_t feature, const uint8_t index) {
setup_packet clear_feature;
clear_feature = cmd_clear_feature;
clear_feature.bValue[0] = feature;
clear_feature.bIndex[0] = index;
return usb_control_transfer(&clear_feature, 0, hub_config->address, hub_config->max_packet_size);
}
usb_error hub_get_status_port(const device_config_hub *const hub_config, const uint8_t index, hub_port_status *const port_status) {
setup_packet get_status_port;
get_status_port = cmd_get_status_port;
get_status_port.bIndex[0] = index;
return usb_control_transfer(&get_status_port, port_status, hub_config->address, hub_config->max_packet_size);
}
usb_error configure_usb_hub(_working *const working) __z88dk_fastcall {
_usb_state *const work_area = get_usb_work_area();
usb_error result;
hub_descriptor hub_description;
hub_port_status port_status;
const device_config_hub *const hub_config = working->hub_config;
CHECK(hub_get_descriptor(hub_config, &hub_description));
uint8_t i = hub_description.bNbrPorts;
do {
CHECK(hub_clear_feature(hub_config, FEAT_PORT_POWER, i));
CHECK(hub_set_feature(hub_config, FEAT_PORT_POWER, i));
hub_clear_feature(hub_config, FEAT_PORT_RESET, i);
CHECK(hub_set_feature(hub_config, FEAT_PORT_RESET, i));
CHECK(hub_get_status_port(hub_config, i, &port_status));
if (port_status.wPortStatus & PORT_STAT_CONNECTION) {
CHECK(hub_clear_feature(hub_config, HUB_FEATURE_PORT_CONNECTION_CHANGE, i));
CHECK(hub_clear_feature(hub_config, FEAT_PORT_ENABLE_CHANGE, i));
CHECK(hub_clear_feature(hub_config, FEAT_PORT_RESET_CHANGE, i));
delay_short();
CHECK(hub_get_status_port(hub_config, i, &port_status));
delay_short();
CHECK(read_all_configs(working->state));
} else {
CHECK(hub_clear_feature(hub_config, FEAT_PORT_POWER, i));
}
} while (--i != 0);
return USB_ERR_OK;
done:
return result;
}

10
Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_hub.h

@ -0,0 +1,10 @@
#ifndef __USB_ENUMERATE_HUB
#define __USB_ENUMERATE_HUB
#include "enumerate.h"
#include "protocol.h"
#include "usb_state.h"
extern usb_error configure_usb_hub(_working *const working) __z88dk_fastcall;
#endif

27
Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_storage.c

@ -0,0 +1,27 @@
#include "enumerate_storage.h"
#include "protocol.h"
#include <string.h>
void parse_endpoints(device_config_storage *const storage_dev, const endpoint_descriptor const *pEndpoint) {
if (!(pEndpoint->bmAttributes & 0x02))
return;
const uint8_t x = calc_max_packet_sizex(pEndpoint->wMaxPacketSize);
endpoint_param *const eps = storage_dev->endpoints;
endpoint_param *ep;
if (pEndpoint->bmAttributes & 0x01) { // 3 -> Interrupt
if (!(pEndpoint->bEndpointAddress & 0x80))
return;
ep = &eps[ENDPOINT_INTERRUPT_IN];
} else {
ep = (pEndpoint->bEndpointAddress & 0x80) ? &eps[ENDPOINT_BULK_IN] : &eps[ENDPOINT_BULK_OUT];
}
ep->number = pEndpoint->bEndpointAddress & 0x07;
ep->toggle = 0;
ep->max_packet_sizex = x;
}

9
Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_storage.h

@ -0,0 +1,9 @@
#ifndef __USB_ENUMERATE_STORAGE
#define __USB_ENUMERATE_STORAGE
#include "dev_transfers.h"
#include "protocol.h"
extern void parse_endpoints(device_config_storage *const storage_dev, const endpoint_descriptor const *pEndpoint);
#endif

1
Source/HBIOS/ch376-native/source-doc/base-drv/ez80-helpers.h

@ -0,0 +1 @@
#define debugger() __asm__("PUSH AF \n PUSH BC \n XOR A \n LD B, 7 \n .DB 0x49, 0xD7 \n POP BC \n POP AF")

11
Source/HBIOS/ch376-native/source-doc/base-drv/hbios-driver-storage.c

@ -0,0 +1,11 @@
#include "hbios-driver-storage.h"
hbios_storage_device_t hbios_usb_storage_devices[MAX_NUMBER_OF_DEVICES] = {{NULL}};
uint8_t find_storage_dev(void) {
for (uint8_t i = 0; i < MAX_NUMBER_OF_DEVICES; i++)
if (hbios_usb_storage_devices[i].drive_index == 0)
return i;
return -1;
}

15
Source/HBIOS/ch376-native/source-doc/base-drv/hbios-driver-storage.h

@ -0,0 +1,15 @@
#ifndef __HBIOS_DRIVER_STORAGE
#define __HBIOS_DRIVER_STORAGE
#include "usb_state.h"
typedef struct _hbios_storage_device {
uint8_t drive_index;
uint8_t usb_device;
} hbios_storage_device_t;
extern hbios_storage_device_t hbios_usb_storage_devices[MAX_NUMBER_OF_DEVICES];
uint8_t find_storage_dev(void);
#endif

6
Source/HBIOS/ch376-native/source-doc/base-drv/hbios.h

@ -0,0 +1,6 @@
#ifndef _HBIOS_H_
#define _HBIOS_H_
extern void dio_add_entry(const uint16_t fnc_table[], const void *const storage_device) __sdcccall(1);
#endif

11
Source/HBIOS/ch376-native/source-doc/base-drv/print.h

@ -0,0 +1,11 @@
#ifndef __XPRINT
#define __XPRINT
#include <stdint.h>
#include <stdlib.h>
extern void print_hex(const char c) __z88dk_fastcall;
extern void print_string(const char *p) __z88dk_fastcall;
extern void print_uint16(const uint16_t n) __z88dk_fastcall;
#endif

159
Source/HBIOS/ch376-native/source-doc/base-drv/protocol.c

@ -0,0 +1,159 @@
/**
* @file protocol.c
* @author Dean Netherton
* @brief A simplest implementation of common usb transfer functions, based on the CH376S chip
* @details For a basic walkthrough of the usb protocol see https://www.beyondlogic.org/usbnutshell/usb1.shtml
* @version 1.0
* @date 2023-09-22
*
* @copyright Copyright (c) 2023
*
*/
#include "protocol.h"
#include "ch376.h"
#include "delay.h"
#include <stdlib.h>
#include "ez80-helpers.h"
#include "print.h"
const setup_packet cmd_get_device_descriptor = {0x80, 6, {0, 1}, {0, 0}, 8};
/**
* @brief Issue GET_DESCRIPTOR request to retrieve the device descriptor for usb device at address 0
*
* @param buffer the buffer to store the device descriptor in
* @return usb_error USB_ERR_OK if all good, otherwise specific error code
*/
usb_error usbtrn_get_descriptor(device_descriptor *const buffer) {
usb_error result;
setup_packet cmd;
cmd = cmd_get_device_descriptor;
cmd.wLength = 8;
result = usb_control_transfer(&cmd, (uint8_t *)buffer, 0, 8);
CHECK(result);
cmd = cmd_get_device_descriptor;
cmd.wLength = 18;
result = usb_control_transfer(&cmd, (uint8_t *)buffer, 0, buffer->bMaxPacketSize0);
RETURN_CHECK(result);
done:
return result;
}
/**
* @brief Issue GET_DESCRIPTOR request to retrieve the device descriptor for usb device at the specified address
*
* @param buffer the buffer to store the device descriptor in
* @return usb_error USB_ERR_OK if all good, otherwise specific error code
*/
usb_error usbtrn_get_descriptor2(device_descriptor *const buffer, const uint8_t device_address) {
usb_error result;
setup_packet cmd;
cmd = cmd_get_device_descriptor;
cmd.wLength = 8;
result = usb_control_transfer(&cmd, (uint8_t *)buffer, device_address, 8);
CHECK(result);
cmd = cmd_get_device_descriptor;
cmd.wLength = 18;
RETURN_CHECK(usb_control_transfer(&cmd, (uint8_t *)buffer, device_address, buffer->bMaxPacketSize0));
done:
return result;
}
const setup_packet cmd_set_device_address = {0x00, 5, {0, 0}, {0, 0}, 0};
/**
* @brief configure device at address 0 to be assigned a new device address
*
* @param device_address the new device address
* @return usb_error USB_ERR_OK if all good, otherwise specific error code
*/
usb_error usbtrn_set_address(const uint8_t device_address) __z88dk_fastcall {
setup_packet cmd;
cmd = cmd_set_device_address;
cmd.bValue[0] = device_address;
return usb_control_transfer(&cmd, 0, 0, 0);
}
const setup_packet cmd_set_configuration = {0x00, 9, {0, 0}, {0, 0}, 0};
/**
* @brief configure device at address 0 to be assigned a new configuration
*
* @param config the device to be configured
* @return usb_error USB_ERR_OK if all good, otherwise specific error code
*/
usb_error usbtrn_set_configuration(const uint8_t device_address, const uint8_t max_packet_size, const uint8_t configuration) {
setup_packet cmd;
cmd = cmd_set_configuration;
cmd.bValue[0] = configuration;
return usb_control_transfer(&cmd, 0, device_address, max_packet_size);
}
const setup_packet cmd_get_config_descriptor = {0x80, 6, {0, 2}, {0, 0}, 0};
/**
* @brief request the config descriptor for the specific config index of the specified device
*
* @param buffer the buffer to store the config descriptor in
* @param config_index the index of the config descriptor to retrieve
* @param buffer_size the size of the buffer
* @param device_address the usb address of the device
* @param max_packet_size the max packet size for control transfers (endpoint 0)
* @return usb_error USB_ERR_OK if all good, otherwise specific error code
*/
usb_error usbtrn_get_config_descriptor(config_descriptor *const buffer,
const uint8_t config_index,
const uint8_t buffer_size,
const uint8_t device_address,
const uint8_t max_packet_size) {
setup_packet cmd;
cmd = cmd_get_config_descriptor;
cmd.bValue[0] = config_index;
cmd.wLength = (uint16_t)buffer_size;
return usb_control_transfer(&cmd, (uint8_t *)buffer, device_address, max_packet_size);
}
usb_error usbtrn_gfull_cfg_desc(const uint8_t config_index,
const uint8_t device_address,
const uint8_t max_packet_size,
const uint8_t max_buffer_size,
uint8_t *const buffer) {
usb_error result;
CHECK(usbtrn_get_config_descriptor((config_descriptor *)buffer, config_index, sizeof(config_descriptor), device_address,
max_packet_size));
uint8_t max_length = ((config_descriptor *)buffer)->wTotalLength;
if (max_length > max_buffer_size)
max_length = max_buffer_size;
CHECK(usbtrn_get_config_descriptor((config_descriptor *)buffer, config_index, max_length, device_address, max_packet_size));
return USB_ERR_OK;
done:
return result;
}
const setup_packet usb_cmd_clear_endpoint_halt = {2, 1, {0, 0}, {255, 0}, 0}; // ;byte 4 is the endpoint to be cleared
usb_error usbtrn_clear_endpoint_halt(const uint8_t endpoint_number, const uint8_t device_address, const uint8_t max_packet_size) {
setup_packet cmd;
cmd = usb_cmd_clear_endpoint_halt;
cmd.bIndex[0] = endpoint_number;
return usb_control_transfer(&cmd, (uint8_t *)0, device_address, max_packet_size);
}

98
Source/HBIOS/ch376-native/source-doc/base-drv/protocol.h

@ -0,0 +1,98 @@
#ifndef __HW
#define __HW
#include "ch376.h"
#include "dev_transfers.h"
#include "transfers.h"
#include <stdlib.h>
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
} usb_descriptor_t;
#define USB_DESCR_DEVICE 1
#define USB_DESCR_CONFIGURATION 2
#define USB_DESCR_STRING 3
#define USB_DESCR_INTERFACE 4
#define USB_DESCR_ENDPOINT 5
#define USB_DESCR_DEV_QUALIFIER 6
#define USB_DESCR_OTHER_SPEED 7
#define USB_DESCR_HID 33
#define USB_DESCR_HID_REPORT 34
#define USB_DESCR_HID_PHYSICAL_DESC 35
typedef struct _device_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdUSB;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice;
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber;
uint8_t bNumConfigurations;
} device_descriptor;
typedef struct _config_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumInterfaces;
uint8_t bConfigurationvalue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
} config_descriptor;
typedef struct _interface_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
} interface_descriptor, *p_interface_descriptor;
typedef struct _endpoint_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
} endpoint_descriptor;
extern usb_error usbtrn_get_descriptor(device_descriptor *const buffer);
extern usb_error usbtrn_get_descriptor2(device_descriptor *const buffer, const uint8_t device_address);
extern usb_error usbtrn_get_config_descriptor(config_descriptor *const buffer,
const uint8_t config_index,
const uint8_t buffer_size,
const uint8_t device_address,
const uint8_t max_packet_size);
extern usb_error usbtrn_gfull_cfg_desc(const uint8_t config_index,
const uint8_t device_address,
const uint8_t max_packet_size,
const uint8_t max_buffer_size,
uint8_t *const buffer);
extern usb_error usbtrn_set_configuration(const uint8_t device_address, const uint8_t max_packet_size, const uint8_t configuration);
extern usb_error usbtrn_set_address(const uint8_t device_address) __z88dk_fastcall;
extern usb_error
usbtrn_clear_endpoint_halt(const uint8_t endpoint_number, const uint8_t device_address, const uint8_t max_packet_size);
// extern usb_error usb_clear_endpoint_halt(device_config *const storage_device, const usb_endpoint_type endpoint_type);
#endif

152
Source/HBIOS/ch376-native/source-doc/base-drv/transfers.c

@ -0,0 +1,152 @@
/**
* @file transfers.c
* @author Dean Netherton
* @brief A simplest implementation of common usb transfer functions, based on the CH376S chip
* @details For a basic walkthrough of the usb protocol see https://www.beyondlogic.org/usbnutshell/usb1.shtml
* @version 1.0
* @date 2023-09-22
*
* @copyright Copyright (c) 2023
*
*/
#include "transfers.h"
#include "ch376.h"
#include "critical-section.h"
#include "delay.h"
#include "ez80-helpers.h"
#include "print.h"
#include <stdlib.h>
/**
* @brief Perform a USB control transfer (in or out)
* See https://www.beyondlogic.org/usbnutshell/usb4.shtml for a description of the USB control transfer
*
* @param cmd_packet Pointer to the setup packet - top bit of bmRequestType indicate data direction
* @param buffer Pointer of data to send or receive into
* @param device_address usb device address
* @param max_packet_size Maximum packet size for endpoint
* @return usb_error USB_ERR_OK if all good, otherwise specific error code
*/
usb_error usb_control_transfer(const setup_packet *const cmd_packet,
void *const buffer,
const uint8_t device_address,
const uint8_t max_packet_size) {
usb_error result;
endpoint_param endpoint = {1, 0, max_packet_size};
const uint8_t transferIn = (cmd_packet->bmRequestType & 0x80);
if (transferIn && buffer == 0)
return USB_ERR_OTHER;
critical_begin();
ch_set_usb_address(device_address);
ch_write_data((const uint8_t *)cmd_packet, sizeof(setup_packet));
ch_issue_token_setup();
result = ch_short_wait_int_and_get_status();
CHECK(result);
const uint16_t length = cmd_packet->wLength;
result = length != 0
? (transferIn ? ch_data_in_transfer(buffer, length, &endpoint) : ch_data_out_transfer(buffer, length, &endpoint))
: USB_ERR_OK;
CHECK(result)
if (transferIn) {
ch_command(CH_CMD_WR_HOST_DATA);
CH376_DATA_PORT = 0;
ch_issue_token_out_ep0();
result = ch_long_wait_int_and_get_status(); /* sometimes we get STALL here - seems to be ok to ignore */
if (result == USB_ERR_OK || result == USB_ERR_STALL) {
result = USB_ERR_OK;
goto done;
}
RETURN_CHECK(result);
}
ch_issue_token_in_ep0();
result = ch_long_wait_int_and_get_status();
RETURN_CHECK(result);
done:
critical_end();
return result;
}
/**
* @brief Perform a USB data in on the specified endpoint
*
* @param buffer the buffer to receive the data
* @param buffer_size the maximum size of data to be received
* @param device_address the usb address of the device
* @param endpoint the usb endpoint to receive from (toggle of endpoint is updated)
* @return usb_error USB_ERR_OK if all good, otherwise specific error code
*/
usb_error
usb_data_in_transfer(uint8_t *buffer, const uint16_t buffer_size, const uint8_t device_address, endpoint_param *const endpoint) {
usb_error result;
critical_begin();
ch_set_usb_address(device_address);
result = ch_data_in_transfer(buffer, buffer_size, endpoint);
critical_end();
return result;
}
/**
* @brief Perform a USB data in on the specified endpoint
*
* @param buffer the buffer to receive the data - must be 62 bytes
* @param buffer_size on exit the actual size of data received
* @param device_address the usb address of the device
* @param endpoint the usb endpoint to receive from (toggle of endpoint is updated)
* @return usb_error USB_ERR_OK if all good, otherwise specific error code
*/
usb_error
usb_data_in_transfer_n(uint8_t *buffer, uint8_t *const buffer_size, const uint8_t device_address, endpoint_param *const endpoint) {
usb_error result;
critical_begin();
ch_set_usb_address(device_address);
result = ch_data_in_transfer_n(buffer, buffer_size, endpoint); // does ch_data_in_transfer_n size need to be signed?
critical_end();
return result;
}
/**
* @brief Perform a USB data out on the specififed endpoint
*
* @param buffer the buffer to send the data from
* @param buffer_size the maximum size of data to be sent
* @param device_address the usb address of the device
* @param endpoint the usb endpoint to send to (toggle of endpoint is updated)
* @return usb_error USB_ERR_OK if all good, otherwise specific error code
*/
usb_error
usb_data_out_transfer(const uint8_t *buffer, uint16_t buffer_size, const uint8_t device_address, endpoint_param *const endpoint) {
usb_error result;
critical_begin();
ch_set_usb_address(device_address);
result = ch_data_out_transfer(buffer, buffer_size, endpoint);
critical_end();
return result;
}

103
Source/HBIOS/ch376-native/source-doc/base-drv/transfers.h

@ -0,0 +1,103 @@
/**
* @file transfer.h
* @author Dean Netherton
* @brief A simplest implementation of common usb transfer functions, based on the CH376S chip
* @details For a basic walkthrough of the usb protocol see https://www.beyondlogic.org/usbnutshell/usb1.shtml
* @version 1.0
* @date 2023-09-22
*
* @copyright Copyright (c) 2023
*
*/
#ifndef __USB_TRANSFERS
#define __USB_TRANSFERS
#include "ch376.h"
#include <stdlib.h>
#define GET_STATUS 0
#define CLEAR_FEATURE 1
#define SET_FEATURE 3
#define GET_DESCRIPTOR 6
#define SET_DESCRIPTOR 7
#define CLEAR_TT_BUFFER 8
#define RESET_TT 9
#define GET_TT_STATE 10
#define CSTOP_TT 11
#define FEAT_PORT_POWER 8
#define FEAT_PORT_RESET 4
#define HUB_FEATURE_PORT_CONNECTION_CHANGE 16
#define FEAT_PORT_ENABLE_CHANGE 17
#define FEAT_PORT_RESET_CHANGE 20
// HUB_FEATURE_PORT_CONNECTION = 0,
// HUB_FEATURE_PORT_ENABLE = 1,
// HUB_FEATURE_PORT_SUSPEND = 2,
// HUB_FEATURE_PORT_OVER_CURRENT = 3,
// HUB_FEATURE_PORT_RESET = 4,
// HUB_FEATURE_PORT_POWER = 8,
// HUB_FEATURE_PORT_LOW_SPEED = 9,
// HUB_FEATURE_PORT_CONNECTION_CHANGE = 16,
// HUB_FEATURE_PORT_ENABLE_CHANGE = 17,
// HUB_FEATURE_PORT_SUSPEND_CHANGE = 18,
// HUB_FEATURE_PORT_OVER_CURRENT_CHANGE = 19,
// HUB_FEATURE_PORT_RESET_CHANGE = 20,
// HUB_FEATURE_PORT_TEST = 21,
// HUB_FEATURE_PORT_INDICATOR = 22
#define RT_HOST_TO_DEVICE 0b00000000
#define RT_DEVICE_TO_HOST 0b10000000
#define RT_STANDARD 0b00000000
#define RT_CLASS 0b00100000
#define RT_VENDOR 0b01000000
#define RT_DEVICE 0b00000000
#define RT_INTERFACE 0b00000001
#define RT_ENDPOINT 0b00000010
#define RT_OTHER 0b00000011
typedef struct _setup_packet {
uint8_t bmRequestType;
uint8_t bRequest;
uint8_t bValue[2];
uint8_t bIndex[2];
uint16_t wLength;
} setup_packet;
enum libusb_request_type {
LIBUSB_REQUEST_TYPE_STANDARD = (0x00 << 5),
LIBUSB_REQUEST_TYPE_CLASS = (0x01 << 5),
LIBUSB_REQUEST_TYPE_VENDOR = (0x02 << 5),
LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5),
};
enum libusb_request_recipient {
LIBUSB_RECIPIENT_DEVICE = 0x00,
LIBUSB_RECIPIENT_INTERFACE = 0x01,
LIBUSB_RECIPIENT_ENDPOINT = 0x02,
LIBUSB_RECIPIENT_OTHER = 0x03,
};
enum libusb_endpoint_direction {
LIBUSB_ENDPOINT_IN = 0x80,
LIBUSB_ENDPOINT_OUT = 0x00,
};
extern usb_error usb_control_transfer(const setup_packet *const cmd_packet,
void *const buffer,
const uint8_t device_address,
const uint8_t max_packet_size);
extern usb_error
usb_data_in_transfer(uint8_t *buffer, const uint16_t buffer_size, const uint8_t device_address, endpoint_param *const endpoint);
extern usb_error
usb_data_in_transfer_n(uint8_t *buffer, uint8_t *const buffer_size, const uint8_t device_address, endpoint_param *const endpoint);
extern usb_error
usb_data_out_transfer(const uint8_t *buffer, uint16_t buffer_size, const uint8_t device_address, endpoint_param *const endpoint);
#endif

76
Source/HBIOS/ch376-native/source-doc/base-drv/usb-base-drv.c

@ -0,0 +1,76 @@
#include "usb-base-drv.h"
#include "ch376.h"
#include "enumerate.h"
#include "work-area.h"
#include <string.h>
static usb_error usb_host_bus_reset(void) {
ch_cmd_set_usb_mode(CH_MODE_HOST);
delay_20ms();
ch_cmd_set_usb_mode(CH_MODE_HOST_RESET);
delay_20ms();
ch_cmd_set_usb_mode(CH_MODE_HOST);
delay_20ms();
ch_configure_nak_retry_3s();
return USB_ERR_OK;
}
#define ERASE_LINE "\x1B\x6C\r$"
uint16_t usb_init(uint8_t state) __z88dk_fastcall {
uint8_t r;
USB_MODULE_LEDS = 0x03;
if (state == 0) {
ch_cmd_reset_all();
delay_medium();
if (!ch_probe()) {
USB_MODULE_LEDS = 0x00;
return 0xFF00;
}
USB_MODULE_LEDS = 0x00;
return 1;
}
if (state == 1) {
r = ch_cmd_get_ic_version();
USB_MODULE_LEDS = 0x00;
return (uint16_t)r << 8 | 2;
}
if (state == 2) {
usb_host_bus_reset();
r = ch_very_short_wait_int_and_get_status();
if (r != USB_INT_CONNECT) {
USB_MODULE_LEDS = 0x00;
return 2;
}
return 3;
}
memset(get_usb_work_area(), 0, sizeof(_usb_state));
if (state != 2) {
usb_host_bus_reset();
delay_medium();
}
enumerate_all_devices();
USB_MODULE_LEDS = 0x00;
return (uint16_t)count_of_devices() << 8 | 4;
}
usb_error usb_scsi_seek(const uint16_t dev_index, const uint32_t lba) {
device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index);
dev->current_lba = lba;
return USB_ERR_OK;
}

14
Source/HBIOS/ch376-native/source-doc/base-drv/usb-base-drv.h

@ -0,0 +1,14 @@
#ifndef __USB_BASE_DRV
#define __USB_BASE_DRV
#include "dev_transfers.h"
#include "usb_state.h"
#include <stdint.h>
extern uint16_t usb_init(uint8_t state) __z88dk_fastcall;
// ufi_seek is an alias for scsi_seek
extern usb_error usb_scsi_seek(const uint16_t dev_index, const uint32_t lba);
extern usb_error ufi_seek(const uint16_t dev_index, const uint32_t lba);
#endif

97
Source/HBIOS/ch376-native/source-doc/base-drv/usb_state.c

@ -0,0 +1,97 @@
#include "usb_state.h"
#include "ch376.h"
#include "work-area.h"
extern device_config *first_device_config(const _usb_state *const p) __sdcccall(1);
extern device_config *next_device_config(const _usb_state *const usb_state, const device_config *const p) __sdcccall(1);
const uint8_t device_config_sizes[_USB_LAST_DEVICE_TYPE] = {
0, /* USB_NOT_SUPPORTED = 0 */
sizeof(device_config_storage), /* USB_IS_FLOPPY = 1 */
sizeof(device_config_storage), /* USB_IS_MASS_STORAGE = 2 */
sizeof(device_config), /* USB_IS_CDC = 3 */
sizeof(device_config_keyboard), /* USB_IS_KEYBOARD = 4 */
};
// always usb work area
uint8_t count_of_devices(void) __sdcccall(1) {
_usb_state *const p = get_usb_work_area();
uint8_t count = 0;
const device_config *p_config = first_device_config(p);
while (p_config) {
const uint8_t type = p_config->type;
if (type != USB_IS_HUB && type)
count++;
;
p_config = next_device_config(p, p_config);
};
return count;
}
// always search in boot
device_config *find_first_free(void) {
_usb_state *const boot_state = get_usb_work_area();
uint8_t c = 0;
device_config *p = first_device_config(boot_state);
while (p) {
if (p->type == 0)
return p;
p = next_device_config(boot_state, p);
}
return NULL;
}
device_config *first_device_config(const _usb_state *const p) __sdcccall(1) { return (device_config *)&p->device_configs[0]; }
device_config *next_device_config(const _usb_state *const usb_state, const device_config *const p) __sdcccall(1) {
if (p->type == 0)
return NULL;
const uint8_t size = device_config_sizes[p->type];
// TODO: bug when size is zero we dont increment the pointer
// but if we abort on size 0 - we fail to pick up other devices???
// we should not get size of 0 unless the size entry is missing
// if (size == 0)
// return NULL;
const uint8_t *_p = (uint8_t *)p;
device_config *const result = (device_config *)(_p + size);
if (result >= (device_config *)&usb_state->device_configs_end)
return NULL;
return result;
}
device_config *get_usb_device_config(const uint8_t device_index) __sdcccall(1) {
const _usb_state *const usb_state = get_usb_work_area();
uint8_t counter = 1;
for (device_config *p = first_device_config(usb_state); p; p = next_device_config(usb_state, p)) {
if (p->type != USB_NOT_SUPPORTED) {
if (counter == device_index)
return p;
counter++;
}
}
return NULL; // is not a usb device
}
usb_device_type usb_get_device_type(const uint16_t dev_index) {
const device_config *dev = get_usb_device_config(dev_index);
if (dev == NULL)
return -1;
return dev->type;
}

26
Source/HBIOS/ch376-native/source-doc/base-drv/usb_state.h

@ -0,0 +1,26 @@
#ifndef __USB_STATE
#define __USB_STATE
#include "ch376.h"
#include "protocol.h"
#include <stdlib.h>
#define MAX_NUMBER_OF_DEVICES 6
#define DEVICE_CONFIG_STRUCT_SIZE sizeof(device_config_storage) /* Assumes is largest struct */
typedef struct __usb_state {
uint8_t active : 1; /* if true, a usb operation/interrupt handler is active, prevent re-entrant */
uint8_t reserved : 7;
uint8_t count_of_detected_usb_devices;
uint8_t device_configs[DEVICE_CONFIG_STRUCT_SIZE * MAX_NUMBER_OF_DEVICES];
uint8_t device_configs_end; // always zero to mark end
} _usb_state;
extern device_config *find_first_free(void);
extern uint8_t count_of_devices(void) __sdcccall(1);
extern device_config *get_usb_device_config(const uint8_t device_index) __sdcccall(1);
extern usb_device_type usb_get_device_type(const uint16_t dev_index);
#endif

3
Source/HBIOS/ch376-native/source-doc/base-drv/work-area.c

@ -0,0 +1,3 @@
#include "usb_state.h"
_usb_state x = {0, 0, 0};

54
Source/HBIOS/ch376-native/source-doc/base-drv/work-area.h

@ -0,0 +1,54 @@
#ifndef __WORK_AREA
#define __WORK_AREA
#include "ch376.h"
#include "protocol.h"
#include "stdlib.h"
#include "usb_state.h"
#define PRES_CF 1 /* BIT MASK FOR COMPACTFLASH PRESENT */
#define PRES_MS 2 /* BIT MASK FOR MSX MUSIC NOR FLASH PRESENT */
#define PRES_USB1 4 /* BIT MASK FOR USB1 STORAGE PRESENT AT BOOT UP */
#define PRES_USB2 8 /* BIT MASK FOR USB2 STORAGE PRESENT AT BOOT UP */
#define PRES_USB3 16 /* BIT MASK FOR USB3 STORAGE PRESENT AT BOOT UP */
#define PRES_USB4 32 /* BIT MASK FOR USB4 STORAGE PRESENT AT BOOT UP */
#define PRES_CH376 128 /* BIT MASK FOR CH376 PRESENT AT BOOT UP */
#define BIT_PRES_CF 0 /* BIT POSTION FOR COMPACTFLASH PRESENT */
#define BIT_PRES_MS 1 /* BIT POSTION FOR MSX MUSIC NOR FLASH PRESENT */
#define BIT_PRES_USB1 2 /* BIT POSTION FOR USB1 STORAGE PRESENT */
#define BIT_PRES_USB2 3 /* BIT POSTION FOR USB2 STORAGE PRESENT */
#define BIT_PRES_USB3 4 /* BIT POSTION FOR USB3 STORAGE PRESENT */
#define BIT_PRES_USB4 5 /* BIT POSTION FOR USB4 STORAGE PRESENT */
#define BIT_PRES_CH376 7 /* BIT POSTION FOR CH376 PRESENT */
typedef enum {
DEV_MAP_NONE = 0,
DEV_MAP_ROM = 1,
DEV_MAP_CF = 2,
DEV_MAP_MS = 3,
DEV_MAP_USB1 = 4,
DEV_MAP_USB2 = 5,
DEV_MAP_USB3 = 6,
DEV_MAP_USB4 = 7
} device_map;
typedef struct _work_area {
uint8_t read_count; /* COUNT OF SECTORS TO BE READ */
uint16_t index; /* sector number to be read */
uint8_t *dest; /* destination write address */
uint8_t read_count_requested; /* number of sectors requested */
uint8_t present; /* BIT FIELD FOR DETECTED DEVICES
(BIT 0 -> COMPACTFLASH/IDE, BIT 1-> MSX-MUSIC NOR FLASH, BITS 2-5 FOR USB)*/
_usb_state ch376;
} work_area;
// extern work_area *get_work_area(void);
extern uint8_t get_number_of_usb_drives(void);
extern _usb_state x;
#define get_usb_work_area() (&x)
#endif

54
Source/HBIOS/ch376-native/source-doc/convert-for-uz80as.sh

@ -0,0 +1,54 @@
#!/bin/sh
# Check if exactly two arguments are provided
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <source_file> <destination_file>"
exit 1
fi
source_file="$1"
destination_file="$2"
rm -f "$destination_file"
# create a unique prefix for all generated labels
prefix=$(basename "$source_file" | cut -d. -f1 | tr '-' '_')
sed -E \
-e "1i\;\r\n; Generated from source-doc/${source_file} -- not to be modify directly\r\n;\r\n; " \
-e '/SECTION IGNORE/d' \
-e '/\sEXTERN\s/d' \
-e '/\sGLOBAL\s/d' \
-e '/SECTION .*/d' \
-e 's/^IF 0/#IF 0/g' \
-e 's/^ENDIF/#ENDIF/g' \
-e 's/\s+cp\s+a,\((ix\+[0-9-]+)\)/\tcp\t\(\1\)/g' \
-e 's/\s+sub\s+a,\((iy\+[0-9]+)\)/\tsub\t\(\1\)/g' \
-e 's/\s+sub\s+a,\((ix\+[0-9]+)\)/\tsub\t\(\1\)/g' \
-e 's/\s+sub\s+a,\((ix-[0-9]+)\)/\tsub\t\(\1\)/g' \
-e 's/\s+or\s+a,\((ix\+[0-9-]+)\)/\tor\t\(\1\)/g' \
-e 's/\s+or\s+a,\((ix\-[0-9-]+)\)/\tor\t\(\1\)/g' \
-e 's/\s+or\s+a,\((iy\+[0-9-]+)\)/\tor\t\(\1\)/g' \
-e 's/\s+or\s+a,\s*\((hl)\)/\tor\t\(\1\)/g' \
-e 's/\s+sub\s+a,\s*\((hl)\)/\tsub\t\(\1\)/g' \
-e 's/\s+cp\s+a,(0x[0-9A-Fa-f]{2})/\tcp\t\1/g' \
-e 's/\s+or\s+a,(0x[0-9A-Fa-f]{2})/\tor\t\1/g' \
-e 's/\s+xor\s+a,(0x[0-9A-Fa-f]{2})/\txor\t\1/g' \
-e 's/\s+and\s+a,(0x[0-9A-Fa-f]{2})/\tand\t\1/g' \
-e 's/\s+and\s+a,\s*a/\tand\ta/g' \
-e 's/\s+and\s+a,\s*(b|c|d|e|h|l|iyl|iyh|ixl|ixh)/\tand\t\1/g' \
-e 's/\s+sub\s+a,(0x[0-9A-Fa-f]{2})/\tsub\t\1/g' \
-e 's/\s+cp\s+a,\s*a/\tcp\ta/g' \
-e 's/\s+or\s+a,\s*a/\tor\ta/g' \
-e 's/\s+xor\s+a,\s*a/\txor\ta/g' \
-e 's/\s+or\s+a,\s*(b|c|d|e|h|l|iyl|iyh|ixl|ixh)/\tor\t\1/g' \
-e 's/\s+sub\s+a,\s+(b|c|d|e|h|l|iyl|iyh|ixl|ixh)/\tsub\t\1/g' \
-e 's/\b([a-zA-Z0-9_]{31})[a-zA-Z0-9_]+\b/\1/g' \
-e 's/;\t+/; /g' \
-e 's/defc\s+([a-zA-Z0-9_]+)\s*=\s*(0x[0-9A-Fa-f]+)/\1\t.EQU\t\2/' \
-e "s/___str_([0-9]+)/${prefix}_str_\1/g" \
"$source_file" > "$destination_file"
# -e '/IF 0/d' \
# -e '/ENDIF/d' \

24
Source/HBIOS/ch376-native/source-doc/keyboard/class_hid.c

@ -0,0 +1,24 @@
#include "class_hid.h"
#include <stdint.h>
const setup_packet cmd_hid_set = {0x21, HID_SET_PROTOCOL, {0, 0}, {0, 0}, 0};
usb_error hid_set_protocol(const device_config_keyboard *const dev, const uint8_t protocol) __sdcccall(1) {
setup_packet cmd;
cmd = cmd_hid_set;
cmd.bRequest = HID_SET_PROTOCOL;
cmd.bValue[0] = protocol;
return usb_control_transfer(&cmd, NULL, dev->address, dev->max_packet_size);
}
usb_error hid_set_idle(const device_config_keyboard *const dev, const uint8_t duration) __sdcccall(1) {
setup_packet cmd;
cmd = cmd_hid_set;
cmd.bRequest = HID_SET_IDLE;
cmd.bValue[0] = duration;
return usb_control_transfer(&cmd, NULL, dev->address, dev->max_packet_size);
}

21
Source/HBIOS/ch376-native/source-doc/keyboard/class_hid.h

@ -0,0 +1,21 @@
#ifndef __CLASS_HID_H__
#define __CLASS_HID_H__
#include "ch376.h"
#include "protocol.h"
#define HID_GET_REPORT 0x01
#define HID_GET_IDLE 0x02
#define HID_GET_PROTOCOL 0x03
#define HID_SET_REPORT 0x09
#define HID_SET_IDLE 0x0A
#define HID_SET_PROTOCOL 0x0B
#define HID_BOOT_PROTOCOL 0x00
#define HID_REPORT_PROTOCOL 0x01
extern usb_error hid_set_protocol(const device_config_keyboard *const dev, const uint8_t protocol) __sdcccall(1);
extern usb_error hid_set_idle(const device_config_keyboard *const dev, const uint8_t duration) __sdcccall(1);
extern usb_error hid_get_input_report(const device_config_keyboard *const dev, uint8_t const *report) __sdcccall(1);
#endif

377
Source/HBIOS/ch376-native/source-doc/keyboard/class_hid_keyboard.c

@ -0,0 +1,377 @@
#include "class_hid_keyboard.h"
#define ESC 0x1B
/**
* scan codes sourced from https://deskthority.net/wiki/Scancode
*
*/
char scancodes_shift_table[128] = {
0x00, /*Reserved*/
0x00, /*Reserved*/
0x00, /*Reserved*/
0x00, /*Reserved*/
/* 0x04 */
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
/* 0x0C */
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
/* 0X14 */
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
/* 0X1C */
'Y',
'Z',
'!',
'@',
'#',
'$',
'%',
'^',
/* 0x24 */
'&',
'*',
'(',
')',
'\r',
ESC,
'\b',
'\t',
/* 0x2C */
' ',
'_',
'+',
'{',
'}',
'|',
'~',
':',
/* 0x34 */
'"',
'~',
'<',
'>',
'?',
0x00 /*CAPSLOCK*/,
0x00 /* F1 */,
0x00 /* F2 */,
/* 0x3C */
0x00 /* F3 */,
0x00 /* F4 */,
0x00 /* F5 */,
0x00 /* F6 */,
0x00 /* F7 */,
0x00 /* F8 */,
0x00 /* F9 */,
0x00 /* F10 */,
/* 0x44 */
0x00 /* F11 */,
0x00 /* F12 */,
0x00 /* PRINTSCREEN */,
0x00 /* SCROLLLOCK */,
0x00 /* PAUSE */,
0x00 /* INSERT */,
0x00 /* HOME */,
0x00 /* PAGEUP */,
/* 0x4C */
0x00 /* DELETE */,
0x00 /* END */,
0x00 /* PAGEDOWN */,
0x00 /* RIGHT */,
0x00 /* LEFT */,
0x00 /* DOWN */,
0x00 /* UP */,
0x00 /* NUMLOCK */,
/* 0x54 */
'/' /* KP / */,
'*' /* KP * */,
'-' /* KP - */,
'+' /* KP + */,
'\r' /* KP ENTER */,
'1' /* KP 1 */,
'2' /* KP 2 */,
'3' /* KP 3 */,
/* 0x5C */
'4' /* KP 4 */,
'5' /* KP 5 */,
'6' /* KP 6 */,
'7' /* KP 7 */,
'8' /* KP 8 */,
'9' /* KP 9 */,
'0' /* KP 0 */,
'.' /* KP . */,
/* 0x64 */
'\\',
0x00 /* MENU */,
0x00 /* POWER */,
'=' /* KP = */,
0x00 /* F13 */,
0x00 /* F14 */,
0x00 /* F15 */,
0x00 /* F16 */,
/* 0x6C */
0x00 /* F17 */,
0x00 /* F18 */,
0x00 /* F19 */,
0x00 /* F20 */,
0x00 /* F21 */,
0x00 /* F22 */,
0x00 /* F23 */,
0x00 /* F24 */,
/* 0x74 */
0x00 /* EXECUTE */,
0x00 /* HELP */,
0x00 /* MENU */,
0x00 /* SELECT */,
0x00 /* STOP */,
0x00 /* AGAIN */,
0x00 /* UNDO */,
0x00 /* CUT */,
/* 0x7C */
0x00 /* COPY */,
0x00 /* PASTE */,
0x00 /* FIND */,
0x00 /* MUTE */,
};
char scancodes_table[128] = {
0x00, /*Reserved*/
0x00, /*Reserved*/
0x00, /*Reserved*/
0x00, /*Reserved*/
/* 0x04 */
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
/* 0x0C */
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
/* 0x14 */
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
/* 0x1C */
'y',
'z',
'1',
'2',
'3',
'4',
'5',
'6',
/* 0x24 */
'7',
'8',
'9',
'0',
'\r',
ESC,
'\b',
'\t',
/* 0x2C */
' ',
'-',
'=',
'[',
']',
'\\',
'#',
';',
/* 0x34 */
'\'',
'`',
',',
'.',
'/',
/* 0x39 */
0x00 /*CAPSLOCK*/,
0x00 /* F1 */,
0x00 /* F2 */,
/* 0x3C */
0x00 /* F3 */,
0x00 /* F4 */,
0x00 /* F5 */,
0x00 /* F6 */,
0x00 /* F7 */,
0x00 /* F8 */,
0x00 /* F9 */,
0x00 /* F10 */,
/* 0x44 */
0x00 /* F11 */,
0x00 /* F12 */,
0x00 /* PRINTSCREEN */,
0x00 /* SCROLLLOCK */,
0x00 /* PAUSE */,
0x00 /* INSERT */,
0x00 /* HOME */,
0x00 /* PAGEUP */,
/* 0x4C */
0x00 /* DELETE */,
0x00 /* END */,
0x00 /* PAGEDOWN */,
0x00 /* RIGHT */,
0x00 /* LEFT */,
0x00 /* DOWN */,
0x00 /* UP */,
0x00 /* NUMLOCK */,
/* 0x54 */
'/' /* KP / */,
'*' /* KP * */,
'-' /* KP - */,
'+' /* KP + */,
'\r' /* KP ENTER */,
'1' /* KP 1 */,
'2' /* KP 2 */,
'3' /* KP 3 */,
/* 0x5C */
'4' /* KP 4 */,
'5' /* KP 5 */,
'6' /* KP 6 */,
'7' /* KP 7 */,
'8' /* KP 8 */,
'9' /* KP 9 */,
'0' /* KP 0 */,
'.' /* KP . */,
/* 0x64 */
'\\',
0x00 /* MENU */,
0x00 /* POWER */,
'=' /* KP = */,
0x00 /* F13 */,
0x00 /* F14 */,
0x00 /* F15 */,
0x00 /* F16 */,
/* 0x6C */
0x00 /* F17 */,
0x00 /* F18 */,
0x00 /* F19 */,
0x00 /* F20 */,
0x00 /* F21 */,
0x00 /* F22 */,
0x00 /* F23 */,
0x00 /* F24 */,
/* 0x74 */
0x00 /* EXECUTE */,
0x00 /* HELP */,
0x00 /* MENU */,
0x00 /* SELECT */,
0x00 /* STOP */,
0x00 /* AGAIN */,
0x00 /* UNDO */,
0x00 /* CUT */,
/* 0x7C */
0x00 /* COPY */,
0x00 /* PASTE */,
0x00 /* FIND */,
0x00 /* MUTE */,
};
static char char_with_caps_lock(const char c, const bool caps_lock_engaged) __sdcccall(1) {
if (!caps_lock_engaged)
return c;
if (c >= 'A' && c <= 'Z')
return c - 'A' + 'a';
if (c >= 'a' && c <= 'z')
return c - 'a' + 'A';
return c;
}
char scancode_to_char(const uint8_t modifier_keys, const uint8_t code, const bool caps_lock_engaged) __sdcccall(1) {
if ((modifier_keys & (KEY_MOD_LCTRL | KEY_MOD_RCTRL))) {
if (code >= 4 && code <= 0x1d)
return code - 3;
if (code == 0x1F || code == 0x2C) //@ or SPACE
return 0;
if (code == 0x2F) // [
return 27;
if (code == 0x31) // back slash
return 28;
if (code == 0x30) // ]
return 29;
if (code == 0x23) //^
return 30;
if (code == 0x2D) //_
return 31;
}
if (modifier_keys & (KEY_MOD_LSHIFT | KEY_MOD_RSHIFT))
return char_with_caps_lock(scancodes_shift_table[code], caps_lock_engaged);
return char_with_caps_lock(scancodes_table[code], caps_lock_engaged);
}

27
Source/HBIOS/ch376-native/source-doc/keyboard/class_hid_keyboard.h

@ -0,0 +1,27 @@
#ifndef __CLASS_HID_KEYBOARD_H__
#define __CLASS_HID_KEYBOARD_H__
#include <stdbool.h>
#include <stdint.h>
typedef struct {
uint8_t bModifierKeys;
uint8_t bReserved;
uint8_t keyCode[6];
} keyboard_report_t;
#define KEY_MOD_LCTRL 0x01
#define KEY_MOD_LSHIFT 0x02
#define KEY_MOD_LALT 0x04
#define KEY_MOD_LMETA 0x08
#define KEY_MOD_RCTRL 0x10
#define KEY_MOD_RSHIFT 0x20
#define KEY_MOD_RALT 0x40
#define KEY_MOD_RMETA 0x80
#define KEY_CODE_CAPS_LOCK 0x39
extern char scancodes_table[128];
extern char scancode_to_char(const uint8_t modifier_keys, const uint8_t code, const bool caps_lock_engaged) __sdcccall(1);
#endif

25
Source/HBIOS/ch376-native/source-doc/keyboard/kyb-init.c

@ -0,0 +1,25 @@
#include "kyb_driver.h"
#include <print.h>
#include <stdint.h>
#include <usb_state.h>
uint8_t keyboard_init(void) __sdcccall(1) {
uint8_t index = 1;
do {
usb_device_type t = usb_get_device_type(index);
if (t == USB_IS_KEYBOARD) {
print_string("\r\nUSB: KEYBOARD @ $");
print_uint16(index);
print_string(" $");
usb_kyb_init(index);
return 1;
}
} while (++index != MAX_NUMBER_OF_DEVICES + 1);
print_string("\r\nUSB: KEYBOARD: NOT FOUND$");
return 0;
}

136
Source/HBIOS/ch376-native/source-doc/keyboard/kyb_driver.c

@ -0,0 +1,136 @@
#include "kyb_driver.h"
#include "class_hid.h"
#include "class_hid_keyboard.h"
#include <critical-section.h>
#include <dev_transfers.h>
#include <stdint.h>
#include <usb_state.h>
#define KEYBOARD_BUFFER_SIZE 8
#define KEYBOARD_BUFFER_SIZE_MASK 7
static bool caps_lock_engaged = true;
static device_config_keyboard *keyboard_config = 0;
static uint8_t buffer[KEYBOARD_BUFFER_SIZE] = {0};
static uint8_t write_index = 0;
static uint8_t read_index = 0;
static keyboard_report_t report = {0};
static keyboard_report_t previous = {0};
#define DI __asm__("DI")
#define EI __asm__("EI")
static uint8_t report_diff() __sdcccall(1) {
uint8_t *a = (uint8_t *)&report;
uint8_t *b = (uint8_t *)&previous;
uint8_t i = sizeof(report);
do {
if (*a++ != *b++)
return true;
} while (--i != 0);
return false;
}
static void keyboard_buf_put(const uint8_t indx) __sdcccall(1) {
const uint8_t key_code = report.keyCode[indx];
if (key_code >= 0x80 || key_code == 0)
return; // ignore ???
// if already reported, just skip it
if (previous.keyCode[indx] == key_code)
return;
if (key_code == KEY_CODE_CAPS_LOCK) {
caps_lock_engaged = !caps_lock_engaged;
return;
}
const unsigned char c = scancode_to_char(report.bModifierKeys, key_code, caps_lock_engaged);
if (c == 0)
return;
uint8_t next_write_index = (write_index + 1) & KEYBOARD_BUFFER_SIZE_MASK;
if (next_write_index != read_index) { // Check if buffer is not full
buffer[write_index] = c;
write_index = next_write_index;
}
}
uint8_t usb_kyb_status() __sdcccall(1) {
DI;
uint8_t size;
if (write_index >= read_index)
size = write_index - read_index;
else
size = KEYBOARD_BUFFER_SIZE - read_index + write_index;
EI;
return size;
}
uint16_t usb_kyb_read() {
if (write_index == read_index) // Check if buffer is empty
return 0xFF00; // H = -1, L = 0
DI;
const uint8_t c = buffer[read_index];
read_index = (read_index + 1) & KEYBOARD_BUFFER_SIZE_MASK;
EI;
/* H = 0, L = ascii char */
return c;
}
uint8_t usb_kyb_flush() __sdcccall(1) {
DI;
write_index = read_index = 0;
uint8_t i = sizeof(previous);
uint8_t *a = (uint8_t *)previous;
uint8_t *b = (uint8_t *)report;
do {
*a++ = 0;
*b++ = 0;
} while (--i != 0);
EI;
return 0;
}
void usb_kyb_tick(void) {
usb_error result;
if (is_in_critical_section())
return;
ch_configure_nak_retry_disable();
result = usbdev_dat_in_trnsfer_0((device_config *)keyboard_config, (uint8_t *)&report, 8);
ch_configure_nak_retry_3s();
if (result == 0) {
if (report_diff()) {
uint8_t i = 6;
do {
keyboard_buf_put(i - 1);
} while (--i != 0);
previous = report;
}
}
}
void usb_kyb_init(const uint8_t dev_index) __sdcccall(1) {
keyboard_config = (device_config_keyboard *)get_usb_device_config(dev_index);
if (keyboard_config == NULL)
return;
hid_set_protocol(keyboard_config, 1);
hid_set_idle(keyboard_config, 0x80);
}

12
Source/HBIOS/ch376-native/source-doc/keyboard/kyb_driver.h

@ -0,0 +1,12 @@
#ifndef __KYB_DRIVER__
#define __KYB_DRIVER__
#include <ch376.h>
#include <stdint.h>
extern void usb_kyb_init(const uint8_t dev_index) __sdcccall(1);
extern uint8_t usb_kyb_flush() __sdcccall(1);
extern uint8_t usb_kyb_status() __sdcccall(1);
extern uint16_t usb_kyb_read();
#endif

77
Source/HBIOS/ch376-native/source-doc/scsi-drv/class_scsi.c

@ -0,0 +1,77 @@
#include "class_scsi.h"
#include <critical-section.h>
#include <string.h>
#include <usb_state.h>
#include <z80.h>
_scsi_command_block_wrapper scsi_command_block_wrapper = {{0x55, 0x53, 0x42, 0x43}, {0, 0}, 0, 0, 0, 0};
uint16_t next_tag = 0;
usb_error do_scsi_cmd(device_config_storage *const dev,
_scsi_command_block_wrapper *const cbw,
void *const send_receive_buffer,
const bool send) {
usb_error result;
_scsi_command_status_wrapper csw = {{{0}}};
cbw->dCBWTag[0] = next_tag++;
if (!send)
cbw->bmCBWFlags = 0x80;
critical_begin();
CHECK(usb_data_out_transfer((uint8_t *)cbw, sizeof(_scsi_command_block_wrapper) + 16, dev->address,
&dev->endpoints[ENDPOINT_BULK_OUT]));
if (cbw->dCBWDataTransferLength != 0) {
if (!send) {
CHECK(usb_data_in_transfer(send_receive_buffer, (uint16_t)cbw->dCBWDataTransferLength, dev->address,
&dev->endpoints[ENDPOINT_BULK_IN]));
} else {
CHECK(usb_data_out_transfer(send_receive_buffer, (uint16_t)cbw->dCBWDataTransferLength, dev->address,
&dev->endpoints[ENDPOINT_BULK_OUT]));
}
}
CHECK(
usb_data_in_transfer((uint8_t *)&csw, sizeof(_scsi_command_status_wrapper), dev->address, &dev->endpoints[ENDPOINT_BULK_IN]));
if (csw.bCSWStatus != 0 || csw.dCSWTag[0] != cbw->dCBWTag[0])
result = USB_ERR_FAIL;
else
result = USB_ERR_OK;
done:
critical_end();
return result;
}
usb_error scsi_test(device_config_storage *const dev) {
cbw_scsi_test cbw_scsi;
cbw_scsi.cbw = scsi_command_block_wrapper;
memset(&cbw_scsi.test, 0, sizeof(_scsi_packet_test));
cbw_scsi.cbw.bCBWLUN = 0;
cbw_scsi.cbw.bCBWCBLength = sizeof(_scsi_packet_test);
cbw_scsi.cbw.dCBWDataTransferLength = 0;
return do_scsi_cmd(dev, &cbw_scsi.cbw, 0, false);
}
const _scsi_packet_request_sense scsi_packet_request_sense = {0x03, 0, 0, 0, 18, 0, {0, 0, 0, 0, 0, 0}};
usb_error scsi_request_sense(device_config_storage *const dev, scsi_sense_result *const sens_result) {
cbw_scsi_request_sense cbw_scsi;
cbw_scsi.cbw = scsi_command_block_wrapper;
cbw_scsi.request_sense = scsi_packet_request_sense;
cbw_scsi.cbw.bCBWLUN = 0;
cbw_scsi.cbw.bCBWCBLength = sizeof(_scsi_packet_request_sense);
cbw_scsi.cbw.dCBWDataTransferLength = sizeof(scsi_sense_result);
return do_scsi_cmd(dev, &cbw_scsi.cbw, sens_result, false);
}

196
Source/HBIOS/ch376-native/source-doc/scsi-drv/class_scsi.h

@ -0,0 +1,196 @@
#ifndef __CLASS_SCSI
#define __CLASS_SCSI
#include <protocol.h>
typedef struct {
uint8_t dCBWSignature[4];
uint16_t dCBWTag[2];
uint32_t dCBWDataTransferLength;
uint8_t bmCBWFlags;
uint8_t bCBWLUN;
uint8_t bCBWCBLength;
} _scsi_command_block_wrapper;
typedef struct {
uint8_t operation_code;
uint8_t lun;
uint8_t reserved1;
uint8_t reserved2;
uint8_t allocation_length;
uint8_t reserved3;
uint8_t pad[6];
} _scsi_packet_request_sense;
typedef struct {
_scsi_command_block_wrapper cbw;
_scsi_packet_request_sense request_sense;
} cbw_scsi_request_sense;
typedef struct {
uint8_t operation_code;
uint8_t IMMED : 1;
uint8_t reserved : 7;
uint8_t reserved2;
uint8_t power_condition_modifier : 4;
uint8_t reserved3 : 4;
uint8_t start : 1;
uint8_t loej : 1;
uint8_t no_flush : 1;
uint8_t reserved4 : 1;
uint8_t power_condition : 4;
uint8_t control;
} _scsi_packet_eject;
typedef struct {
_scsi_command_block_wrapper cbw;
_scsi_packet_eject eject;
} cbw_scsi_eject;
typedef struct {
uint8_t operation_code;
uint8_t lun;
uint8_t reserved1;
uint8_t reserved2;
uint8_t reserved3;
uint8_t reserved4;
uint8_t pad[6];
} _scsi_packet_test;
typedef struct {
_scsi_command_block_wrapper cbw;
_scsi_packet_test test;
} cbw_scsi_test;
typedef struct {
uint8_t operation_code;
uint8_t lun;
uint8_t reserved[8];
uint8_t pad[2];
} _scsi_read_capacity;
typedef struct {
_scsi_command_block_wrapper cbw;
_scsi_read_capacity read_capacity;
} cbw_scsi_read_capacity;
typedef struct __scsi_packet_inquiry { // contains information about a specific device
uint8_t operation_code;
uint8_t lun;
uint8_t reserved1;
uint8_t reserved2;
uint8_t allocation_length;
uint8_t reserved3;
uint8_t pad[6];
} _scsi_packet_inquiry;
typedef struct {
_scsi_command_block_wrapper cbw;
_scsi_packet_inquiry inquiry;
} cbw_scsi_inquiry;
typedef struct {
uint8_t device_type : 5;
uint8_t device_type_qualifier : 3;
uint8_t device_type_modifier : 7;
uint8_t removable_media : 1;
union {
uint8_t versions;
struct {
uint8_t ansi_version : 3;
uint8_t ecma_version : 3;
uint8_t iso_version : 2;
};
};
uint8_t response_data_format : 4;
uint8_t hi_support : 1;
uint8_t norm_aca : 1;
uint8_t terminate_task : 1;
uint8_t aerc : 1;
uint8_t additional_length;
uint8_t reserved;
uint8_t addr16 : 1;
uint8_t addr32 : 1;
uint8_t ack_req_q : 1;
uint8_t medium_changer : 1;
uint8_t multi_port : 1;
uint8_t reserved_bit2 : 1;
uint8_t enclosure_services : 1;
uint8_t reserved_bit3 : 1;
uint8_t soft_reset : 1;
uint8_t command_queue : 1;
uint8_t transfer_disable : 1;
uint8_t linked_commands : 1;
uint8_t synchronous : 1;
uint8_t wide16_bit : 1;
uint8_t wide32_bit : 1;
uint8_t relative_addressing : 1;
uint8_t vendor_information[8];
uint8_t product_id[16];
uint8_t product_revision[4];
uint8_t vendor_specific[20];
uint8_t reserved3[40];
} scsi_inquiry_result;
typedef struct __scsi_command_status_wrapper {
uint8_t dCSWSignature[4];
uint16_t dCSWTag[2];
uint8_t dCSWDataResidue[4];
uint8_t bCSWStatus;
} _scsi_command_status_wrapper;
typedef struct {
uint8_t number_of_blocks[4];
uint8_t block_size[4];
} scsi_read_capacity_result;
typedef struct {
uint8_t error_code : 7;
uint8_t valid : 1;
uint8_t segment_number;
uint8_t sense_key : 4;
uint8_t reserved : 1;
uint8_t incorrect_length : 1;
uint8_t end_of_media : 1;
uint8_t file_mark : 1;
uint8_t information[4];
uint8_t additional_sense_length;
uint8_t command_specific_information[4];
uint8_t additional_sense_code;
uint8_t additional_sense_code_qualifier;
uint8_t field_replaceable_unit_code;
uint8_t sense_key_specific[3];
} scsi_sense_result;
typedef struct {
uint8_t operation_code;
uint8_t lun;
uint8_t lba[4]; // high-endian block number
uint8_t reserved1;
uint8_t transfer_len[2]; // high-endian in blocks of block_len (see scsi_capacity)
uint8_t reserved2;
uint8_t pad[2];
} _scsi_packet_read_write;
typedef struct {
_scsi_command_block_wrapper cbw;
_scsi_packet_read_write scsi_cmd;
} cbw_scsi_read_write;
extern _scsi_command_block_wrapper scsi_command_block_wrapper;
extern usb_error do_scsi_cmd(device_config_storage *const dev,
_scsi_command_block_wrapper *const cbw,
void *const send_receive_buffer,
const bool send);
extern usb_error scsi_test(device_config_storage *const dev);
extern usb_error scsi_request_sense(device_config_storage *const dev, scsi_sense_result *const sens_result);
#endif

30
Source/HBIOS/ch376-native/source-doc/scsi-drv/scsi-init.c

@ -0,0 +1,30 @@
#include "hbios-driver-storage.h"
#include "scsi_driver.h"
#include <hbios.h>
#include <print.h>
#include <string.h>
extern const uint16_t const ch_scsi_fntbl[];
void chscsi_init(void) {
uint8_t index = 1;
do {
usb_device_type t = usb_get_device_type(index);
if (t == USB_IS_MASS_STORAGE) {
const uint8_t dev_index = find_storage_dev(); // index == -1 (no more left) should never happen
hbios_usb_storage_devices[dev_index].drive_index = dev_index + 1;
hbios_usb_storage_devices[dev_index].usb_device = index;
print_string("\r\nUSB: MASS STORAGE @ $");
print_uint16(index);
print_string(":$");
print_uint16(dev_index);
print_string(" $");
usb_scsi_init(index);
dio_add_entry(ch_scsi_fntbl, &hbios_usb_storage_devices[dev_index]);
}
} while (++index != MAX_NUMBER_OF_DEVICES + 1);
}

123
Source/HBIOS/ch376-native/source-doc/scsi-drv/scsi_driver.c

@ -0,0 +1,123 @@
#include "scsi_driver.h"
#include "class_scsi.h"
#include <ch376.h>
#include <critical-section.h>
#include <string.h>
#include <usb_state.h>
usb_error usb_scsi_init(const uint16_t dev_index) {
usb_error result;
device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index);
scsi_sense_result response;
uint8_t counter = 3;
critical_begin();
while ((result = scsi_test(dev)) && --counter > 0)
scsi_request_sense(dev, &response);
critical_end();
return result;
}
_scsi_read_capacity scsi_packet_read_capacity = {0x25, 0, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0}};
usb_error usb_scsi_read_capacity(const uint16_t dev_index, scsi_read_capacity_result *cap_result) {
device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index);
cbw_scsi_read_capacity cbw_scsi;
cbw_scsi.cbw = scsi_command_block_wrapper;
cbw_scsi.read_capacity = scsi_packet_read_capacity;
cbw_scsi.cbw.bCBWLUN = 0;
cbw_scsi.cbw.bCBWCBLength = sizeof(_scsi_read_capacity);
cbw_scsi.cbw.dCBWDataTransferLength = sizeof(scsi_read_capacity_result);
return do_scsi_cmd(dev, &cbw_scsi.cbw, cap_result, false);
}
// _scsi_packet_inquiry scsi_packet_inquiry = {0x12, 0, 0, 0, 0x24, 0, {0, 0, 0, 0, 0, 0}};
// usb_error usb_scsi_inquiry(const uint16_t dev_index, scsi_inquiry_result *inq_result) {
// device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index);
// cbw_scsi_inquiry cbw_scsi;
// cbw_scsi.cbw = scsi_command_block_wrapper;
// cbw_scsi.inquiry = scsi_packet_inquiry;
// cbw_scsi.cbw.bCBWLUN = 0;
// cbw_scsi.cbw.bCBWCBLength = sizeof(_scsi_packet_inquiry);
// cbw_scsi.cbw.dCBWDataTransferLength = 0x24;
// return do_scsi_cmd(dev, &cbw_scsi.cbw, inq_result, false);
// }
static cbw_scsi_read_write cbw = {{{0}}};
usb_error usb_scsi_read(const uint16_t dev_index, uint8_t *const buffer) {
usb_error result;
device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index);
memset(&cbw, 0, sizeof(cbw_scsi_read_write));
cbw.cbw = scsi_command_block_wrapper;
cbw.cbw.bCBWLUN = 0;
cbw.cbw.bCBWCBLength = sizeof(_scsi_packet_read_write);
cbw.cbw.dCBWDataTransferLength = 512;
cbw.scsi_cmd.operation_code = 0x28; // read operation
cbw.scsi_cmd.transfer_len[1] = 1;
cbw.scsi_cmd.lba[0] = dev->current_lba >> 24;
cbw.scsi_cmd.lba[1] = dev->current_lba >> 16;
cbw.scsi_cmd.lba[2] = dev->current_lba >> 8;
cbw.scsi_cmd.lba[3] = dev->current_lba;
result = do_scsi_cmd(dev, &cbw.cbw, buffer, false);
if (result == USB_ERR_OK)
dev->current_lba++;
return result;
}
usb_error usb_scsi_write(const uint16_t dev_index, uint8_t *const buffer) {
usb_error result;
device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index);
memset(&cbw, 0, sizeof(cbw_scsi_read_write));
cbw.cbw = scsi_command_block_wrapper;
cbw.cbw.bCBWLUN = 0;
cbw.cbw.bCBWCBLength = sizeof(_scsi_packet_read_write);
cbw.cbw.dCBWDataTransferLength = 512;
cbw.scsi_cmd.operation_code = 0x2A; // write operation
cbw.scsi_cmd.transfer_len[1] = 1;
cbw.scsi_cmd.lba[0] = dev->current_lba >> 24;
cbw.scsi_cmd.lba[1] = dev->current_lba >> 16;
cbw.scsi_cmd.lba[2] = dev->current_lba >> 8;
cbw.scsi_cmd.lba[3] = dev->current_lba;
result = do_scsi_cmd(dev, &cbw.cbw, buffer, true);
if (result == USB_ERR_OK)
dev->current_lba++;
return result;
}
// usb_error scsi_eject(device_config_storage *const dev) {
// cbw_scsi_eject cbw_scsi;
// cbw_scsi.cbw = scsi_command_block_wrapper;
// memset(&cbw_scsi.eject, 0, sizeof(_scsi_packet_eject));
// cbw_scsi.eject.operation_code = 0x1B;
// cbw_scsi.eject.loej = 1;
// cbw_scsi.cbw.bCBWLUN = 0;
// cbw_scsi.cbw.bCBWCBLength = sizeof(_scsi_packet_eject);
// cbw_scsi.cbw.dCBWDataTransferLength = 0;
// return do_scsi_cmd(dev, &cbw_scsi.cbw, 0, false);
// }

14
Source/HBIOS/ch376-native/source-doc/scsi-drv/scsi_driver.h

@ -0,0 +1,14 @@
#ifndef __SCSI_DRIVER__
#define __SCSI_DRIVER__
#include "class_scsi.h"
#include <ch376.h>
#include <stdint.h>
extern usb_error usb_scsi_init(const uint16_t dev_index);
extern usb_error usb_scsi_read_capacity(const uint16_t dev_index, scsi_read_capacity_result *result);
extern usb_error usb_scsi_read(const uint16_t dev_index, uint8_t *const buffer);
extern usb_error usb_scsi_write(const uint16_t dev_index, uint8_t *const buffer);
extern usb_error usb_scsi_seek(const uint16_t dev_index, const uint32_t lba);
#endif

179
Source/HBIOS/ch376-native/source-doc/ufi-drv/class_ufi.c

@ -0,0 +1,179 @@
#include "class_ufi.h"
#include <delay.h>
#include <protocol.h>
#include <stdlib.h>
#include <string.h>
#include <z80.h>
const ufi_request_sense_command _ufi_cmd_request_sense = {0x03, 0, 0, 0, 18, {0, 0, 0, 0, 0, 0, 0}};
const ufi_read_format_capacities_command _ufi_cmd_read_format_capacities = {0x23, 0, {0, 0, 0, 0, 0}, {0, 12}, {0, 0, 0}};
const ufi_inquiry_command _ufi_cmd_inquiry = {0x12, 0, 0, 0, 0x24, {0, 0, 0, 0, 0, 0, 0}};
const ufi_format_command _ufi_cmd_format = {0x04, 7 | 1 << 4, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0, 0}};
const ufi_send_diagnostic_command _ufi_cmd_send_diagnostic = {0x1D, 1 << 2, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
uint8_t wait_for_device_ready(device_config *const storage_device, uint8_t timeout_counter) {
usb_error result;
ufi_request_sense_response sense;
do {
memset(&sense, 0, sizeof(sense));
result = ufi_test_unit_ready(storage_device, &sense);
if ((result == USB_ERR_OK && (sense.sense_key & 15) == 0) || timeout_counter-- == 0)
break;
delay_medium();
} while (true);
return result | (sense.sense_key & 15);
}
usb_error ufi_test_unit_ready(device_config *const storage_device, ufi_request_sense_response const *response) {
usb_error result;
ufi_test_unit_ready_command ufi_cmd_request_test_unit_ready;
memset(&ufi_cmd_request_test_unit_ready, 0, sizeof(ufi_test_unit_ready_command));
usb_execute_cbi(storage_device, (uint8_t *)&ufi_cmd_request_test_unit_ready, false, 0, NULL, NULL);
ufi_request_sense_command ufi_cmd_request_sense;
ufi_cmd_request_sense = _ufi_cmd_request_sense;
result = usb_execute_cbi(storage_device, (uint8_t *)&ufi_cmd_request_sense, false, sizeof(ufi_request_sense_response),
(uint8_t *)response, NULL);
RETURN_CHECK(result);
done:
return result;
}
usb_error ufi_request_sense(device_config *const storage_device, ufi_request_sense_response const *response) {
ufi_request_sense_command ufi_cmd_request_sense;
ufi_cmd_request_sense = _ufi_cmd_request_sense;
usb_error result = usb_execute_cbi(storage_device, (uint8_t *)&ufi_cmd_request_sense, false, sizeof(ufi_request_sense_response),
(uint8_t *)response, NULL);
RETURN_CHECK(result);
done:
return result;
}
usb_error ufi_read_frmt_caps(device_config *const storage_device, ufi_format_capacities_response const *response) {
usb_error result;
ufi_read_format_capacities_command ufi_cmd_read_format_capacities;
ufi_cmd_read_format_capacities = _ufi_cmd_read_format_capacities;
result = usb_execute_cbi(storage_device, (uint8_t *)&ufi_cmd_read_format_capacities, false, 12, (uint8_t *)response, NULL);
TRACE_USB_ERROR(result);
CHECK(result);
const uint8_t available_length = response->capacity_list_length;
const uint8_t max_length =
available_length > sizeof(ufi_format_capacities_response) ? sizeof(ufi_format_capacities_response) : available_length;
ufi_read_format_capacities_command cmd;
memcpy(&cmd, &ufi_cmd_read_format_capacities, sizeof(cmd));
cmd.allocation_length[1] = max_length;
result = usb_execute_cbi(storage_device, (uint8_t *)&cmd, false, max_length, (uint8_t *)response, NULL);
TRACE_USB_ERROR(result);
RETURN_CHECK(result);
done:
return result;
}
usb_error ufi_inquiry(device_config *const storage_device, ufi_inquiry_response const *response) {
ufi_inquiry_command ufi_cmd_inquiry;
ufi_cmd_inquiry = _ufi_cmd_inquiry;
usb_error result =
usb_execute_cbi(storage_device, (uint8_t *)&ufi_cmd_inquiry, false, sizeof(ufi_inquiry_response), (uint8_t *)response, NULL);
RETURN_CHECK(result);
done:
return result;
}
usb_error ufi_read_write_sector(device_config *const storage_device,
const bool send,
const uint16_t sector_number,
const uint8_t sector_count,
uint8_t *const buffer,
uint8_t *const sense_codes) {
ufi_read_write_command cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.operation_code = send ? 0x2A : 0x28;
cmd.lba[2] = sector_number >> 8;
cmd.lba[3] = sector_number & 0xFF;
cmd.transfer_length[1] = sector_count;
usb_error result = usb_execute_cbi(storage_device, (uint8_t *)&cmd, send, 512 * sector_count, (uint8_t *)buffer, sense_codes);
RETURN_CHECK(result);
done:
return result;
}
/**
* Medium | Medium Type Code | Capacity | Tracks | Heads | Sectors/Track | Total Blocks | Block Length |
* DD | 1Eh | 720 KB | 80 | 2 | 9 | 1440 05A0h | 512 0200h |
* HD | 93h | 1.25 MB | 77 | 2 | 8 | 1232 04D0h | 1024 0400h |
* HD | 94h | 1.44 MB | 80 | 2 | 18 | 2880 0B40h | 512 0200h |
*/
usb_error ufi_format(device_config *const storage_device,
const uint8_t side,
const uint8_t track_number,
const ufi_format_capacity_descriptor *const format) {
ufi_interrupt_status sense_codes;
ufi_format_parameter_list parameter_list;
memset(&parameter_list, 0, sizeof(parameter_list));
ufi_format_command cmd;
cmd = _ufi_cmd_format;
// memcpy(&cmd, &_ufi_cmd_format, sizeof(cmd));
cmd.track_number = track_number;
cmd.interleave[1] = 0;
cmd.parameter_list_length[1] = sizeof(parameter_list);
parameter_list.defect_list_header.status =
FMT_DEFECT_STATUS_FOV | FMT_DEFECT_STATUS_DCRT | FMT_DEFECT_STATUS_SINGLE_TRACK | (side & 1);
parameter_list.defect_list_header.defect_list_length_msb = 0;
parameter_list.defect_list_header.defect_list_length_lsb = 8;
memcpy(&parameter_list.format_descriptor, (void *)format, sizeof(ufi_format_capacity_descriptor));
usb_error result = usb_execute_cbi(storage_device, (uint8_t *)&cmd, true, sizeof(parameter_list), (uint8_t *)&parameter_list,
(void *)&sense_codes);
// trace_printf("ufi_format: %d, %02X %02X (len: %d)\r\n", result, sense_codes.bASC, sense_codes.bASCQ, sizeof(parameter_list));
RETURN_CHECK(result);
done:
return result;
}
usb_error ufi_send_diagnostics(device_config *const storage_device) {
ufi_send_diagnostic_command ufi_cmd_send_diagnostic;
ufi_cmd_send_diagnostic = _ufi_cmd_send_diagnostic;
return usb_execute_cbi(storage_device, (uint8_t *)&ufi_cmd_send_diagnostic, true, 0, NULL, NULL);
}
uint32_t convert_from_msb_first(const uint8_t *const buffer) {
uint32_t result;
uint8_t *p_output = ((uint8_t *)&result);
const uint8_t *p_input = buffer + 3;
*p_output++ = *p_input--;
*p_output++ = *p_input--;
*p_output++ = *p_input--;
*p_output = *p_input--;
return result;
}

186
Source/HBIOS/ch376-native/source-doc/ufi-drv/class_ufi.h

@ -0,0 +1,186 @@
#ifndef __CLASS_UFI2
#define __CLASS_UFI2
#include "ch376.h"
#include "protocol.h"
#include "usb_cbi.h"
#include "usb_state.h"
#include <stdlib.h>
typedef struct {
uint8_t bASC;
uint8_t bASCQ;
} ufi_interrupt_status;
typedef struct {
uint8_t operation_code;
uint8_t lun; // in top 3 bits
uint8_t reserved1[5];
uint8_t allocation_length[2];
uint8_t reserved[3];
} ufi_read_format_capacities_command;
typedef enum { UNFORMATTED_MEDIA = 1, FORMATTED_MEDIA = 2, NO_MEDIA = 3 } UFI_DESCRIPTOR_CODE;
#define UFI_DESCRIPTOR_CODE_UNFORMATTED_MEDIA 1
#define UFI_DESCRIPTOR_CODE_FORMATTED_MEDIA 2
#define UFI_DESCRIPTOR_CODE_NO_MEDIA 3
typedef struct {
uint8_t number_of_blocks[4];
uint8_t descriptor_codex; // UFI_DESCRIPTOR_CODE
uint8_t block_size[3];
} ufi_format_capacity_descriptor;
typedef struct {
uint8_t reserved1[3];
uint8_t capacity_list_length;
ufi_format_capacity_descriptor descriptors[4]; // support upto
} ufi_format_capacities_response;
typedef struct {
uint8_t operation_code;
uint8_t lun;
uint8_t reserved[10];
} ufi_test_unit_ready_command;
typedef struct {
uint8_t operation_code;
uint8_t lun_and_evpd;
uint8_t page_code;
uint8_t reserved3;
uint8_t allocation_length;
uint8_t reserved4[7];
} ufi_inquiry_command;
typedef struct {
uint8_t operation_code;
uint8_t lun; // top 3 bits
uint8_t reserved2;
uint8_t reserved3;
uint8_t allocation_length;
uint8_t reserved4[7];
} ufi_request_sense_command;
typedef struct {
uint8_t error_code;
uint8_t reserved1;
uint8_t sense_key; // lower 4 bits
uint8_t information[4];
uint8_t additional_length;
uint8_t reserved3[4];
uint8_t asc; // Additional Sense Code
uint8_t ascq; // Additional Sense Code Qualifier
uint8_t reserved4[4];
} ufi_request_sense_response;
typedef struct {
// device_type: identifies the device currently connected to the requested logical unit.
// 00h Direct-access device (floppy)
// 1Fh none (no FDD connected to the requested logical unit)
uint8_t device_type; // lower 5 bits
// Removable Media Bit: this shall be set to one to indicate removable media.
uint8_t removable_media; // top bit
// ANSI Version: must contain a zero to comply with this version of the Specification.
// ISO/ECMA: These fields shall be zero for the UFI device.
uint8_t version;
// Response Data Format: a value of 01h shall be used for UFI device
uint8_t response_data_format; // lower 4 bits
// The Additional Length field shall specify the length in bytes of the parameters. If the Allocation Length of the
// Command Packet is too small to transfer all of the parameters, the Additional Length shall not be adjusted to
// reflect the truncation. The UFI device shall set this field to 1Fh.
uint8_t additional_length;
uint8_t reserved4[3];
// The Vendor Identification field contains 8 bytes of ASCII data identifying the vendor of the product. The data
// shall be left aligned within this field.
char vendor_information[8];
// The Product Identification field contains 16 bytes of ASCII data as defined by the vendor. The data shall be
// left-aligned within this field.
char product_id[16];
// The Product Revision Level field contains 4 bytes of ASCII data as defined by the vendor.
char product_revision[4];
} ufi_inquiry_response;
typedef struct {
uint8_t operation_code; /*0*/
uint8_t byte_1; /*1*/
/* [7:5] lun, [4] dpo, [3] fua, [0]rel_adr*/
uint8_t lba[4]; /*2, 3, 4, 5*/
uint8_t reserved2; /*6*/
uint8_t transfer_length[2]; /*7, 8*/
uint8_t reserved3[3]; /*9, 10, 11*/
} ufi_read_write_command;
typedef struct {
struct {
uint8_t reserved1;
/* [7] FOV, [6] Extend, [5] DCRT, [4] SingleTrack, [1] Immediate, [0] Side*/
uint8_t status;
uint8_t defect_list_length_msb;
uint8_t defect_list_length_lsb;
} defect_list_header;
ufi_format_capacity_descriptor format_descriptor;
} ufi_format_parameter_list;
#define FMT_DEFECT_STATUS_FOV 0x80
#define FMT_DEFECT_STATUS_EXTEND 0x40
#define FMT_DEFECT_STATUS_DCRT 0x20
#define FMT_DEFECT_STATUS_SINGLE_TRACK 0x10
#define FMT_DEFECT_STATUS_IMMEDIATE 0x02
#define FMT_DEFECT_STATUS_SIDE 0x01
typedef struct {
uint8_t operation_code; /* 0x04 */
/* [7:5] lun, [4]format_data, [3]cmp_list, [2:0] defect_list_format*/
uint8_t status;
uint8_t track_number;
uint8_t interleave[2];
uint8_t reserved1[2];
uint8_t parameter_list_length[2];
uint8_t reserved2[3];
} ufi_format_command;
typedef struct {
uint8_t operation_code; /*0x1D*/
/* [7:5] lun, [4] pf, [2] self test, [1] def of l [0] unit of l*/
uint8_t status;
uint8_t reserved[10];
} ufi_send_diagnostic_command;
extern usb_error ufi_request_sense(device_config *const storage_device, ufi_request_sense_response const *response);
extern usb_error ufi_read_frmt_caps(device_config *const storage_device, ufi_format_capacities_response const *response);
extern usb_error ufi_test_unit_ready(device_config *const storage_device, ufi_request_sense_response const *response);
extern usb_error ufi_inquiry(device_config *const storage_device, ufi_inquiry_response const *response);
extern usb_error ufi_read_write_sector(device_config *const storage_device,
const bool send,
const uint16_t sector_number,
const uint8_t sector_count,
const uint8_t *const buffer,
uint8_t *const sense_codes);
uint8_t wait_for_device_ready(device_config *const storage_device, uint8_t timeout_counter);
usb_error ufi_format(device_config *const storage_device,
const uint8_t side,
const uint8_t track_number,
const ufi_format_capacity_descriptor *const format);
usb_error ufi_send_diagnostics(device_config *const storage_device);
uint32_t convert_from_msb_first(const uint8_t *const buffer);
extern usb_error ufi_seek(const uint16_t dev_index, const uint32_t lba);
#endif

29
Source/HBIOS/ch376-native/source-doc/ufi-drv/ufi-init.c

@ -0,0 +1,29 @@
#include "hbios-driver-storage.h"
#include <hbios.h>
#include <print.h>
#include <usb_state.h>
extern const uint16_t const ch_ufi_fntbl[];
void chufi_init(void) {
uint8_t index = 1;
do {
usb_device_type t = usb_get_device_type(index);
if (t == USB_IS_FLOPPY) {
const uint8_t dev_index = find_storage_dev(); // dev_index == -1 (no more left) should never happen
hbios_usb_storage_devices[dev_index].drive_index = dev_index + 1;
hbios_usb_storage_devices[dev_index].usb_device = index;
print_string("\r\nUSB: FLOPPY @ $");
print_uint16(index);
print_string(":$");
print_uint16(dev_index);
print_string(" $");
dio_add_entry(ch_ufi_fntbl, &hbios_usb_storage_devices[dev_index]);
}
} while (++index != MAX_NUMBER_OF_DEVICES + 1);
}

85
Source/HBIOS/ch376-native/source-doc/ufi-drv/ufi_driver.c

@ -0,0 +1,85 @@
#include "ufi_driver.h"
#include "class_ufi.h"
#include <dev_transfers.h>
#include <string.h>
uint32_t usb_ufi_get_cap(const uint16_t dev_index) {
device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index);
ufi_format_capacities_response response;
memset(&response, 0, sizeof(ufi_format_capacities_response));
wait_for_device_ready(dev, 25);
// not sure if we need to do this to 'clear' some state
ufi_inquiry_response inquiry;
ufi_inquiry(dev, &inquiry);
wait_for_device_ready(dev, 15);
const usb_error result = ufi_read_frmt_caps(dev, &response);
if (result != USB_ERR_OK)
return 0;
return convert_from_msb_first(response.descriptors[0].number_of_blocks);
}
usb_error usb_ufi_read(const uint16_t dev_index, uint8_t *const buffer) {
device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index);
if (wait_for_device_ready((device_config *)dev, 20) != 0)
return -1; // Not READY!
usb_error result;
ufi_interrupt_status sense_codes;
memset(&sense_codes, 0, sizeof(sense_codes));
if (ufi_read_write_sector((device_config *)dev, false, dev->current_lba, 1, buffer, (uint8_t *)&sense_codes) != USB_ERR_OK)
return -1; // general error
ufi_request_sense_response response;
memset(&response, 0, sizeof(response));
if ((result = ufi_request_sense((device_config *)dev, &response)) != USB_ERR_OK)
return -1; // error
const uint8_t asc = response.asc;
const uint8_t ascq = response.ascq;
const uint8_t sense_key = response.sense_key & 15;
if (sense_key != 0)
return -1;
return USB_ERR_OK;
}
usb_error usb_ufi_write(const uint16_t dev_index, uint8_t *const buffer) {
device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index);
if (wait_for_device_ready((device_config *)dev, 20) != 0)
return -1; // Not READY!
ufi_interrupt_status sense_codes;
memset(&sense_codes, 0, sizeof(sense_codes));
if ((ufi_read_write_sector((device_config *)dev, true, dev->current_lba, 1, buffer, (uint8_t *)&sense_codes)) != USB_ERR_OK) {
return -1;
}
ufi_request_sense_response response;
memset(&response, 0, sizeof(response));
if ((ufi_request_sense((device_config *)dev, &response)) != USB_ERR_OK) {
return -1;
}
const uint8_t asc = response.asc;
const uint8_t ascq = response.ascq;
const uint8_t sense_key = response.sense_key & 15;
if (sense_key != 0)
return -1;
return USB_ERR_OK;
}

11
Source/HBIOS/ch376-native/source-doc/ufi-drv/ufi_driver.h

@ -0,0 +1,11 @@
#ifndef __UFI_DRIVER__
#define __UFI_DRIVER__
#include <ch376.h>
#include <stdint.h>
extern uint32_t usb_ufi_get_cap(const uint16_t dev_index);
extern usb_error usb_ufi_read(const uint16_t dev_index, uint8_t *const buffer);
extern usb_error usb_ufi_write(const uint16_t dev_index, uint8_t *const buffer);
#endif

69
Source/HBIOS/ch376-native/source-doc/ufi-drv/usb_cbi.c

@ -0,0 +1,69 @@
#include "usb_cbi.h"
#include "dev_transfers.h"
#include "protocol.h"
#include <ch376.h>
#include <critical-section.h>
setup_packet cbi2_adsc = {0x21, 0, {0, 0}, {255, 0}, 12}; // ;4th byte is interface number
// was no clear
usb_error usb_execute_cbi(device_config *const storage_device,
const uint8_t *const cmd,
const bool send,
const uint16_t buffer_size,
uint8_t *const buffer,
uint8_t *const sense_codes) {
usb_error result;
const uint8_t interface_number = storage_device->interface_number;
setup_packet adsc;
adsc = cbi2_adsc;
adsc.bIndex[0] = interface_number;
critical_begin();
result = usbdev_control_transfer(storage_device, &adsc, (uint8_t *const)cmd);
if (result == USB_ERR_STALL) {
if (sense_codes != NULL)
usbdev_dat_in_trnsfer(storage_device, sense_codes, 2, ENDPOINT_INTERRUPT_IN);
result = USB_ERR_STALL;
goto done;
}
if (result != USB_ERR_OK) {
TRACE_USB_ERROR(result);
goto done;
}
if (send) {
result = usbdev_blk_out_trnsfer(storage_device, buffer, buffer_size);
if (result != USB_ERR_OK) {
TRACE_USB_ERROR(result);
goto done;
}
} else {
result = usbdev_dat_in_trnsfer(storage_device, buffer, buffer_size, ENDPOINT_BULK_IN);
if (result != USB_ERR_OK) {
TRACE_USB_ERROR(result);
goto done;
}
}
if (sense_codes != NULL) {
result = usbdev_dat_in_trnsfer(storage_device, sense_codes, 2, ENDPOINT_INTERRUPT_IN);
if (result != USB_ERR_OK) {
TRACE_USB_ERROR(result);
// goto done;
}
}
done:
critical_end();
return result;
}

14
Source/HBIOS/ch376-native/source-doc/ufi-drv/usb_cbi.h

@ -0,0 +1,14 @@
#ifndef __USB_CBI_H__
#define __USB_CBI_H__
#include <ch376.h>
#include <dev_transfers.h>
usb_error usb_execute_cbi(device_config *const storage_device,
const uint8_t *const cmd,
const bool send,
const uint16_t buffer_size,
uint8_t *const buffer,
uint8_t *const asc);
#endif

11
Source/HBIOS/ch376-native/ufi-drv.s

@ -0,0 +1,11 @@
; Generated File -- not to be modify directly
#IF (!CHNATIVEEZ80)
#include "ch376-native/ufi-drv/class_ufi.c.s"
#ENDIF
#IF (!CHNATIVEEZ80)
#include "ch376-native/ufi-drv/ufi_driver.c.s"
#ENDIF
#include "ch376-native/ufi-drv/ufi-init.c.s"
#IF (!CHNATIVEEZ80)
#include "ch376-native/ufi-drv/usb_cbi.c.s"
#ENDIF

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save