Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
465 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
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
 
774 Rus 17
API_VERSION	  equ 0
18
UART_VERSION	  equ API_VERSION
465 serge 19
 
774 Rus 20
PG_SW		  equ 0x003
21
page_tabs	  equ 0xFDC00000     ;hack
465 serge 22
 
774 Rus 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
 
774 Rus 29
struc APPOBJ	       ;common object header
465 serge 30
{
774 Rus 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
774 Rus 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
 
774 Rus 55
DEBUG		 equ   1
465 serge 56
 
774 Rus 57
DRV_ENTRY	 equ   1
58
DRV_EXIT	 equ  -1
465 serge 59
 
774 Rus 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
 
774 Rus 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
 
774 Rus 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
 
774 Rus 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
 
774 Rus 98
IIR_INTR	 equ  0x01     ;1= no interrupts
465 serge 99
 
774 Rus 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
 
774 Rus 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
 
774 Rus 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
 
774 Rus 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
 
774 Rus 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
 
774 Rus 143
COM_1_BASE	 equ 0x3F8
144
COM_2_BASE	 equ 0x2F8
465 serge 145
 
774 Rus 146
COM_1_IRQ	 equ  4
147
COM_2_IRQ	 equ  3
465 serge 148
 
774 Rus 149
UART_CLOSED	 equ  0
150
UART_TRANSMIT	 equ  1
151
UART_STOP	 equ  2
465 serge 152
 
153
struc UART
154
{
774 Rus 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
 
774 Rus 163
   .rcvr_buff	 dd ?
164
   .rcvr_rp	 dd ?
165
   .rcvr_wp	 dd ?
166
   .rcvr_count	 dd ?
167
   .rcvr_top	 dd ?
465 serge 168
 
774 Rus 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
{
774 Rus 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
 
774 Rus 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
 
774 Rus 208
	   cmp [state], 1
209
	   jne .stop
465 serge 210
 
774 Rus 211
	   mov eax, UART_SIZE
212
	   call Kmalloc
213
	   test eax, eax
214
	   jz .fail
465 serge 215
 
774 Rus 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
 
774 Rus 223
	   mov eax, [com1]
224
	   mov [eax+UART.base], COM_1_BASE
465 serge 225
 
774 Rus 226
	   stdcall AllocKernelSpace, 32768
465 serge 227
 
774 Rus 228
	   mov edi, [com1]
229
	   mov edx, eax
465 serge 230
 
774 Rus 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
 
774 Rus 239
	   call AllocPage
240
	   test eax, eax
241
	   jz .fail
465 serge 242
 
774 Rus 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
 
774 Rus 248
	   call AllocPage
249
	   test eax, eax
250
	   jz .fail
465 serge 251
 
774 Rus 252
	   or eax, PG_SW
253
	   mov [page_tabs+edx*4+4], eax
254
	   mov [page_tabs+edx*4+12], eax
465 serge 255
 
774 Rus 256
	   call AllocPage
257
	   test eax, eax
258
	   jz .fail
465 serge 259
 
774 Rus 260
	   or eax, PG_SW
261
	   mov [page_tabs+edx*4+16], eax
262
	   mov [page_tabs+edx*4+24], eax
465 serge 263
 
774 Rus 264
	   call AllocPage
265
	   test eax, eax
266
	   jz .fail
465 serge 267
 
774 Rus 268
	   or eax, PG_SW
269
	   mov [page_tabs+edx*4+20], eax
270
	   mov [page_tabs+edx*4+28], eax
465 serge 271
 
774 Rus 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
 
774 Rus 282
	   mov eax, edi
283
	   call uart_reset.internal   ;eax= uart
465 serge 284
 
774 Rus 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:
774 Rus 290
	   xor eax, eax
291
	   ret
465 serge 292
endp
293
 
294
 
774 Rus 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
 
774 Rus 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
 
774 Rus 316
	   mov ebx, [ioctl]
317
	   mov eax, [ebx+io_code]
318
	   cmp eax, PORT_WRITE
319
	   ja .fail
465 serge 320
 
774 Rus 321
	   cmp eax, SRV_GETVERSION
322
	   jne @F
465 serge 323
 
774 Rus 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
@@:
774 Rus 331
	   cmp eax, PORT_OPEN
332
	   jne @F
465 serge 333
 
774 Rus 334
	   cmp [ebx+out_size], 4
335
	   jne .fail
465 serge 336
 
774 Rus 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
@@:
774 Rus 345
	   mov esi, [ebx+input]     ;input buffer
346
	   mov edi, [ebx+output]
347
	   call [uart_func+eax*4]
348
	   ret
465 serge 349
.fail:
774 Rus 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:
774 Rus 372
	   mov eax, [esi]
373
	   cmp [eax+APPOBJ.magic], 'CNCT'
374
	   jne .fail
465 serge 375
 
774 Rus 376
	   cmp [eax+APPOBJ.destroy], uart_close.destroy
377
	   jne .fail
465 serge 378
 
774 Rus 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:
774 Rus 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
 
774 Rus 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
 
774 Rus 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:
774 Rus 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
 
774 Rus 416
	   mov edx, [esi+UART.base]
417
	   in al, dx
418
	   jmp .clear_RB
465 serge 419
@@:
774 Rus 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:
774 Rus 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
 
774 Rus 431
	   shr eax, 1
432
	   and eax, 3
433
	   jnz @F
465 serge 434
 
774 Rus 435
	   mov edx, [esi+UART.base]
436
	   add edx, MSR_REG
437
	   in al, dx
438
	   jmp .clear_IIR
465 serge 439
@@:
774 Rus 440
	   cmp eax, 1
441
	   je .clear_IIR
465 serge 442
 
774 Rus 443
	   cmp eax, 2
444
	   jne @F
465 serge 445
 
774 Rus 446
	   mov edx, [esi+UART.base]
447
	   in al, dx
448
	   jmp .clear_IIR
465 serge 449
@@:
774 Rus 450
	   mov edx, [esi+UART.base]
451
	   add edx, LSR_REG
452
	   in al, dx
453
	   jmp .clear_IIR
465 serge 454
.done:
774 Rus 455
	   mov edi, [esi+UART.rcvr_buff]
456
	   mov ecx, 8192/4
457
	   xor eax, eax
465 serge 458
 
774 Rus 459
	   mov [esi+UART.rcvr_rp], edi
460
	   mov [esi+UART.rcvr_wp], edi
461
	   mov [esi+UART.rcvr_count], eax
465 serge 462
 
774 Rus 463
	   cld
464
	   rep stosd
465 serge 465
 
774 Rus 466
	   mov edi, [esi+UART.xmit_buff]
467
	   mov ecx, 8192/4
465 serge 468
 
774 Rus 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
 
774 Rus 474
	   rep stosd
475
	   ret		     ;eax= 0
465 serge 476
.fail:
774 Rus 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:
774 Rus 491
	   mov eax, [esi]
492
	   cmp [eax+APPOBJ.magic], 'CNCT'
493
	   jne .fail
465 serge 494
 
774 Rus 495
	   cmp [eax+APPOBJ.destroy], uart_close.destroy
496
	   jne .fail
465 serge 497
 
774 Rus 498
	   mov eax, [eax+CONNECTION.uart]
499
	   test eax, eax
500
	   jz .fail
465 serge 501
 
774 Rus 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:
774 Rus 512
	   cmp ebx, RATE_115200
513
	   ja .fail
465 serge 514
 
774 Rus 515
	   cmp ecx, LCR_BREAK
516
	   jae .fail
465 serge 517
 
774 Rus 518
	   mov [eax+UART.rate], ebx
519
	   mov [eax+UART.mode], ecx
465 serge 520
 
774 Rus 521
	   mov esi, eax
522
	   mov bx, [divisor+ebx*2]
465 serge 523
 
774 Rus 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
 
774 Rus 531
	   pop edx
532
	   mov al, bl
533
	   out dx, al
465 serge 534
 
774 Rus 535
	   inc dx
536
	   mov al, bh
537
	   out dx, al
465 serge 538
 
774 Rus 539
	   add edx, LCR_REG-1
540
	   mov eax, ecx
541
	   out dx, al
542
	   xor eax, eax
543
	   ret
465 serge 544
.fail:
774 Rus 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
 
774 Rus 559
	   mov eax, [esi]
560
	   cmp [eax+APPOBJ.magic], 'CNCT'
561
	   jne .fail
465 serge 562
 
774 Rus 563
	   cmp [eax+APPOBJ.destroy], uart_close.destroy
564
	   jne .fail
465 serge 565
 
774 Rus 566
	   mov eax, [eax+CONNECTION.uart]
567
	   test eax, eax
568
	   jz .fail
465 serge 569
 
774 Rus 570
	   mov ebx, [esi+4]
465 serge 571
 
774 Rus 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:
774 Rus 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:
774 Rus 592
	   dec eax
593
	   cmp eax, COM_MAX
594
	   jae .fail
465 serge 595
 
774 Rus 596
	   mov esi, [com1+eax*4]	     ;uart
597
	   push esi
465 serge 598
.do_wait:
774 Rus 599
	   cmp dword [esi+UART.lock],0
600
	   je .get_lock
465 serge 601
      ;     call change_task
774 Rus 602
	   jmp .do_wait
465 serge 603
.get_lock:
774 Rus 604
	   mov eax, 1
605
	   xchg eax, [esi+UART.lock]
606
	   test eax, eax
607
	   jnz .do_wait
465 serge 608
 
774 Rus 609
	   mov eax, esi 		 ;uart
610
	   call uart_reset.internal
465 serge 611
 
774 Rus 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
 
774 Rus 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:
774 Rus 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:
774 Rus 637
	   mov eax, [esi]
638
	   cmp [eax+APPOBJ.magic], 'CNCT'
639
	   jne .fail
465 serge 640
 
774 Rus 641
	   cmp [eax+APPOBJ.destroy], uart_close.destroy
642
	   jne .fail
465 serge 643
.destroy:
774 Rus 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
 
774 Rus 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:
774 Rus 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:
774 Rus 665
	   cmp ebx, RATE_115200
666
	   ja .fail
465 serge 667
 
774 Rus 668
	   mov [eax+UART.rate], ebx
669
	   mov bx, [divisor+ebx*2]
465 serge 670
 
774 Rus 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
 
774 Rus 678
	   sub edx, LCR_REG
679
	   mov al, bl
680
	   out dx, al
465 serge 681
 
774 Rus 682
	   inc edx
683
	   mov al, bh
684
	   out dx, al
465 serge 685
 
774 Rus 686
	   pop eax
687
	   add edx, LCR_REG-1
688
	   out dx, al
465 serge 689
.fail:
774 Rus 690
	   ret
465 serge 691
 
692
 
693
; param
694
;   ebx= uart
695
 
696
align 4
697
transmit:
774 Rus 698
	   push esi
699
	   push edi
465 serge 700
 
774 Rus 701
	   mov edx, [ebx+UART.base]
465 serge 702
 
774 Rus 703
	   pushfd
704
	   cli
465 serge 705
 
774 Rus 706
	   mov esi, [ebx+UART.xmit_rp]
707
	   mov ecx, [ebx+UART.xmit_count]
708
	   test ecx, ecx
709
	   je .stop
465 serge 710
 
774 Rus 711
	   cmp ecx, 16
712
	   jbe @F
713
	   mov ecx, 16
465 serge 714
@@:
774 Rus 715
	   sub [ebx+UART.xmit_count], ecx
716
	   add [ebx+UART.xmit_free], ecx
717
	   cld
465 serge 718
@@:
774 Rus 719
	   lodsb
720
	   out dx, al
721
	   dec ecx
722
	   jnz @B
465 serge 723
 
774 Rus 724
	   cmp esi,[ebx+UART.xmit_top]
725
	   jb @F
726
	   sub esi, 8192
465 serge 727
@@:
774 Rus 728
	   mov [ebx+UART.xmit_rp], esi
465 serge 729
 
774 Rus 730
	   cmp [ebx+UART.xmit_count], 0
731
	   je .stop
465 serge 732
 
774 Rus 733
	   mov [ebx+UART.state], UART_TRANSMIT
734
	   jmp @F
465 serge 735
.stop:
774 Rus 736
	   mov [ebx+UART.state], UART_STOP
465 serge 737
@@:
774 Rus 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:
774 Rus 757
	   mov eax, [esi]
758
	   cmp [eax+APPOBJ.magic], 'CNCT'
759
	   jne .fail
465 serge 760
 
774 Rus 761
	   cmp [eax+APPOBJ.destroy], uart_close.destroy
762
	   jne .fail
465 serge 763
 
774 Rus 764
	   mov eax, [eax+CONNECTION.uart]
765
	   test eax, eax
766
	   jz .fail
465 serge 767
 
774 Rus 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
@@:
774 Rus 774
	   mov [edi], ecx      ;bytes read
775
	   test ecx, ecx
776
	   jz .done
465 serge 777
 
774 Rus 778
	   push ecx
465 serge 779
 
774 Rus 780
	   mov edi, [esi+4]    ;dst
781
	   mov esi, [eax+UART.rcvr_rp]
782
	   cld
783
	   rep movsb
784
	   pop ecx
465 serge 785
 
774 Rus 786
	   cmp esi, [eax+UART.rcvr_top]
787
	   jb @F
788
	   sub esi, 8192
465 serge 789
@@:
774 Rus 790
	   mov [eax+UART.rcvr_rp], esi
791
	   sub [eax+UART.rcvr_count], ecx
465 serge 792
.done:
774 Rus 793
	   xor eax, eax
794
	   ret
465 serge 795
.fail:
774 Rus 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:
774 Rus 810
	   mov eax, [esi]
811
	   cmp [eax+APPOBJ.magic], 'CNCT'
812
	   jne .fail
465 serge 813
 
774 Rus 814
	   cmp [eax+APPOBJ.destroy], uart_close.destroy
815
	   jne .fail
465 serge 816
 
774 Rus 817
	   mov eax, [eax+CONNECTION.uart]
818
	   test eax, eax
819
	   jz .fail
465 serge 820
 
774 Rus 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:
774 Rus 831
	   mov esi, ebx
832
	   mov edi, [eax+UART.xmit_wp]
465 serge 833
.write:
774 Rus 834
	   test edx, edx
835
	   jz .fail
465 serge 836
.wait:
774 Rus 837
	   cmp [eax+UART.xmit_free], 0
838
	   jne .fill
465 serge 839
 
774 Rus 840
	   cmp [eax+UART.state], UART_TRANSMIT
841
	   je .wait
465 serge 842
 
774 Rus 843
	   mov ebx, eax
844
	   push edx
845
	   call transmit
846
	   pop edx
847
	   mov eax, ebx
848
	   jmp .write
465 serge 849
.fill:
774 Rus 850
	   mov ecx, [eax+UART.xmit_free]
851
	   cmp ecx, edx
852
	   jbe @F
853
	   mov ecx, edx
465 serge 854
@@:
774 Rus 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:
774 Rus 864
	   cmp edi, [eax+UART.xmit_top]
865
	   jb @F
866
	   sub edi, 8192
465 serge 867
@@:
774 Rus 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
@@:
774 Rus 874
	   xor eax, eax
875
	   ret
465 serge 876
.fail:
774 Rus 877
	   or eax, -1
878
	   ret
465 serge 879
 
880
 
881
align 4
882
com_2_isr:
774 Rus 883
	   mov ebx, [com2]
884
	   jmp com_1_isr.get_info
465 serge 885
align 4
886
com_1_isr:
774 Rus 887
	   mov ebx, [com1]
465 serge 888
.get_info:
774 Rus 889
	   mov edx, [ebx+UART.base]
890
	   add edx, IIR_REG
891
	   in  al, dx
465 serge 892
 
774 Rus 893
	   test al, IIR_INTR
894
	   jnz .done
465 serge 895
 
774 Rus 896
	   shr eax, 1
897
	   and eax, 3
465 serge 898
 
774 Rus 899
	   call [isr_action+eax*4]
900
	   jmp .get_info
465 serge 901
.done:
774 Rus 902
	   ret
465 serge 903
 
904
align 4
905
isr_line:
774 Rus 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:
774 Rus 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:
774 Rus 919
	   mov edx, esi
920
	   in al, dx
921
	   test eax, LSR_DR
922
	   jz .done
465 serge 923
 
774 Rus 924
	   mov edx, [ebx+UART.base]
925
	   in al, dx
926
	   stosb
927
	   inc ecx
928
	   jmp .read
465 serge 929
.done:
774 Rus 930
	   cmp edi, [ebx+UART.rcvr_top]
931
	   jb @F
932
	   sub edi, 8192
465 serge 933
@@:
774 Rus 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:
774 Rus 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
774 Rus 948
	   dw  192,   96,   64,  58,  48,  32
949
	   dw	24,   16,   12,   6,   3,   2, 1
465 serge 950
 
951
align 4
774 Rus 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
774 Rus 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
 
774 Rus 974
com1	    rd 1
975
com2	    rd 1
465 serge 976