Subversion Repositories Kolibri OS

Rev

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