Subversion Repositories Kolibri OS

Rev

Rev 1687 | 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: 1941 $
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:
1941 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
1687 art_zh 145
;
1941 art_zh 146
;       and     al, 2
147
;       jz      @f
148
;       mov     eax, dword[edx]
149
;       pop     edx
150
;       ret
1687 art_zh 151
;@@:
1941 art_zh 152
;       and     al, 1
153
;       jz      @f
154
;       mov     ax, word[edx]
155
;       pop     edx
156
;       ret
1687 art_zh 157
;@@:
1941 art_zh 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:
1941 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
1687 art_zh 230
;
1941 art_zh 231
;       test    al, 2
232
;       jz      @f
233
;       mov     dword[edx], ecx
234
;       ret
1687 art_zh 235
;@@:
1941 art_zh 236
;       test    al, 1
237
;       jz      @f
238
;       mov     word[edx], cx
239
;       pop     edx
240
;       ret
1687 art_zh 241
;@@:
1941 art_zh 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
 
1941 art_zh 431
 
432
;------------------------------------------------
433
align 4
434
sys_map1:
435
;       copies a block from kernel to user space
436
;  in: esi = address in kernel space
437
;      edi = eddress in user space
438
;      ebx = count (dwords)
439
; out: nothing
440
;------------------------------------------------
441
	mov     ecx, ebx
442
        pushfd
443
	cld
444
	rep	movsd
445
	popfd
446
	ret
447
 
448
 
586 serge 449
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1375 Lrz 450
uglobal
451
align 4
586 serge 452
; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1)
453
pci_emu_dat:	times	30*10 db 0
1375 Lrz 454
endg
586 serge 455
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
456
align 4
457
sys_pcibios:
594 diamond 458
	cmp	[pci_access_enabled], 1
1348 art_zh 459
	jne	.unsupported_func
460
	cmp	[pci_bios_entry], 0
594 diamond 461
	jz	.emulate_bios
586 serge 462
 
1348 art_zh 463
	push	ds
464
	mov	ax, pci_data_sel
465
	mov	ds, ax
466
	mov	eax, ebp
467
	mov	ah, 0B1h
468
	call	pword [cs:pci_bios_entry]
469
	pop	ds
586 serge 470
 
471
	jmp	.return
472
	;-=-=-=-=-=-=-=-=
473
.emulate_bios:
474
	cmp	ebp, 1			; PCI_FUNCTION_ID
475
	jnz	.not_PCI_BIOS_PRESENT
476
	mov	edx, 'PCI '
1348 art_zh 477
	mov	al, [OS_BASE+0x2F0000 + 0x9020]
478
	mov	bx, [OS_BASE+0x2F0000 + 0x9022]
479
	mov	cl, [OS_BASE+0x2F0000 + 0x9021]
480
	xor	ah, ah
594 diamond 481
	jmp	.return_abcd
586 serge 482
 
483
.not_PCI_BIOS_PRESENT:
484
	cmp	ebp, 2			; FIND_PCI_DEVICE
485
	jne	.not_FIND_PCI_DEVICE
594 diamond 486
	mov	ebx, pci_emu_dat
487
..nxt:	cmp	[ebx], dx
586 serge 488
	jne	..no
594 diamond 489
	cmp	[ebx + 2], cx
586 serge 490
	jne	..no
594 diamond 491
	dec	si
586 serge 492
	jns	..no
594 diamond 493
	mov	bx, [ebx + 4]
1348 art_zh 494
	xor	ah, ah
594 diamond 495
	jmp	.return_ab
496
..no:	cmp	word[ebx], 0
586 serge 497
	je	..dev_not_found
594 diamond 498
	add	ebx, 10
586 serge 499
	jmp	..nxt
500
..dev_not_found:
501
	mov	ah, 0x86		; DEVICE_NOT_FOUND
594 diamond 502
	jmp	.return_a
586 serge 503
 
504
.not_FIND_PCI_DEVICE:
505
	cmp	ebp, 3			; FIND_PCI_CLASS_CODE
506
	jne	.not_FIND_PCI_CLASS_CODE
507
	mov	esi, pci_emu_dat
594 diamond 508
	shl	ecx, 8
1348 art_zh 509
..nxt2: cmp	[esi], ecx
586 serge 510
	jne	..no2
511
	mov	bx, [esi]
1348 art_zh 512
	xor	ah, ah
594 diamond 513
	jmp	.return_ab
586 serge 514
..no2:	cmp	dword[esi], 0
594 diamond 515
	je	..dev_not_found
586 serge 516
	add	esi, 10
517
	jmp	..nxt2
518
 
519
.not_FIND_PCI_CLASS_CODE:
520
	cmp	ebp, 8			; READ_CONFIG_*
521
	jb	.not_READ_CONFIG
522
	cmp	ebp, 0x0A
523
	ja	.not_READ_CONFIG
1348 art_zh 524
	mov	eax, ebp
525
	mov	ah, bh
526
	mov	edx, edi
527
	mov	bh, bl
528
	mov	bl, dl
586 serge 529
	call	pci_read_reg
530
	mov	ecx, eax
531
	xor	ah, ah			; SUCCESSFUL
594 diamond 532
	jmp	.return_abc
586 serge 533
.not_READ_CONFIG:
534
	cmp	ebp, 0x0B		; WRITE_CONFIG_*
535
	jb	.not_WRITE_CONFIG
536
	cmp	ebp, 0x0D
537
	ja	.not_WRITE_CONFIG
1348 art_zh 538
	lea	eax, [ebp+1]
539
	mov	ah, bh
540
	mov	edx, edi
541
	mov	bh, bl
542
	mov	bl, dl
586 serge 543
	call	pci_write_reg
544
	xor	ah, ah			; SUCCESSFUL
594 diamond 545
	jmp	.return_abc
586 serge 546
.not_WRITE_CONFIG:
547
.unsupported_func:
548
	mov	ah, 0x81		; FUNC_NOT_SUPPORTED
1375 Lrz 549
.return:mov	dword[esp + 4 ], edi
550
	mov	dword[esp + 8], esi
594 diamond 551
.return_abcd:
1375 Lrz 552
	mov	dword[esp + 24], edx
594 diamond 553
.return_abc:
1375 Lrz 554
	mov	dword[esp + 28], ecx
594 diamond 555
.return_ab:
1375 Lrz 556
	mov	dword[esp + 20], ebx
594 diamond 557
.return_a:
1375 Lrz 558
	mov	dword[esp + 32], eax
586 serge 559
	ret