Subversion Repositories Kolibri OS

Rev

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