Subversion Repositories Kolibri OS

Rev

Rev 6717 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2017. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;; i8255x (Intel eepro 100) driver for KolibriOS                   ;;
  7. ;;                                                                 ;;
  8. ;;    Written by hidnplayr@kolibrios.org                           ;;
  9. ;;                                                                 ;;
  10. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  11. ;;             Version 2, June 1991                                ;;
  12. ;;                                                                 ;;
  13. ;; Some parts of this driver are based on the code of eepro100.c   ;;
  14. ;;  from linux.                                                    ;;
  15. ;;                                                                 ;;
  16. ;; Intel's programming manual for i8255x:                          ;;
  17. ;; http://www.intel.com/design/network/manuals/8255x_opensdm.htm   ;;
  18. ;;                                                                 ;;
  19. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  20.  
  21. ;TODO: use more RX buffers
  22.  
  23. format PE DLL native
  24. entry START
  25.  
  26.         CURRENT_API             = 0x0200
  27.         COMPATIBLE_API          = 0x0100
  28.         API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
  29.  
  30.         MAX_DEVICES             = 16
  31.  
  32.         TX_RING_SIZE            = 16
  33.  
  34.         DEBUG                   = 1
  35.         __DEBUG__               = 1
  36.         __DEBUG_LEVEL__         = 2             ; 1 = verbose, 2 = errors only
  37.  
  38. section '.flat' readable writable executable
  39.  
  40. include '../proc32.inc'
  41. include '../struct.inc'
  42. include '../macros.inc'
  43. include '../fdo.inc'
  44. include '../netdrv.inc'
  45.  
  46. ; I/O registers
  47. REG_SCB_STATUS          = 0
  48. REG_SCB_CMD             = 2
  49. REG_SCB_PTR             = 4
  50. REG_PORT                = 8
  51. REG_EEPROM              = 14
  52. REG_MDI_CTRL            = 16
  53.  
  54. ; Port commands
  55. PORT_SOFT_RESET         = 0x0
  56. PORT_SELF_TEST          = 0x1
  57. PORT_SELECTIVE_RESET    = 0x2
  58. PORT_DUMP               = 0x3
  59. PORT_DUMP_WAKEUP        = 0x7
  60. PORT_PTR_MASK           = 0xfffffff0
  61.  
  62. ; Serial EEPROM
  63. EE_SK                   = 1 shl 0       ; serial clock
  64. EE_CS                   = 1 shl 1       ; chip select
  65. EE_DI                   = 1 shl 2       ; data in
  66. EE_DO                   = 1 shl 3       ; data out
  67. EE_MASK                 = EE_SK + EE_CS + EE_DI + EE_DO
  68. ; opcodes, first bit is start bit and must be 1
  69. EE_READ                 = 110b
  70. EE_WRITE                = 101b
  71. EE_ERASE                = 111b
  72.  
  73. ; The SCB accepts the following controls for the Tx and Rx units:
  74. CU_START                = 0x0010
  75. CU_RESUME               = 0x0020
  76. CU_STATSADDR            = 0x0040
  77. CU_SHOWSTATS            = 0x0050        ; Dump statistics counters.
  78. CU_CMD_BASE             = 0x0060        ; Base address to add CU commands.
  79. CU_DUMPSTATS            = 0x0070        ; Dump then reset stats counters.
  80.  
  81. RX_START                = 0x0001
  82. RX_RESUME               = 0x0002
  83. RX_ABORT                = 0x0004
  84. RX_ADDR_LOAD            = 0x0006
  85. RX_RESUMENR             = 0x0007
  86. INT_MASK                = 0x0100
  87. DRVR_INT                = 0x0200        ; Driver generated interrupt
  88.  
  89. PHY_100a                = 0x000003E0
  90. PHY_100c                = 0x035002A8
  91. PHY_82555_tx            = 0x015002A8
  92. PHY_nsc_tx              = 0x5C002000
  93. PHY_82562_et            = 0x033002A8
  94. PHY_82562_em            = 0x032002A8
  95. PHY_82562_ek            = 0x031002A8
  96. PHY_82562_eh            = 0x017002A8
  97. PHY_82552_v             = 0xd061004d
  98. PHY_unknown             = 0xFFFFFFFF
  99.  
  100. MAC_82557_D100_A        = 0
  101. MAC_82557_D100_B        = 1
  102. MAC_82557_D100_C        = 2
  103. MAC_82558_D101_A4       = 4
  104. MAC_82558_D101_B0       = 5
  105. MAC_82559_D101M         = 8
  106. MAC_82559_D101S         = 9
  107. MAC_82550_D102          = 12
  108. MAC_82550_D102_C        = 13
  109. MAC_82551_E             = 14
  110. MAC_82551_F             = 15
  111. MAC_82551_10            = 16
  112. MAC_unknown             = 0xFF
  113.  
  114. SCB_STATUS_RUS          = 111100b       ; RU Status
  115. RU_STATUS_IDLE          = 0000b shl 2
  116. RU_STATUS_SUSPENDED     = 0001b shl 2
  117. RU_STATUS_NO_RESOURCES  = 0010b shl 2
  118. RU_STATUS_READY         = 0100b shl 2
  119. SCB_STATUS_FCP          = 1 shl 8       ; Flow Control Pause
  120. SCB_STATUS_SWI          = 1 shl 10      ; Software Interrupt
  121. SCB_STATUS_MDI          = 1 shl 11      ; MDI read/write complete
  122. SCB_STATUS_RNR          = 1 shl 12      ; Receiver Not Ready
  123. SCB_STATUS_CNA          = 1 shl 13      ; Command unit Not Active
  124. SCB_STATUS_FR           = 1 shl 14      ; Frame received
  125. SCB_STATUS_CX_TNO       = 1 shl 15      ; Command finished / Transmit Not Okay
  126.  
  127. struct  rxfd
  128.  
  129.         status          dw ?
  130.         command         dw ?
  131.         link            dd ?
  132.         rx_buf_addr     dd ?
  133.         count           dw ?
  134.         size            dw ?
  135.         packet          rb 1500
  136.  
  137. ends
  138.  
  139. RXFD_STATUS_RC          = 1 shl 0       ; Receive collision
  140. RXFD_STATUS_IA          = 1 shl 1       ; IA mismatch
  141. RXFD_STATUS_NA          = 1 shl 2       ; No address match
  142. RXFD_STATUS_RE          = 1 shl 4       ; Receive Error
  143. RXFD_STATUS_TL          = 1 shl 5       ; Type/length
  144. RXFD_STATUS_FS          = 1 shl 7       ; Frame too short
  145. RXFD_STATUS_DMA_FAIL    = 1 shl 8       ; DMA overrun failure
  146. RXFD_STATUS_NR          = 1 shl 9       ; Out of buffer space; no resources
  147. RXFD_STATUS_MISA        = 1 shl 10      ; Alignment error
  148. RXFD_STATUS_CRC_ERR     = 1 shl 11      ; CRC error in aligned frame
  149. RXFD_STATUS_OK          = 1 shl 13      ; Frame received and stored
  150. RXFD_STATUS_C           = 1 shl 15      ; Completion of frame reception
  151.  
  152. RXFD_CMD_SF             = 1 shl 3
  153. RXFD_CMD_H              = 1 shl 4       ; Header RFD
  154. RXFD_CMD_SUSPEND        = 1 shl 14      ; Suspends RU after receiving the frame
  155. RXFD_CMD_EL             = 1 shl 15      ; Last RFD in RFA
  156.  
  157. struct  txfd
  158.  
  159.         status          dw ?
  160.         command         dw ?
  161.         link            dd ?
  162.         desc_addr       dd ?
  163.         count           dd ?
  164.  
  165.         buf_addr        dd ?
  166.         buf_size        dd ?
  167.         virt_addr       dd ?
  168.                         dd ?            ; alignment
  169.  
  170. ends
  171.  
  172. TXFD_CMD_IA             = 1 shl 0
  173. TXFD_CMD_CFG            = 1 shl 1
  174. TXFD_CMD_TX             = 1 shl 2
  175. TXFD_CMD_TX_FLEX        = 1 shl 3
  176. TXFD_CMD_SUSPEND        = 1 shl 14
  177.  
  178. struc   confcmd {
  179.  
  180.         .status         dw ?
  181.         .command        dw ?
  182.         .link           dd ?
  183.         .data           rb 64
  184.  
  185. }
  186.  
  187. struc   lstats {
  188.  
  189.         .tx_good_frames         dd ?
  190.         .tx_coll16_errs         dd ?
  191.         .tx_late_colls          dd ?
  192.         .tx_underruns           dd ?
  193.         .tx_lost_carrier        dd ?
  194.         .tx_deferred            dd ?
  195.         .tx_one_colls           dd ?
  196.         .tx_multi_colls         dd ?
  197.         .tx_total_colls         dd ?
  198.  
  199.         .rx_good_frames         dd ?
  200.         .rx_crc_errs            dd ?
  201.         .rx_align_errs          dd ?
  202.         .rx_resource_errs       dd ?
  203.         .rx_overrun_errs        dd ?
  204.         .rx_colls_errs          dd ?
  205.         .rx_runt_errs           dd ?
  206.  
  207. }
  208.  
  209. struct  device          ETH_DEVICE
  210.  
  211.         io_addr         dd ?
  212.         pci_bus         dd ?
  213.         pci_dev         dd ?
  214.         rx_desc         dd ?
  215.         cur_tx          dd ?
  216.         last_tx         dd ?
  217.         ee_bus_width    db ?
  218.         irq_line        db ?
  219.  
  220.         rb 0x100 - ($ and 0xff) ; align 256
  221.         tx_ring         rb TX_RING_SIZE*sizeof.txfd
  222.  
  223.         rb 0x100 - ($ and 0xff) ; align 256
  224.         confcmd         confcmd
  225.  
  226.         rb 0x100 - ($ and 0xff) ; align 256
  227.         lstats          lstats
  228.  
  229. ends
  230.  
  231. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  232. ;;                        ;;
  233. ;; proc START             ;;
  234. ;;                        ;;
  235. ;; (standard driver proc) ;;
  236. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  237.  
  238. proc START c, state:dword
  239.  
  240.         cmp [state], 1
  241.         jne .exit
  242.  
  243.   .entry:
  244.  
  245.         DEBUGF 1,"Loading driver\n"
  246.         invoke  RegService, my_service, service_proc
  247.         ret
  248.  
  249.   .fail:
  250.   .exit:
  251.         xor eax, eax
  252.         ret
  253.  
  254. endp
  255.  
  256.  
  257. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  258. ;;                        ;;
  259. ;; proc SERVICE_PROC      ;;
  260. ;;                        ;;
  261. ;; (standard driver proc) ;;
  262. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  263.  
  264. align 4
  265. proc service_proc stdcall, ioctl:dword
  266.  
  267.         mov     edx, [ioctl]
  268.         mov     eax, [edx + IOCTL.io_code]
  269.  
  270. ;------------------------------------------------------
  271.  
  272.         cmp     eax, 0 ;SRV_GETVERSION
  273.         jne     @F
  274.  
  275.         cmp     [edx + IOCTL.out_size], 4
  276.         jb      .fail
  277.         mov     eax, [edx + IOCTL.output]
  278.         mov     [eax], dword API_VERSION
  279.  
  280.         xor     eax, eax
  281.         ret
  282.  
  283. ;------------------------------------------------------
  284.   @@:
  285.         cmp     eax, 1 ;SRV_HOOK
  286.         jne     .fail
  287.  
  288.         cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
  289.         jb      .fail
  290.  
  291.         mov     eax, [edx + IOCTL.input]
  292.         cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
  293.         jne     .fail                                   ; other types arent supported for this card yet
  294.  
  295. ; check if the device is already listed
  296.  
  297.         mov     esi, device_list
  298.         mov     ecx, [devices]
  299.         test    ecx, ecx
  300.         jz      .firstdevice
  301.  
  302. ;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
  303.         mov     ax , [eax+1]                            ;
  304.   .nextdevice:
  305.         mov     ebx, [esi]
  306.         cmp     al, byte[ebx + device.pci_bus]
  307.         jne     @f
  308.         cmp     ah, byte[ebx + device.pci_dev]
  309.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  310.        @@:
  311.         add     esi, 4
  312.         loop    .nextdevice
  313.  
  314.  
  315. ; This device doesnt have its own eth_device structure yet, lets create one
  316.   .firstdevice:
  317.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  318.         jae     .fail
  319.  
  320.         allocate_and_clear ebx, sizeof.device, .fail      ; Allocate the buffer for device structure
  321.  
  322. ; Fill in the direct call addresses into the struct
  323.  
  324.         mov     [ebx + device.reset], reset
  325.         mov     [ebx + device.transmit], transmit
  326.         mov     [ebx + device.unload], unload
  327.         mov     [ebx + device.name], devicename
  328.  
  329. ; save the pci bus and device numbers
  330.  
  331.         mov     eax, [edx + IOCTL.input]
  332.         movzx   ecx, byte[eax+1]
  333.         mov     [ebx + device.pci_bus], ecx
  334.         movzx   ecx, byte[eax+2]
  335.         mov     [ebx + device.pci_dev], ecx
  336.  
  337. ; Now, it's time to find the base io addres of the PCI device
  338.  
  339.         stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
  340.         mov     [ebx + device.io_addr], eax
  341.  
  342. ; We've found the io address, find IRQ now
  343.  
  344.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
  345.         mov     [ebx + device.irq_line], al
  346.  
  347.         DEBUGF  1,"Hooking into device, devfn:%x, bus:%x, irq:%x, addr:%x\n",\
  348.         [ebx + device.pci_dev]:2,[ebx + device.pci_bus]:2,[ebx + device.irq_line]:2,[ebx + device.io_addr]:4
  349.  
  350. ; Ok, the eth_device structure is ready, let's probe the device
  351.  
  352.         mov     eax, [devices]                                          ; Add the device structure to our device list
  353.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  354.         inc     [devices]                                               ;
  355.  
  356.         call    probe                                                   ; this function will output in eax
  357.         test    eax, eax
  358.         jnz     .err                                                 ; If an error occured, exit
  359.  
  360.         mov     [ebx + device.type], NET_TYPE_ETH
  361.         invoke  NetRegDev
  362.  
  363.         cmp     eax, -1
  364.         je      .err
  365.  
  366.         ret
  367.  
  368. ; If the device was already loaded, find the device number and return it in eax
  369.  
  370.   .find_devicenum:
  371.         DEBUGF  2,"Trying to find device number of already registered device\n"
  372.         invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  373.                                                                         ; into a device number in edi
  374.         mov     eax, edi                                                ; Application wants it in eax instead
  375.         DEBUGF  2,"Kernel says: %u\n", eax
  376.         ret
  377.  
  378. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  379.   .err:
  380.         invoke  KernelFree, ebx
  381.  
  382.   .fail:
  383.         or      eax, -1
  384.         ret
  385.  
  386. ;------------------------------------------------------
  387. endp
  388.  
  389.  
  390.  
  391.  
  392.  
  393. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  394. ;;                                                                        ;;
  395. ;;        Actual Hardware dependent code starts here                      ;;
  396. ;;                                                                        ;;
  397. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  398.  
  399.  
  400. unload:
  401.         ; TODO: (in this particular order)
  402.         ;
  403.         ; - Stop the device
  404.         ; - Detach int handler
  405.         ; - Remove device from local list (device_list)
  406.         ; - call unregister function in kernel
  407.         ; - Remove all allocated structures and buffers the card used
  408.  
  409.         or      eax, -1
  410.         ret
  411.  
  412.  
  413. ;-------------
  414. ;
  415. ; Probe
  416. ;
  417. ;-------------
  418.  
  419. align 4
  420. probe:
  421.  
  422.         DEBUGF  1,"Probing\n"
  423.  
  424. ; Make the device a bus master
  425.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
  426.         or      al, PCI_CMD_MASTER or PCI_CMD_PIO
  427.         invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
  428.  
  429. ;---------------------------
  430. ; First, identify the device
  431.  
  432.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.vendor_id ; get device/vendor id
  433.  
  434.         DEBUGF  1,"Vendor_id=0x%x\n", ax
  435.         cmp     ax, 0x8086
  436.         jne     .notfound
  437.         shr     eax, 16
  438.  
  439.         DEBUGF  1,"Device_id=0x%x\n", ax
  440.         mov     ecx, DEVICE_IDs
  441.         mov     edi, device_id_list
  442.         repne   scasw
  443.         jne     .notfound
  444.         jmp     .found
  445.  
  446.   .notfound:
  447.         DEBUGF  2,"Unsupported device!\n"
  448.         or      eax, -1
  449.         ret
  450.  
  451.   .found:
  452.  
  453.  
  454.  
  455. ;----------
  456. ;
  457. ;  Reset
  458. ;
  459. ;----------
  460.  
  461. align 4
  462. reset:
  463.  
  464.         movzx   eax, [ebx + device.irq_line]
  465.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  466.         invoke  AttachIntHandler, eax, int_handler, ebx
  467.         test    eax, eax
  468.         jnz     @f
  469.         DEBUGF  2,"Could not attach int handler!\n"
  470.         or      eax, -1
  471.         ret
  472.   @@:
  473.  
  474.         DEBUGF  1,"Resetting\n"
  475.  
  476. ;----------------
  477. ; Selective reset
  478.  
  479.         set_io  [ebx + device.io_addr], 0
  480.         set_io  [ebx + device.io_addr], REG_EEPROM
  481.         mov     eax, PORT_SELECTIVE_RESET
  482.         out     dx, eax
  483.  
  484.         mov     esi, 10
  485.         invoke  Sleep
  486.  
  487. ;-----------
  488. ; Soft reset
  489.  
  490.         set_io  [ebx + device.io_addr], REG_PORT
  491.         mov     eax, PORT_SOFT_RESET
  492.         out     dx, eax
  493.  
  494.         mov     esi, 10
  495.         invoke  Sleep
  496.  
  497. ;-------------
  498. ; Read PHY IDs
  499.  
  500.         mov     cx, 1
  501.         mov     dx, MII_PHYSID1
  502.         call    mdio_read
  503.         DEBUGF  1, "PHY ID1: 0x%x\n", ax
  504.  
  505.         mov     cx, 1
  506.         mov     dx, MII_PHYSID2
  507.         call    mdio_read
  508.         DEBUGF  1, "PHY ID2: 0x%x\n", ax
  509.  
  510. ;---------------------
  511. ; Read MAC from eeprom
  512.  
  513.         call    ee_get_width
  514.         call    mac_read_eeprom
  515.  
  516. ;---------------------------------
  517. ; Tell device where to store stats
  518.  
  519.         lea     eax, [ebx + device.lstats.tx_good_frames]      ; lstats
  520.         invoke  GetPhysAddr
  521.         set_io  [ebx + device.io_addr], 0
  522.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  523.         out     dx, eax
  524.  
  525.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  526.         mov     ax, CU_STATSADDR or INT_MASK
  527.         out     dx, ax
  528.         call    cmd_wait
  529.  
  530. ;------------------------
  531. ; setup RX base addr to 0
  532.  
  533.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  534.         xor     eax, eax
  535.         out     dx, eax
  536.  
  537.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  538.         mov     ax, RX_ADDR_LOAD or INT_MASK
  539.         out     dx, ax
  540.         call    cmd_wait
  541.  
  542. ;-----------------------------
  543. ; Create RX and TX descriptors
  544.  
  545.         call    init_rx_ring
  546.         test    eax, eax
  547.         jz      .error
  548.  
  549.         call    init_tx_ring
  550.  
  551.  
  552. ;---------
  553. ; Start RX
  554.  
  555.         DEBUGF  1, "Starting RX"
  556.  
  557.         set_io  [ebx + device.io_addr], 0
  558.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  559.         mov     eax, [ebx + device.rx_desc]
  560.         invoke  GetPhysAddr
  561.         add     eax, NET_BUFF.data
  562.         out     dx, eax
  563.  
  564.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  565.         mov     ax, RX_START or INT_MASK
  566.         out     dx, ax
  567.         call    cmd_wait
  568.  
  569. ;----------
  570. ; Set-up TX
  571.  
  572.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  573.         xor     eax, eax
  574.         out     dx, eax
  575.  
  576.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  577.         mov     ax, CU_CMD_BASE or INT_MASK
  578.         out     dx, ax
  579.         call    cmd_wait
  580.  
  581. ;-------------------------
  582. ; Individual address setup
  583.  
  584.         mov     [ebx + device.confcmd.command], TXFD_CMD_IA + TXFD_CMD_SUSPEND
  585.         mov     [ebx + device.confcmd.status], 0
  586.         lea     eax, [ebx + device.tx_ring]
  587.         invoke  GetPhysAddr
  588.         mov     [ebx + device.confcmd.link], eax
  589.         lea     edi, [ebx + device.confcmd.data]
  590.         lea     esi, [ebx + device.mac]
  591.         movsd
  592.         movsw
  593.  
  594.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  595.         lea     eax, [ebx + device.confcmd.status]
  596.         invoke  GetPhysAddr
  597.         out     dx, eax
  598.  
  599.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  600.         mov     ax, CU_START or INT_MASK
  601.         out     dx, ax
  602.         call    cmd_wait
  603.  
  604. ;-------------
  605. ; Configure CU
  606.  
  607.         mov     [ebx + device.confcmd.command], TXFD_CMD_CFG + TXFD_CMD_SUSPEND
  608.         mov     [ebx + device.confcmd.status], 0
  609.         lea     eax, [ebx + device.confcmd.status]
  610.         invoke  GetPhysAddr
  611.         mov     [ebx + device.confcmd.link], eax
  612.  
  613.         mov     esi, confcmd_data
  614.         lea     edi, [ebx + device.confcmd.data]
  615.         mov     ecx, 22
  616.         rep     movsb
  617.  
  618.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  619.         lea     eax, [ebx + device.confcmd.status]
  620.         invoke  GetPhysAddr
  621.         out     dx, eax
  622.  
  623.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  624.         mov     ax, CU_START                            ; expect Interrupts from now on
  625.         out     dx, ax
  626.         call    cmd_wait
  627.  
  628.         DEBUGF  1,"Reset complete\n"
  629.         mov     [ebx + device.mtu], 1514
  630.  
  631. ; Set link state to unknown
  632.         mov     [ebx + device.state], ETH_LINK_UNKNOWN
  633.  
  634.         xor     eax, eax        ; indicate that we have successfully reset the card
  635.         ret
  636.  
  637.   .error:
  638.         or      eax, -1
  639.         ret
  640.  
  641.  
  642. align 4
  643. init_rx_ring:
  644.  
  645.         DEBUGF  1,"Creating ring\n"
  646.  
  647. ;---------------------
  648. ; build rxfd structure
  649.  
  650.         invoke  NetAlloc, 2000
  651.         test    eax, eax
  652.         jz      .out_of_mem
  653.         mov     [ebx + device.rx_desc], eax
  654.         mov     esi, eax
  655.         invoke  GetPhysAddr
  656.         add     eax, NET_BUFF.data
  657.         mov     [esi + sizeof.NET_BUFF + rxfd.status], 0
  658.         mov     [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
  659.         mov     [esi + sizeof.NET_BUFF + rxfd.link], eax
  660.         mov     [esi + sizeof.NET_BUFF + rxfd.count], 0
  661.         mov     [esi + sizeof.NET_BUFF + rxfd.size], 1528
  662.  
  663.         ret
  664.  
  665.   .out_of_mem:
  666.         ret
  667.  
  668.  
  669.  
  670.  
  671. align 4
  672. init_tx_ring:
  673.  
  674.         DEBUGF  1,"Creating TX ring\n"
  675.  
  676.         lea     esi, [ebx + device.tx_ring]
  677.         mov     eax, esi
  678.         invoke  GetPhysAddr
  679.         mov     ecx, TX_RING_SIZE
  680.   .next_desc:
  681.         mov     [esi + txfd.status], 0
  682.         mov     [esi + txfd.command], 0
  683.         lea     edx, [eax + txfd.buf_addr]
  684.         mov     [esi + txfd.desc_addr], edx
  685.         add     eax, sizeof.txfd
  686.         mov     [esi + txfd.link], eax
  687.         mov     [esi + txfd.count], 0x01208000          ; One buffer, 0x20 bytes of transmit threshold, end of frame
  688.         add     esi, sizeof.txfd
  689.         dec     ecx
  690.         jnz     .next_desc
  691.  
  692.         lea     eax, [ebx + device.tx_ring]
  693.         invoke  GetPhysAddr
  694.         mov     dword[ebx + device.tx_ring + sizeof.txfd*(TX_RING_SIZE-1) + txfd.link], eax
  695.  
  696.         mov     [ebx + device.cur_tx], 0
  697.         mov     [ebx + device.last_tx], 0
  698.  
  699.         ret
  700.  
  701.  
  702. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  703. ;;                                         ;;
  704. ;; Transmit                                ;;
  705. ;;                                         ;;
  706. ;; In: pointer to device structure in ebx  ;;
  707. ;;                                         ;;
  708. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  709.  
  710. proc transmit stdcall bufferptr
  711.  
  712.         pushf
  713.         cli
  714.  
  715.         mov     esi, [bufferptr]
  716.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
  717.         lea     eax, [esi + NET_BUFF.data]
  718.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  719.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  720.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  721.         [eax+13]:2,[eax+12]:2
  722.  
  723.         cmp     [esi + NET_BUFF.length], 1514
  724.         ja      .fail
  725.         cmp     [esi + NET_BUFF.length], 60
  726.         jb      .fail
  727.  
  728.         ; Get current TX descriptor
  729.         mov     edi, [ebx + device.cur_tx]
  730.         mov     eax, sizeof.txfd
  731.         mul     edi
  732.         lea     edi, [ebx + device.tx_ring + eax]
  733.  
  734.         ; Check if current descriptor is free or still in use
  735.         cmp     [edi + txfd.status], 0
  736.         jne     .fail
  737.  
  738.         ; Fill in status and command values
  739.         mov     [edi + txfd.status], 0
  740.         mov     [edi + txfd.command], TXFD_CMD_SUSPEND + TXFD_CMD_TX + TXFD_CMD_TX_FLEX
  741.         mov     [edi + txfd.count], 0x01208000
  742.  
  743.         ; Fill in buffer address and size
  744.         mov     [edi + txfd.virt_addr], esi
  745.         mov     eax, esi
  746.         add     eax, [esi + NET_BUFF.offset]
  747.         push    edi
  748.         invoke  GetPhysAddr
  749.         pop     edi
  750.         mov     [edi + txfd.buf_addr], eax
  751.         mov     ecx, [esi + NET_BUFF.length]
  752.         mov     [edi + txfd.buf_size], ecx
  753.  
  754.         ; Inform device of the new/updated transmit descriptor
  755.         mov     eax, edi
  756.         invoke  GetPhysAddr
  757.         set_io  [ebx + device.io_addr], 0
  758.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  759.         out     dx, eax
  760.  
  761.         ; Start the transmit
  762.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  763.         mov     ax, CU_START
  764.         out     dx, ax
  765.  
  766.         ; Update stats
  767.         inc     [ebx + device.packets_tx]
  768.         add     dword[ebx + device.bytes_tx], ecx
  769.         adc     dword[ebx + device.bytes_tx + 4], 0
  770.  
  771.         ; Wait for command to complete
  772.         call    cmd_wait
  773.  
  774.         inc     [ebx + device.cur_tx]
  775.         and     [ebx + device.cur_tx], TX_RING_SIZE - 1
  776.  
  777.         DEBUGF  1,"Transmit OK\n"
  778.         popf
  779.         xor     eax, eax
  780.         ret
  781.  
  782.   .fail:
  783.         DEBUGF  2,"Transmit failed!\n"
  784.         invoke  NetFree, [bufferptr]
  785.         popf
  786.         or      eax, -1
  787.         ret
  788.  
  789. endp
  790.  
  791.  
  792. ;;;;;;;;;;;;;;;;;;;;;;;
  793. ;;                   ;;
  794. ;; Interrupt handler ;;
  795. ;;                   ;;
  796. ;;;;;;;;;;;;;;;;;;;;;;;
  797.  
  798. align 4
  799. int_handler:
  800.  
  801.         push    ebx esi edi
  802.  
  803.         DEBUGF  1,"INT\n"
  804.  
  805. ; find pointer of device wich made IRQ occur
  806.  
  807.         mov     ecx, [devices]
  808.         test    ecx, ecx
  809.         jz      .nothing
  810.         mov     esi, device_list
  811.   .nextdevice:
  812.         mov     ebx, [esi]
  813.  
  814. ;        set_io  [ebx + device.io_addr], 0      ; REG_SCB_STATUS = 0
  815.         set_io  [ebx + device.io_addr], REG_SCB_STATUS
  816.         in      ax, dx
  817.         out     dx, ax                          ; send it back to ACK
  818.         test    ax, ax
  819.         jnz     .got_it
  820.   .continue:
  821.         add     esi, 4
  822.         dec     ecx
  823.         jnz     .nextdevice
  824.   .nothing:
  825.         pop     edi esi ebx
  826.         xor     eax, eax
  827.  
  828.         ret                                         ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
  829.  
  830.   .got_it:
  831.  
  832.         DEBUGF  1,"Device: %x Status: %x\n", ebx, ax
  833.  
  834.         test    ax, SCB_STATUS_FR               ; did we receive a frame?
  835.         jz      .no_rx
  836.  
  837.         push    ax
  838.  
  839.         DEBUGF  1,"Receiving\n"
  840.  
  841.         push    ebx
  842.   .rx_loop:
  843.         pop     ebx
  844.  
  845.         mov     esi, [ebx + device.rx_desc]
  846.         test    [esi + sizeof.NET_BUFF + rxfd.status], RXFD_STATUS_C            ; Completed?
  847.         jz      .no_rx_
  848.         test    [esi + sizeof.NET_BUFF + rxfd.status], RXFD_STATUS_OK           ; OK?
  849.         jz      .not_ok
  850.  
  851.         DEBUGF  1,"rxfd status=0x%x\n", [esi + sizeof.NET_BUFF + rxfd.status]:4
  852.  
  853.         movzx   ecx, [esi + sizeof.NET_BUFF + rxfd.count]
  854.         and     ecx, 0x3fff
  855.  
  856.         push    ebx
  857.         push    .rx_loop
  858.         push    esi
  859.         mov     [esi + NET_BUFF.length], ecx
  860.         mov     [esi + NET_BUFF.device], ebx
  861.         mov     [esi + NET_BUFF.offset], NET_BUFF.data + rxfd.packet
  862.  
  863. ; Update stats
  864.         add     dword [ebx + device.bytes_rx], ecx
  865.         adc     dword [ebx + device.bytes_rx + 4], 0
  866.         inc     dword [ebx + device.packets_rx]
  867.  
  868. ; allocate new descriptor
  869.  
  870.         invoke  NetAlloc, 2000
  871.         test    eax, eax
  872.         jz      .out_of_mem
  873.         mov     [ebx + device.rx_desc], eax
  874.         mov     esi, eax
  875.         invoke  GetPhysAddr
  876.         add     eax, NET_BUFF.data
  877.         mov     [esi + sizeof.NET_BUFF + rxfd.status], 0
  878.         mov     [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
  879.         mov     [esi + sizeof.NET_BUFF + rxfd.link], eax
  880.         mov     [esi + sizeof.NET_BUFF + rxfd.count], 0
  881.         mov     [esi + sizeof.NET_BUFF + rxfd.size], 1528
  882.  
  883. ; restart RX
  884.  
  885.         set_io  [ebx + device.io_addr], 0
  886.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  887. ;        mov     eax, [ebx + device.rx_desc]
  888. ;        invoke  GetPhysAddr
  889. ;        add     eax, NET_BUFF.data
  890.         out     dx, eax
  891.  
  892.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  893.         mov     ax, RX_START
  894.         out     dx, ax
  895.         call    cmd_wait
  896.   .out_of_mem:
  897.  
  898. ; Hand the frame over to the kernel
  899.         jmp     [EthInput]
  900.  
  901.   .not_ok:
  902. ; Reset the FD
  903.         mov     [esi + sizeof.NET_BUFF + rxfd.status], 0
  904.         mov     [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
  905.         mov     [esi + sizeof.NET_BUFF + rxfd.count], 0
  906.  
  907. ; Restart RX
  908.         set_io  [ebx + device.io_addr], 0
  909.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  910.         mov     eax, esi
  911.         invoke  GetPhysAddr
  912.         add     eax, NET_BUFF.data
  913.         out     dx, eax
  914.  
  915.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  916.         mov     ax, RX_START
  917.         out     dx, ax
  918.         call    cmd_wait
  919.  
  920.         push    ebx
  921.         jmp     .rx_loop
  922.  
  923.   .no_rx_:
  924.         DEBUGF  1, "no more data\n"
  925.         pop     ax
  926.  
  927.   .no_rx:
  928.  
  929.         test    ax, SCB_STATUS_CNA
  930.         jz      .no_tx
  931.         DEBUGF  1, "Command completed\n"
  932.  
  933.         push    eax
  934.   .loop_tx:
  935.         mov     edi, [ebx + device.last_tx]
  936.         mov     eax, sizeof.txfd
  937.         mul     eax
  938.         lea     edi, [ebx + device.tx_ring + eax]
  939.  
  940.         cmp     [edi + txfd.status], 0
  941.         je      .tx_done
  942.  
  943.         cmp     [edi + txfd.virt_addr], 0
  944.         je      .tx_done
  945.  
  946.         DEBUGF  1,"Freeing buffer 0x%x\n", [edi + txfd.virt_addr]
  947.  
  948.         push    [edi + txfd.virt_addr]
  949.         mov     [edi + txfd.virt_addr], 0
  950.         invoke  NetFree
  951.  
  952.         inc     [ebx + device.last_tx]
  953.         and     [ebx + device.last_tx], TX_RING_SIZE - 1
  954.  
  955.         jmp     .loop_tx
  956.   .tx_done:
  957.         pop     eax
  958.   .no_tx:
  959.  
  960.         test    ax, RU_STATUS_NO_RESOURCES
  961.         jne     .fail
  962.  
  963.         DEBUGF  2, "Out of resources!\n"
  964.  
  965.   .fail:
  966.         pop     edi esi ebx
  967.         xor     eax, eax
  968.         inc     eax
  969.  
  970.         ret
  971.  
  972.  
  973.  
  974.  
  975. align 4
  976. cmd_wait:
  977.  
  978.         in      al, dx
  979.         test    al, al
  980.         jnz     cmd_wait
  981.  
  982.         ret
  983.  
  984.  
  985.  
  986.  
  987.  
  988.  
  989. align 4
  990. ee_read:        ; esi = address to read
  991.  
  992.         DEBUGF  1,"Eeprom read from 0x%x\n", esi
  993.  
  994.         set_io  [ebx + device.io_addr], 0
  995.         set_io  [ebx + device.io_addr], REG_EEPROM
  996.  
  997. ;-----------------------------------------------------
  998. ; Prepend start bit + read opcode to the address field
  999. ; and shift it to the very left bits of esi
  1000.  
  1001.         mov     cl, 29
  1002.         sub     cl, [ebx + device.ee_bus_width]
  1003.         shl     esi, cl
  1004.         or      esi, EE_READ shl 29
  1005.  
  1006.         movzx   ecx, [ebx + device.ee_bus_width]
  1007.         add     ecx, 3
  1008.  
  1009.         mov     ax, 0x4800 + EE_CS
  1010.         out     dx, ax
  1011.         call    udelay
  1012.  
  1013. ;-----------------------
  1014. ; Write this to the chip
  1015.  
  1016.   .loop:
  1017.         mov     al, EE_CS
  1018.         shl     esi, 1
  1019.         jnc     @f
  1020.         or      al, EE_DI
  1021.        @@:
  1022.         out     dx, al
  1023.         call    udelay
  1024.  
  1025.         or      al, EE_SK
  1026.         out     dx, al
  1027.         call    udelay
  1028.  
  1029.         loop    .loop
  1030.  
  1031. ;------------------------------
  1032. ; Now read the data from eeprom
  1033.  
  1034.         xor     esi, esi
  1035.         mov     ecx, 16
  1036.  
  1037.   .loop2:
  1038.         shl     esi, 1
  1039.         mov     al, EE_CS
  1040.         out     dx, al
  1041.         call    udelay
  1042.  
  1043.         or      al, EE_SK
  1044.         out     dx, al
  1045.         call    udelay
  1046.  
  1047.         in      al, dx
  1048.         test    al, EE_DO
  1049.         jz      @f
  1050.         inc     esi
  1051.        @@:
  1052.  
  1053.         loop    .loop2
  1054.  
  1055. ;-----------------------
  1056. ; de-activate the eeprom
  1057.  
  1058.         xor     al, al
  1059.         out     dx, al
  1060.  
  1061.         DEBUGF  1,"0x%x\n", esi:4
  1062.         ret
  1063.  
  1064.  
  1065.  
  1066. align 4
  1067. ee_write:       ; esi = address to write to, di = data
  1068.  
  1069.         DEBUGF  1,"Eeprom write 0x%x to 0x%x\n", di, esi
  1070.  
  1071.         set_io  [ebx + device.io_addr], 0
  1072.         set_io  [ebx + device.io_addr], REG_EEPROM
  1073.  
  1074. ;-----------------------------------------------------
  1075. ; Prepend start bit + write opcode to the address field
  1076. ; and shift it to the very left bits of esi
  1077.  
  1078.         mov     cl, 29
  1079.         sub     cl, [ebx + device.ee_bus_width]
  1080.         shl     esi, cl
  1081.         or      esi, EE_WRITE shl 29
  1082.  
  1083.         movzx   ecx, [ebx + device.ee_bus_width]
  1084.         add     ecx, 3
  1085.  
  1086.         mov     ax, 0x4800 + EE_CS       ; enable chip
  1087.         out     dx, ax
  1088.  
  1089. ;-----------------------
  1090. ; Write this to the chip
  1091.  
  1092.   .loop:
  1093.         mov     al, EE_CS
  1094.         shl     esi, 1
  1095.         jnc     @f
  1096.         or      al, EE_DI
  1097.        @@:
  1098.         out     dx, al
  1099.         call    udelay
  1100.  
  1101.         or      al, EE_SK
  1102.         out     dx, al
  1103.         call    udelay
  1104.  
  1105.         loop    .loop
  1106.  
  1107. ;-----------------------------
  1108. ; Now write the data to eeprom
  1109.  
  1110.         mov     ecx, 16
  1111.  
  1112.   .loop2:
  1113.         mov     al, EE_CS
  1114.         shl     di, 1
  1115.         jnc     @f
  1116.         or      al, EE_DI
  1117.        @@:
  1118.         out     dx, al
  1119.         call    udelay
  1120.  
  1121.         or      al, EE_SK
  1122.         out     dx, al
  1123.         call    udelay
  1124.  
  1125.         loop    .loop2
  1126.  
  1127. ;-----------------------
  1128. ; de-activate the eeprom
  1129.  
  1130.         xor     al, al
  1131.         out     dx, al
  1132.  
  1133.  
  1134.         ret
  1135.  
  1136.  
  1137.  
  1138. align 4
  1139. ee_get_width:
  1140.  
  1141.         set_io  [ebx + device.io_addr], 0
  1142.         set_io  [ebx + device.io_addr], REG_EEPROM
  1143.  
  1144.         mov     ax, 0x4800 + EE_CS      ; activate eeprom
  1145.         out     dx, ax
  1146.         call    udelay
  1147.  
  1148.         mov     si, EE_READ shl 13
  1149.         xor     ecx, ecx
  1150.   .loop:
  1151.         mov     al, EE_CS
  1152.         shl     si, 1
  1153.         jnc     @f
  1154.         or      al, EE_DI
  1155.        @@:
  1156.         out     dx, ax
  1157.         call    udelay
  1158.  
  1159.         or      al, EE_SK
  1160.         out     dx, ax
  1161.         call    udelay
  1162.  
  1163.         inc     ecx
  1164.  
  1165.         cmp     ecx, 15
  1166.         jae     .give_up
  1167.  
  1168.         in      al, dx
  1169.         test    al, EE_DO
  1170.         jnz     .loop
  1171.  
  1172.         xor     al, al
  1173.         out     dx, al                  ; de-activate eeprom
  1174.  
  1175.         sub     cl, 3                   ; dont count the opcode bits
  1176.         mov     [ebx + device.ee_bus_width], cl
  1177.         DEBUGF  1, "Eeprom width=%u bit\n", ecx
  1178.  
  1179.         ret
  1180.  
  1181.   .give_up:
  1182.         DEBUGF  2, "Eeprom not found!\n"
  1183.         xor     al, al
  1184.         out     dx, al                  ; de-activate eeprom
  1185.  
  1186.         ret
  1187.  
  1188.  
  1189. ; Wait a minimum of 2╡s
  1190. udelay:
  1191.         pusha
  1192.         mov     esi, 1
  1193.         invoke  Sleep
  1194.         popa
  1195.  
  1196.         ret
  1197.  
  1198.  
  1199.  
  1200. ; cx = phy addr
  1201. ; dx = phy reg addr
  1202.  
  1203. ; ax = data
  1204.  
  1205. align 4
  1206. mdio_read:
  1207.  
  1208.         DEBUGF  1,"MDIO read\n"
  1209.  
  1210.         shl     ecx, 21                 ; PHY addr
  1211.         mov     eax, ecx
  1212.         shl     edx, 16                 ; PHY reg addr
  1213.         or      eax, edx
  1214.         or      eax, 10b shl 26         ; read opcode
  1215.  
  1216.         set_io  [ebx + device.io_addr], 0
  1217.         set_io  [ebx + device.io_addr], REG_MDI_CTRL
  1218.         out     dx, eax
  1219.  
  1220.   .wait:
  1221.         call    udelay
  1222.         in      eax, dx
  1223.         test    eax, 1 shl 28           ; ready bit
  1224.         jz      .wait
  1225.  
  1226.         ret
  1227.  
  1228.  
  1229.  
  1230. ; ax = data
  1231. ; cx = phy addr
  1232. ; dx = phy reg addr
  1233.  
  1234. ; ax = data
  1235.  
  1236. align 4
  1237. mdio_write:
  1238.  
  1239.         DEBUGF  1,"MDIO write\n"
  1240.  
  1241.         and     eax, 0xffff
  1242.  
  1243.         shl     ecx, 21                 ; PHY addr
  1244.         shl     edx, 16                 ; PHY reg addr
  1245.  
  1246.         or      eax, ecx
  1247.         or      eax, edx
  1248.         or      eax, 01b shl 26         ; write opcode
  1249.  
  1250.         set_io  [ebx + device.io_addr], 0
  1251.         set_io  [ebx + device.io_addr], REG_MDI_CTRL
  1252.         out     dx, eax
  1253.  
  1254.   .wait:
  1255.         call    udelay
  1256.         in      eax, dx
  1257.         test    eax, 1 shl 28           ; ready bit
  1258.         jz      .wait
  1259.  
  1260.         ret
  1261.  
  1262.  
  1263. align 4
  1264. mac_read_eeprom:
  1265.  
  1266.         mov     esi, 0
  1267.         call    ee_read
  1268.         mov     word[ebx + device.mac], si
  1269.  
  1270.         mov     esi, 1
  1271.         call    ee_read
  1272.         mov     word[ebx + device.mac+2], si
  1273.  
  1274.         mov     esi, 2
  1275.         call    ee_read
  1276.         mov     word[ebx + device.mac+4], si
  1277.  
  1278.  
  1279.         ret
  1280.  
  1281.  
  1282. ; End of code
  1283.  
  1284.  
  1285. data fixups
  1286. end data
  1287.  
  1288. include '../peimport.inc'
  1289.  
  1290. my_service      db 'I8255X', 0                    ; max 16 chars include zero
  1291. devicename      db 'Intel Etherexpress pro/100', 0
  1292.  
  1293. confcmd_data    db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1
  1294.                 db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2
  1295.                 db 0x80, 0x3f, 0x05                                     ; 22 bytes total
  1296.  
  1297.  
  1298. device_id_list:
  1299. dw 0x1029
  1300. dw 0x1030
  1301. dw 0x1031
  1302. dw 0x1032
  1303. dw 0x1033
  1304. dw 0x1034
  1305. dw 0x1038
  1306. dw 0x1039
  1307. dw 0x103A
  1308. dw 0x103B
  1309. dw 0x103C
  1310. dw 0x103D
  1311. dw 0x103E
  1312. dw 0x1050
  1313. dw 0x1051
  1314. dw 0x1052
  1315. dw 0x1053
  1316. dw 0x1054
  1317. dw 0x1055
  1318. dw 0x1056
  1319. dw 0x1057
  1320. dw 0x1059
  1321. dw 0x1064
  1322. dw 0x1065
  1323. dw 0x1066
  1324. dw 0x1067
  1325. dw 0x1068
  1326. dw 0x1069
  1327. dw 0x106A
  1328. dw 0x106B
  1329. dw 0x1091
  1330. dw 0x1092
  1331. dw 0x1093
  1332. dw 0x1094
  1333. dw 0x1095
  1334. dw 0x10fe
  1335. dw 0x1209
  1336. dw 0x1229
  1337. dw 0x2449
  1338. dw 0x2459
  1339. dw 0x245D
  1340. dw 0x27DC
  1341.  
  1342. DEVICE_IDs = ($ - device_id_list) / 2
  1343.  
  1344. include_debug_strings                           ; All data wich FDO uses will be included here
  1345.  
  1346. align 4
  1347. devices         dd 0                              ; number of currently running devices
  1348. device_list     rd MAX_DEVICES                    ; This list contains all pointers to device structures the driver is handling
  1349.  
  1350.