]> git.sur5r.net Git - cc65/blob - libsrc/atari/ser/atrrdev.s
7243e29e0165b7a78e1724dbf74d7189cdd4271c
[cc65] / libsrc / atari / ser / atrrdev.s
1 ;
2 ; Christian Groessler, Dec-2001
3 ; converted to driver interface Dec-2013
4 ;
5 ; RS232 routines using the R: device (currently tested with an 850 only)
6 ;
7
8         .include        "zeropage.inc"
9         .include        "ser-kernel.inc"
10         .include        "ser-error.inc"
11         .include        "atari.inc"
12
13
14 ; ------------------------------------------------------------------------
15 ; Header. Includes jump table
16
17 .segment        "JUMPTABLE"
18
19 ; Driver signature
20
21         .byte   $73, $65, $72           ; "ser"
22         .byte   SER_API_VERSION         ; Serial API version number
23
24 ; Library reference
25
26 libref: .addr   $0000
27
28 ; Jump table
29
30         .word   SER_INSTALL
31         .word   SER_UNINSTALL
32         .word   SER_OPEN
33         .word   SER_CLOSE
34         .word   SER_GET
35         .word   SER_PUT
36         .word   SER_STATUS
37         .word   SER_IOCTL
38         .word   SER_IRQ
39
40
41         .rodata
42
43 rdev:   .byte   "R:", ATEOL, 0
44 bauds:  .byte   1               ; SER_BAUD_45_5
45         .byte   2               ; SER_BAUD_50
46         .byte   4               ; SER_BAUD_75
47         .byte   5               ; SER_BAUD_110
48         .byte   6               ; SER_BAUD_134_5
49         .byte   7               ; SER_BAUD_150
50         .byte   8               ; SER_BAUD_300
51         .byte   9               ; SER_BAUD_600
52         .byte   10              ; SER_BAUD_1200
53         .byte   11              ; SER_BAUD_1800
54         .byte   12              ; SER_BAUD_2400
55         .byte   0               ; SER_BAUD_3600
56         .byte   13              ; SER_BAUD_4800
57         .byte   0               ; SER_BAUD_7200
58         .byte   14              ; SER_BAUD_9600
59         .byte   0               ; SER_BAUD_19200
60         .byte   0               ; SER_BAUD_38400
61         .byte   0               ; SER_BAUD_57600
62         .byte   0               ; SER_BAUD_115200
63         .byte   0               ; SER_BAUD_230400
64         .byte   0               ; SER_BAUD_31250
65         .byte   0               ; SER_BAUD_62500
66         .byte   3               ; SER_BAUD_56_875
67 num_bauds       =       * - bauds
68 databits:
69         .byte   48              ; SER_BITS_5
70         .byte   32              ; SER_BITS_6
71         .byte   16              ; SER_BITS_7
72         .byte   0               ; SER_BITS_8
73 num_databits    =       * - databits
74 parities:
75         .byte   0               ; SER_PAR_NONE
76         .byte   4+1             ; SER_PAR_ODD
77         .byte   2+8             ; SER_PAR_EVEN
78         ;.byte  0               ; SER_PAR_MARK
79         ;.byte  0               ; SER_PAR_SPACE
80 num_parities    =       * - parities
81
82         .bss
83
84 ; receive buffer
85 RECVBUF_SZ = 256
86 recv_buf: .res  RECVBUF_SZ
87
88 cm_run: .res    1       ; concurrent mode running?
89
90         .data
91
92 rshand: .word   $ffff
93
94 ; jump table into main program, initialized from libref
95 my_newfd:
96         .byte   $4C
97         .word   0
98 my__close:
99         .byte   $4C
100         .word   0
101 my_pushax:
102         .byte   $4C
103         .word   0
104 my_popax:
105         .byte   $4C
106         .word   0
107 my_findfreeiocb:
108         .byte   $4C
109         .word   0
110 my___do_oserror:
111         .byte   $4C
112         .word   0
113 my_fddecusage:
114         .byte   $4C
115         .word   0
116 my_fdtoiocb:
117         .byte   $4C
118         .word   0
119 my___inviocb:
120         .byte   $4C
121         .word   0
122 my_clriocb:
123         .byte   $4C
124         .word   0
125 my_CIOV:
126         .byte   $4C
127         .word   0
128
129         .code
130
131 invbaud:
132         lda     #<SER_ERR_BAUD_UNAVAIL
133         ldx     #>SER_ERR_BAUD_UNAVAIL
134 openerr:
135         rts
136
137
138 ;----------------------------------------------------------------------------
139 ; SER_OPEN: A pointer to a ser_params structure is passed in ptr1.
140 ; Must return an SER_ERR_xx code in a/x.
141
142 SER_OPEN:
143         jsr     do_open
144         bne     openerr
145
146 ; set line parameters
147         lda     rshand
148         ldx     #0
149         jsr     my_fdtoiocb     ; get iocb index into X
150         bmi     openerr         ; shouldn't happen
151         tax
152
153         ; set baud rate, word size, stop bits and ready monitoring
154
155         ; build ICAX1 value
156         ldy     #SER_PARAMS::BAUDRATE
157         lda     (ptr1),y
158         cmp     #num_bauds
159         bcs     invbaud
160
161         tay
162         lda     bauds,y
163         beq     invbaud
164         sta     ICAX1,x
165
166         ldy     #SER_PARAMS::DATABITS
167         lda     (ptr1),y
168         cmp     #num_databits
169         bcs     init_err
170
171         tay
172         lda     databits,y
173         ora     ICAX1,x
174         sta     ICAX1,x
175
176         ldy     #SER_PARAMS::STOPBITS
177         lda     (ptr1),y
178         clc
179         ror     a
180         ror     a
181         ora     ICAX1,x
182         sta     ICAX1,x
183
184         lda     #36             ; xio 36, baud rate
185         sta     ICCOM,x
186         lda     #0
187         ;ICAX2 = 0, monitor nothing
188         sta     ICAX2,x
189         sta     ICBLL,x
190         sta     ICBLH,x
191         sta     ICBAL,x
192         sta     ICBAH,x
193         jsr     my_CIOV
194         bmi     cioerr
195
196         ; check if the handshake setting is valid
197         ldy     #SER_PARAMS::HANDSHAKE
198         lda     (ptr1),y
199         cmp     #SER_HS_HW      ; this is all we support
200         bne     init_err
201
202         ; set handshake lines
203         lda     #34             ; xio 34, set cts, dtr etc
204         sta     ICCOM,x
205         lda     #192+48+3       ; DTR on, RTS on, XMT on
206         sta     ICAX1,x
207         jsr     my_CIOV
208         bmi     cioerr
209
210         ; set translation and parity
211         ldy     #SER_PARAMS::PARITY
212         lda     (ptr1),y
213         cmp     #num_parities
214         bcs     init_err
215
216         tay
217         lda     parities,y
218         ora     #32             ; no translation
219         sta     ICAX1,x
220
221         lda     #38             ; xio 38, translation and parity
222         sta     ICCOM,x
223         jsr     my_CIOV
224         bmi     cioerr
225
226         lda     #<SER_ERR_OK
227         tax                             ; A is zero
228         rts
229
230 inverr: jmp     my___inviocb
231
232 cioerr:
233         ; @@@ need to close IOCB here
234         jsr     my_fddecusage   ; decrement usage counter of fd as open failed
235
236 init_err:
237         ldx     #0
238         lda     #SER_ERR_INIT_FAILED
239         rts
240
241 ;---- open the device
242
243 do_open:
244         jsr     my_findfreeiocb
245         bne     init_err
246         txa
247         tay                     ; move iocb # into Y
248         lda     #3
249         sta     tmp3            ; name length + 1
250         lda     #<rdev
251         ldx     #>rdev
252         jsr     my_newfd
253         tya
254         bcs     @doopen         ; C set: open needed / device not already open
255
256         pha
257         jsr     SER_CLOSE       ;** shut down if started  @@@TODO check this out!!
258         pla
259
260 @doopen:tax
261         pha
262         jsr     my_clriocb
263         pla
264         tax
265         lda     #<rdev
266         sta     ICBAL,x
267         lda     #>rdev
268         sta     ICBAH,x
269         lda     #OPEN
270         sta     ICCOM,x
271
272         lda     #$0D            ; mode in+out+concurrent
273         sta     ICAX1,x
274         lda     #0
275         sta     ICAX2,x
276         sta     ICBLL,x         ; zap buf len
277         sta     ICBLH,x
278         jsr     my_CIOV
279         bmi     cioerr
280
281         lda     tmp2            ; get fd (from newfd)
282         sta     rshand
283         ldx     #0
284         stx     rshand+1
285         txa
286         rts
287
288 ;----------------------------------------------------------------------------
289 ; CLOSE: Close the port, disable interrupts and flush the buffer. Called
290 ; without parameters. Must return an error code in a/x.
291 ;
292 ;----------------------------------------------------------------------------
293 ; SER_UNINSTALL routine. Is called before the driver is removed from memory.
294 ; Must return an SER_ERR_xx code in a/x.
295 ;
296
297 SER_UNINSTALL:
298 SER_CLOSE:
299         lda     rshand
300         cmp     #$ff
301         beq     @done
302
303         ldx     rshand+1
304         jsr     my__close
305         ldx     #$ff
306         stx     rshand
307         stx     rshand+1
308         inx
309         stx     cm_run
310 @done:  lda     #<SER_ERR_OK
311         ldx     #>SER_ERR_OK
312         rts
313
314 ;----------------------------------------------------------------------------
315 ; SER_GET: Will fetch a character from the receive buffer and store it into the
316 ; variable pointer to by ptr1. If no data is available, SER_ERR_NO_DATA is
317 ; return.
318 ;
319
320 SER_GET:
321         ldy     rshand
322         cpy     #$ff
323         beq     ni_err           ; work only if initialized
324
325         lda     rshand
326         ldx     #0
327         jsr     my_fdtoiocb
328         tax
329         lda     cm_run          ; concurrent mode already running?
330         bne     @go
331         jsr     ena_cm          ; turn on concurrent mode
332
333 @go:    ; check whether there is any input available
334
335         lda     #STATIS         ; status request, returns bytes pending
336         sta     ICCOM,x
337         jsr     my_CIOV
338         bmi     ser_error
339
340         lda     DVSTAT+1        ; get byte count pending
341         ora     DVSTAT+2
342         beq     @nix_da         ; no input waiting...
343
344         ; input is available: get it!
345
346         lda     #GETCHR         ; get raw bytes
347         sta     ICCOM,x         ; in command code
348         lda     #0
349         sta     ICBLL,x
350         sta     ICBLH,x
351         sta     ICBAL,x
352         sta     ICBAH,x
353         jsr     my_CIOV         ; go get it
354         bmi     ser_error
355
356         ldx     #0
357         sta     (ptr1,x)        ; return received byte
358         txa
359         rts
360
361 @nix_da:lda     #SER_ERR_NO_DATA
362         ldx     #0
363         rts
364
365 ser_error:
366         lda     #SER_ERR_OVERFLOW       ; there is no large selection of serial error codes... :-/
367         ldx     #0
368         rts
369
370 ni_err: lda     #SER_ERR_NOT_OPEN
371         ldx     #0
372         rts
373
374 ;----------------------------------------------------------------------------
375 ; SER_PUT: Output character in A.
376 ; Must return an error code in a/x.
377 ;
378
379 SER_PUT:
380         ldy     rshand
381         cpy     #$ff
382         beq     ni_err          ; work only if initialized
383
384         pha                     ; remember char to write
385         lda     rshand
386         ldx     #0
387         jsr     my_fdtoiocb
388         tax
389
390         lda     cm_run          ; concurrent mode already running?
391         bne     @go
392         jsr     ena_cm          ; turn on concurrent mode
393
394         ; @@@TODO:       check output buffer overflow
395 @go:    lda     #PUTCHR         ; put raw bytes
396         sta     ICCOM,x         ; in command code
397         lda     #0
398         sta     ICBLL,x
399         sta     ICBLH,x
400         sta     ICBAL,x
401         sta     ICBAH,x
402         pla                     ; get the char back
403         jsr     my_CIOV         ; go do it
404         bmi     ser_error
405         lda     #0
406         tax
407         rts
408
409 ;----------------------------------------------------------------------------
410 ; SER_STATUS: Return the status in the variable pointed to by ptr1.
411 ; Must return an error code in a/x.
412 ;
413
414 SER_STATUS:
415         ; fall through to SER_IOCTL
416
417 ;----------------------------------------------------------------------------
418 ; SER_IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
419 ; specific data in ptr1, and the ioctl code in A.
420 ; Must return an error code in a/x.
421 ;
422
423 SER_IOCTL:
424         lda     #<SER_ERR_INV_IOCTL     ; We don't support ioclts for now
425         ldx     #>SER_ERR_INV_IOCTL
426         rts
427
428 ;----------------------------------------------------------------------------
429 ; SER_IRQ: Not used on the Atari
430 ;
431
432 SER_IRQ     = $0000
433
434 ;----------------------------------------------------------------------------
435 ; SER_INSTALL routine. Is called after the driver is loaded into memory. If
436 ; possible, check if the hardware is present.
437 ; Must return an SER_ERR_xx code in a/x.
438
439 SER_INSTALL:
440         ; check if R: device is installed
441         ldy     #0
442 search: lda     HATABS,y                ; get device name
443         cmp     #'R'
444         beq     found
445         iny
446         iny
447         iny
448         cpy     #MAXDEV
449         bcc     search
450
451 ; R: device not found, return error
452
453         lda     #<SER_ERR_NO_DEVICE
454         ldx     #0
455         rts
456
457 ; R: device found, initialize jump table into main program
458
459 found:  lda     ptr3
460         pha
461         lda     ptr3+1
462         pha
463         lda     libref
464         sta     ptr3
465         lda     libref+1
466         sta     ptr3+1
467
468         ldy     #0
469         lda     (ptr3),y
470         sta     my_newfd+1
471         iny
472         lda     (ptr3),y
473         sta     my_newfd+2
474         iny
475
476         lda     (ptr3),y
477         sta     my__close+1
478         iny
479         lda     (ptr3),y
480         sta     my__close+2
481         iny
482
483         lda     (ptr3),y
484         sta     my_pushax+1
485         iny
486         lda     (ptr3),y
487         sta     my_pushax+2
488         iny
489
490         lda     (ptr3),y
491         sta     my_popax+1
492         iny
493         lda     (ptr3),y
494         sta     my_popax+2
495         iny
496
497         lda     (ptr3),y
498         sta     my_findfreeiocb+1
499         iny
500         lda     (ptr3),y
501         sta     my_findfreeiocb+2
502         iny
503
504         lda     (ptr3),y
505         sta     my___do_oserror+1
506         iny
507         lda     (ptr3),y
508         sta     my___do_oserror+2
509         iny
510
511         lda     (ptr3),y
512         sta     my_fddecusage+1
513         iny
514         lda     (ptr3),y
515         sta     my_fddecusage+2
516         iny
517
518         lda     (ptr3),y
519         sta     my_fdtoiocb+1
520         iny
521         lda     (ptr3),y
522         sta     my_fdtoiocb+2
523         iny
524
525         lda     (ptr3),y
526         sta     my___inviocb+1
527         iny
528         lda     (ptr3),y
529         sta     my___inviocb+2
530         iny
531
532         lda     (ptr3),y
533         sta     my_clriocb+1
534         iny
535         lda     (ptr3),y
536         sta     my_clriocb+2
537         iny
538
539         lda     (ptr3),y
540         sta     my_CIOV+1
541         iny
542         lda     (ptr3),y
543         sta     my_CIOV+2
544         ;iny
545
546         pla
547         sta     ptr3+1
548         pla
549         sta     ptr3
550
551         lda     #<SER_ERR_OK
552         tax                     ; A is zero
553         rts
554
555
556 ; enable concurrent rs232 mode
557 ; gets iocb index in X
558 ; all registers destroyed
559
560 .proc   ena_cm
561
562         lda     #40             ; XIO 40, start concurrent IO
563         sta     ICCOM,x
564         sta     cm_run          ; indicate concurrent mode is running
565         lda     #$0D            ; value from 850 manual, p62.  must be $0D?,
566         sta     ICAX1,x         ;  or any non-zero?
567         lda     #0
568         sta     ICAX2,x
569         lda     #<recv_buf
570         sta     ICBAL,x
571         lda     #>recv_buf
572         sta     ICBAH,x
573         lda     #<RECVBUF_SZ
574         sta     ICBLL,x
575         lda     #>RECVBUF_SZ
576         sta     ICBLH,x
577         jmp     my_CIOV
578
579 .endproc        ;ena_cm