Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
586 serge 2
;;                                                              ;;
431 serge 3
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;                                                              ;;
586 serge 7
;;  PCI32.INC                                                   ;;
8
;;                                                              ;;
9
;;  32 bit PCI driver code                                      ;;
10
;;                                                              ;;
11
;;  Version 0.3  April 9, 2007                                  ;;
12
;;  Version 0.2  December 21st, 2002                            ;;
13
;;                                                              ;;
14
;;  Author: Victor Prodan, victorprodan@yahoo.com               ;;
15
;;          Mihailov Ilia, ghost.nsk@gmail.com                  ;;
16
;;    Credits:                                                  ;;
17
;;          Ralf Brown                                          ;;
18
;;          Mike Hibbett, mikeh@oceanfree.net                   ;;
19
;;                                                              ;;
20
;;  See file COPYING for details                                ;;
21
;;                                                              ;;
431 serge 22
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1 ha 23
 
750 victor 24
$Revision: 1354 $
1 ha 25
 
26
;***************************************************************************
27
;   Function
28
;      pci_api:
29
;
30
;   Description
31
;       entry point for system PCI calls
32
;***************************************************************************
33
 
34
align 4
35
 
36
pci_api:
37
 
1348 art_zh 38
	cmp  [pci_access_enabled],1
39
	jne  no_pci_access_for_applications
1 ha 40
 
1348 art_zh 41
	or al,al
42
	jnz pci_fn_1
43
	; PCI function 0: get pci version (AH.AL)
44
	movzx eax,word [BOOT_VAR+0x9022]
45
	ret
1 ha 46
 
47
pci_fn_1:
1348 art_zh 48
	cmp al,1
49
	jnz pci_fn_2
1 ha 50
 
1348 art_zh 51
	; PCI function 1: get last bus in AL
52
	mov al,[BOOT_VAR+0x9021]
53
	ret
1 ha 54
 
55
pci_fn_2:
1348 art_zh 56
	cmp al,2
57
	jne pci_fn_3
58
	; PCI function 2: get pci access mechanism
59
	mov al,[BOOT_VAR+0x9020]
60
	ret
1 ha 61
pci_fn_3:
62
 
1348 art_zh 63
	cmp al,4
64
	jz pci_read_reg   ;byte
65
	cmp al,5
66
	jz pci_read_reg   ;word
67
	cmp al,6
68
	jz pci_read_reg   ;dword
1 ha 69
 
1348 art_zh 70
	cmp al,8
71
	jz pci_write_reg  ;byte
72
	cmp al,9
73
	jz pci_write_reg  ;word
74
	cmp al,10
75
	jz pci_write_reg  ;dword
1 ha 76
 
1354 diamond 77
if defined mmio_pci_addr
1348 art_zh 78
	cmp al,11	    ; <<< user-level MMIO functions <<< NEW!
79
	jz pci_mmio_init
80
	cmp al,12
81
	jz pci_mmio_map
82
	cmp al,13
83
	jz pci_mmio_unmap
1354 diamond 84
end if
1348 art_zh 85
 
1 ha 86
      no_pci_access_for_applications:
87
 
1348 art_zh 88
	mov eax,-1
1 ha 89
 
1348 art_zh 90
	ret
1 ha 91
 
92
;***************************************************************************
93
;   Function
94
;      pci_make_config_cmd
95
;
96
;   Description
97
;       creates a command dword  for use with the PCI bus
98
;       bus # in ah
99
;       device+func in bh (dddddfff)
100
;       register in bl
101
;
102
;      command dword returned in eax ( 10000000 bbbbbbbb dddddfff rrrrrr00 )
103
;***************************************************************************
104
 
105
align 4
106
 
107
pci_make_config_cmd:
1348 art_zh 108
    shl     eax,8	   ; move bus to bits 16-23
109
    mov     ax,bx	   ; combine all
1 ha 110
    and     eax,0xffffff
1348 art_zh 111
    or	    eax,0x80000000
1 ha 112
    ret
113
 
114
;***************************************************************************
115
;   Function
116
;      pci_read_reg:
117
;
118
;   Description
119
;       read a register from the PCI config space into EAX/AX/AL
120
;       IN: ah=bus,device+func=bh,register address=bl
121
;           number of bytes to read (1,2,4) coded into AL, bits 0-1
586 serge 122
;           (0 - byte, 1 - word, 2 - dword)
1 ha 123
;***************************************************************************
124
 
125
align 4
126
 
127
pci_read_reg:
1348 art_zh 128
	cmp	byte [BOOT_VAR+0x9020],2 ;what mechanism will we use?
129
	je	pci_read_reg_2
1 ha 130
 
1348 art_zh 131
		; mechanism 1
132
	push	esi   ; save register size into ESI
133
	mov	esi,eax
134
	and	esi,3
1 ha 135
 
1348 art_zh 136
	call	pci_make_config_cmd
137
	mov	ebx,eax
138
		; get current state
139
	mov	dx,0xcf8
140
	in	eax, dx
141
	push	eax
142
		; set up addressing to config data
143
	mov	eax,ebx
144
	and	al,0xfc ; make address dword-aligned
145
	out	dx,eax
146
		; get requested DWORD of config data
147
	mov	dl,0xfc
148
	and	bl,3
149
	or	dl,bl	 ; add to port address first 2 bits of register address
1 ha 150
 
1348 art_zh 151
	or	esi,esi
152
	jz	pci_read_byte1
153
	cmp	esi,1
154
	jz	pci_read_word1
155
	cmp	esi,2
156
	jz	pci_read_dword1
157
	jmp	pci_fin_read1
1 ha 158
 
159
pci_read_byte1:
1348 art_zh 160
	in	al,dx
161
	jmp pci_fin_read1
1 ha 162
pci_read_word1:
1348 art_zh 163
	in	ax,dx
164
	jmp pci_fin_read1
1 ha 165
pci_read_dword1:
1348 art_zh 166
	in	eax,dx
167
	jmp	pci_fin_read1
1 ha 168
pci_fin_read1:
1348 art_zh 169
		; restore configuration control
170
	xchg	eax,[esp]
171
	mov	dx,0xcf8
172
	out	dx,eax
1 ha 173
 
1348 art_zh 174
	pop	eax
175
	pop	esi
176
	ret
1 ha 177
pci_read_reg_2:
178
 
1348 art_zh 179
	test	bh,128	;mech#2 only supports 16 devices per bus
180
	jnz	pci_read_reg_err
1 ha 181
 
1348 art_zh 182
	push esi   ; save register size into ESI
183
	mov esi,eax
184
	and esi,3
1 ha 185
 
1348 art_zh 186
	push	eax
187
		;store current state of config space
188
	mov	dx,0xcf8
189
	in	al,dx
190
	mov	ah,al
191
	mov	dl,0xfa
192
	in	al,dx
1 ha 193
 
1348 art_zh 194
	xchg	eax,[esp]
195
		; out 0xcfa,bus
196
	mov	al,ah
197
	out	dx,al
198
		; out 0xcf8,0x80
199
	mov	dl,0xf8
200
	mov	al,0x80
201
	out	dx,al
202
		; compute addr
203
	shr	bh,3 ; func is ignored in mechanism 2
204
	or	bh,0xc0
205
	mov	dx,bx
1 ha 206
 
1348 art_zh 207
	or	esi,esi
208
	jz	pci_read_byte2
209
	cmp	esi,1
210
	jz	pci_read_word2
211
	cmp	esi,2
212
	jz	pci_read_dword2
213
	jmp	pci_fin_read2
1 ha 214
 
215
pci_read_byte2:
1348 art_zh 216
	in	al,dx
217
	jmp pci_fin_read2
1 ha 218
pci_read_word2:
1348 art_zh 219
	in	ax,dx
220
	jmp pci_fin_read2
1 ha 221
pci_read_dword2:
1348 art_zh 222
	in	eax,dx
1 ha 223
;       jmp pci_fin_read2
224
pci_fin_read2:
225
 
1348 art_zh 226
		; restore configuration space
227
	xchg	eax,[esp]
228
	mov	dx,0xcfa
229
	out	dx,al
230
	mov	dl,0xf8
231
	mov	al,ah
232
	out	dx,al
1 ha 233
 
1348 art_zh 234
	pop	eax
235
	pop	esi
236
	ret
1 ha 237
 
238
pci_read_reg_err:
1348 art_zh 239
	xor	eax,eax
240
	dec	eax
241
	ret
1 ha 242
 
243
 
244
;***************************************************************************
245
;   Function
246
;      pci_write_reg:
247
;
248
;   Description
249
;       write a register from ECX/CX/CL into the PCI config space
250
;       IN: ah=bus,device+func=bh,register address (dword aligned)=bl,
251
;           value to write in ecx
252
;           number of bytes to write (1,2,4) coded into AL, bits 0-1
586 serge 253
;           (0 - byte, 1 - word, 2 - dword)
1 ha 254
;***************************************************************************
255
 
256
align 4
257
 
258
pci_write_reg:
1348 art_zh 259
	cmp byte [BOOT_VAR+0x9020],2 ;what mechanism will we use?
260
	je pci_write_reg_2
1 ha 261
 
1348 art_zh 262
		; mechanism 1
263
	push	esi   ; save register size into ESI
264
	mov	esi,eax
265
	and	esi,3
1 ha 266
 
1348 art_zh 267
	call	pci_make_config_cmd
268
	mov	ebx,eax
269
		; get current state into ecx
270
	mov	dx,0xcf8
271
	in	eax, dx
272
	push	eax
273
		; set up addressing to config data
274
	mov	eax,ebx
275
	and	al,0xfc ; make address dword-aligned
276
	out	dx,eax
277
		; write DWORD of config data
278
	mov	dl,0xfc
279
	and	bl,3
280
	or	dl,bl
281
	mov	eax,ecx
1 ha 282
 
1348 art_zh 283
	or	esi,esi
284
	jz	pci_write_byte1
285
	cmp	esi,1
286
	jz	pci_write_word1
287
	cmp	esi,2
288
	jz	pci_write_dword1
289
	jmp	pci_fin_write1
1 ha 290
 
291
pci_write_byte1:
1348 art_zh 292
	out	dx,al
293
	jmp pci_fin_write1
1 ha 294
pci_write_word1:
1348 art_zh 295
	out	dx,ax
296
	jmp pci_fin_write1
1 ha 297
pci_write_dword1:
1348 art_zh 298
	out	dx,eax
299
	jmp	pci_fin_write1
1 ha 300
pci_fin_write1:
301
 
1348 art_zh 302
		; restore configuration control
303
	pop	eax
304
	mov	dl,0xf8
305
	out	dx,eax
1 ha 306
 
1348 art_zh 307
	xor	eax,eax
308
	pop	esi
1 ha 309
 
1348 art_zh 310
	ret
1 ha 311
pci_write_reg_2:
312
 
1348 art_zh 313
	test	bh,128	;mech#2 only supports 16 devices per bus
314
	jnz	pci_write_reg_err
1 ha 315
 
316
 
1348 art_zh 317
	push esi   ; save register size into ESI
318
	mov esi,eax
319
	and esi,3
1 ha 320
 
1348 art_zh 321
	push	eax
322
		;store current state of config space
323
	mov	dx,0xcf8
324
	in	al,dx
325
	mov	ah,al
326
	mov	dl,0xfa
327
	in	al,dx
328
	xchg	eax,[esp]
329
		; out 0xcfa,bus
330
	mov	al,ah
331
	out	dx,al
332
		; out 0xcf8,0x80
333
	mov	dl,0xf8
334
	mov	al,0x80
335
	out	dx,al
336
		; compute addr
337
	shr	bh,3 ; func is ignored in mechanism 2
338
	or	bh,0xc0
339
	mov	dx,bx
340
		; write register
341
	mov	eax,ecx
1 ha 342
 
1348 art_zh 343
	or	esi,esi
344
	jz	pci_write_byte2
345
	cmp	esi,1
346
	jz	pci_write_word2
347
	cmp	esi,2
348
	jz	pci_write_dword2
349
	jmp	pci_fin_write2
1 ha 350
 
351
pci_write_byte2:
1348 art_zh 352
	out	dx,al
353
	jmp pci_fin_write2
1 ha 354
pci_write_word2:
1348 art_zh 355
	out	dx,ax
356
	jmp pci_fin_write2
1 ha 357
pci_write_dword2:
1348 art_zh 358
	out	dx,eax
359
	jmp	pci_fin_write2
1 ha 360
pci_fin_write2:
1348 art_zh 361
		; restore configuration space
362
	pop	eax
363
	mov	dx,0xcfa
364
	out	dx,al
365
	mov	dl,0xf8
366
	mov	al,ah
367
	out	dx,al
1 ha 368
 
1348 art_zh 369
	xor	eax,eax
370
	pop	esi
371
	ret
1 ha 372
 
373
pci_write_reg_err:
1348 art_zh 374
	xor	eax,eax
375
	dec	eax
376
	ret
586 serge 377
 
1354 diamond 378
if defined mmio_pci_addr
1348 art_zh 379
;***************************************************************************
380
;   Function
381
;      pci_mmio_init ; NEW!
382
;
383
;   Description
384
;       IN:  bx = device's PCI bus address (bbbbbbbbdddddfff)
385
;       returns ax = user heap space available (bytes)
386
;   Error codes
387
;       eax = -1 : PCI user access blocked,
388
;       eax = -2 : device not registered for uMMIO service
389
;       eax = -3 : user heap initialization failure
390
;***************************************************************************
391
pci_mmio_init:
1354 diamond 392
    cmp     bx, mmio_pci_addr	; must be set in kernel/data32.inc
1348 art_zh 393
    jz	    @f
394
    mov     eax,-2
395
    ret
396
@@:
397
    call    init_heap	   ; (if not initialized yet)
398
    or	    eax,eax
399
    jz	    @f
400
    ret
401
@@:
402
    mov     eax,-3
403
    ret
404
 
405
 
406
;***************************************************************************
407
;   Function
408
;      pci_mmio_map ; NEW!
409
;
410
;   Description
411
;       maps a block of PCI memory to user-accessible linear address
412
;
413
;       WARNING! This VERY EXPERIMENTAL service is for one chosen PCI device only!
414
;       The target device address should be set in kernel var mmio_pci_addr
415
;
416
;       IN:  ah = BAR#;
417
;       IN: ebx = block size (bytes);
418
;       IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages);
419
;
420
;   Returns eax = MMIO block's linear address in the userspace (if no error)
421
;
422
;
423
;   Error codes
424
;       eax = -1 : user access to PCI blocked,
425
;       eax = -2 : an invalid BAR register referred
426
;       eax = -3 : no i/o space on that BAR
427
;       eax = -4 : a port i/o BAR register referred
428
;       eax = -5 : dynamic userspace allocation problem
429
;***************************************************************************
430
 
431
pci_mmio_map:
432
    and     edx,0x0ffff
433
    cmp     ah,6
1353 art_zh 434
    jc     .bar_0_5
435
    jz     .bar_rom
1348 art_zh 436
    mov     eax,-2
437
    ret
1353 art_zh 438
.bar_rom:
439
    mov    ah, 8	; bar6 = Expansion ROM base address
440
.bar_0_5:
1348 art_zh 441
    push    ecx
442
    add     ebx, 4095
443
    and     ebx,-4096
444
    push    ebx
1353 art_zh 445
    mov     bl, ah	; bl = BAR# (0..5), however bl=8 for BAR6
1348 art_zh 446
    shl     bl, 1
447
    shl     bl, 1
1353 art_zh 448
    add     bl, 0x10	; now bl = BAR offset in PCI config. space
1354 diamond 449
    mov     ax, mmio_pci_addr
1348 art_zh 450
    mov     bh, al	; bh = dddddfff
451
    mov     al, 2	; al : DW to read
452
    call    pci_read_reg
453
    or	    eax, eax
454
    jnz     @f
455
    mov     eax,-3	; empty I/O space
456
    jmp     mmio_ret_fail
457
@@:
458
    test    eax, 1
459
    jz	    @f
460
    mov     eax,-4	; damned ports (not MMIO space)
461
    jmp     mmio_ret_fail
462
@@:
463
    pop     ecx 	; ecx = block size, bytes (expanded to whole page)
464
    mov     ebx, ecx	; user_alloc destroys eax, ecx, edx, but saves ebx
465
    push    eax 	; store MMIO physical address + keep 2DWords in the stack
466
    stdcall user_alloc, ecx
467
    or	    eax, eax
468
    jnz     mmio_map_over
469
    mov     eax,-5	; problem with page allocation
470
 
471
mmio_ret_fail:
472
    pop     ecx
473
    pop     edx
474
    ret
475
 
476
mmio_map_over:
477
    mov     ecx, ebx	; ecx = size (bytes, expanded to whole page)
478
    shr     ecx, 12	; ecx = number of pages
479
    mov     ebx, eax	; ebx = linear address
480
    pop     eax 	; eax = MMIO start
481
    pop     edx 	; edx = MMIO shift (pages)
482
    shl     edx, 12	; edx = MMIO shift (bytes)
483
    add     eax, edx	; eax = uMMIO physical address
484
    or	    eax, PG_SHARED
485
    or	    eax, PG_UW
486
    or	    eax, PG_NOCACHE
487
    mov     edi, ebx
488
    call    commit_pages
489
    mov     eax, edi
490
    ret
491
 
492
;***************************************************************************
493
;   Function
494
;      pci_mmio_unmap_page ; NEW!
495
;
496
;   Description
497
;       unmaps the linear space previously tied to a PCI memory block
498
;
499
;       IN: ebx = linear address of space previously allocated by pci_mmio_map
500
;       returns eax = 1 if successfully unmapped
501
;
502
;   Error codes
503
;       eax = -1 if no user PCI access allowed,
504
;       eax =  0 if unmapping failed
505
;***************************************************************************
506
 
507
pci_mmio_unmap:
508
    stdcall user_free, ebx
509
    ret
510
 
1354 diamond 511
end if
1348 art_zh 512
 
586 serge 513
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
514
 
515
; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1)
516
pci_emu_dat:	times	30*10 db 0
517
 
518
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
519
align 4
520
sys_pcibios:
521
	xchg	ebx, eax
522
	xchg	ecx, eax
523
	xchg	edx, eax
524
	xchg	esi, eax
1348 art_zh 525
	xchg	edi, eax
594 diamond 526
	cmp	[pci_access_enabled], 1
1348 art_zh 527
	jne	.unsupported_func
528
	cmp	[pci_bios_entry], 0
594 diamond 529
	jz	.emulate_bios
586 serge 530
 
1348 art_zh 531
	push	ds
532
	mov	ax, pci_data_sel
533
	mov	ds, ax
534
	mov	eax, ebp
535
	mov	ah, 0B1h
536
	call	pword [cs:pci_bios_entry]
537
	pop	ds
586 serge 538
 
539
	jmp	.return
540
	;-=-=-=-=-=-=-=-=
541
.emulate_bios:
542
	cmp	ebp, 1			; PCI_FUNCTION_ID
543
	jnz	.not_PCI_BIOS_PRESENT
544
	mov	edx, 'PCI '
1348 art_zh 545
	mov	al, [OS_BASE+0x2F0000 + 0x9020]
546
	mov	bx, [OS_BASE+0x2F0000 + 0x9022]
547
	mov	cl, [OS_BASE+0x2F0000 + 0x9021]
548
	xor	ah, ah
594 diamond 549
	jmp	.return_abcd
586 serge 550
 
551
.not_PCI_BIOS_PRESENT:
552
	cmp	ebp, 2			; FIND_PCI_DEVICE
553
	jne	.not_FIND_PCI_DEVICE
594 diamond 554
	mov	ebx, pci_emu_dat
555
..nxt:	cmp	[ebx], dx
586 serge 556
	jne	..no
594 diamond 557
	cmp	[ebx + 2], cx
586 serge 558
	jne	..no
594 diamond 559
	dec	si
586 serge 560
	jns	..no
594 diamond 561
	mov	bx, [ebx + 4]
1348 art_zh 562
	xor	ah, ah
594 diamond 563
	jmp	.return_ab
564
..no:	cmp	word[ebx], 0
586 serge 565
	je	..dev_not_found
594 diamond 566
	add	ebx, 10
586 serge 567
	jmp	..nxt
568
..dev_not_found:
569
	mov	ah, 0x86		; DEVICE_NOT_FOUND
594 diamond 570
	jmp	.return_a
586 serge 571
 
572
.not_FIND_PCI_DEVICE:
573
	cmp	ebp, 3			; FIND_PCI_CLASS_CODE
574
	jne	.not_FIND_PCI_CLASS_CODE
575
	mov	esi, pci_emu_dat
594 diamond 576
	shl	ecx, 8
1348 art_zh 577
..nxt2: cmp	[esi], ecx
586 serge 578
	jne	..no2
579
	mov	bx, [esi]
1348 art_zh 580
	xor	ah, ah
594 diamond 581
	jmp	.return_ab
586 serge 582
..no2:	cmp	dword[esi], 0
594 diamond 583
	je	..dev_not_found
586 serge 584
	add	esi, 10
585
	jmp	..nxt2
586
 
587
.not_FIND_PCI_CLASS_CODE:
588
	cmp	ebp, 8			; READ_CONFIG_*
589
	jb	.not_READ_CONFIG
590
	cmp	ebp, 0x0A
591
	ja	.not_READ_CONFIG
1348 art_zh 592
	mov	eax, ebp
593
	mov	ah, bh
594
	mov	edx, edi
595
	mov	bh, bl
596
	mov	bl, dl
586 serge 597
	call	pci_read_reg
598
	mov	ecx, eax
599
	xor	ah, ah			; SUCCESSFUL
594 diamond 600
	jmp	.return_abc
586 serge 601
.not_READ_CONFIG:
602
	cmp	ebp, 0x0B		; WRITE_CONFIG_*
603
	jb	.not_WRITE_CONFIG
604
	cmp	ebp, 0x0D
605
	ja	.not_WRITE_CONFIG
1348 art_zh 606
	lea	eax, [ebp+1]
607
	mov	ah, bh
608
	mov	edx, edi
609
	mov	bh, bl
610
	mov	bl, dl
586 serge 611
	call	pci_write_reg
612
	xor	ah, ah			; SUCCESSFUL
594 diamond 613
	jmp	.return_abc
586 serge 614
.not_WRITE_CONFIG:
615
.unsupported_func:
616
	mov	ah, 0x81		; FUNC_NOT_SUPPORTED
617
.return:mov	dword[esp + 8 ], edi
618
	mov	dword[esp + 12], esi
594 diamond 619
.return_abcd:
586 serge 620
	mov	dword[esp + 28], edx
594 diamond 621
.return_abc:
586 serge 622
	mov	dword[esp + 32], ecx
594 diamond 623
.return_ab:
624
	mov	dword[esp + 24], ebx
625
.return_a:
586 serge 626
	mov	dword[esp + 36], eax
627
	ret