Subversion Repositories Kolibri OS

Rev

Rev 1508 | Rev 1587 | 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: 1560 $
1 ha 27
 
28
;***************************************************************************
29
;   Function
30
;      pci_api:
31
;
32
;   Description
33
;       entry point for system PCI calls
34
;***************************************************************************
1560 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
 
1560 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
	push	esi   ; save register size into ESI
132
	mov	esi,eax
133
	and	esi,3
1 ha 134
 
1348 art_zh 135
	call	pci_make_config_cmd
136
	mov	ebx,eax
137
		; get current state
138
	mov	dx,0xcf8
139
	in	eax, dx
140
	push	eax
141
		; set up addressing to config data
142
	mov	eax,ebx
143
	and	al,0xfc ; make address dword-aligned
144
	out	dx,eax
145
		; get requested DWORD of config data
146
	mov	dl,0xfc
147
	and	bl,3
148
	or	dl,bl	 ; add to port address first 2 bits of register address
1 ha 149
 
1348 art_zh 150
	or	esi,esi
151
	jz	pci_read_byte1
152
	cmp	esi,1
153
	jz	pci_read_word1
154
	cmp	esi,2
155
	jz	pci_read_dword1
156
	jmp	pci_fin_read1
1 ha 157
 
158
pci_read_byte1:
1348 art_zh 159
	in	al,dx
160
	jmp pci_fin_read1
1 ha 161
pci_read_word1:
1348 art_zh 162
	in	ax,dx
163
	jmp pci_fin_read1
1 ha 164
pci_read_dword1:
1348 art_zh 165
	in	eax,dx
166
	jmp	pci_fin_read1
1 ha 167
pci_fin_read1:
1348 art_zh 168
		; restore configuration control
169
	xchg	eax,[esp]
170
	mov	dx,0xcf8
171
	out	dx,eax
1 ha 172
 
1348 art_zh 173
	pop	eax
174
	pop	esi
175
	ret
1 ha 176
 
177
pci_read_reg_err:
1348 art_zh 178
	xor	eax,eax
179
	dec	eax
180
	ret
1 ha 181
 
182
 
183
;***************************************************************************
184
;   Function
185
;      pci_write_reg:
186
;
187
;   Description
188
;       write a register from ECX/CX/CL into the PCI config space
189
;       IN: ah=bus,device+func=bh,register address (dword aligned)=bl,
190
;           value to write in ecx
191
;           number of bytes to write (1,2,4) coded into AL, bits 0-1
586 serge 192
;           (0 - byte, 1 - word, 2 - dword)
1 ha 193
;***************************************************************************
194
 
195
align 4
196
 
197
pci_write_reg:
1348 art_zh 198
	push	esi   ; save register size into ESI
199
	mov	esi,eax
200
	and	esi,3
1 ha 201
 
1348 art_zh 202
	call	pci_make_config_cmd
203
	mov	ebx,eax
204
		; get current state into ecx
205
	mov	dx,0xcf8
206
	in	eax, dx
207
	push	eax
208
		; set up addressing to config data
209
	mov	eax,ebx
210
	and	al,0xfc ; make address dword-aligned
211
	out	dx,eax
212
		; write DWORD of config data
213
	mov	dl,0xfc
214
	and	bl,3
215
	or	dl,bl
216
	mov	eax,ecx
1 ha 217
 
1348 art_zh 218
	or	esi,esi
219
	jz	pci_write_byte1
220
	cmp	esi,1
221
	jz	pci_write_word1
222
	cmp	esi,2
223
	jz	pci_write_dword1
224
	jmp	pci_fin_write1
1 ha 225
 
226
pci_write_byte1:
1348 art_zh 227
	out	dx,al
228
	jmp pci_fin_write1
1 ha 229
pci_write_word1:
1348 art_zh 230
	out	dx,ax
231
	jmp pci_fin_write1
1 ha 232
pci_write_dword1:
1348 art_zh 233
	out	dx,eax
234
	jmp	pci_fin_write1
1 ha 235
pci_fin_write1:
1348 art_zh 236
		; restore configuration control
237
	pop	eax
238
	mov	dl,0xf8
239
	out	dx,eax
1 ha 240
 
1348 art_zh 241
	xor	eax,eax
242
	pop	esi
243
	ret
1 ha 244
 
245
pci_write_reg_err:
1348 art_zh 246
	xor	eax,eax
247
	dec	eax
248
	ret
586 serge 249
 
1348 art_zh 250
;***************************************************************************
251
;   Function
1560 art_zh 252
;      pci_mmio_init
1348 art_zh 253
;
254
;   Description
255
;       IN:  bx = device's PCI bus address (bbbbbbbbdddddfff)
1560 art_zh 256
;   Returns  eax = phys. address of user-accessible DMA block
1348 art_zh 257
;   Error codes
258
;       eax = -1 : PCI user access blocked,
259
;       eax = -3 : user heap initialization failure
260
;***************************************************************************
261
pci_mmio_init:
1508 art_zh 262
    mov     [mmio_pci_addr],bx
263
 
1348 art_zh 264
    call    init_heap	   ; (if not initialized yet)
265
    or	    eax,eax
266
    jz	    @f
1507 art_zh 267
    mov     eax, [UserDMAaddr]
1348 art_zh 268
    ret
269
@@:
270
    mov     eax,-3
271
    ret
272
 
273
 
274
;***************************************************************************
275
;   Function
1560 art_zh 276
;      pci_mmio_map
1348 art_zh 277
;
278
;   Description
279
;       maps a block of PCI memory to user-accessible linear address
280
;
281
;
1507 art_zh 282
;       IN:  ah = BAR#; or
1560 art_zh 283
;       IN:  ah = 0xDA for DMA-mapping requests;
1348 art_zh 284
;       IN: ebx = block size (bytes);
285
;       IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages);
286
;
287
;   Returns eax = MMIO block's linear address in the userspace (if no error)
288
;
289
;
290
;   Error codes
291
;       eax = -1 : user access to PCI blocked,
292
;       eax = -2 : an invalid BAR register referred
293
;       eax = -3 : no i/o space on that BAR
294
;       eax = -4 : a port i/o BAR register referred
295
;       eax = -5 : dynamic userspace allocation problem
296
;***************************************************************************
297
 
298
pci_mmio_map:
299
    and     edx,0x0ffff
1507 art_zh 300
    cmp     ah, 0xDA
1560 art_zh 301
    jz	   .dma_map
1348 art_zh 302
    cmp     ah,6
1560 art_zh 303
    jc	   .bar_0_5
304
    jz	   .bar_rom
1348 art_zh 305
    mov     eax,-2
306
    ret
1507 art_zh 307
 
308
.dma_map:
309
    push    ecx
310
    mov     ecx,ebx
311
    mov     eax,[UserDMAaddr]
312
    jmp    .allocate_block
1560 art_zh 313
 
1353 art_zh 314
.bar_rom:
315
    mov    ah, 8	; bar6 = Expansion ROM base address
316
.bar_0_5:
1348 art_zh 317
    push    ecx
318
    add     ebx, 4095
319
    and     ebx,-4096
320
    push    ebx
1353 art_zh 321
    mov     bl, ah	; bl = BAR# (0..5), however bl=8 for BAR6
1348 art_zh 322
    shl     bl, 1
323
    shl     bl, 1
1353 art_zh 324
    add     bl, 0x10	; now bl = BAR offset in PCI config. space
1507 art_zh 325
    mov     ax, [mmio_pci_addr]
1348 art_zh 326
    mov     bh, al	; bh = dddddfff
327
    mov     al, 2	; al : DW to read
328
    call    pci_read_reg
329
    or	    eax, eax
330
    jnz     @f
331
    mov     eax,-3	; empty I/O space
332
    jmp     mmio_ret_fail
333
@@:
334
    test    eax, 1
335
    jz	    @f
336
    mov     eax,-4	; damned ports (not MMIO space)
337
    jmp     mmio_ret_fail
338
@@:
339
    pop     ecx 	; ecx = block size, bytes (expanded to whole page)
340
    mov     ebx, ecx	; user_alloc destroys eax, ecx, edx, but saves ebx
1462 art_zh 341
    and     eax, 0xFFFFFFF0
1507 art_zh 342
 
343
.allocate_block:
1560 art_zh 344
    push    eax 	; store MMIO physical address + keep the stack 2x4b deep
1348 art_zh 345
    stdcall user_alloc, ecx
346
    or	    eax, eax
347
    jnz     mmio_map_over
348
    mov     eax,-5	; problem with page allocation
349
 
350
mmio_ret_fail:
351
    pop     ecx
352
    pop     edx
353
    ret
354
 
355
mmio_map_over:
356
    mov     ecx, ebx	; ecx = size (bytes, expanded to whole page)
357
    shr     ecx, 12	; ecx = number of pages
358
    mov     ebx, eax	; ebx = linear address
359
    pop     eax 	; eax = MMIO start
360
    pop     edx 	; edx = MMIO shift (pages)
361
    shl     edx, 12	; edx = MMIO shift (bytes)
362
    add     eax, edx	; eax = uMMIO physical address
1507 art_zh 363
    or	    eax, (PG_SHARED+PG_UW+PG_NOCACHE)
1348 art_zh 364
    mov     edi, ebx
365
    call    commit_pages
366
    mov     eax, edi
367
    ret
368
 
369
;***************************************************************************
370
;   Function
1560 art_zh 371
;      pci_mmio_unmap_page
1348 art_zh 372
;
373
;   Description
374
;       unmaps the linear space previously tied to a PCI memory block
375
;
376
;       IN: ebx = linear address of space previously allocated by pci_mmio_map
377
;       returns eax = 1 if successfully unmapped
378
;
379
;   Error codes
380
;       eax = -1 if no user PCI access allowed,
381
;       eax =  0 if unmapping failed
382
;***************************************************************************
383
 
384
pci_mmio_unmap:
385
    stdcall user_free, ebx
386
    ret
387
 
586 serge 388
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1375 Lrz 389
uglobal
390
align 4
586 serge 391
; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1)
392
pci_emu_dat:	times	30*10 db 0
1375 Lrz 393
endg
586 serge 394
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
395
align 4
396
sys_pcibios:
594 diamond 397
	cmp	[pci_access_enabled], 1
1348 art_zh 398
	jne	.unsupported_func
399
	cmp	[pci_bios_entry], 0
594 diamond 400
	jz	.emulate_bios
586 serge 401
 
1348 art_zh 402
	push	ds
403
	mov	ax, pci_data_sel
404
	mov	ds, ax
405
	mov	eax, ebp
406
	mov	ah, 0B1h
407
	call	pword [cs:pci_bios_entry]
408
	pop	ds
586 serge 409
 
410
	jmp	.return
411
	;-=-=-=-=-=-=-=-=
412
.emulate_bios:
413
	cmp	ebp, 1			; PCI_FUNCTION_ID
414
	jnz	.not_PCI_BIOS_PRESENT
415
	mov	edx, 'PCI '
1348 art_zh 416
	mov	al, [OS_BASE+0x2F0000 + 0x9020]
417
	mov	bx, [OS_BASE+0x2F0000 + 0x9022]
418
	mov	cl, [OS_BASE+0x2F0000 + 0x9021]
419
	xor	ah, ah
594 diamond 420
	jmp	.return_abcd
586 serge 421
 
422
.not_PCI_BIOS_PRESENT:
423
	cmp	ebp, 2			; FIND_PCI_DEVICE
424
	jne	.not_FIND_PCI_DEVICE
594 diamond 425
	mov	ebx, pci_emu_dat
426
..nxt:	cmp	[ebx], dx
586 serge 427
	jne	..no
594 diamond 428
	cmp	[ebx + 2], cx
586 serge 429
	jne	..no
594 diamond 430
	dec	si
586 serge 431
	jns	..no
594 diamond 432
	mov	bx, [ebx + 4]
1348 art_zh 433
	xor	ah, ah
594 diamond 434
	jmp	.return_ab
435
..no:	cmp	word[ebx], 0
586 serge 436
	je	..dev_not_found
594 diamond 437
	add	ebx, 10
586 serge 438
	jmp	..nxt
439
..dev_not_found:
440
	mov	ah, 0x86		; DEVICE_NOT_FOUND
594 diamond 441
	jmp	.return_a
586 serge 442
 
443
.not_FIND_PCI_DEVICE:
444
	cmp	ebp, 3			; FIND_PCI_CLASS_CODE
445
	jne	.not_FIND_PCI_CLASS_CODE
446
	mov	esi, pci_emu_dat
594 diamond 447
	shl	ecx, 8
1348 art_zh 448
..nxt2: cmp	[esi], ecx
586 serge 449
	jne	..no2
450
	mov	bx, [esi]
1348 art_zh 451
	xor	ah, ah
594 diamond 452
	jmp	.return_ab
586 serge 453
..no2:	cmp	dword[esi], 0
594 diamond 454
	je	..dev_not_found
586 serge 455
	add	esi, 10
456
	jmp	..nxt2
457
 
458
.not_FIND_PCI_CLASS_CODE:
459
	cmp	ebp, 8			; READ_CONFIG_*
460
	jb	.not_READ_CONFIG
461
	cmp	ebp, 0x0A
462
	ja	.not_READ_CONFIG
1348 art_zh 463
	mov	eax, ebp
464
	mov	ah, bh
465
	mov	edx, edi
466
	mov	bh, bl
467
	mov	bl, dl
586 serge 468
	call	pci_read_reg
469
	mov	ecx, eax
470
	xor	ah, ah			; SUCCESSFUL
594 diamond 471
	jmp	.return_abc
586 serge 472
.not_READ_CONFIG:
473
	cmp	ebp, 0x0B		; WRITE_CONFIG_*
474
	jb	.not_WRITE_CONFIG
475
	cmp	ebp, 0x0D
476
	ja	.not_WRITE_CONFIG
1348 art_zh 477
	lea	eax, [ebp+1]
478
	mov	ah, bh
479
	mov	edx, edi
480
	mov	bh, bl
481
	mov	bl, dl
586 serge 482
	call	pci_write_reg
483
	xor	ah, ah			; SUCCESSFUL
594 diamond 484
	jmp	.return_abc
586 serge 485
.not_WRITE_CONFIG:
486
.unsupported_func:
487
	mov	ah, 0x81		; FUNC_NOT_SUPPORTED
1375 Lrz 488
.return:mov	dword[esp + 4 ], edi
489
	mov	dword[esp + 8], esi
594 diamond 490
.return_abcd:
1375 Lrz 491
	mov	dword[esp + 24], edx
594 diamond 492
.return_abc:
1375 Lrz 493
	mov	dword[esp + 28], ecx
594 diamond 494
.return_ab:
1375 Lrz 495
	mov	dword[esp + 20], ebx
594 diamond 496
.return_a:
1375 Lrz 497
	mov	dword[esp + 32], eax
586 serge 498
	ret