cpm: initial cbios
[z80.git] / z80 / cpm / cbios.S
1 ; Z80 CBIOS
2 .area BIOS (ABS)
3
4 ; configuration
5 MSIZE   = 20                    ; memory size
6 NDRIVES = 2                     ; number of drives
7 TTY_D   = 0x10                  ; usart data port
8 TTY_S   = 0x11                  ; usart status port
9 ROMDISK = 0x0f                  ; romdisk port
10
11 ; constants
12 BIAS    = (MSIZE-20)*1024       ; address offset from 0x3400
13 CCP     = (0x3400+BIAS)         ; ccp  base
14 BDOS    = (CCP+0x806)           ; bdos base
15 BIOS    = (CCP+0x1600)          ; bios base
16 NSECTS  = (BIOS-CCP)/128        ; sector count for CCP+BDOS
17
18 IOBYTE  = 3                     ; address of IOBYTE
19 CDISK   = 4                     ; address of CDISK
20
21 ;============================================================================
22 ; COLD BOOT ROUTINE
23 .org 0
24         LD SP, #0x80
25         JP BIOS
26
27 ;============================================================================
28 ;BIOS ENTRY POINT
29 .org BIOS
30         JP BOOT         ; COLD START
31         JP WBOOT        ; WARM START
32         JP CONST        ; CONSOLE STATUS
33         JP CONIN        ; CONSOLE CHARACTER IN
34         JP CONOUT       ; CONSOLE CHARACTER OUT
35         JP LIST         ; LIST CHARACTER OUT
36         JP PUNCH        ; PUNCH CHARACTER OUT
37         JP READER       ; READER CHARACTER IN
38         JP HOME         ; MOVE HEAD TO HOME
39         JP SELDSK       ; SELECT DISK
40         JP SETTRK       ; SET TRACK NUMBER
41         JP SETSEC       ; SET SECTOR NUMBER
42         JP SETDMA       ; SET DMA ADDRESS
43         JP READ         ; READ DISK
44         JP WRITE        ; WRITE DISK
45         JP LISTST       ; RETURN LIST STATUS
46         JP SECTRAN      ; SECTOR TRANSLATE
47
48 ;============================================================================
49 ; DATA TABLES
50 DPHEAD:
51         ; A: ROM DISK
52         .dw 0x0000, 0x0000, 0x0000, 0x0000
53         .dw DIRBF,  DPB_A,  0x0000, ALV_A
54
55         ; B: 8MB DRIVE
56         .dw 0x0000, 0x0000, 0x0000, 0x0000
57         .dw DIRBF,  DPB_B,  CHK_B,  ALV_B
58
59 DPB_A:
60         .dw 1           ; SPT      -> 1 sector/track
61         .db 3, 7        ; BSH, BLM -> 1k blocksize
62         .db 0           ; EXM      -> no extends
63         .dw 23          ; DSM      -> 24 blocks
64         .dw 31          ; DRM      -> 32 directory entries
65         .db 0x80,0x00   ; AL0/AL1  -> 1 block used for directory
66         .dw 0           ; CKS      -> fixed disk (no change scratchpad)
67         .dw 44          ; OFF      -> 44 reserved tracks (5.5 KB)
68
69 DPB_B:
70         ; FIXME
71         .db 26,0,3,7,0,242,0,63,0,192,0,16,0,2,0
72
73 ;============================================================================
74 ; MESSAGES
75 MSG_SIGNON:     .asciz "CP/M 2.2 CBIOS v0\r\n"
76
77 ;============================================================================
78 OUTMSG:
79         LD A,(HL)       ; load char
80         OR A,A
81         RET Z           ; return if zero
82         OUT (TTY_D),A
83         INC HL          ; next char
84         JR OUTMSG
85
86 OUTHEX: ; input = HL
87         LD C, H
88         CALL OUTHEX8
89         LD C, L
90 OUTHEX8: ; input = C
91         LD A, C
92         RRA
93         RRA
94         RRA
95         RRA
96         CALL OUTHEXC
97         LD A, C
98 OUTHEXC:
99         AND #0x0F
100         ADD A, #0x90
101         DAA
102         ADC A, #0x40
103         DAA
104         OUT (TTY_D), A
105         RET
106
107 ;============================================================================
108 BOOT:
109         LD HL, #MSG_SIGNON
110         CALL OUTMSG
111
112         XOR A
113         LD (IOBYTE),A   ; CON:TTY,RDR:TTY,PUN:TTY,LST:TTY
114         LD (CDISK),A    ; drive A
115         ;JP GOCPM
116
117 ;============================================================================
118 WBOOT:
119         ; read cp/m
120         LD HL, #CCP     ; destination
121         LD C,  #ROMDISK ; port
122         LD D,  #(NSECTS)        ; count sectors down
123         LD A,  #0       ; count sectors up
124 1$:
125         OUT (C),A       ; select track
126         LD B, #128      ; number of bytes
127         INIR            ; read
128         INC A           ; next track
129         DEC D           ; one sector less
130         JR NZ, 1$       ; repeat
131
132         JP GOCPM
133
134 ;============================================================================
135 GOCPM:
136         LD A, #0xC3     ; JP opcode
137         LD (0), A       ; ...at 0x0000
138         LD (5), A       ; ...at 0x0005
139         LD HL, #WBOOT
140         LD (1), HL      ; WBOOT pointer at 0x0001
141         LD HL, #BDOS
142         LD (6), HL      ; BDOS pointer at 0x0006
143
144         LD BC, #0x0080
145         CALL SETDMA     ; default DMA address 0x0080
146
147         EI              ; enable interrupts
148         LD A, (CDISK)
149         LD C, A         ; set active drive
150
151         JP CCP          ; go to cp/m
152
153 ;============================================================================
154 CONST:
155         IN A, (#TTY_S)
156         OR A,A
157         RET Z           ; no data: A=0x00
158         LD A, #0xFF
159         RET             ; else: A=0xFF
160
161 ;============================================================================
162 CONIN:
163         CALL CONST
164         JR Z, CONIN
165         IN A, (TTY_D)   ; read data
166         AND #0x7F       ; strip parity bit
167         RET
168
169 ;============================================================================
170 CONOUT:
171         LD A, C
172         OUT (TTY_D), A  ; write data
173         RET
174
175 ;============================================================================
176 LIST:
177         RET
178
179 ;============================================================================
180 PUNCH:
181         RET
182
183 ;============================================================================
184 READER:
185         LD A, #0x1A
186         AND #0x7F
187         RET
188
189 ;============================================================================
190 HOME:
191         LD C, #0
192         JP SETTRK       ; will return for us
193
194 ;============================================================================
195 ; select disk from C (0..15 => A..P)
196 ; return HL=dph or 0x0000 on error
197 SELDSK:
198         ; check for valid drive
199         LD HL, #0       ; error code
200         LD A, C
201         LD (DISKNO), A  ; select drive
202         CP #NDRIVES
203         RET NC          ; return if >NDRIVES
204
205         ; put disk parameter header in HL
206         LD H, #0
207         LD L, A         ; drive number in HL
208         ADD HL, HL
209         ADD HL, HL
210         ADD HL, HL
211         ADD HL, HL      ; * sizeof(dph)
212         LD DE, #DPHEAD
213         ADD HL, DE      ; HL = table base + 16*drive
214         RET
215
216 ;============================================================================
217 SETTRK:
218         LD (TRACK), BC
219         RET
220
221 ;============================================================================
222 SETSEC:
223         LD (SECTOR), BC
224         RET
225
226 ;============================================================================
227 SETDMA:
228         LD (DMAAD), BC
229         RET
230
231 ;============================================================================
232 ; return A=0 on success, A=1 on error; do retry
233 READ:
234         LD A,(TRACK)
235         OUT (ROMDISK),A         ; select sector=track
236
237         LD HL,(DMAAD)           ; select destination
238         LD C, #ROMDISK          ; disk data port
239         LD B, #128              ; 128 bytes
240         INIR                    ; read
241
242         LD A, #0
243         RET
244
245 ;============================================================================
246 ; return A=0 on success, A=1 on error; do retry
247 WRITE:
248         LD A, #1
249         RET             ; fail
250
251 ;============================================================================
252 ; return A=0 if printer busy, A=0xFF otherwise
253 LISTST:
254         XOR A
255         RET             ; fail
256
257 ;============================================================================
258 ; logical sector number in BC and translation table address in DE,
259 ; return physical sector in HL
260 SECTRAN:
261         RET
262
263
264 ;============================================================================
265 ; VARIABLES AND SCRATCH RAM
266 DISKNO: .ds 1           ; selected disk
267 TRACK:  .ds 2           ; selected track
268 SECTOR: .ds 2           ; selected sector
269 DMAAD:  .ds 2           ; selected DMA address
270
271 DIRBF:  .ds 128         ; shared directory buffer
272 ALV_A:  .ds 3           ; allocation buffer for ROM DISK
273 CHK_B:  .ds 16          ; FIXME
274 ALV_B:  .ds 31          ; FIXME
275