Subversion Repositories Kolibri OS

Rev

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