Subversion Repositories Kolibri OS

Rev

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