Subversion Repositories Kolibri OS

Rev

Rev 2434 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
465 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2465 Serge 3
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
465 serge 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
format MS COFF
9
 
850 serge 10
DEBUG           equ 1
11
 
465 serge 12
include 'proc32.inc'
13
include 'imports.inc'
14
 
850 serge 15
 
16
 
2434 Serge 17
API_VERSION       equ 0
18
UART_VERSION      equ API_VERSION
465 serge 19
 
2434 Serge 20
PG_SW             equ 0x003
21
page_tabs         equ 0xFDC00000     ;hack
465 serge 22
 
2434 Serge 23
OS_BASE           equ 0x80000000
24
SLOT_BASE         equ (OS_BASE+0x0080000)
25
TASK_COUNT        equ (OS_BASE+0x0003004)
26
CURRENT_TASK      equ (OS_BASE+0x0003000)
465 serge 27
 
28
 
2434 Serge 29
struc APPOBJ           ;common object header
465 serge 30
{
2434 Serge 31
   .magic       dd ?   ;
32
   .destroy     dd ?   ;internal destructor
33
   .fd          dd ?   ;next object in list
34
   .bk          dd ?   ;prev object in list
35
   .pid         dd ?   ;owner id
465 serge 36
};
37
 
38
virtual at 0
39
  APPOBJ APPOBJ
40
end virtual
41
 
42
struc IOCTL
2434 Serge 43
{  .handle      dd ?
44
   .io_code     dd ?
45
   .input       dd ?
46
   .inp_size    dd ?
47
   .output      dd ?
48
   .out_size    dd ?
465 serge 49
}
50
 
51
virtual at 0
52
  IOCTL IOCTL
53
end virtual
54
 
2434 Serge 55
DEBUG            equ   1
465 serge 56
 
2434 Serge 57
DRV_ENTRY        equ   1
58
DRV_EXIT         equ  -1
465 serge 59
 
2434 Serge 60
THR_REG          equ  0;  x3f8   ;transtitter/reciever
61
IER_REG          equ  1;  x3f9   ;interrupt enable
62
IIR_REG          equ  2;  x3fA   ;interrupt info
63
LCR_REG          equ  3;  x3FB   ;line control
64
MCR_REG          equ  4;  x3FC   ;modem control
65
LSR_REG          equ  5;  x3FD   ;line status
66
MSR_REG          equ  6;  x3FE   ;modem status
465 serge 67
 
2434 Serge 68
LCR_5BIT         equ  0x00
69
LCR_6BIT         equ  0x01
70
LCR_7BIT         equ  0x02
71
LCR_8BIT         equ  0x03
72
LCR_STOP_1       equ  0x00
73
LCR_STOP_2       equ  0x04
74
LCR_PARITY       equ  0x08
75
LCR_EVEN         equ  0x10
76
LCR_STICK        equ  0x20
77
LCR_BREAK        equ  0x40
78
LCR_DLAB         equ  0x80
465 serge 79
 
2434 Serge 80
LSR_DR           equ  0x01     ;data ready
81
LSR_OE           equ  0x02     ;overrun error
82
LSR_PE           equ  0x04     ;parity error
83
LSR_FE           equ  0x08     ;framing error
84
LSR_BI           equ  0x10     ;break interrupt
85
LSR_THRE         equ  0x20     ;transmitter holding empty
86
LSR_TEMT         equ  0x40     ;transmitter empty
87
LSR_FER          equ  0x80     ;FIFO error
465 serge 88
 
2434 Serge 89
FCR_EFIFO        equ  0x01     ;enable FIFO
90
FCR_CRB          equ  0x02     ;clear reciever FIFO
91
FCR_CXMIT        equ  0x04     ;clear transmitter FIFO
92
FCR_RDY          equ  0x08     ;set RXRDY and TXRDY pins
93
FCR_FIFO_1       equ  0x00     ;1  byte trigger
94
FCR_FIFO_4       equ  0x40     ;4  bytes trigger
95
FCR_FIFO_8       equ  0x80     ;8  bytes trigger
96
FCR_FIFO_14      equ  0xC0     ;14 bytes trigger
465 serge 97
 
2434 Serge 98
IIR_INTR         equ  0x01     ;1= no interrupts
465 serge 99
 
2434 Serge 100
IER_RDAI         equ  0x01     ;reciever data interrupt
101
IER_THRI         equ  0x02     ;transmitter empty interrupt
102
IER_LSI          equ  0x04     ;line status interrupt
103
IER_MSI          equ  0x08     ;modem status interrupt
465 serge 104
 
2434 Serge 105
MCR_DTR          equ  0x01     ;0-> DTR=1, 1-> DTR=0
106
MCR_RTS          equ  0x02     ;0-> RTS=1, 1-> RTS=0
107
MCR_OUT_1        equ  0x04     ;0-> OUT1=1, 1-> OUT1=0
108
MCR_OUT_2        equ  0x08     ;0-> OUT2=1, 1-> OUT2=0;  enable intr
109
MCR_LOOP         equ  0x10     ;lopback mode
465 serge 110
 
2434 Serge 111
MSR_DCTS         equ  0x01     ;delta clear to send
112
MSR_DDSR         equ  0x02     ;delta data set redy
113
MSR_TERI         equ  0x04     ;trailinh edge of ring
114
MSR_DDCD         equ  0x08     ;delta carrier detect
465 serge 115
 
116
 
2434 Serge 117
RATE_50          equ  0
118
RATE_75          equ  1
119
RATE_110         equ  2
120
RATE_134         equ  3
121
RATE_150         equ  4
122
RATE_300         equ  5
123
RATE_600         equ  6
124
RATE_1200        equ  7
125
RATE_1800        equ  8
126
RATE_2000        equ  9
127
RATE_2400        equ 10
128
RATE_3600        equ 11
129
RATE_4800        equ 12
130
RATE_7200        equ 13
131
RATE_9600        equ 14
132
RATE_19200       equ 15
133
RATE_38400       equ 16
134
RATE_57600       equ 17
135
RATE_115200      equ 18
465 serge 136
 
2434 Serge 137
COM_1            equ  1
138
COM_2            equ  2
139
COM_3            equ  3
140
COM_4            equ  4
141
COM_MAX          equ  2    ;only two port supported
465 serge 142
 
2434 Serge 143
COM_1_BASE       equ 0x3F8
144
COM_2_BASE       equ 0x2F8
465 serge 145
 
2434 Serge 146
COM_1_IRQ        equ  4
147
COM_2_IRQ        equ  3
465 serge 148
 
2434 Serge 149
UART_CLOSED      equ  0
150
UART_TRANSMIT    equ  1
151
UART_STOP        equ  2
465 serge 152
 
153
struc UART
154
{
2434 Serge 155
   .lock         dd ?
156
   .base         dd ?
157
   .lcr_reg      dd ?
158
   .mcr_reg      dd ?
159
   .rate         dd ?
160
   .mode         dd ?
161
   .state        dd ?
465 serge 162
 
2434 Serge 163
   .rcvr_buff    dd ?
164
   .rcvr_rp      dd ?
165
   .rcvr_wp      dd ?
166
   .rcvr_count   dd ?
167
   .rcvr_top     dd ?
465 serge 168
 
2434 Serge 169
   .xmit_buff    dd ?
170
   .xmit_rp      dd ?
171
   .xmit_wp      dd ?
172
   .xmit_count   dd ?
173
   .xmit_free    dd ?
174
   .xmit_top     dd ?
465 serge 175
}
176
virtual at 0
177
  UART UART
178
end virtual
179
 
180
UART_SIZE     equ 18*4
181
 
182
struc CONNECTION
183
{
2434 Serge 184
   .magic       dd ?   ;'CNCT'
185
   .destroy     dd ?   ;internal destructor
186
   .fd          dd ?   ;next object in list
187
   .bk          dd ?   ;prev object in list
188
   .pid         dd ?   ;owner id
465 serge 189
 
2434 Serge 190
   .id          dd ?   ;reserved
191
   .uart        dd ?   ;uart pointer
465 serge 192
}
193
 
194
virtual at 0
195
  CONNECTION CONNECTION
196
end virtual
197
 
198
CONNECTION_SIZE equ 7*4
199
 
200
public START
201
public service_proc
202
public version
203
 
204
section '.flat' code readable align 16
205
 
206
proc START stdcall, state:dword
207
 
2434 Serge 208
        cmp     [state], 1
209
        jne     .stop
465 serge 210
 
2434 Serge 211
        mov     eax, UART_SIZE
212
        call    Kmalloc
213
        test    eax, eax
214
        jz      .fail
465 serge 215
 
2434 Serge 216
        mov     [com1], eax
217
        mov     edi, eax
218
        mov     ecx, UART_SIZE/4
219
        xor     eax, eax
220
        cld
221
        rep stosd
465 serge 222
 
2434 Serge 223
        mov     eax, [com1]
224
        mov     [eax+UART.base], COM_1_BASE
465 serge 225
 
2434 Serge 226
        stdcall AllocKernelSpace, 32768
465 serge 227
 
2434 Serge 228
        mov     edi, [com1]
229
        mov     edx, eax
465 serge 230
 
2434 Serge 231
        mov     [edi+UART.rcvr_buff], eax
232
        add     eax, 8192
233
        mov     [edi+UART.rcvr_top], eax
234
        add     eax, 8192
235
        mov     [edi+UART.xmit_buff], eax
236
        add     eax, 8192
237
        mov     [edi+UART.xmit_top], eax
465 serge 238
 
2434 Serge 239
        call    AllocPage
240
        test    eax, eax
241
        jz      .fail
465 serge 242
 
2434 Serge 243
        shr     edx, 12
244
        or      eax, PG_SW
245
        mov     [page_tabs+edx*4], eax
246
        mov     [page_tabs+edx*4+8], eax
465 serge 247
 
2434 Serge 248
        call    AllocPage
249
        test    eax, eax
250
        jz      .fail
465 serge 251
 
2434 Serge 252
        or      eax, PG_SW
253
        mov     [page_tabs+edx*4+4], eax
254
        mov     [page_tabs+edx*4+12], eax
465 serge 255
 
2434 Serge 256
        call    AllocPage
257
        test    eax, eax
258
        jz      .fail
465 serge 259
 
2434 Serge 260
        or      eax, PG_SW
261
        mov     [page_tabs+edx*4+16], eax
262
        mov     [page_tabs+edx*4+24], eax
465 serge 263
 
2434 Serge 264
        call    AllocPage
265
        test    eax, eax
266
        jz      .fail
465 serge 267
 
2434 Serge 268
        or      eax, PG_SW
269
        mov     [page_tabs+edx*4+20], eax
270
        mov     [page_tabs+edx*4+28], eax
465 serge 271
 
2434 Serge 272
        mov     eax, [edi+UART.rcvr_buff]
273
        invlpg  [eax]
274
        invlpg  [eax+0x1000]
275
        invlpg  [eax+0x2000]
276
        invlpg  [eax+0x3000]
277
        invlpg  [eax+0x4000]
278
        invlpg  [eax+0x5000]
279
        invlpg  [eax+0x6000]
280
        invlpg  [eax+0x7000]
465 serge 281
 
2434 Serge 282
        mov     eax, edi
283
        call    uart_reset.internal   ;eax= uart
465 serge 284
 
2434 Serge 285
        stdcall AttachIntHandler, COM_1_IRQ, com_1_isr, dword 0
286
        stdcall RegService, sz_uart_srv, service_proc
287
        ret
465 serge 288
.fail:
289
.stop:
2434 Serge 290
        xor     eax, eax
291
        ret
465 serge 292
endp
293
 
294
 
2434 Serge 295
handle     equ  IOCTL.handle
296
io_code    equ  IOCTL.io_code
297
input      equ  IOCTL.input
298
inp_size   equ  IOCTL.inp_size
299
output     equ  IOCTL.output
300
out_size   equ  IOCTL.out_size
465 serge 301
 
2434 Serge 302
SRV_GETVERSION  equ 0
303
PORT_OPEN       equ 1
304
PORT_CLOSE      equ 2
305
PORT_RESET      equ 3
306
PORT_SETMODE    equ 4
307
PORT_GETMODE    equ 5
308
PORT_SETMCR     equ 6
309
PORT_GETMCR     equ 7
310
PORT_READ       equ 8
311
PORT_WRITE      equ 9
465 serge 312
 
313
align 4
314
proc service_proc stdcall, ioctl:dword
315
 
2434 Serge 316
        mov     ebx, [ioctl]
317
        mov     eax, [ebx+io_code]
318
        cmp     eax, PORT_WRITE
319
        ja      .fail
465 serge 320
 
2434 Serge 321
        cmp     eax, SRV_GETVERSION
322
        jne     @F
465 serge 323
 
2434 Serge 324
        mov     eax, [ebx+output]
325
        cmp     [ebx+out_size], 4
326
        jne     .fail
327
        mov     [eax], dword UART_VERSION
328
        xor     eax, eax
329
        ret
465 serge 330
@@:
2434 Serge 331
        cmp     eax, PORT_OPEN
332
        jne     @F
465 serge 333
 
2434 Serge 334
        cmp     [ebx+out_size], 4
335
        jne     .fail
465 serge 336
 
2434 Serge 337
        mov     ebx, [ebx+input]
338
        mov     eax, [ebx]
339
        call    uart_open
340
        mov     ebx, [ioctl]
341
        mov     ebx, [ebx+output]
342
        mov     [ebx], ecx
343
        ret
465 serge 344
@@:
2434 Serge 345
        mov     esi, [ebx+input]    ;input buffer
346
        mov     edi, [ebx+output]
347
        call    [uart_func+eax*4]
348
        ret
465 serge 349
.fail:
2434 Serge 350
        or      eax, -1
351
        ret
465 serge 352
 
353
endp
354
 
355
restore   handle
356
restore   io_code
357
restore   input
358
restore   inp_size
359
restore   output
360
restore   out_size
361
 
362
 
363
; param
364
;  esi=  input buffer
365
;        +0 connection
366
;
367
; retval
368
;  eax= error code
369
 
370
align 4
371
uart_reset:
2434 Serge 372
        mov     eax, [esi]
373
        cmp     [eax+APPOBJ.magic], 'CNCT'
374
        jne     .fail
465 serge 375
 
2434 Serge 376
        cmp     [eax+APPOBJ.destroy], uart_close.destroy
377
        jne     .fail
465 serge 378
 
2434 Serge 379
        mov     eax, [eax+CONNECTION.uart]
380
        test    eax, eax
381
        jz      .fail
465 serge 382
 
383
; set mode 2400 bod 8-bit
384
; disable DTR & RTS
385
; clear FIFO
386
; clear pending interrupts
387
;
388
; param
389
;  eax= uart
390
 
391
align 4
392
.internal:
2434 Serge 393
        mov     esi, eax
394
        mov     [eax+UART.state], UART_CLOSED
395
        mov     edx, [eax+UART.base]
396
        add     edx, MCR_REG
397
        xor     eax, eax
398
        out     dx, al       ;clear DTR & RTS
465 serge 399
 
2434 Serge 400
        mov     eax, esi
401
        mov     ebx, RATE_2400
402
        mov     ecx, LCR_8BIT+LCR_STOP_1
403
        call    uart_set_mode.internal
465 serge 404
 
2434 Serge 405
        mov     edx, [esi+UART.base]
406
        add     edx, IIR_REG
407
        mov     eax, FCR_EFIFO+FCR_CRB+FCR_CXMIT+FCR_FIFO_14
408
        out     dx, al
465 serge 409
.clear_RB:
2434 Serge 410
        mov     edx, [esi+UART.base]
411
        add     edx, LSR_REG
412
        in      al, dx
413
        test    eax, LSR_DR
414
        jz      @F
465 serge 415
 
2434 Serge 416
        mov     edx, [esi+UART.base]
417
        in      al, dx
418
        jmp     .clear_RB
465 serge 419
@@:
2434 Serge 420
        mov     edx, [esi+UART.base]
421
        add     edx, IER_REG
422
        mov     eax, IER_RDAI+IER_THRI+IER_LSI
423
        out     dx, al
465 serge 424
.clear_IIR:
2434 Serge 425
        mov     edx, [esi+UART.base]
426
        add     edx, IIR_REG
427
        in      al, dx
428
        test    al, IIR_INTR
429
        jnz     .done
465 serge 430
 
2434 Serge 431
        shr     eax, 1
432
        and     eax, 3
433
        jnz     @F
465 serge 434
 
2434 Serge 435
        mov     edx, [esi+UART.base]
436
        add     edx, MSR_REG
437
        in      al, dx
438
        jmp     .clear_IIR
465 serge 439
@@:
2434 Serge 440
        cmp     eax, 1
441
        je      .clear_IIR
465 serge 442
 
2434 Serge 443
        cmp     eax, 2
444
        jne     @F
465 serge 445
 
2434 Serge 446
        mov     edx, [esi+UART.base]
447
        in      al, dx
448
        jmp     .clear_IIR
465 serge 449
@@:
2434 Serge 450
        mov     edx, [esi+UART.base]
451
        add     edx, LSR_REG
452
        in      al, dx
453
        jmp     .clear_IIR
465 serge 454
.done:
2434 Serge 455
        mov     edi, [esi+UART.rcvr_buff]
456
        mov     ecx, 8192/4
457
        xor     eax, eax
465 serge 458
 
2434 Serge 459
        mov     [esi+UART.rcvr_rp], edi
460
        mov     [esi+UART.rcvr_wp], edi
461
        mov     [esi+UART.rcvr_count], eax
465 serge 462
 
2434 Serge 463
        cld
464
        rep stosd
465 serge 465
 
2434 Serge 466
        mov     edi, [esi+UART.xmit_buff]
467
        mov     ecx, 8192/4
465 serge 468
 
2434 Serge 469
        mov     [esi+UART.xmit_rp], edi
470
        mov     [esi+UART.xmit_wp], edi
471
        mov     [esi+UART.xmit_count], eax
472
        mov     [esi+UART.xmit_free], 8192
465 serge 473
 
2434 Serge 474
        rep stosd
475
        ret                  ;eax= 0
465 serge 476
.fail:
2434 Serge 477
        or      eax, -1
478
        ret
465 serge 479
 
480
; param
481
;  esi=  input buffer
482
;        +0 connection
483
;        +4 rate
484
;        +8 mode
485
;
486
; retval
487
;  eax= error code
488
 
489
align 4
490
uart_set_mode:
2434 Serge 491
        mov     eax, [esi]
492
        cmp     [eax+APPOBJ.magic], 'CNCT'
493
        jne     .fail
465 serge 494
 
2434 Serge 495
        cmp     [eax+APPOBJ.destroy], uart_close.destroy
496
        jne     .fail
465 serge 497
 
2434 Serge 498
        mov     eax, [eax+CONNECTION.uart]
499
        test    eax, eax
500
        jz      .fail
465 serge 501
 
2434 Serge 502
        mov     ebx, [esi+4]
503
        mov     ecx, [esi+8]
465 serge 504
 
505
; param
506
;  eax= uart
507
;  ebx= baud rate
508
;  ecx= mode
509
 
510
align 4
511
.internal:
2434 Serge 512
        cmp     ebx, RATE_115200
513
        ja      .fail
465 serge 514
 
2434 Serge 515
        cmp     ecx, LCR_BREAK
516
        jae     .fail
465 serge 517
 
2434 Serge 518
        mov     [eax+UART.rate], ebx
519
        mov     [eax+UART.mode], ecx
465 serge 520
 
2434 Serge 521
        mov     esi, eax
522
        mov     bx, [divisor+ebx*2]
465 serge 523
 
2434 Serge 524
        mov     edx, [esi+UART.base]
525
        push    edx
526
        add     edx, LCR_REG
527
        in      al, dx
528
        or      al, 0x80
529
        out     dx, al
465 serge 530
 
2434 Serge 531
        pop     edx
532
        mov     al, bl
533
        out     dx, al
465 serge 534
 
2434 Serge 535
        inc     dx
536
        mov     al, bh
537
        out     dx, al
465 serge 538
 
2434 Serge 539
        add     edx, LCR_REG-1
540
        mov     eax, ecx
541
        out     dx, al
542
        xor     eax, eax
543
        ret
465 serge 544
.fail:
2434 Serge 545
        or      eax, -1
546
        ret
465 serge 547
 
548
; param
549
;  esi=  input buffer
550
;        +0 connection
551
;        +4 modem control reg valie
552
;
553
; retval
554
;  eax= error code
555
 
556
align 4
557
uart_set_mcr:
558
 
2434 Serge 559
        mov     eax, [esi]
560
        cmp     [eax+APPOBJ.magic], 'CNCT'
561
        jne     .fail
465 serge 562
 
2434 Serge 563
        cmp     [eax+APPOBJ.destroy], uart_close.destroy
564
        jne     .fail
465 serge 565
 
2434 Serge 566
        mov     eax, [eax+CONNECTION.uart]
567
        test    eax, eax
568
        jz      .fail
465 serge 569
 
2434 Serge 570
        mov     ebx, [esi+4]
465 serge 571
 
2434 Serge 572
        mov     [eax+UART.mcr_reg], ebx
573
        mov     edx, [eax+UART.base]
574
        add     edx, MCR_REG
575
        mov     al, bl
576
        out     dx, al
577
        xor     eax, eax
578
        ret
465 serge 579
.fail:
2434 Serge 580
        or      eax, -1
581
        ret
465 serge 582
 
583
; param
584
;  eax= port
585
;
586
; retval
587
;  ecx= connection
588
;  eax= error code
589
 
590
align 4
591
uart_open:
2434 Serge 592
        dec     eax
593
        cmp     eax, COM_MAX
594
        jae     .fail
465 serge 595
 
2434 Serge 596
        mov     esi, [com1+eax*4]            ;uart
597
        push    esi
465 serge 598
.do_wait:
2434 Serge 599
        cmp     dword [esi+UART.lock], 0
600
        je      .get_lock
465 serge 601
      ;     call change_task
2434 Serge 602
        jmp     .do_wait
465 serge 603
.get_lock:
2434 Serge 604
        mov     eax, 1
605
        xchg    eax, [esi+UART.lock]
606
        test    eax, eax
607
        jnz     .do_wait
465 serge 608
 
2434 Serge 609
        mov     eax, esi                 ;uart
610
        call    uart_reset.internal
465 serge 611
 
2434 Serge 612
        mov     ebx, [CURRENT_TASK]
613
        shl     ebx, 5
614
        mov     ebx, [CURRENT_TASK+ebx+4]
615
        mov     eax, CONNECTION_SIZE
616
        call    CreateObject
617
        pop     esi                      ;uart
618
        test    eax, eax
619
        jz      .fail
465 serge 620
 
2434 Serge 621
        mov     [eax+APPOBJ.magic], 'CNCT'
622
        mov     [eax+APPOBJ.destroy], uart_close.destroy
623
        mov     [eax+CONNECTION.uart], esi
624
        mov     ecx, eax
625
        xor     eax, eax
626
        ret
465 serge 627
.fail:
2434 Serge 628
        or      eax, -1
629
        ret
465 serge 630
restore .uart
631
 
632
; param
633
;  esi= input buffer
634
 
635
align 4
636
uart_close:
2434 Serge 637
        mov     eax, [esi]
638
        cmp     [eax+APPOBJ.magic], 'CNCT'
639
        jne     .fail
465 serge 640
 
2434 Serge 641
        cmp     [eax+APPOBJ.destroy], uart_close.destroy
642
        jne     .fail
465 serge 643
.destroy:
2434 Serge 644
        push    [eax+CONNECTION.uart]
645
        call    DestroyObject   ;eax= object
646
        pop     eax                     ;eax= uart
647
        test    eax, eax
648
        jz      .fail
465 serge 649
 
2434 Serge 650
        mov     [eax+UART.state], UART_CLOSED
651
        mov     [eax+UART.lock], 0;release port
652
        xor     eax, eax
653
        ret
465 serge 654
.fail:
2434 Serge 655
        or      eax, -1
656
        ret
465 serge 657
 
658
 
659
; param
660
;  eax= uart
661
;  ebx= baud rate
662
 
663
align 4
664
set_rate:
2434 Serge 665
        cmp     ebx, RATE_115200
666
        ja      .fail
465 serge 667
 
2434 Serge 668
        mov     [eax+UART.rate], ebx
669
        mov     bx, [divisor+ebx*2]
465 serge 670
 
2434 Serge 671
        mov     edx, [eax+UART.base]
672
        add     edx, LCR_REG
673
        in      al, dx
674
        push    eax
675
        or      al, 0x80
676
        out     dx, al
465 serge 677
 
2434 Serge 678
        sub     edx, LCR_REG
679
        mov     al, bl
680
        out     dx, al
465 serge 681
 
2434 Serge 682
        inc     edx
683
        mov     al, bh
684
        out     dx, al
465 serge 685
 
2434 Serge 686
        pop     eax
687
        add     edx, LCR_REG-1
688
        out     dx, al
465 serge 689
.fail:
2434 Serge 690
        ret
465 serge 691
 
692
 
693
; param
694
;   ebx= uart
695
 
696
align 4
697
transmit:
2434 Serge 698
        push    esi
699
        push    edi
465 serge 700
 
2434 Serge 701
        mov     edx, [ebx+UART.base]
465 serge 702
 
2434 Serge 703
        pushfd
704
        cli
465 serge 705
 
2434 Serge 706
        mov     esi, [ebx+UART.xmit_rp]
707
        mov     ecx, [ebx+UART.xmit_count]
708
        test    ecx, ecx
709
        je      .stop
465 serge 710
 
2434 Serge 711
        cmp     ecx, 16
712
        jbe     @F
713
        mov     ecx, 16
465 serge 714
@@:
2434 Serge 715
        sub     [ebx+UART.xmit_count], ecx
716
        add     [ebx+UART.xmit_free], ecx
717
        cld
465 serge 718
@@:
2434 Serge 719
        lodsb
720
        out     dx, al
721
        dec     ecx
722
        jnz     @B
465 serge 723
 
2434 Serge 724
        cmp     esi, [ebx+UART.xmit_top]
725
        jb      @F
726
        sub     esi, 8192
465 serge 727
@@:
2434 Serge 728
        mov     [ebx+UART.xmit_rp], esi
465 serge 729
 
2434 Serge 730
        cmp     [ebx+UART.xmit_count], 0
731
        je      .stop
465 serge 732
 
2434 Serge 733
        mov     [ebx+UART.state], UART_TRANSMIT
734
        jmp     @F
465 serge 735
.stop:
2434 Serge 736
        mov     [ebx+UART.state], UART_STOP
465 serge 737
@@:
2434 Serge 738
        popfd
739
        pop     edi
740
        pop     esi
741
        ret
465 serge 742
 
743
 
744
; param
745
;  esi=  input buffer
746
;        +0 connection
747
;        +4 dst buffer
748
;        +8 dst size
749
;  edi=  output buffer
750
;        +0 bytes read
751
 
752
; retval
753
;  eax= error code
754
 
755
align 4
756
uart_read:
2434 Serge 757
        mov     eax, [esi]
758
        cmp     [eax+APPOBJ.magic], 'CNCT'
759
        jne     .fail
465 serge 760
 
2434 Serge 761
        cmp     [eax+APPOBJ.destroy], uart_close.destroy
762
        jne     .fail
465 serge 763
 
2434 Serge 764
        mov     eax, [eax+CONNECTION.uart]
765
        test    eax, eax
766
        jz      .fail
465 serge 767
 
2434 Serge 768
        mov     ebx, [esi+8]   ;dst size
769
        mov     ecx, [eax+UART.rcvr_count]
770
        cmp     ecx, ebx
771
        jbe     @F
772
        mov     ecx, ebx
465 serge 773
@@:
2434 Serge 774
        mov     [edi], ecx     ;bytes read
775
        test    ecx, ecx
776
        jz      .done
465 serge 777
 
2434 Serge 778
        push    ecx
465 serge 779
 
2434 Serge 780
        mov     edi, [esi+4]   ;dst
781
        mov     esi, [eax+UART.rcvr_rp]
782
        cld
783
        rep movsb
784
        pop     ecx
465 serge 785
 
2434 Serge 786
        cmp     esi, [eax+UART.rcvr_top]
787
        jb      @F
788
        sub     esi, 8192
465 serge 789
@@:
2434 Serge 790
        mov     [eax+UART.rcvr_rp], esi
791
        sub     [eax+UART.rcvr_count], ecx
465 serge 792
.done:
2434 Serge 793
        xor     eax, eax
794
        ret
465 serge 795
.fail:
2434 Serge 796
        or      eax, -1
797
        ret
465 serge 798
 
799
; param
800
;  esi=  input buffer
801
;        +0 connection
802
;        +4 src buffer
803
;        +8 src size
804
;
805
; retval
806
;  eax= error code
807
 
808
align 4
809
uart_write:
2434 Serge 810
        mov     eax, [esi]
811
        cmp     [eax+APPOBJ.magic], 'CNCT'
812
        jne     .fail
465 serge 813
 
2434 Serge 814
        cmp     [eax+APPOBJ.destroy], uart_close.destroy
815
        jne     .fail
465 serge 816
 
2434 Serge 817
        mov     eax, [eax+CONNECTION.uart]
818
        test    eax, eax
819
        jz      .fail
465 serge 820
 
2434 Serge 821
        mov     ebx, [esi+4]
822
        mov     edx, [esi+8]
465 serge 823
 
824
; param
825
;  eax= uart
826
;  ebx= src
827
;  edx= count
828
 
829
align 4
830
.internal:
2434 Serge 831
        mov     esi, ebx
832
        mov     edi, [eax+UART.xmit_wp]
465 serge 833
.write:
2434 Serge 834
        test    edx, edx
835
        jz      .fail
465 serge 836
.wait:
2434 Serge 837
        cmp     [eax+UART.xmit_free], 0
838
        jne     .fill
465 serge 839
 
2434 Serge 840
        cmp     [eax+UART.state], UART_TRANSMIT
841
        je      .wait
465 serge 842
 
2434 Serge 843
        mov     ebx, eax
844
        push    edx
845
        call    transmit
846
        pop     edx
847
        mov     eax, ebx
848
        jmp     .write
465 serge 849
.fill:
2434 Serge 850
        mov     ecx, [eax+UART.xmit_free]
851
        cmp     ecx, edx
852
        jbe     @F
853
        mov     ecx, edx
465 serge 854
@@:
2434 Serge 855
        push    ecx
856
        cld
857
        rep movsb
858
        pop     ecx
859
        sub     [eax+UART.xmit_free], ecx
860
        add     [eax+UART.xmit_count], ecx
861
        sub     edx, ecx
862
        jnz     .wait
465 serge 863
.done:
2434 Serge 864
        cmp     edi, [eax+UART.xmit_top]
865
        jb      @F
866
        sub     edi, 8192
465 serge 867
@@:
2434 Serge 868
        mov     [eax+UART.xmit_wp], edi
869
        cmp     [eax+UART.state], UART_TRANSMIT
870
        je      @F
871
        mov     ebx, eax
872
        call    transmit
465 serge 873
@@:
2434 Serge 874
        xor     eax, eax
875
        ret
465 serge 876
.fail:
2434 Serge 877
        or      eax, -1
878
        ret
465 serge 879
 
880
 
881
align 4
882
com_2_isr:
2434 Serge 883
        mov     ebx, [com2]
884
        jmp     com_1_isr.get_info
465 serge 885
align 4
886
com_1_isr:
2434 Serge 887
        mov     ebx, [com1]
465 serge 888
.get_info:
2434 Serge 889
        mov     edx, [ebx+UART.base]
890
        add     edx, IIR_REG
891
        in      al, dx
465 serge 892
 
2434 Serge 893
        test    al, IIR_INTR
894
        jnz     .done
465 serge 895
 
2434 Serge 896
        shr     eax, 1
897
        and     eax, 3
465 serge 898
 
2434 Serge 899
        call    [isr_action+eax*4]
900
        jmp     .get_info
465 serge 901
.done:
2434 Serge 902
        ret
465 serge 903
 
904
align 4
905
isr_line:
2434 Serge 906
        mov     edx, [ebx+UART.base]
907
        add     edx, LSR_REG
908
        in      al, dx
909
        ret
465 serge 910
 
911
align 4
912
isr_recieve:
2434 Serge 913
        mov     esi, [ebx+UART.base]
914
        add     esi, LSR_REG
915
        mov     edi, [ebx+UART.rcvr_wp]
916
        xor     ecx, ecx
917
        cld
465 serge 918
.read:
2434 Serge 919
        mov     edx, esi
920
        in      al, dx
921
        test    eax, LSR_DR
922
        jz      .done
465 serge 923
 
2434 Serge 924
        mov     edx, [ebx+UART.base]
925
        in      al, dx
926
        stosb
927
        inc     ecx
928
        jmp     .read
465 serge 929
.done:
2434 Serge 930
        cmp     edi, [ebx+UART.rcvr_top]
931
        jb      @F
932
        sub     edi, 8192
465 serge 933
@@:
2434 Serge 934
        mov     [ebx+UART.rcvr_wp], edi
935
        add     [ebx+UART.rcvr_count], ecx
936
        ret
465 serge 937
 
938
align 4
939
isr_modem:
2434 Serge 940
        mov     edx, [ebx+UART.base]
941
        add     edx, MSR_REG
942
        in      al, dx
943
        ret
465 serge 944
 
945
 
946
align 4
947
divisor    dw 2304, 1536, 1047, 857, 768, 384
2434 Serge 948
           dw  192,   96,   64,  58,  48,  32
949
           dw   24,   16,   12,   6,   3,   2, 1
465 serge 950
 
951
align 4
2434 Serge 952
uart_func   dd 0                ;SRV_GETVERSION
953
            dd 0                ;PORT_OPEN
954
            dd uart_close       ;PORT_CLOSE
955
            dd uart_reset       ;PORT_RESET
956
            dd uart_set_mode    ;PORT_SETMODE
957
            dd 0                ;PORT_GETMODE
958
            dd uart_set_mcr     ;PORT_SETMODEM
959
            dd 0                ;PORT_GETMODEM
960
            dd uart_read        ;PORT_READ
961
            dd uart_write       ;PORT_WRITE
465 serge 962
 
963
isr_action  dd isr_modem
2434 Serge 964
            dd transmit
965
            dd isr_recieve
966
            dd isr_line
465 serge 967
 
968
version     dd (5 shl 16) or (UART_VERSION and 0xFFFF)
969
 
970
sz_uart_srv db 'UART',0
971
 
972
align 4
973
 
2434 Serge 974
com1        rd 1
975
com2        rd 1
465 serge 976