Subversion Repositories Kolibri OS

Rev

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