Subversion Repositories Kolibri OS

Rev

Rev 5562 | 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-2016. 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.  
  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.  
  456.  
  457. ;----------
  458. ;
  459. ;  Reset
  460. ;
  461. ;----------
  462.  
  463. align 4
  464. reset:
  465.  
  466.         movzx   eax, [ebx + device.irq_line]
  467.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  468.         invoke  AttachIntHandler, eax, int_handler, ebx
  469.         test    eax, eax
  470.         jnz     @f
  471.         DEBUGF  2,"Could not attach int handler!\n"
  472.         or      eax, -1
  473.         ret
  474.   @@:
  475.  
  476.         DEBUGF  1,"Resetting\n"
  477.  
  478. ;----------------
  479. ; Selective reset
  480.  
  481.         set_io  [ebx + device.io_addr], 0
  482.         set_io  [ebx + device.io_addr], REG_EEPROM
  483.         mov     eax, PORT_SELECTIVE_RESET
  484.         out     dx, eax
  485.  
  486.         mov     esi, 1
  487.         invoke  Sleep
  488.  
  489. ;-----------
  490. ; Soft reset
  491.  
  492.         set_io  [ebx + device.io_addr], REG_PORT
  493.         mov     eax, PORT_SOFT_RESET
  494.         out     dx, eax
  495.  
  496.         mov     esi, 10
  497.         invoke  Sleep
  498.  
  499. ;-------------
  500. ; Read PHY IDs
  501.  
  502.         mov     cx, 1
  503.         mov     dx, MII_PHYSID1
  504.         call    mdio_read
  505.         DEBUGF  1, "PHY ID1: 0x%x\n", ax
  506.  
  507.         mov     cx, 1
  508.         mov     dx, MII_PHYSID2
  509.         call    mdio_read
  510.         DEBUGF  1, "PHY ID2: 0x%x\n", ax
  511.  
  512. ;---------------------
  513. ; Read MAC from eeprom
  514.  
  515.         call    ee_get_width
  516.         call    mac_read_eeprom
  517.  
  518. ;---------------------------------
  519. ; Tell device where to store stats
  520.  
  521.         lea     eax, [ebx + device.lstats.tx_good_frames]      ; lstats
  522.         invoke  GetPhysAddr
  523.         set_io  [ebx + device.io_addr], 0
  524.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  525.         out     dx, eax
  526.  
  527.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  528.         mov     ax, CU_STATSADDR or INT_MASK
  529.         out     dx, ax
  530.         call    cmd_wait
  531.  
  532. ;------------------------
  533. ; setup RX base addr to 0
  534.  
  535.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  536.         xor     eax, eax
  537.         out     dx, eax
  538.  
  539.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  540.         mov     ax, RX_ADDR_LOAD or INT_MASK
  541.         out     dx, ax
  542.         call    cmd_wait
  543.  
  544. ;-----------------------------
  545. ; Create RX and TX descriptors
  546.  
  547.         call    init_rx_ring
  548.         test    eax, eax
  549.         jz      .error
  550.  
  551.         call    init_tx_ring
  552.  
  553.  
  554. ;---------
  555. ; Start RX
  556.  
  557.         DEBUGF  1, "Starting RX"
  558.  
  559.         set_io  [ebx + device.io_addr], 0
  560.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  561.         mov     eax, [ebx + device.rx_desc]
  562.         invoke  GetPhysAddr
  563.         add     eax, NET_BUFF.data
  564.         out     dx, eax
  565.  
  566.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  567.         mov     ax, RX_START or INT_MASK
  568.         out     dx, ax
  569.         call    cmd_wait
  570.  
  571. ;----------
  572. ; Set-up TX
  573.  
  574.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  575.         xor     eax, eax
  576.         out     dx, eax
  577.  
  578.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  579.         mov     ax, CU_CMD_BASE or INT_MASK
  580.         out     dx, ax
  581.         call    cmd_wait
  582.  
  583. ;-------------------------
  584. ; Individual address setup
  585.  
  586.         mov     [ebx + device.confcmd.command], TXFD_CMD_IA + TXFD_CMD_SUSPEND
  587.         mov     [ebx + device.confcmd.status], 0
  588.         lea     eax, [ebx + device.tx_ring]
  589.         invoke  GetPhysAddr
  590.         mov     [ebx + device.confcmd.link], eax
  591.         lea     edi, [ebx + device.confcmd.data]
  592.         lea     esi, [ebx + device.mac]
  593.         movsd
  594.         movsw
  595.  
  596.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  597.         lea     eax, [ebx + device.confcmd.status]
  598.         invoke  GetPhysAddr
  599.         out     dx, eax
  600.  
  601.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  602.         mov     ax, CU_START or INT_MASK
  603.         out     dx, ax
  604.         call    cmd_wait
  605.  
  606. ;-------------
  607. ; Configure CU
  608.  
  609.         mov     [ebx + device.confcmd.command], TXFD_CMD_CFG + TXFD_CMD_SUSPEND
  610.         mov     [ebx + device.confcmd.status], 0
  611.         lea     eax, [ebx + device.confcmd.status]
  612.         invoke  GetPhysAddr
  613.         mov     [ebx + device.confcmd.link], eax
  614.  
  615.         mov     esi, confcmd_data
  616.         lea     edi, [ebx + device.confcmd.data]
  617.         mov     ecx, 22
  618.         rep     movsb
  619.  
  620.         mov     byte[ebx + device.confcmd.data + 1], 0x88  ; fifo of 8 each
  621.         mov     byte[ebx + device.confcmd.data + 4], 0
  622.         mov     byte[ebx + device.confcmd.data + 5], 0x80
  623.         mov     byte[ebx + device.confcmd.data + 15], 0x48
  624.         mov     byte[ebx + device.confcmd.data + 19], 0x80
  625.         mov     byte[ebx + device.confcmd.data + 21], 0x05
  626.  
  627.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  628.         lea     eax, [ebx + device.confcmd.status]
  629.         invoke  GetPhysAddr
  630.         out     dx, eax
  631.  
  632.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  633.         mov     ax, CU_START                            ; expect Interrupts from now on
  634.         out     dx, ax
  635.         call    cmd_wait
  636.  
  637.         DEBUGF  1,"Reset complete\n"
  638.         mov     [ebx + device.mtu], 1514
  639.  
  640. ; Set link state to unknown
  641.         mov     [ebx + device.state], ETH_LINK_UNKNOWN
  642.  
  643.         xor     eax, eax        ; indicate that we have successfully reset the card
  644.         ret
  645.  
  646.   .error:
  647.         or      eax, -1
  648.         ret
  649.  
  650.  
  651. align 4
  652. init_rx_ring:
  653.  
  654.         DEBUGF  1,"Creating ring\n"
  655.  
  656. ;---------------------
  657. ; build rxfd structure
  658.  
  659.         invoke  NetAlloc, 2000
  660.         test    eax, eax
  661.         jz      .out_of_mem
  662.         mov     [ebx + device.rx_desc], eax
  663.         mov     esi, eax
  664.         invoke  GetPhysAddr
  665.         add     eax, NET_BUFF.data
  666.         mov     [esi + sizeof.NET_BUFF + rxfd.status], 0
  667.         mov     [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
  668.         mov     [esi + sizeof.NET_BUFF + rxfd.link], eax
  669.         mov     [esi + sizeof.NET_BUFF + rxfd.count], 0
  670.         mov     [esi + sizeof.NET_BUFF + rxfd.size], 1528
  671.  
  672.         ret
  673.  
  674.   .out_of_mem:
  675.         ret
  676.  
  677.  
  678.  
  679.  
  680. align 4
  681. init_tx_ring:
  682.  
  683.         DEBUGF  1,"Creating TX ring\n"
  684.  
  685.         lea     esi, [ebx + device.tx_ring]
  686.         mov     eax, esi
  687.         invoke  GetPhysAddr
  688.         mov     ecx, TX_RING_SIZE
  689.   .next_desc:
  690.         mov     [esi + txfd.status], 0
  691.         mov     [esi + txfd.command], 0
  692.         lea     edx, [eax + txfd.buf_addr]
  693.         mov     [esi + txfd.desc_addr], edx
  694.         add     eax, sizeof.txfd
  695.         mov     [esi + txfd.link], eax
  696.         mov     [esi + txfd.count], 0x01208000          ; One buffer, 0x20 bytes of transmit threshold, end of frame
  697.         add     esi, sizeof.txfd
  698.         dec     ecx
  699.         jnz     .next_desc
  700.  
  701.         lea     eax, [ebx + device.tx_ring]
  702.         invoke  GetPhysAddr
  703.         mov     dword[ebx + device.tx_ring + sizeof.txfd*(TX_RING_SIZE-1) + txfd.link], eax
  704.  
  705.         mov     [ebx + device.cur_tx], 0
  706.         mov     [ebx + device.last_tx], 0
  707.  
  708.         ret
  709.  
  710.  
  711. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  712. ;;                                         ;;
  713. ;; Transmit                                ;;
  714. ;;                                         ;;
  715. ;; In: pointer to device structure in ebx  ;;
  716. ;;                                         ;;
  717. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  718.  
  719. proc transmit stdcall bufferptr
  720.  
  721.         pushf
  722.         cli
  723.  
  724.         mov     esi, [bufferptr]
  725.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
  726.         lea     eax, [esi + NET_BUFF.data]
  727.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  728.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  729.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  730.         [eax+13]:2,[eax+12]:2
  731.  
  732.         cmp     [esi + NET_BUFF.length], 1514
  733.         ja      .fail
  734.         cmp     [esi + NET_BUFF.length], 60
  735.         jb      .fail
  736.  
  737.         ; Get current TX descriptor
  738.         mov     edi, [ebx + device.cur_tx]
  739.         mov     eax, sizeof.txfd
  740.         mul     edi
  741.         lea     edi, [ebx + device.tx_ring + eax]
  742.  
  743.         ; Check if current descriptor is free or still in use
  744.         cmp     [edi + txfd.status], 0
  745.         jne     .fail
  746.  
  747.         ; Fill in status and command values
  748.         mov     [edi + txfd.status], 0
  749.         mov     [edi + txfd.command], TXFD_CMD_SUSPEND + TXFD_CMD_TX + TXFD_CMD_TX_FLEX
  750.         mov     [edi + txfd.count], 0x01208000
  751.  
  752.         ; Fill in buffer address and size
  753.         mov     [edi + txfd.virt_addr], esi
  754.         mov     eax, esi
  755.         add     eax, [esi + NET_BUFF.offset]
  756.         push    edi
  757.         invoke  GetPhysAddr
  758.         pop     edi
  759.         mov     [edi + txfd.buf_addr], eax
  760.         mov     ecx, [esi + NET_BUFF.length]
  761.         mov     [edi + txfd.buf_size], ecx
  762.  
  763.         ; Inform device of the new/updated transmit descriptor
  764.         mov     eax, edi
  765.         invoke  GetPhysAddr
  766.         set_io  [ebx + device.io_addr], 0
  767.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  768.         out     dx, eax
  769.  
  770.         ; Start the transmit
  771.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  772.         mov     ax, CU_START
  773.         out     dx, ax
  774.  
  775.         ; Update stats
  776.         inc     [ebx + device.packets_tx]
  777.         add     dword[ebx + device.bytes_tx], ecx
  778.         adc     dword[ebx + device.bytes_tx + 4], 0
  779.  
  780.         ; Wait for command to complete
  781.         call    cmd_wait
  782.  
  783.         inc     [ebx + device.cur_tx]
  784.         and     [ebx + device.cur_tx], TX_RING_SIZE - 1
  785.  
  786.         DEBUGF  1,"Transmit OK\n"
  787.         popf
  788.         xor     eax, eax
  789.         ret
  790.  
  791.   .fail:
  792.         DEBUGF  2,"Transmit failed!\n"
  793.         invoke  NetFree, [bufferptr]
  794.         popf
  795.         or      eax, -1
  796.         ret
  797.  
  798. endp
  799.  
  800.  
  801. ;;;;;;;;;;;;;;;;;;;;;;;
  802. ;;                   ;;
  803. ;; Interrupt handler ;;
  804. ;;                   ;;
  805. ;;;;;;;;;;;;;;;;;;;;;;;
  806.  
  807. align 4
  808. int_handler:
  809.  
  810.         push    ebx esi edi
  811.  
  812.         DEBUGF  1,"INT\n"
  813.  
  814. ; find pointer of device wich made IRQ occur
  815.  
  816.         mov     ecx, [devices]
  817.         test    ecx, ecx
  818.         jz      .nothing
  819.         mov     esi, device_list
  820.   .nextdevice:
  821.         mov     ebx, [esi]
  822.  
  823. ;        set_io  [ebx + device.io_addr], 0      ; REG_SCB_STATUS = 0
  824.         set_io  [ebx + device.io_addr], REG_SCB_STATUS
  825.         in      ax, dx
  826.         out     dx, ax                          ; send it back to ACK
  827.         test    ax, ax
  828.         jnz     .got_it
  829.   .continue:
  830.         add     esi, 4
  831.         dec     ecx
  832.         jnz     .nextdevice
  833.   .nothing:
  834.         pop     edi esi ebx
  835.         xor     eax, eax
  836.  
  837.         ret                                         ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
  838.  
  839.   .got_it:
  840.  
  841.         DEBUGF  1,"Device: %x Status: %x\n", ebx, ax
  842.  
  843.         test    ax, SCB_STATUS_FR               ; did we receive a frame?
  844.         jz      .no_rx
  845.  
  846.         push    ax
  847.  
  848.         DEBUGF  1,"Receiving\n"
  849.  
  850.         push    ebx
  851.   .rx_loop:
  852.         pop     ebx
  853.  
  854.         mov     esi, [ebx + device.rx_desc]
  855.         test    [esi + sizeof.NET_BUFF + rxfd.status], RXFD_STATUS_C            ; Completed?
  856.         jz      .no_rx_
  857.         test    [esi + sizeof.NET_BUFF + rxfd.status], RXFD_STATUS_OK           ; OK?
  858.         jz      .not_ok
  859.  
  860.         DEBUGF  1,"rxfd status=0x%x\n", [esi + sizeof.NET_BUFF + rxfd.status]:4
  861.  
  862.         movzx   ecx, [esi + sizeof.NET_BUFF + rxfd.count]
  863.         and     ecx, 0x3fff
  864.  
  865.         push    ebx
  866.         push    .rx_loop
  867.         push    esi
  868.         mov     [esi + NET_BUFF.length], ecx
  869.         mov     [esi + NET_BUFF.device], ebx
  870.         mov     [esi + NET_BUFF.offset], NET_BUFF.data + rxfd.packet
  871.  
  872. ; Update stats
  873.         add     dword [ebx + device.bytes_rx], ecx
  874.         adc     dword [ebx + device.bytes_rx + 4], 0
  875.         inc     dword [ebx + device.packets_rx]
  876.  
  877. ; allocate new descriptor
  878.  
  879.         invoke  NetAlloc, 2000
  880.         test    eax, eax
  881.         jz      .out_of_mem
  882.         mov     [ebx + device.rx_desc], eax
  883.         mov     esi, eax
  884.         invoke  GetPhysAddr
  885.         add     eax, NET_BUFF.data
  886.         mov     [esi + sizeof.NET_BUFF + rxfd.status], 0
  887.         mov     [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
  888.         mov     [esi + sizeof.NET_BUFF + rxfd.link], eax
  889.         mov     [esi + sizeof.NET_BUFF + rxfd.count], 0
  890.         mov     [esi + sizeof.NET_BUFF + rxfd.size], 1528
  891.  
  892. ; restart RX
  893.  
  894.         set_io  [ebx + device.io_addr], 0
  895.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  896. ;        mov     eax, [ebx + device.rx_desc]
  897. ;        invoke  GetPhysAddr
  898. ;        add     eax, NET_BUFF.data
  899.         out     dx, eax
  900.  
  901.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  902.         mov     ax, RX_START
  903.         out     dx, ax
  904.         call    cmd_wait
  905.   .out_of_mem:
  906.  
  907. ; Hand the frame over to the kernel
  908.         jmp     [EthInput]
  909.  
  910.   .not_ok:
  911. ; Reset the FD
  912.         mov     [esi + sizeof.NET_BUFF + rxfd.status], 0
  913.         mov     [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
  914.         mov     [esi + sizeof.NET_BUFF + rxfd.count], 0
  915.  
  916. ; Restart RX
  917.         set_io  [ebx + device.io_addr], 0
  918.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  919.         mov     eax, esi
  920.         invoke  GetPhysAddr
  921.         add     eax, NET_BUFF.data
  922.         out     dx, eax
  923.  
  924.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  925.         mov     ax, RX_START
  926.         out     dx, ax
  927.         call    cmd_wait
  928.  
  929.         push    ebx
  930.         jmp     .rx_loop
  931.  
  932.   .no_rx_:
  933.         DEBUGF  1, "no more data\n"
  934.         pop     ax
  935.  
  936.   .no_rx:
  937.  
  938.         test    ax, SCB_STATUS_CNA
  939.         jz      .no_tx
  940.         DEBUGF  1, "Command completed\n"
  941.  
  942.         push    eax
  943.   .loop_tx:
  944.         mov     edi, [ebx + device.last_tx]
  945.         mov     eax, sizeof.txfd
  946.         mul     eax
  947.         lea     edi, [ebx + device.tx_ring + eax]
  948.  
  949.         cmp     [edi + txfd.status], 0
  950.         je      .tx_done
  951.  
  952.         cmp     [edi + txfd.virt_addr], 0
  953.         je      .tx_done
  954.  
  955.         DEBUGF  1,"Freeing buffer 0x%x\n", [edi + txfd.virt_addr]
  956.  
  957.         push    [edi + txfd.virt_addr]
  958.         mov     [edi + txfd.virt_addr], 0
  959.         invoke  NetFree
  960.  
  961.         inc     [ebx + device.last_tx]
  962.         and     [ebx + device.last_tx], TX_RING_SIZE - 1
  963.  
  964.         jmp     .loop_tx
  965.   .tx_done:
  966.         pop     eax
  967.   .no_tx:
  968.  
  969.         test    ax, RU_STATUS_NO_RESOURCES
  970.         jne     .fail
  971.  
  972.         DEBUGF  2, "Out of resources!\n"
  973.  
  974.   .fail:
  975.         pop     edi esi ebx
  976.         xor     eax, eax
  977.         inc     eax
  978.  
  979.         ret
  980.  
  981.  
  982.  
  983.  
  984. align 4
  985. cmd_wait:
  986.  
  987.         in      al, dx
  988.         test    al, al
  989.         jnz     cmd_wait
  990.  
  991.         ret
  992.  
  993.  
  994.  
  995.  
  996.  
  997.  
  998. align 4
  999. ee_read:        ; esi = address to read
  1000.  
  1001.         DEBUGF  1,"Eeprom read from 0x%x\n", esi
  1002.  
  1003.         set_io  [ebx + device.io_addr], 0
  1004.         set_io  [ebx + device.io_addr], REG_EEPROM
  1005.  
  1006. ;-----------------------------------------------------
  1007. ; Prepend start bit + read opcode to the address field
  1008. ; and shift it to the very left bits of esi
  1009.  
  1010.         mov     cl, 29
  1011.         sub     cl, [ebx + device.ee_bus_width]
  1012.         shl     esi, cl
  1013.         or      esi, EE_READ shl 29
  1014.  
  1015.         movzx   ecx, [ebx + device.ee_bus_width]
  1016.         add     ecx, 3
  1017.  
  1018.         mov     ax, 0x4800 + EE_CS
  1019.         out     dx, ax
  1020.         call    udelay
  1021.  
  1022. ;-----------------------
  1023. ; Write this to the chip
  1024.  
  1025.   .loop:
  1026.         mov     al, EE_CS
  1027.         shl     esi, 1
  1028.         jnc     @f
  1029.         or      al, EE_DI
  1030.        @@:
  1031.         out     dx, al
  1032.         call    udelay
  1033.  
  1034.         or      al, EE_SK
  1035.         out     dx, al
  1036.         call    udelay
  1037.  
  1038.         loop    .loop
  1039.  
  1040. ;------------------------------
  1041. ; Now read the data from eeprom
  1042.  
  1043.         xor     esi, esi
  1044.         mov     ecx, 16
  1045.  
  1046.   .loop2:
  1047.         shl     esi, 1
  1048.         mov     al, EE_CS
  1049.         out     dx, al
  1050.         call    udelay
  1051.  
  1052.         or      al, EE_SK
  1053.         out     dx, al
  1054.         call    udelay
  1055.  
  1056.         in      al, dx
  1057.         test    al, EE_DO
  1058.         jz      @f
  1059.         inc     esi
  1060.        @@:
  1061.  
  1062.         loop    .loop2
  1063.  
  1064. ;-----------------------
  1065. ; de-activate the eeprom
  1066.  
  1067.         xor     al, al
  1068.         out     dx, al
  1069.  
  1070.         DEBUGF  1,"0x%x\n", esi:4
  1071.         ret
  1072.  
  1073.  
  1074.  
  1075. align 4
  1076. ee_write:       ; esi = address to write to, di = data
  1077.  
  1078.         DEBUGF  1,"Eeprom write 0x%x to 0x%x\n", di, esi
  1079.  
  1080.         set_io  [ebx + device.io_addr], 0
  1081.         set_io  [ebx + device.io_addr], REG_EEPROM
  1082.  
  1083. ;-----------------------------------------------------
  1084. ; Prepend start bit + write opcode to the address field
  1085. ; and shift it to the very left bits of esi
  1086.  
  1087.         mov     cl, 29
  1088.         sub     cl, [ebx + device.ee_bus_width]
  1089.         shl     esi, cl
  1090.         or      esi, EE_WRITE shl 29
  1091.  
  1092.         movzx   ecx, [ebx + device.ee_bus_width]
  1093.         add     ecx, 3
  1094.  
  1095.         mov     ax, 0x4800 + EE_CS       ; enable chip
  1096.         out     dx, ax
  1097.  
  1098. ;-----------------------
  1099. ; Write this to the chip
  1100.  
  1101.   .loop:
  1102.         mov     al, EE_CS
  1103.         shl     esi, 1
  1104.         jnc     @f
  1105.         or      al, EE_DI
  1106.        @@:
  1107.         out     dx, al
  1108.         call    udelay
  1109.  
  1110.         or      al, EE_SK
  1111.         out     dx, al
  1112.         call    udelay
  1113.  
  1114.         loop    .loop
  1115.  
  1116. ;-----------------------------
  1117. ; Now write the data to eeprom
  1118.  
  1119.         mov     ecx, 16
  1120.  
  1121.   .loop2:
  1122.         mov     al, EE_CS
  1123.         shl     di, 1
  1124.         jnc     @f
  1125.         or      al, EE_DI
  1126.        @@:
  1127.         out     dx, al
  1128.         call    udelay
  1129.  
  1130.         or      al, EE_SK
  1131.         out     dx, al
  1132.         call    udelay
  1133.  
  1134.         loop    .loop2
  1135.  
  1136. ;-----------------------
  1137. ; de-activate the eeprom
  1138.  
  1139.         xor     al, al
  1140.         out     dx, al
  1141.  
  1142.  
  1143.         ret
  1144.  
  1145.  
  1146.  
  1147. align 4
  1148. ee_get_width:
  1149.  
  1150.         set_io  [ebx + device.io_addr], 0
  1151.         set_io  [ebx + device.io_addr], REG_EEPROM
  1152.  
  1153.         mov     ax, 0x4800 + EE_CS      ; activate eeprom
  1154.         out     dx, ax
  1155.         call    udelay
  1156.  
  1157.         mov     si, EE_READ shl 13
  1158.         xor     ecx, ecx
  1159.   .loop:
  1160.         mov     al, EE_CS
  1161.         shl     si, 1
  1162.         jnc     @f
  1163.         or      al, EE_DI
  1164.        @@:
  1165.         out     dx, ax
  1166.         call    udelay
  1167.  
  1168.         or      al, EE_SK
  1169.         out     dx, ax
  1170.         call    udelay
  1171.  
  1172.         inc     ecx
  1173.  
  1174.         cmp     ecx, 15
  1175.         jae     .give_up
  1176.  
  1177.         in      al, dx
  1178.         test    al, EE_DO
  1179.         jnz     .loop
  1180.  
  1181.         xor     al, al
  1182.         out     dx, al                  ; de-activate eeprom
  1183.  
  1184.         sub     cl, 3                   ; dont count the opcode bits
  1185.         mov     [ebx + device.ee_bus_width], cl
  1186.         DEBUGF  1, "Eeprom width=%u bit\n", ecx
  1187.  
  1188.         ret
  1189.  
  1190.   .give_up:
  1191.         DEBUGF  2, "Eeprom not found!\n"
  1192.         xor     al, al
  1193.         out     dx, al                  ; de-activate eeprom
  1194.  
  1195.         ret
  1196.  
  1197.  
  1198. ; Wait a minimum of 2µs
  1199. udelay:
  1200.         pusha
  1201.         mov     esi, 1
  1202.         invoke  Sleep
  1203.         popa
  1204.  
  1205.         ret
  1206.  
  1207.  
  1208.  
  1209. ; cx = phy addr
  1210. ; dx = phy reg addr
  1211.  
  1212. ; ax = data
  1213.  
  1214. align 4
  1215. mdio_read:
  1216.  
  1217.         DEBUGF  1,"MDIO read\n"
  1218.  
  1219.         shl     ecx, 21                 ; PHY addr
  1220.         mov     eax, ecx
  1221.         shl     edx, 16                 ; PHY reg addr
  1222.         or      eax, edx
  1223.         or      eax, 10b shl 26         ; read opcode
  1224.  
  1225.         set_io  [ebx + device.io_addr], 0
  1226.         set_io  [ebx + device.io_addr], REG_MDI_CTRL
  1227.         out     dx, eax
  1228.  
  1229.   .wait:
  1230.         call    udelay
  1231.         in      eax, dx
  1232.         test    eax, 1 shl 28           ; ready bit
  1233.         jz      .wait
  1234.  
  1235.         ret
  1236.  
  1237.  
  1238.  
  1239. ; ax = data
  1240. ; cx = phy addr
  1241. ; dx = phy reg addr
  1242.  
  1243. ; ax = data
  1244.  
  1245. align 4
  1246. mdio_write:
  1247.  
  1248.         DEBUGF  1,"MDIO write\n"
  1249.  
  1250.         and     eax, 0xffff
  1251.  
  1252.         shl     ecx, 21                 ; PHY addr
  1253.         shl     edx, 16                 ; PHY reg addr
  1254.  
  1255.         or      eax, ecx
  1256.         or      eax, edx
  1257.         or      eax, 01b shl 26         ; write opcode
  1258.  
  1259.         set_io  [ebx + device.io_addr], 0
  1260.         set_io  [ebx + device.io_addr], REG_MDI_CTRL
  1261.         out     dx, eax
  1262.  
  1263.   .wait:
  1264.         call    udelay
  1265.         in      eax, dx
  1266.         test    eax, 1 shl 28           ; ready bit
  1267.         jz      .wait
  1268.  
  1269.         ret
  1270.  
  1271.  
  1272. align 4
  1273. mac_read_eeprom:
  1274.  
  1275.         mov     esi, 0
  1276.         call    ee_read
  1277.         mov     word[ebx + device.mac], si
  1278.  
  1279.         mov     esi, 1
  1280.         call    ee_read
  1281.         mov     word[ebx + device.mac+2], si
  1282.  
  1283.         mov     esi, 2
  1284.         call    ee_read
  1285.         mov     word[ebx + device.mac+4], si
  1286.  
  1287.  
  1288.         ret
  1289.  
  1290.  
  1291. ; End of code
  1292.  
  1293.  
  1294. data fixups
  1295. end data
  1296.  
  1297. include '../peimport.inc'
  1298.  
  1299. my_service      db 'I8255X', 0                    ; max 16 chars include zero
  1300. devicename      db 'Intel Etherexpress pro/100', 0
  1301.  
  1302. confcmd_data    db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1
  1303.                 db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2
  1304.                 db 0x80, 0x3f, 0x05                                     ; 22 bytes total
  1305.  
  1306.  
  1307. device_id_list:
  1308. dw 0x1029
  1309. dw 0x1030
  1310. dw 0x1031
  1311. dw 0x1032
  1312. dw 0x1033
  1313. dw 0x1034
  1314. dw 0x1038
  1315. dw 0x1039
  1316. dw 0x103A
  1317. dw 0x103B
  1318. dw 0x103C
  1319. dw 0x103D
  1320. dw 0x103E
  1321. dw 0x1050
  1322. dw 0x1051
  1323. dw 0x1052
  1324. dw 0x1053
  1325. dw 0x1054
  1326. dw 0x1055
  1327. dw 0x1056
  1328. dw 0x1057
  1329. dw 0x1059
  1330. dw 0x1064
  1331. dw 0x1065
  1332. dw 0x1066
  1333. dw 0x1067
  1334. dw 0x1068
  1335. dw 0x1069
  1336. dw 0x106A
  1337. dw 0x106B
  1338. dw 0x1091
  1339. dw 0x1092
  1340. dw 0x1093
  1341. dw 0x1094
  1342. dw 0x1095
  1343. dw 0x10fe
  1344. dw 0x1209
  1345. dw 0x1229
  1346. dw 0x2449
  1347. dw 0x2459
  1348. dw 0x245D
  1349. dw 0x27DC
  1350.  
  1351. DEVICE_IDs = ($ - device_id_list) / 2
  1352.  
  1353. include_debug_strings                           ; All data wich FDO uses will be included here
  1354.  
  1355. align 4
  1356. devices         dd 0                              ; number of currently running devices
  1357. device_list     rd MAX_DEVICES                    ; This list contains all pointers to device structures the driver is handling
  1358.  
  1359.