diff --git a/Firmware/Driver.asm b/Firmware/Driver.asm new file mode 100644 index 0000000..f09f980 --- /dev/null +++ b/Firmware/Driver.asm @@ -0,0 +1,181 @@ +; ProDOS Global Page +Device2S1 = $bf14 ;POINTER FOR SLOT 2 DRIVE 1 DRIVER +DeviceCount = $bf31 ;DEVICE COUNT -1 +DeviceList = $bf32 ;DEVICE LIST + +; ProDOS Zero Page +Command = $42 ;ProDOS Command +Unit = $43 ;ProDOS unit (SDDD0000) +BufferLo = $44 +BufferHi = $45 +BlockLo = $46 +BlockHi = $47 + +; ProDOS Error Codes +IOError = $27 +NoDevice = $28 +WriteProtect = $2B + +SlotDrive = $50 +InputByte = $c0de +OutputByte = $c0dd +ReadBlockCommand = $01 +WriteBlockCommand = $02 +NibbleStorage = $1d + + .org $1000 + +; Register the driver with ProDOS + lda #Driver + sta Device2S1+1 +; Add the drive to the device list + inc DeviceCount + lda DeviceCount + lda #SlotDrive + sta DeviceList,y + rts + +; ProDOS Driver code +; First check that this is the right drive +Driver: + lda Unit + cmp #SlotDrive + beq DoCommand ;correct device, so proceed + sec ;set carry as ProDOS treats this as an error + lda #NoDevice ;put the error code in accumulator for ProDOS + rts + +; Check which command is being requested +DoCommand: + lda Command + beq GetStatus ;0 = Status command + cmp #ReadBlockCommand + beq ReadBlock + cmp #WriteBlockCommand + beq WriteBlock + sec ;set carry as we don't support any other commands + lda #$53 ;Invalid parameter error + rts + +; ProDOS Status Command Handler +GetStatus: + lda #$00 ;0 indicates ready to read/write + lda #$ff ;low byte number of blocks + lda #$ff ;high byte number of blocks + lda #$0 ;zero accumulator and clear carry for success + clc + rts + +; ProDOS Read Block Command +ReadBlock: + lda #ReadBlockCommand + jsr SendCommand + lda BlockLo + jsr SendByte + lda BlockHi + jsr SendByte + ldy #$0 + jsr read256 + inc BufferHi + jsr read256 + dec BufferHi + lda #$0 ;zero accumulator and clear carry for success + clc + rts + +read256: + jsr GetByte + sta (BufferLo),y + iny + bne read256 + rts + +; ProDOS Write Block Command +WriteBlock: + lda #WriteBlockCommand + jsr SendCommand + lda BlockLo + jsr SendByte + lda BlockHi + jsr SendByte + ldy #$0 + jsr write256 + inc BufferHi + jsr write256 + dec BufferHi + lda #$0 ;zero accumulator and clear carry for success + clc + rts + +write256: + lda (BufferLo),y + jsr SendByte + iny + bne write256 + rts + +SendCommand: + ora #$D0 ;Write Hi, Read Hi, Command Write Lo, Command Read Hi + sta OutputByte +commandWait: + lda InputByte + asl + asl + asl + bmi commandWait + lda #$F0 ;set write/read/command flags high + sta OutputByte + rts + +SendByte: + pha + lsr + lsr + lsr + lsr + jsr SendNibble + pla + jsr SendNibble + rts + +SendNibble: + and #$0F + ora #$70 ;Write bit low + pha +waitWrite: + lda InputByte + asl ;Second highest bit goes low when ready + bmi waitWrite + pla + sta OutputByte +finishWrite: + lda InputByte + asl + bpl finishWrite + rts + +GetByte: + jsr GetNibble + asl + asl + asl + asl + sta NibbleStorage + jsr GetNibble + and #$0f + ora NibbleStorage + lda NibbleStorage + rts + +GetNibble: + lda #$b0 ;set read flag low + sta OutputByte +waitRead: + lda InputByte + bmi waitRead + and #$f0 ;set all flags high + sta OutputByte + rts + diff --git a/Firmware/Driver.lst b/Firmware/Driver.lst new file mode 100644 index 0000000..5bf06e9 --- /dev/null +++ b/Firmware/Driver.lst @@ -0,0 +1,186 @@ +ca65 V2.18 - Ubuntu 2.18-1 +Main file : Driver.asm +Current file: Driver.asm + +000000r 1 ; ProDOS Global Page +000000r 1 Device2S1 = $bf14 ;POINTER FOR SLOT 2 DRIVE 1 DRIVER +000000r 1 DeviceCount = $bf31 ;DEVICE COUNT -1 +000000r 1 DeviceList = $bf32 ;DEVICE LIST +000000r 1 +000000r 1 ; ProDOS Zero Page +000000r 1 Command = $42 ;ProDOS Command +000000r 1 Unit = $43 ;ProDOS unit (SDDD0000) +000000r 1 BufferLo = $44 +000000r 1 BufferHi = $45 +000000r 1 BlockLo = $46 +000000r 1 BlockHi = $47 +000000r 1 +000000r 1 ; ProDOS Error Codes +000000r 1 IOError = $27 +000000r 1 NoDevice = $28 +000000r 1 WriteProtect = $2B +000000r 1 +000000r 1 SlotDrive = $50 +000000r 1 InputByte = $c0de +000000r 1 OutputByte = $c0dd +000000r 1 ReadBlockCommand = $01 +000000r 1 WriteBlockCommand = $02 +000000r 1 NibbleStorage = $1d +000000r 1 +000000r 1 .org $1000 +001000 1 +001000 1 ; Register the driver with ProDOS +001000 1 A9 16 lda #Driver +001007 1 8D 15 BF sta Device2S1+1 +00100A 1 ; Add the drive to the device list +00100A 1 EE 31 BF inc DeviceCount +00100D 1 AD 31 BF lda DeviceCount +001010 1 A9 50 lda #SlotDrive +001012 1 99 32 BF sta DeviceList,y +001015 1 60 rts +001016 1 +001016 1 ; ProDOS Driver code +001016 1 ; First check that this is the right drive +001016 1 Driver: +001016 1 A5 43 lda Unit +001018 1 C9 50 cmp #SlotDrive +00101A 1 F0 04 beq DoCommand ;correct device, so proceed +00101C 1 38 sec ;set carry as ProDOS treats this as an error +00101D 1 A9 28 lda #NoDevice ;put the error code in accumulator for ProDOS +00101F 1 60 rts +001020 1 +001020 1 ; Check which command is being requested +001020 1 DoCommand: +001020 1 A5 42 lda Command +001022 1 F0 0C beq GetStatus ;0 = Status command +001024 1 C9 01 cmp #ReadBlockCommand +001026 1 F0 12 beq ReadBlock +001028 1 C9 02 cmp #WriteBlockCommand +00102A 1 F0 36 beq WriteBlock +00102C 1 38 sec ;set carry as we don't support any other commands +00102D 1 A9 53 lda #$53 ;Invalid parameter error +00102F 1 60 rts +001030 1 +001030 1 ; ProDOS Status Command Handler +001030 1 GetStatus: +001030 1 A9 00 lda #$00 ;0 indicates ready to read/write +001032 1 A9 FF lda #$ff ;low byte number of blocks +001034 1 A9 FF lda #$ff ;high byte number of blocks +001036 1 A9 00 lda #$0 ;zero accumulator and clear carry for success +001038 1 18 clc +001039 1 60 rts +00103A 1 +00103A 1 ; ProDOS Read Block Command +00103A 1 ReadBlock: +00103A 1 A9 01 lda #ReadBlockCommand +00103C 1 20 8A 10 jsr SendCommand +00103F 1 A5 46 lda BlockLo +001041 1 20 9D 10 jsr SendByte +001044 1 A5 47 lda BlockHi +001046 1 20 9D 10 jsr SendByte +001049 1 A0 00 ldy #$0 +00104B 1 20 59 10 jsr read256 +00104E 1 E6 45 inc BufferHi +001050 1 20 59 10 jsr read256 +001053 1 C6 45 dec BufferHi +001055 1 A9 00 lda #$0 ;zero accumulator and clear carry for success +001057 1 18 clc +001058 1 60 rts +001059 1 +001059 1 read256: +001059 1 20 C0 10 jsr GetByte +00105C 1 91 44 sta (BufferLo),y +00105E 1 C8 iny +00105F 1 D0 F8 bne read256 +001061 1 60 rts +001062 1 +001062 1 ; ProDOS Write Block Command +001062 1 WriteBlock: +001062 1 A9 02 lda #WriteBlockCommand +001064 1 20 8A 10 jsr SendCommand +001067 1 A5 46 lda BlockLo +001069 1 20 9D 10 jsr SendByte +00106C 1 A5 47 lda BlockHi +00106E 1 20 9D 10 jsr SendByte +001071 1 A0 00 ldy #$0 +001073 1 20 81 10 jsr write256 +001076 1 E6 45 inc BufferHi +001078 1 20 81 10 jsr write256 +00107B 1 C6 45 dec BufferHi +00107D 1 A9 00 lda #$0 ;zero accumulator and clear carry for success +00107F 1 18 clc +001080 1 60 rts +001081 1 +001081 1 write256: +001081 1 B1 44 lda (BufferLo),y +001083 1 20 9D 10 jsr SendByte +001086 1 C8 iny +001087 1 D0 F8 bne write256 +001089 1 60 rts +00108A 1 +00108A 1 SendCommand: +00108A 1 09 D0 ora #$D0 ;Write Hi, Read Hi, Command Write Lo, Command Read Hi +00108C 1 8D DD C0 sta OutputByte +00108F 1 commandWait: +00108F 1 AD DE C0 lda InputByte +001092 1 0A asl +001093 1 0A asl +001094 1 0A asl +001095 1 30 F8 bmi commandWait +001097 1 A9 F0 lda #$F0 ;set write/read/command flags high +001099 1 8D DD C0 sta OutputByte +00109C 1 60 rts +00109D 1 +00109D 1 SendByte: +00109D 1 48 pha +00109E 1 4A lsr +00109F 1 4A lsr +0010A0 1 4A lsr +0010A1 1 4A lsr +0010A2 1 20 AA 10 jsr SendNibble +0010A5 1 68 pla +0010A6 1 20 AA 10 jsr SendNibble +0010A9 1 60 rts +0010AA 1 +0010AA 1 SendNibble: +0010AA 1 29 0F and #$0F +0010AC 1 09 70 ora #$70 ;Write bit low +0010AE 1 48 pha +0010AF 1 waitWrite: +0010AF 1 AD DE C0 lda InputByte +0010B2 1 0A asl ;Second highest bit goes low when ready +0010B3 1 30 FA bmi waitWrite +0010B5 1 68 pla +0010B6 1 8D DD C0 sta OutputByte +0010B9 1 finishWrite: +0010B9 1 AD DE C0 lda InputByte +0010BC 1 0A asl +0010BD 1 10 FA bpl finishWrite +0010BF 1 60 rts +0010C0 1 +0010C0 1 GetByte: +0010C0 1 20 D3 10 jsr GetNibble +0010C3 1 0A asl +0010C4 1 0A asl +0010C5 1 0A asl +0010C6 1 0A asl +0010C7 1 85 1D sta NibbleStorage +0010C9 1 20 D3 10 jsr GetNibble +0010CC 1 29 0F and #$0f +0010CE 1 05 1D ora NibbleStorage +0010D0 1 A5 1D lda NibbleStorage +0010D2 1 60 rts +0010D3 1 +0010D3 1 GetNibble: +0010D3 1 A9 B0 lda #$b0 ;set read flag low +0010D5 1 8D DD C0 sta OutputByte +0010D8 1 waitRead: +0010D8 1 AD DE C0 lda InputByte +0010DB 1 30 FB bmi waitRead +0010DD 1 29 F0 and #$f0 ;set all flags high +0010DF 1 8D DD C0 sta OutputByte +0010E2 1 60 rts +0010E3 1 +0010E3 1