Subversion Repositories Kolibri OS

Rev

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