Subversion Repositories Kolibri OS

Rev

Rev 750 | Rev 1353 | 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: 1348 $
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
434
    jc	    @f
435
    mov     eax,-2
436
    ret
437
@@:
438
    push    ecx
439
    add     ebx, 4095
440
    and     ebx,-4096
441
    push    ebx
442
    mov     bl, ah	; bl = BAR# (0..5)
443
    shl     bl, 1
444
    shl     bl, 1
445
    add     bl, 0x10	; bl = BARs offset in PCI config. space
446
    mov     ax,word [mmio_pci_addr]
447
    mov     bh, al	; bh = dddddfff
448
    mov     al, 2	; al : DW to read
449
    call    pci_read_reg
450
    or	    eax, eax
451
    jnz     @f
452
    mov     eax,-3	; empty I/O space
453
    jmp     mmio_ret_fail
454
@@:
455
    test    eax, 1
456
    jz	    @f
457
    mov     eax,-4	; damned ports (not MMIO space)
458
    jmp     mmio_ret_fail
459
@@:
460
    pop     ecx 	; ecx = block size, bytes (expanded to whole page)
461
    mov     ebx, ecx	; user_alloc destroys eax, ecx, edx, but saves ebx
462
    push    eax 	; store MMIO physical address + keep 2DWords in the stack
463
    stdcall user_alloc, ecx
464
    or	    eax, eax
465
    jnz     mmio_map_over
466
    mov     eax,-5	; problem with page allocation
467
 
468
mmio_ret_fail:
469
    pop     ecx
470
    pop     edx
471
    ret
472
 
473
mmio_map_over:
474
    mov     ecx, ebx	; ecx = size (bytes, expanded to whole page)
475
    shr     ecx, 12	; ecx = number of pages
476
    mov     ebx, eax	; ebx = linear address
477
    pop     eax 	; eax = MMIO start
478
    pop     edx 	; edx = MMIO shift (pages)
479
    shl     edx, 12	; edx = MMIO shift (bytes)
480
    add     eax, edx	; eax = uMMIO physical address
481
    or	    eax, PG_SHARED
482
    or	    eax, PG_UW
483
    or	    eax, PG_NOCACHE
484
    mov     edi, ebx
485
    call    commit_pages
486
    mov     eax, edi
487
    ret
488
 
489
;***************************************************************************
490
;   Function
491
;      pci_mmio_unmap_page ; NEW!
492
;
493
;   Description
494
;       unmaps the linear space previously tied to a PCI memory block
495
;
496
;       IN: ebx = linear address of space previously allocated by pci_mmio_map
497
;       returns eax = 1 if successfully unmapped
498
;
499
;   Error codes
500
;       eax = -1 if no user PCI access allowed,
501
;       eax =  0 if unmapping failed
502
;***************************************************************************
503
 
504
align 4
505
pci_mmio_unmap:
506
    stdcall user_free, ebx
507
    ret
508
 
509
 
586 serge 510
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
511
 
512
; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1)
513
pci_emu_dat:	times	30*10 db 0
514
 
515
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
516
align 4
517
sys_pcibios:
518
	xchg	ebx, eax
519
	xchg	ecx, eax
520
	xchg	edx, eax
521
	xchg	esi, eax
1348 art_zh 522
	xchg	edi, eax
594 diamond 523
	cmp	[pci_access_enabled], 1
1348 art_zh 524
	jne	.unsupported_func
525
	cmp	[pci_bios_entry], 0
594 diamond 526
	jz	.emulate_bios
586 serge 527
 
1348 art_zh 528
	push	ds
529
	mov	ax, pci_data_sel
530
	mov	ds, ax
531
	mov	eax, ebp
532
	mov	ah, 0B1h
533
	call	pword [cs:pci_bios_entry]
534
	pop	ds
586 serge 535
 
536
	jmp	.return
537
	;-=-=-=-=-=-=-=-=
538
.emulate_bios:
539
	cmp	ebp, 1			; PCI_FUNCTION_ID
540
	jnz	.not_PCI_BIOS_PRESENT
541
	mov	edx, 'PCI '
1348 art_zh 542
	mov	al, [OS_BASE+0x2F0000 + 0x9020]
543
	mov	bx, [OS_BASE+0x2F0000 + 0x9022]
544
	mov	cl, [OS_BASE+0x2F0000 + 0x9021]
545
	xor	ah, ah
594 diamond 546
	jmp	.return_abcd
586 serge 547
 
548
.not_PCI_BIOS_PRESENT:
549
	cmp	ebp, 2			; FIND_PCI_DEVICE
550
	jne	.not_FIND_PCI_DEVICE
594 diamond 551
	mov	ebx, pci_emu_dat
552
..nxt:	cmp	[ebx], dx
586 serge 553
	jne	..no
594 diamond 554
	cmp	[ebx + 2], cx
586 serge 555
	jne	..no
594 diamond 556
	dec	si
586 serge 557
	jns	..no
594 diamond 558
	mov	bx, [ebx + 4]
1348 art_zh 559
	xor	ah, ah
594 diamond 560
	jmp	.return_ab
561
..no:	cmp	word[ebx], 0
586 serge 562
	je	..dev_not_found
594 diamond 563
	add	ebx, 10
586 serge 564
	jmp	..nxt
565
..dev_not_found:
566
	mov	ah, 0x86		; DEVICE_NOT_FOUND
594 diamond 567
	jmp	.return_a
586 serge 568
 
569
.not_FIND_PCI_DEVICE:
570
	cmp	ebp, 3			; FIND_PCI_CLASS_CODE
571
	jne	.not_FIND_PCI_CLASS_CODE
572
	mov	esi, pci_emu_dat
594 diamond 573
	shl	ecx, 8
1348 art_zh 574
..nxt2: cmp	[esi], ecx
586 serge 575
	jne	..no2
576
	mov	bx, [esi]
1348 art_zh 577
	xor	ah, ah
594 diamond 578
	jmp	.return_ab
586 serge 579
..no2:	cmp	dword[esi], 0
594 diamond 580
	je	..dev_not_found
586 serge 581
	add	esi, 10
582
	jmp	..nxt2
583
 
584
.not_FIND_PCI_CLASS_CODE:
585
	cmp	ebp, 8			; READ_CONFIG_*
586
	jb	.not_READ_CONFIG
587
	cmp	ebp, 0x0A
588
	ja	.not_READ_CONFIG
1348 art_zh 589
	mov	eax, ebp
590
	mov	ah, bh
591
	mov	edx, edi
592
	mov	bh, bl
593
	mov	bl, dl
586 serge 594
	call	pci_read_reg
595
	mov	ecx, eax
596
	xor	ah, ah			; SUCCESSFUL
594 diamond 597
	jmp	.return_abc
586 serge 598
.not_READ_CONFIG:
599
	cmp	ebp, 0x0B		; WRITE_CONFIG_*
600
	jb	.not_WRITE_CONFIG
601
	cmp	ebp, 0x0D
602
	ja	.not_WRITE_CONFIG
1348 art_zh 603
	lea	eax, [ebp+1]
604
	mov	ah, bh
605
	mov	edx, edi
606
	mov	bh, bl
607
	mov	bl, dl
586 serge 608
	call	pci_write_reg
609
	xor	ah, ah			; SUCCESSFUL
594 diamond 610
	jmp	.return_abc
586 serge 611
.not_WRITE_CONFIG:
612
.unsupported_func:
613
	mov	ah, 0x81		; FUNC_NOT_SUPPORTED
614
.return:mov	dword[esp + 8 ], edi
615
	mov	dword[esp + 12], esi
594 diamond 616
.return_abcd:
586 serge 617
	mov	dword[esp + 28], edx
594 diamond 618
.return_abc:
586 serge 619
	mov	dword[esp + 32], ecx
594 diamond 620
.return_ab:
621
	mov	dword[esp + 24], ebx
622
.return_a:
586 serge 623
	mov	dword[esp + 36], eax
624
	ret