Subversion Repositories Kolibri OS

Rev

Rev 7122 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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