Subversion Repositories Kolibri OS

Rev

Rev 5522 | Rev 8898 | 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. ;;  AMD PCnet driver for KolibriOS                                  ;;
  7. ;;                                                                  ;;
  8. ;;  By hidnplayr & clevermouse                                      ;;
  9. ;;                                                                  ;;
  10. ;;  Based on the PCnet32 driver for MenuetOS, by Jarek Pelczar      ;;
  11. ;;                                                                  ;;
  12. ;;          GNU GENERAL PUBLIC LICENSE                              ;;
  13. ;;             Version 2, June 1991                                 ;;
  14. ;;                                                                  ;;
  15. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  16.  
  17. format PE DLL native
  18. entry START
  19.  
  20.         CURRENT_API             = 0x0200
  21.         COMPATIBLE_API          = 0x0100
  22.         API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
  23.  
  24.         MAX_DEVICES             = 16
  25.  
  26.         __DEBUG__               = 1
  27.         __DEBUG_LEVEL__         = 2             ; 1 = verbose, 2 = errors only
  28.  
  29.         TX_RING_SIZE            = 4
  30.         RX_RING_SIZE            = 4
  31.  
  32. section '.flat' readable writable executable
  33.  
  34. include '../struct.inc'
  35. include '../macros.inc'
  36. include '../proc32.inc'
  37. include '../fdo.inc'
  38. include '../netdrv.inc'
  39.  
  40.  
  41.         PORT_AUI                = 0x00
  42.         PORT_10BT               = 0x01
  43.         PORT_GPSI               = 0x02
  44.         PORT_MII                = 0x03
  45.         PORT_PORTSEL            = 0x03
  46.         PORT_ASEL               = 0x04
  47.         PORT_100                = 0x40
  48.         PORT_FD                 = 0x80
  49.  
  50.         DMA_MASK                = 0xffffffff
  51.  
  52.         LOG_TX_BUFFERS          = 2             ; FIXME
  53.         LOG_RX_BUFFERS          = 2
  54.  
  55.         TX_RING_MOD_MASK        = (TX_RING_SIZE-1)
  56.         TX_RING_LEN_BITS        = (LOG_TX_BUFFERS shl 12)
  57.  
  58.         RX_RING_MOD_MASK        = (RX_RING_SIZE-1)
  59.         RX_RING_LEN_BITS        = (LOG_RX_BUFFERS shl 4)
  60.  
  61.         PKT_BUF_SZ              = 1544
  62.  
  63.         WIO_RDP                 = 0x10
  64.         WIO_RAP                 = 0x12
  65.         WIO_RESET               = 0x14
  66.         WIO_BDP                 = 0x16
  67.  
  68.         DWIO_RDP                = 0x10
  69.         DWIO_RAP                = 0x14
  70.         DWIO_RESET              = 0x18
  71.         DWIO_BDP                = 0x1C
  72.  
  73. ; CSR registers
  74.  
  75.         CSR_CSR                 = 0x00
  76.         CSR_IAB0                = 0x01
  77.         CSR_IAB1                = 0x02
  78.         CSR_IMR                 = 0x03
  79.         CSR_TFEAT               = 0x04
  80.         CSR_EXTCTL1             = 0x05
  81.         CSR_DTBLLEN             = 0x06
  82.         CSR_EXTCTL2             = 0x07
  83.         CSR_MAR0                = 0x08
  84.         CSR_MAR1                = 0x09
  85.         CSR_MAR2                = 0x0A
  86.         CSR_MAR3                = 0x0B
  87.         CSR_PAR0                = 0x0C
  88.         CSR_PAR1                = 0x0D
  89.         CSR_PAR2                = 0x0E
  90.         CSR_MODE                = 0x0F
  91.         CSR_RXADDR0             = 0x18
  92.         CSR_RXADDR1             = 0x19
  93.         CSR_TXADDR0             = 0x1E
  94.         CSR_TXADDR1             = 0x1F
  95.         CSR_TXPOLL              = 0x2F
  96.         CSR_RXPOLL              = 0x31
  97.         CSR_RXRINGLEN           = 0x4C
  98.         CSR_TXRINGLEN           = 0x4E
  99.         CSR_DMACTL              = 0x50
  100.         CSR_BUSTIMER            = 0x52
  101.         CSR_MEMERRTIMEO         = 0x64
  102.         CSR_ONNOWMISC           = 0x74
  103.         CSR_ADVFEAT             = 0x7A
  104.         CSR_MACCFG              = 0x7D
  105.         CSR_CHIPID0             = 0x58
  106.         CSR_CHIPID1             = 0x59
  107.  
  108. ; Control and Status Register (CSR0)
  109.  
  110.         CSR_INIT                = 0x0001 ;1 shl 0
  111.         CSR_START               = 0x0002 ;1 shl 1
  112.         CSR_STOP                = 0x0004 ;1 shl 2
  113.         CSR_TX                  = 0x0008 ;1 shl 3
  114.         CSR_TXON                = 0x0010 ;1 shl 4
  115.         CSR_RXON                = 0x0020 ;1 shl 5
  116.         CSR_INTEN               = 0x0040 ;1 shl 6
  117.         CSR_INTR                = 0x0080 ;1 shl 7
  118.         CSR_IDONE               = 0x0100 ;1 shl 8
  119.         CSR_TINT                = 0x0200 ;1 shl 9
  120.         CSR_RINT                = 0x0400 ;1 shl 10
  121.         CSR_MERR                = 0x0800 ;1 shl 11
  122.         CSR_MISS                = 0x1000 ;1 shl 12
  123.         CSR_CERR                = 0x2000 ;1 shl 13
  124.  
  125. ; Interrupt masks and deferral control (CSR3)
  126.  
  127.         IMR_BSWAP               = 0x0004
  128.         IMR_ENMBA               = 0x0008  ; enable modified backoff alg
  129.         IMR_DXMT2PD             = 0x0010
  130.         IMR_LAPPEN              = 0x0020  ; lookahead packet processing enb
  131.         IMR_DXSUFLO             = 0x0040  ; disable TX stop on underflow
  132.         IMR_IDONE               = 0x0100
  133.         IMR_TINT                = 0x0200
  134.         IMR_RINT                = 0x0400
  135.         IMR_MERR                = 0x0800
  136.         IMR_MISS                = 0x1000
  137.  
  138.         ; Masked interrupts will be disabled.
  139.         IMR                     = 0 ;IMR_IDONE ;or IMR_TINT or IMR_RINT or IMR_MERR or IMR_MISS
  140.  
  141. ; Test and features control (CSR4)
  142.  
  143.         TFEAT_TXSTRTMASK        = 0x0004
  144.         TFEAT_TXSTRT            = 0x0008
  145.         TFEAT_RXCCOFLOWM        = 0x0010  ; Rx collision counter oflow
  146.         TFEAT_RXCCOFLOW         = 0x0020
  147.         TFEAT_UINT              = 0x0040
  148.         TFEAT_UINTREQ           = 0x0080
  149.         TFEAT_MISSOFLOWM        = 0x0100
  150.         TFEAT_MISSOFLOW         = 0x0200
  151.         TFEAT_STRIP_FCS         = 0x0400
  152.         TFEAT_PAD_TX            = 0x0800
  153.         TFEAT_TXDPOLL           = 0x1000
  154.         TFEAT_DMAPLUS           = 0x4000
  155.  
  156. ; Extended control and interrupt 1 (CSR5)
  157.  
  158.         EXTCTL1_SPND            = 0x0001  ; suspend
  159.         EXTCTL1_MPMODE          = 0x0002  ; magic packet mode
  160.         EXTCTL1_MPENB           = 0x0004  ; magic packet enable
  161.         EXTCTL1_MPINTEN         = 0x0008  ; magic packet interrupt enable
  162.         EXTCTL1_MPINT           = 0x0010  ; magic packet interrupt
  163.         EXTCTL1_MPPLBA          = 0x0020  ; magic packet phys. logical bcast
  164.         EXTCTL1_EXDEFEN         = 0x0040  ; excessive deferral interrupt enb.
  165.         EXTCTL1_EXDEF           = 0x0080  ; excessive deferral interrupt
  166.         EXTCTL1_SINTEN          = 0x0400  ; system interrupt enable
  167.         EXTCTL1_SINT            = 0x0800  ; system interrupt
  168.         EXTCTL1_LTINTEN         = 0x4000  ; last TX interrupt enb
  169.         EXTCTL1_TXOKINTD        = 0x8000  ; TX OK interrupt disable
  170.  
  171. ; RX/TX descriptor len (CSR6)
  172.  
  173.         DTBLLEN_RLEN            = 0x0F00
  174.         DTBLLEN_TLEN            = 0xF000
  175.  
  176. ; Extended control and interrupt 2 (CSR7)
  177.  
  178.         EXTCTL2_MIIPDTINTE      = 0x0001
  179.         EXTCTL2_MIIPDTINT       = 0x0002
  180.         EXTCTL2_MCCIINTE        = 0x0004
  181.         EXTCTL2_MCCIINT         = 0x0008
  182.         EXTCTL2_MCCINTE         = 0x0010
  183.         EXTCTL2_MCCINT          = 0x0020
  184.         EXTCTL2_MAPINTE         = 0x0040
  185.         EXTCTL2_MAPINT          = 0x0080
  186.         EXTCTL2_MREINTE         = 0x0100
  187.         EXTCTL2_MREINT          = 0x0200
  188.         EXTCTL2_STINTE          = 0x0400
  189.         EXTCTL2_STINT           = 0x0800
  190.         EXTCTL2_RXDPOLL         = 0x1000
  191.         EXTCTL2_RDMD            = 0x2000
  192.         EXTCTL2_RXFRTG          = 0x4000
  193.         EXTCTL2_FASTSPNDE       = 0x8000
  194.  
  195. ; Mode (CSR15)
  196.  
  197.         MODE_RXD                = 0x0001  ; RX disable
  198.         MODE_TXD                = 0x0002  ; TX disable
  199.         MODE_LOOP               = 0x0004  ; loopback enable
  200.         MODE_TXCRCD             = 0x0008
  201.         MODE_FORCECOLL          = 0x0010
  202.         MODE_RETRYD             = 0x0020
  203.         MODE_INTLOOP            = 0x0040
  204.         MODE_PORTSEL            = 0x0180
  205.         MODE_RXVPAD             = 0x2000
  206.         MODE_RXNOBROAD          = 0x4000
  207.         MODE_PROMISC            = 0x8000
  208.  
  209. ; BCR (Bus Control Registers)
  210.  
  211.         BCR_MMRA                = 0x00    ; Master Mode Read Active
  212.         BCR_MMW                 = 0x01    ; Master Mode Write Active
  213.         BCR_MISCCFG             = 0x02
  214.         BCR_LED0                = 0x04
  215.         BCR_LED1                = 0x05
  216.         BCR_LED2                = 0x06
  217.         BCR_LED3                = 0x07
  218.         BCR_DUPLEX              = 0x09
  219.         BCR_BUSCTL              = 0x12
  220.         BCR_EECTL               = 0x13
  221.         BCR_SSTYLE              = 0x14
  222.         BCR_PCILAT              = 0x16
  223.         BCR_PCISUBVENID         = 0x17
  224.         BCR_PCISUBSYSID         = 0x18
  225.         BCR_SRAMSIZE            = 0x19
  226.         BCR_SRAMBOUND           = 0x1A
  227.         BCR_SRAMCTL             = 0x1B
  228.         BCR_MIICTL              = 0x20
  229.         BCR_MIIADDR             = 0x21
  230.         BCR_MIIDATA             = 0x22
  231.         BCR_PCIVENID            = 0x23
  232.         BCR_PCIPCAP             = 0x24
  233.         BCR_DATA0               = 0x25
  234.         BCR_DATA1               = 0x26
  235.         BCR_DATA2               = 0x27
  236.         BCR_DATA3               = 0x28
  237.         BCR_DATA4               = 0x29
  238.         BCR_DATA5               = 0x2A
  239.         BCR_DATA6               = 0x2B
  240.         BCR_DATA7               = 0x2C
  241.         BCR_ONNOWPAT0           = 0x2D
  242.         BCR_ONNOWPAT1           = 0x2E
  243.         BCR_ONNOWPAT2           = 0x2F
  244.         BCR_PHYSEL              = 0x31
  245.  
  246. ; RX status register
  247.  
  248.         RXSTAT_BPE              = 0x0080        ; bus parity error
  249.         RXSTAT_ENP              = 0x0100        ; end of packet
  250.         RXSTAT_STP              = 0x0200        ; start of packet
  251.         RXSTAT_BUFF             = 0x0400        ; buffer error
  252.         RXSTAT_CRC              = 0x0800        ; CRC error
  253.         RXSTAT_OFLOW            = 0x1000        ; rx overrun
  254.         RXSTAT_FRAM             = 0x2000        ; framing error
  255.         RXSTAT_ERR              = 0x4000        ; error summary
  256.         RXSTAT_OWN              = 0x8000
  257.  
  258. ; TX status register
  259.  
  260.         TXSTAT_TRC              = 0x0000000F    ; transmit retries
  261.         TXSTAT_RTRY             = 0x04000000    ; retry
  262.         TXSTAT_LCAR             = 0x08000000    ; lost carrier
  263.         TXSTAT_LCOL             = 0x10000000    ; late collision
  264.         TXSTAT_EXDEF            = 0x20000000    ; excessive deferrals
  265.         TXSTAT_UFLOW            = 0x40000000    ; transmit underrun
  266.         TXSTAT_BUFF             = 0x80000000    ; buffer error
  267.  
  268.         TXCTL_OWN               = 0x8000
  269.         TXCTL_ERR               = 0x4000        ; error summary
  270.         TXCTL_ADD_FCS           = 0x2000        ; add FCS to pkt
  271.         TXCTL_MORE_LTINT        = 0x1000
  272.         TXCTL_ONE               = 0x0800
  273.         TXCTL_DEF               = 0x0400
  274.         TXCTL_STP               = 0x0200
  275.         TXCTL_ENP               = 0x0100
  276.         TXCTL_BPE               = 0x0080
  277.  
  278.         TXCTL_MBO               = 0x0000F000
  279.         TXCTL_BUFSZ             = 0x00000FFF
  280.  
  281.         MAX_PHYS                = 32
  282.  
  283.  
  284. struct  device          ETH_DEVICE
  285.  
  286.         rb 0x100-($ and 0xff)   ; align 256
  287.  
  288. ; Pcnet configuration structure
  289.         mode            dw ?
  290.         tlen_rlen       dw ?
  291.         phys_addr       dp ?
  292.         reserved        dw ?
  293.         filter          dq ?
  294.         rx_ring_phys    dd ?
  295.         tx_ring_phys    dd ?
  296. ; end of pcnet config struct
  297.  
  298.         rb 0x100-($ and 0xff)   ; align 256
  299.  
  300.         rx_ring         rb RX_RING_SIZE * sizeof.descriptor
  301.  
  302.         rb 0x100-($ and 0xff)   ; align 256
  303.  
  304.         tx_ring         rb TX_RING_SIZE * sizeof.descriptor
  305.  
  306.         cur_rx          db ?
  307.         cur_tx          db ?
  308.         last_tx         db ?
  309.         options         dd ?
  310.         full_duplex     db ?
  311.         chip_version    dw ?
  312.         mii             db ?
  313.         ltint           db ?
  314.         dxsuflo         db ?
  315.         fset            db ?
  316.         fdx             db ?
  317.  
  318.         io_addr         dd ?
  319.         irq_line        db ?
  320.         pci_bus         dd ?
  321.         pci_dev         dd ?
  322.  
  323.         phy             dw ?
  324.  
  325.         read_csr        dd ?
  326.         write_csr       dd ?
  327.         read_bcr        dd ?
  328.         write_bcr       dd ?
  329.         read_rap        dd ?
  330.         write_rap       dd ?
  331.         sw_reset        dd ?
  332.  
  333. ends
  334.  
  335. struct  descriptor
  336.  
  337.         base            dd ?
  338.         length          dw ?
  339.         status          dw ?
  340.         msg_length      dw ?
  341.         misc            dw ?
  342.         virtual         dd ?
  343.  
  344. ends
  345.  
  346.  
  347. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  348. ;;                        ;;
  349. ;; proc START             ;;
  350. ;;                        ;;
  351. ;; (standard driver proc) ;;
  352. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  353.  
  354. proc START c, reason:dword, cmdline:dword
  355.  
  356.         cmp     [reason], DRV_ENTRY
  357.         jne     .fail
  358.  
  359.         DEBUGF  2,"Loading driver\n"
  360.         invoke  RegService, my_service, service_proc
  361.         ret
  362.  
  363.   .fail:
  364.         xor eax, eax
  365.         ret
  366.  
  367. endp
  368.  
  369.  
  370. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  371. ;;                        ;;
  372. ;; proc SERVICE_PROC      ;;
  373. ;;                        ;;
  374. ;; (standard driver proc) ;;
  375. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  376.  
  377. align 4
  378. proc service_proc stdcall, ioctl:dword
  379.  
  380.         mov     edx, [ioctl]
  381.         mov     eax, [edx + IOCTL.io_code]
  382.  
  383. ;------------------------------------------------------
  384.  
  385.         cmp     eax, 0 ;SRV_GETVERSION
  386.         jne     @F
  387.  
  388.         cmp     [edx + IOCTL.out_size], 4
  389.         jb      .fail
  390.         mov     eax, [edx + IOCTL.output]
  391.         mov     [eax], dword API_VERSION
  392.  
  393.         xor     eax, eax
  394.         ret
  395.  
  396. ;------------------------------------------------------
  397.   @@:
  398.         cmp     eax, 1 ;SRV_HOOK
  399.         jne     .fail
  400.  
  401.         cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
  402.         jb      .fail
  403.  
  404.         mov     eax, [edx + IOCTL.input]
  405.         cmp     byte[eax], 1                            ; 1 means device number and bus number (pci) are given
  406.         jne     .fail                                   ; other types arent supported for this card yet
  407.  
  408. ; check if the device is already listed
  409.  
  410.         mov     ecx, [devices]
  411.         test    ecx, ecx
  412.         jz      .firstdevice
  413.  
  414.         mov     esi, device_list
  415. ;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
  416.         mov     ax, [eax+1]                             ;
  417.   .nextdevice:
  418.         mov     ebx, [esi]
  419.         cmp     al, byte[ebx + device.pci_bus]
  420.         jne     @f
  421.         cmp     ah, byte[ebx + device.pci_dev]
  422.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  423.        @@:
  424.         add     esi, 4
  425.         loop    .nextdevice
  426.  
  427. ; This device doesnt have its own eth_device structure yet, lets create one
  428.  
  429.   .firstdevice:
  430.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  431.         jae     .fail
  432.  
  433.         allocate_and_clear ebx, sizeof.device, .fail
  434.  
  435. ; Fill in the direct call addresses into the struct
  436.  
  437.         mov     [ebx + device.reset], reset
  438.         mov     [ebx + device.transmit], transmit
  439.         mov     [ebx + device.unload], unload
  440.         mov     [ebx + device.name], my_service
  441.  
  442. ; save the pci bus and device numbers
  443.  
  444.         mov     eax, [edx + IOCTL.input]
  445.         movzx   ecx, byte[eax+1]
  446.         mov     [ebx + device.pci_bus], ecx
  447.         movzx   ecx, byte[eax+2]
  448.         mov     [ebx + device.pci_dev], ecx
  449.  
  450. ; Now, it's time to find the base io addres of the PCI device
  451.  
  452.         stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
  453.         mov     [ebx + device.io_addr], eax
  454.  
  455. ; We've found the io address, find IRQ now
  456.  
  457.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
  458.         mov     [ebx + device.irq_line], al
  459.  
  460.         DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  461.         [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:4
  462.  
  463. ; Ok, the eth_device structure is ready, let's probe the device
  464. ; Because initialization fires IRQ, IRQ handler must be aware of this device
  465.         mov     eax, [devices]                                          ; Add the device structure to our device list
  466.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  467.         inc     [devices]                                               ;
  468.  
  469.         call    probe                                                   ; this function will output in eax
  470.         test    eax, eax
  471.         jnz     .destroy                                                ; If an error occured, exit
  472.  
  473.         mov     [ebx + device.type], NET_TYPE_ETH
  474.         invoke  NetRegDev
  475.         cmp     eax, -1
  476.         je      .destroy
  477.  
  478.         ret
  479.  
  480. ; If the device was already loaded, find the device number and return it in eax
  481.  
  482.   .find_devicenum:
  483.         DEBUGF  1,"Trying to find device number of already registered device\n"
  484.         invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  485.                                                                         ; into a device number in edi
  486.         mov     eax, edi                                                ; Application wants it in eax instead
  487.         DEBUGF  1,"Kernel says: %u\n", eax
  488.         ret
  489.  
  490. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  491.  
  492.   .destroy:
  493.         ; todo: reset device into virgin state
  494.         add     eax, NET_BUFF.data
  495.         dec     [devices]
  496.   .err:
  497.         DEBUGF  2,"Error, removing all data !\n"
  498.         invoke  KernelFree, ebx
  499.  
  500.   .fail:
  501.         or      eax, -1
  502.         ret
  503.  
  504. ;------------------------------------------------------
  505. endp
  506.  
  507.  
  508. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  509. ;;                                                                        ;;
  510. ;;        Actual Hardware dependent code starts here                      ;;
  511. ;;                                                                        ;;
  512. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  513.  
  514. align 4
  515. unload:
  516.         ; TODO: (in this particular order)
  517.         ;
  518.         ; - Stop the device
  519.         ; - Detach int handler
  520.         ; - Remove device from local list (device_list)
  521.         ; - call unregister function in kernel
  522.         ; - Remove all allocated structures and buffers the card used
  523.  
  524.         or      eax, -1
  525.         ret
  526.  
  527.  
  528. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  529. ;;
  530. ;;  probe: enables the device (if it really is a PCnet device)
  531. ;;
  532. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  533.  
  534. align 4
  535. probe:
  536.  
  537.         mov     edx, [ebx + device.io_addr]
  538.  
  539.         call    wio_reset
  540.  
  541.         xor     ecx, ecx
  542.         call    wio_read_csr
  543.         cmp     eax, 4
  544.         jne     .try_dwio
  545.  
  546.         ; Try Word I/O
  547.         mov     ax, 88
  548.         add     edx, WIO_RAP
  549.         out     dx, ax
  550.         nop
  551.         nop
  552.         in      ax, dx
  553.         sub     edx, WIO_RAP
  554.         cmp     ax, 88
  555.         jne     .try_dwio
  556.  
  557.         call    switch_to_wio
  558.  
  559.         jmp     .L1
  560.  
  561.   .try_dwio:
  562.         call    dwio_reset
  563.  
  564.         xor     ecx, ecx
  565.         call    dwio_read_csr
  566.         cmp     eax, 4
  567.         jne     .no_dev
  568.  
  569.         ; Try Dword I/O
  570.         add     edx, DWIO_RAP
  571.         mov     eax, 88
  572.         out     dx, eax
  573.         nop
  574.         nop
  575.         in      eax, dx
  576.         sub     edx, DWIO_RAP
  577.         and     eax, 0xffff
  578.         cmp     eax, 88
  579.         jne     .no_dev
  580.  
  581.         call    switch_to_dwio
  582.  
  583.         jmp     .L1
  584.  
  585.   .no_dev:
  586.         DEBUGF  2,"device not found!\n"
  587.         mov     eax, 1
  588.         ret
  589.  
  590.   .L1:
  591.         mov     ecx, CSR_CHIPID0
  592.         call    [ebx + device.read_csr]
  593.  
  594.         mov     esi, eax
  595.         shr     esi, 12
  596.  
  597.         and     ax, 0xfff
  598.         cmp     ax, 3
  599.         jne     .no_dev
  600.  
  601.         mov     ecx, CSR_CHIPID1
  602.         call    [ebx + device.read_csr]
  603.         shl     eax, 4
  604.         or      eax, esi
  605.         mov     [ebx + device.chip_version], ax
  606.  
  607.         mov     [ebx + device.fdx], 0
  608.         mov     [ebx + device.mii], 0
  609.         mov     [ebx + device.fset], 0
  610.         mov     [ebx + device.dxsuflo], 0
  611.         mov     [ebx + device.ltint], 0
  612.  
  613.         cmp     ax, 0x2420
  614.         je      .L2
  615.         cmp     ax, 0x2430
  616.         je      .L2
  617.  
  618.         mov     [ebx + device.fdx], 1
  619.  
  620.         cmp     ax, 0x2621
  621.         je      .L4
  622.         cmp     ax, 0x2623
  623.         je      .L5
  624.         cmp     ax, 0x2624
  625.         je      .L6
  626.         cmp     ax, 0x2625
  627.         je      .L7
  628.         cmp     ax, 0x2626
  629.         je      .L8
  630.         cmp     ax, 0x2627
  631.         je      .L9
  632.  
  633.         DEBUGF  2,"Invalid chip rev\n"
  634.         jmp     .no_dev
  635.   .L2:
  636.         mov     [ebx + device.name], device_l2
  637.         jmp     .L10
  638.   .L4:
  639.         mov     [ebx + device.name], device_l4
  640. ;        mov     [ebx + device.fdx], 1
  641.         jmp     .L10
  642.   .L5:
  643.         mov     [ebx + device.name], device_l5
  644. ;        mov     [ebx + device.fdx], 1
  645.         mov     [ebx + device.mii], 1
  646.         mov     [ebx + device.fset], 1
  647.         mov     [ebx + device.ltint], 1
  648.         jmp     .L10
  649.   .L6:
  650.         mov     [ebx + device.name], device_l6
  651. ;        mov     [ebx + device.fdx], 1
  652.         mov     [ebx + device.mii], 1
  653.         mov     [ebx + device.fset], 1
  654.         jmp     .L10
  655.   .L7:
  656.         mov     [ebx + device.name], device_l7
  657. ;        mov     [ebx + device.fdx], 1
  658.         mov     [ebx + device.mii], 1
  659.         jmp     .L10
  660.   .L8:
  661.         mov     [ebx + device.name], device_l8
  662. ;        mov     [ebx + device.fdx], 1
  663.         mov     ecx, CSR_RXPOLL
  664.         call    dword [ebx + device.read_bcr]
  665.         call    dword [ebx + device.write_bcr]
  666.         jmp     .L10
  667.   .L9:
  668.         mov     [ebx + device.name], device_l9
  669. ;        mov     [ebx + device.fdx], 1
  670.         mov     [ebx + device.mii], 1
  671.   .L10:
  672.         DEBUGF  1,"device name: %s\n", [ebx + device.name]
  673.  
  674.         cmp     [ebx + device.fset], 1
  675.         jne     .L11
  676.         mov     ecx, BCR_BUSCTL
  677.         call    [ebx + device.read_bcr]
  678.         or      eax, 0x800
  679.         call    [ebx + device.write_bcr]
  680.  
  681.         mov     ecx, CSR_DMACTL
  682. ;        call    [ebx + device.read_csr]
  683.         mov     eax, 0xc00
  684.         call    [ebx + device.write_csr]
  685.  
  686.         mov     [ebx + device.dxsuflo],1
  687.         mov     [ebx + device.ltint],1
  688.   .L11:
  689.  
  690. ; Make the device a bus master
  691.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
  692.         or      al, PCI_CMD_MASTER
  693.         invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
  694.  
  695.         mov     [ebx + device.options], PORT_ASEL
  696.         mov     [ebx + device.mode], MODE_RXD + MODE_TXD     ; disable receive and transmit
  697.         mov     [ebx + device.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
  698.  
  699.         mov     dword[ebx + device.filter], 0
  700.         mov     dword[ebx + device.filter+4], 0
  701.  
  702. align 4
  703. reset:
  704.  
  705. ; attach int handler
  706.  
  707.         movzx   eax, [ebx + device.irq_line]
  708.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  709.         invoke  AttachIntHandler, eax, int_handler, ebx
  710.         test    eax, eax
  711.         jnz     @f
  712.         DEBUGF  2,"Could not attach int handler!\n"
  713.         or      eax, -1
  714.         ret
  715.   @@:
  716.  
  717.         mov     edx, [ebx + device.io_addr]
  718.         call    [ebx + device.sw_reset]
  719.  
  720.         ; Switch pcnet32 to 32bit mode
  721.         mov     ecx, BCR_SSTYLE
  722.         mov     eax, 2
  723.         call    [ebx + device.write_bcr]
  724.  
  725.         ; set/reset autoselect bit
  726.         mov     ecx, BCR_MISCCFG
  727.         call    [ebx + device.read_bcr]
  728.         and     eax, not 2
  729.         test    [ebx + device.options], PORT_ASEL
  730.         jz      @f
  731.         or      eax, 2
  732.   @@:
  733.         call    [ebx + device.write_bcr]
  734.  
  735.         ; Handle full duplex setting
  736.         cmp     byte [ebx + device.full_duplex], 0
  737.         je      .duplex_ok
  738.         mov     ecx, BCR_DUPLEX
  739.         call    [ebx + device.read_bcr]
  740.         and     eax, not 3
  741.         test    [ebx + device.options], PORT_FD
  742.         jz      @f
  743.         or      eax, 1
  744.         cmp     [ebx + device.options], PORT_FD or PORT_AUI
  745.         jne     .set_duplex
  746.         or      eax, 2
  747.         jmp     .set_duplex
  748.   @@:
  749.         test    [ebx + device.options], PORT_ASEL
  750.         jz      .set_duplex
  751.         cmp     [ebx + device.chip_version], 0x2627
  752.         jne     .set_duplex
  753.         or      eax, 3
  754.   .set_duplex:
  755.         mov     ecx, BCR_DUPLEX
  756.         call    [ebx + device.write_bcr]
  757.   .duplex_ok:
  758.  
  759.         ; set/reset GPSI bit in test register
  760.         mov     ecx, 124
  761.         call    [ebx + device.read_csr]
  762.         mov     ecx, [ebx + device.options]
  763.         and     ecx, PORT_PORTSEL
  764.         cmp     ecx, PORT_GPSI
  765.         jne     @f
  766.         or      eax, 0x10
  767.   @@:
  768.         call    [ebx + device.write_csr]
  769.         cmp     [ebx + device.mii], 0
  770.         je      .L6
  771.         test    [ebx + device.options], PORT_ASEL
  772.         jnz     .L6
  773.         mov     ecx, BCR_MIICTL
  774.         call    [ebx + device.read_bcr]
  775.         and     eax, not 0x38
  776.         test    [ebx + device.options], PORT_FD
  777.         jz      @f
  778.         or      eax, 0x10
  779.   @@:
  780.         test    [ebx + device.options], PORT_100
  781.         jz      @f
  782.         or      eax, 0x08
  783.   @@:
  784.         call    [ebx + device.write_bcr]
  785.         jmp     .L9
  786.   .L6:
  787.         test    [ebx + device.options], PORT_ASEL
  788.         jz      .L9
  789.         mov     ecx, BCR_MIICTL
  790.         DEBUGF  1,"ASEL, enable auto-negotiation\n"
  791.         call    [ebx + device.read_bcr]
  792.         and     eax, not 0x98
  793.         or      eax, 0x20
  794.         call    [ebx + device.write_bcr]
  795.   .L9:
  796.         cmp     [ebx + device.ltint], 0
  797.         je      @f
  798.         mov     ecx, 5
  799.         call    [ebx + device.read_csr]
  800.         or      eax, (1 shl 14)
  801.         call    [ebx + device.write_csr]
  802.   @@:
  803.         mov     eax, [ebx + device.options]
  804.         and     eax, PORT_PORTSEL
  805.         shl     eax, 7
  806.         mov     [ebx + device.mode], ax
  807.         mov     dword [ebx + device.filter], -1
  808.         mov     dword [ebx + device.filter+4], -1
  809.  
  810.  
  811.  
  812. ;-----------------------------
  813.  
  814.         test    [ebx + device.mii], 1
  815.         jz      .no_mii
  816.  
  817.         mov     [ebx + device.phy], 0
  818.  
  819.   .mii_loop:
  820.         mov     ecx, MII_PHYSID1
  821.         call    mdio_read
  822.         cmp     ax, 0xffff
  823.         je      .next
  824.  
  825.         DEBUGF  1, "0x%x\n", ax
  826.  
  827.         mov     ecx, MII_PHYSID2
  828.         call    mdio_read
  829.         cmp     ax, 0xffff
  830.         je      .next
  831.  
  832.         DEBUGF  1, "0x%x\n", ax
  833.  
  834.         jmp     .got_phy
  835.  
  836.         cmp     [ebx + device.phy], 31
  837.         jne     .next
  838.         mov     ax, [ebx + device.chip_version]
  839.         inc     ax
  840.         and     ax, 0xfffe
  841.         cmp     ax, 0x2624              ; 79c971 & 79c972 have phantom phy at id 31
  842.         je      .got_phy
  843.  
  844.   .next:
  845.         inc     [ebx + device.phy]
  846.         cmp     [ebx + device.phy], MAX_PHYS
  847.         jb      .mii_loop
  848.  
  849.         DEBUGF  2, "No PHY found!\n"
  850.         or      eax, -1
  851.         ret
  852.  
  853.   .got_phy:
  854.         DEBUGF  1, "Found PHY at 0x%x\n", [ebx + device.phy]:4
  855.  
  856.   .no_mii:
  857.  
  858. ;-----------------------------------------------
  859.  
  860.         call    read_mac
  861.  
  862.         lea     esi, [ebx + device.mac]
  863.         lea     edi, [ebx + device.phys_addr]
  864.         movsd
  865.         movsw
  866.  
  867.         call    init_ring
  868.         test    eax, eax
  869.         jnz     .fail
  870.  
  871.         mov     edx, [ebx + device.io_addr]   ; init ring destroys edx
  872.  
  873.         lea     eax, [ebx + device.mode]
  874.         invoke  GetPhysAddr
  875.         push    eax
  876.         and     eax, 0xffff
  877.         mov     ecx, 1
  878.         call    [ebx + device.write_csr]
  879.         pop     eax
  880.         shr     eax, 16
  881.         mov     ecx, 2
  882.         call    [ebx + device.write_csr]
  883.  
  884.         mov     ecx, 4
  885.         mov     eax, 0x0915
  886.         call    [ebx + device.write_csr]
  887.  
  888. ; Set the interrupt mask
  889.         mov     ecx, CSR_IMR
  890.         mov     eax, IMR
  891.         call    [ebx + device.write_csr]
  892.  
  893. ; Initialise the device
  894.         xor     ecx, ecx
  895.         mov     eax, CSR_INIT
  896.         call    [ebx + device.write_csr]
  897.  
  898.         mov     esi, 100
  899. ;        xor     ecx, ecx
  900.   @@:
  901.         call    [ebx + device.read_csr]
  902.         test    ax, CSR_IDONE
  903.         jnz     @f
  904.  
  905.         dec     esi
  906.         jnz     @r
  907.         DEBUGF  2,"Initialize timeout!\n"
  908.   @@:
  909.  
  910. ; Start the device and enable interrupts
  911.         xor     ecx, ecx
  912.         mov     eax, CSR_START + CSR_INTEN
  913.         call    [ebx + device.write_csr]
  914.  
  915. ; Set the mtu, kernel will be able to send now
  916.         mov     [ebx + device.mtu], 1514
  917.  
  918. ; get link status
  919.         mov     [ebx + device.state], ETH_LINK_UNKNOWN
  920.  
  921.         call    check_media
  922.  
  923.         DEBUGF  1,"reset complete\n"
  924.         xor     eax, eax
  925.   .fail:
  926.         ret
  927.  
  928.  
  929. align 4
  930. init_ring:
  931.  
  932.         DEBUGF  1,"init ring\n"
  933.  
  934.         lea     edi, [ebx + device.rx_ring]
  935.         mov     eax, edi
  936.         invoke  GetPhysAddr
  937.         mov     [ebx + device.rx_ring_phys], eax
  938.         mov     ecx, RX_RING_SIZE
  939.   .rx_init:
  940.         push    ecx
  941.         invoke  NetAlloc, PKT_BUF_SZ+NET_BUFF.data
  942.         pop     ecx
  943.         test    eax, eax
  944.         jz      .out_of_mem
  945.         mov     [edi + descriptor.virtual], eax
  946.         invoke  GetPhysAddr
  947.         add     eax, NET_BUFF.data
  948.         mov     [edi + descriptor.base], eax
  949.         mov     [edi + descriptor.length], - PKT_BUF_SZ
  950.         mov     [edi + descriptor.status], RXSTAT_OWN
  951.         mov     dword[edi + descriptor.msg_length], 0    ; also clears misc field
  952.         add     edi, sizeof.descriptor
  953.         dec     ecx
  954.         jnz     .rx_init
  955.  
  956.         lea     edi, [ebx + device.tx_ring]
  957.         mov     eax, edi
  958.         invoke  GetPhysAddr
  959.         mov     [ebx + device.tx_ring_phys], eax
  960.         mov     ecx, TX_RING_SIZE
  961.   .tx_init:
  962.         mov     [edi + descriptor.status], 0
  963.         add     edi, sizeof.descriptor
  964.         dec     ecx
  965.         jnz     .tx_init
  966.  
  967.         mov     [ebx + device.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
  968.  
  969.         mov     [ebx + device.cur_tx], 0
  970.         mov     [ebx + device.last_tx], 0
  971.         mov     [ebx + device.cur_rx], 0
  972.  
  973.         xor     eax, eax
  974.         ret
  975.  
  976.   .out_of_mem:
  977.         DEBUGF  2,"Out of memory!\n"
  978.  
  979.         or      eax, -1
  980.         ret
  981.  
  982.  
  983.  
  984.  
  985. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  986. ;;                                         ;;
  987. ;; Transmit                                ;;
  988. ;;                                         ;;
  989. ;; In: pointer to device structure in ebx  ;;
  990. ;;                                         ;;
  991. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  992.  
  993. proc transmit stdcall bufferptr
  994.  
  995.         pushf
  996.         cli
  997.  
  998.         mov     esi, [bufferptr]
  999.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
  1000.         lea     eax, [esi + NET_BUFF.data]
  1001.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  1002.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  1003.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  1004.         [eax+13]:2,[eax+12]:2
  1005.  
  1006.         cmp     [esi + NET_BUFF.length], 1514
  1007.         ja      .fail
  1008.         cmp     [esi + NET_BUFF.length], 60
  1009.         jb      .fail
  1010.  
  1011. ; check descriptor
  1012.         lea     edi, [ebx + device.tx_ring]
  1013.         movzx   ecx, [ebx + device.cur_tx]
  1014.         shl     ecx, 4
  1015.         add     edi, ecx
  1016.  
  1017.         test    [edi + descriptor.status], TXCTL_OWN
  1018.         jnz     .fail
  1019. ; descriptor is free, use it
  1020.         mov     [edi + descriptor.virtual], esi
  1021.         mov     eax, esi
  1022.         add     eax, [eax + NET_BUFF.offset]
  1023.         invoke  GetPhysAddr
  1024.         mov     [edi + descriptor.base], eax
  1025. ; set length
  1026.         mov     eax, [esi + NET_BUFF.length]
  1027.         neg     eax
  1028.         mov     [edi + descriptor.length], ax
  1029. ; put to transfer queue
  1030.         mov     [edi + descriptor.status], TXCTL_OWN + TXCTL_STP + TXCTL_ENP
  1031.  
  1032. ; trigger an immediate send
  1033.         mov     edx, [ebx + device.io_addr]
  1034.         xor     ecx, ecx                        ; CSR0
  1035.         call    [ebx + device.read_csr]
  1036.         or      eax, CSR_TX
  1037.         call    [ebx + device.write_csr]
  1038.  
  1039. ; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
  1040.         inc     [ebx + device.cur_tx]
  1041.         and     [ebx + device.cur_tx], TX_RING_SIZE - 1
  1042.  
  1043. ; Update stats
  1044.         inc     [ebx + device.packets_tx]
  1045.         mov     eax, [esi + NET_BUFF.length]
  1046.         add     dword[ebx + device.bytes_tx], eax
  1047.         adc     dword[ebx + device.bytes_tx + 4], 0
  1048.  
  1049.   .finish:
  1050.         popf
  1051.         xor     eax, eax
  1052.         ret
  1053.  
  1054.   .fail:
  1055.         DEBUGF  2, "Send failed\n"
  1056.         invoke  NetFree, [bufferptr]
  1057.         popf
  1058.         or      eax, -1
  1059.         ret
  1060.  
  1061. endp
  1062.  
  1063.  
  1064. ;;;;;;;;;;;;;;;;;;;;;;;
  1065. ;;                   ;;
  1066. ;; Interrupt handler ;;
  1067. ;;                   ;;
  1068. ;;;;;;;;;;;;;;;;;;;;;;;
  1069.  
  1070. align 4
  1071. int_handler:
  1072.  
  1073.         push    ebx esi edi
  1074.  
  1075.         DEBUGF  1,"INT\n"
  1076.  
  1077. ; find pointer of device wich made IRQ occur
  1078.  
  1079.         mov     ecx, [devices]
  1080.         test    ecx, ecx
  1081.         jz      .nothing
  1082.         mov     esi, device_list
  1083.   .nextdevice:
  1084.         mov     ebx, [esi]
  1085.         mov     edx, [ebx + device.io_addr]
  1086.         push    ecx
  1087.         xor     ecx, ecx                        ; CSR0
  1088.         call    [ebx + device.read_csr]         ; get IRQ reason
  1089.         call    [ebx + device.write_csr]        ; write it back to ACK
  1090.         pop     ecx
  1091.         test    ax, CSR_RINT or CSR_TINT
  1092.         jnz     .got_it
  1093.   .continue:
  1094.         add     esi, 4
  1095.         dec     ecx
  1096.         jnz     .nextdevice
  1097.   .nothing:
  1098.         pop     edi esi ebx
  1099.         xor     eax, eax
  1100.  
  1101.         ret
  1102.  
  1103.   .got_it:
  1104.         DEBUGF  1,"Device: %x status: %x\n", ebx, eax:4
  1105.  
  1106.         push    ax
  1107.         test    ax, CSR_RINT
  1108.         jz      .not_receive
  1109.  
  1110.         push    ebx
  1111.   .rx_loop:
  1112.         pop     ebx
  1113.         movzx   eax, [ebx + device.cur_rx]
  1114.         shl     eax, 4
  1115.         lea     edi, [ebx + device.rx_ring]
  1116.         add     edi, eax                        ; edi now points to current rx ring entry
  1117.  
  1118.         mov     ax, [edi + descriptor.status]
  1119.         DEBUGF  1,"RX packet status: %x\n", eax:4
  1120.  
  1121.         test    ax, RXSTAT_OWN                  ; If this bit is set, the controller OWN's the packet, if not, we do
  1122.         jnz     .not_receive
  1123.  
  1124.         test    ax, RXSTAT_ENP
  1125.         jz      .not_receive
  1126.  
  1127.         test    ax, RXSTAT_STP
  1128.         jz      .not_receive
  1129.  
  1130.         movzx   ecx, [edi + descriptor.msg_length]      ; get packet length in ecx
  1131.         sub     ecx, 4                                  ; We dont need the CRC
  1132.         DEBUGF  1,"Got %u bytes\n", ecx
  1133.  
  1134. ; Set pointers for ETH_input
  1135.         push    ebx
  1136.  
  1137.         push    .rx_loop                                ; return address
  1138.         mov     eax, [edi + descriptor.virtual]
  1139.         push    eax                                     ; packet address
  1140.         mov     [eax + NET_BUFF.length], ecx
  1141.         mov     [eax + NET_BUFF.device], ebx
  1142.         mov     [eax + NET_BUFF.offset], NET_BUFF.data
  1143.  
  1144. ; Update stats
  1145.         add     dword[ebx + device.bytes_rx], ecx
  1146.         adc     dword[ebx + device.bytes_rx + 4], 0
  1147.         inc     [ebx + device.packets_rx]
  1148.  
  1149. ; now allocate a new buffer
  1150.         invoke  NetAlloc, PKT_BUF_SZ+NET_BUFF.data      ; Allocate a buffer for the next packet
  1151.         test    eax, eax
  1152.         jz      .out_of_mem
  1153.         mov     [edi + descriptor.virtual], eax         ; set virtual address
  1154.         invoke  GetPhysAddr
  1155.         add     eax, NET_BUFF.data
  1156.         mov     [edi + descriptor.base], eax            ; and physical address
  1157.         mov     [edi + descriptor.status], RXSTAT_OWN   ; give it back to PCnet controller
  1158.  
  1159.         inc     [ebx + device.cur_rx]                   ; set next receive descriptor
  1160.         and     [ebx + device.cur_rx], RX_RING_SIZE - 1
  1161.  
  1162.         jmp     [EthInput]
  1163.  
  1164.   .out_of_mem:
  1165.         DEBUGF  2,"Out of memory!\n"
  1166.  
  1167.         inc     [ebx + device.cur_rx]                   ; set next receive descriptor
  1168.         and     [ebx + device.cur_rx], RX_RING_SIZE - 1
  1169.  
  1170.         jmp     [EthInput]
  1171.  
  1172.   .not_receive:
  1173.         pop     ax
  1174.  
  1175.         test    ax, CSR_TINT
  1176.         jz      .not_transmit
  1177.  
  1178.   .tx_loop:
  1179.         lea     edi, [ebx + device.tx_ring]
  1180.         movzx   eax, [ebx + device.last_tx]
  1181.         shl     eax, 4
  1182.         add     edi, eax
  1183.  
  1184.         test    [edi + descriptor.status], TXCTL_OWN
  1185.         jnz     .not_transmit
  1186.  
  1187.         mov     eax, [edi + descriptor.virtual]
  1188.         test    eax, eax
  1189.         jz      .not_transmit
  1190.  
  1191.         mov     [edi + descriptor.virtual], 0
  1192.  
  1193.         DEBUGF  1,"Removing packet %x from memory\n", eax
  1194.  
  1195.         invoke  NetFree, eax
  1196.  
  1197.         inc     [ebx + device.last_tx]
  1198.         and     [ebx + device.last_tx], TX_RING_SIZE - 1
  1199.         jmp     .tx_loop
  1200.  
  1201.   .not_transmit:
  1202.         pop     edi esi ebx
  1203.         xor     eax, eax
  1204.         inc     eax
  1205.  
  1206.         ret
  1207.  
  1208.  
  1209.  
  1210.  
  1211. ;;;;;;;;;;;;;;;;;;;;;;;
  1212. ;;                   ;;
  1213. ;; Write MAC address ;;
  1214. ;;                   ;;
  1215. ;;;;;;;;;;;;;;;;;;;;;;;
  1216.  
  1217. align 4
  1218. write_mac:      ; in: mac pushed onto stack (as 3 words)
  1219.  
  1220.         DEBUGF  1,"Writing MAC: %x-%x-%x-%x-%x-%x\n",\
  1221.         [esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
  1222.  
  1223.         mov     edx, [ebx + device.io_addr]
  1224.         add     dx, 2
  1225.         xor     eax, eax
  1226.  
  1227.         mov     ecx, CSR_PAR0
  1228.        @@:
  1229.         pop     ax
  1230.         call    [ebx + device.write_csr]
  1231.         inc     ecx
  1232.         cmp     ecx, CSR_PAR2
  1233.         jb      @r
  1234.  
  1235. ; Notice this procedure does not ret, but continues to read_mac instead.
  1236.  
  1237. ;;;;;;;;;;;;;;;;;;;;;;
  1238. ;;                  ;;
  1239. ;; Read MAC address ;;
  1240. ;;                  ;;
  1241. ;;;;;;;;;;;;;;;;;;;;;;
  1242. align 4
  1243. read_mac:
  1244.         DEBUGF  1,"Reading MAC\n"
  1245.  
  1246.         mov     edx, [ebx + device.io_addr]
  1247.         lea     edi, [ebx + device.mac]
  1248.         in      ax, dx
  1249.         stosw
  1250.  
  1251.         inc     dx
  1252.         inc     dx
  1253.         in      ax, dx
  1254.         stosw
  1255.  
  1256.         inc     dx
  1257.         inc     dx
  1258.         in      ax, dx
  1259.         stosw
  1260.  
  1261.         DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
  1262.         [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,\
  1263.         [ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
  1264.  
  1265.         ret
  1266.  
  1267. align 4
  1268. switch_to_wio:
  1269.  
  1270.         DEBUGF  1,"Switching to 16-bit mode\n"
  1271.  
  1272.         mov     [ebx + device.read_csr], wio_read_csr
  1273.         mov     [ebx + device.write_csr], wio_write_csr
  1274.         mov     [ebx + device.read_bcr], wio_read_bcr
  1275.         mov     [ebx + device.write_bcr], wio_write_bcr
  1276.         mov     [ebx + device.read_rap], wio_read_rap
  1277.         mov     [ebx + device.write_rap], wio_write_rap
  1278.         mov     [ebx + device.sw_reset], wio_reset
  1279.  
  1280.         ret
  1281.  
  1282. align 4
  1283. switch_to_dwio:
  1284.  
  1285.         DEBUGF  1,"Switching to 32-bit mode\n"
  1286.  
  1287.         mov     [ebx + device.read_csr], dwio_read_csr
  1288.         mov     [ebx + device.write_csr], dwio_write_csr
  1289.         mov     [ebx + device.read_bcr], dwio_read_bcr
  1290.         mov     [ebx + device.write_bcr], dwio_write_bcr
  1291.         mov     [ebx + device.read_rap], dwio_read_rap
  1292.         mov     [ebx + device.write_rap], dwio_write_rap
  1293.         mov     [ebx + device.sw_reset], dwio_reset
  1294.  
  1295.         ret
  1296.  
  1297.  
  1298. ; ecx - index
  1299. ; return:
  1300. ; eax - data
  1301. align 4
  1302. wio_read_csr:
  1303.  
  1304.         add     edx, WIO_RAP
  1305.         mov     ax, cx
  1306.         out     dx, ax
  1307.         add     edx, WIO_RDP - WIO_RAP
  1308.         in      ax, dx
  1309.         and     eax, 0xffff
  1310.         sub     edx, WIO_RDP
  1311.  
  1312.         ret
  1313.  
  1314.  
  1315. ; eax - data
  1316. ; ecx - index
  1317. align 4
  1318. wio_write_csr:
  1319.  
  1320.         add     edx, WIO_RAP
  1321.         xchg    eax, ecx
  1322.         out     dx, ax
  1323.         xchg    eax, ecx
  1324.         add     edx, WIO_RDP - WIO_RAP
  1325.         out     dx, ax
  1326.         sub     edx, WIO_RDP
  1327.  
  1328.         ret
  1329.  
  1330.  
  1331. ; ecx - index
  1332. ; return:
  1333. ; eax - data
  1334. align 4
  1335. wio_read_bcr:
  1336.  
  1337.         add     edx, WIO_RAP
  1338.         mov     ax, cx
  1339.         out     dx, ax
  1340.         add     edx, WIO_BDP - WIO_RAP
  1341.         in      ax, dx
  1342.         and     eax, 0xffff
  1343.         sub     edx, WIO_BDP
  1344.  
  1345.         ret
  1346.  
  1347.  
  1348. ; eax - data
  1349. ; ecx - index
  1350. align 4
  1351. wio_write_bcr:
  1352.  
  1353.         add     edx, WIO_RAP
  1354.         xchg    eax, ecx
  1355.         out     dx, ax
  1356.         xchg    eax, ecx
  1357.         add     edx, WIO_BDP - WIO_RAP
  1358.         out     dx, ax
  1359.         sub     edx, WIO_BDP
  1360.  
  1361.         ret
  1362.  
  1363. align 4
  1364. wio_read_rap:
  1365.  
  1366.         add     edx, WIO_RAP
  1367.         in      ax, dx
  1368.         and     eax, 0xffff
  1369.         sub     edx, WIO_RAP
  1370.  
  1371.         ret
  1372.  
  1373. ; eax - val
  1374. align 4
  1375. wio_write_rap:
  1376.  
  1377.         add     edx, WIO_RAP
  1378.         out     dx, ax
  1379.         sub     edx, WIO_RAP
  1380.  
  1381.         ret
  1382.  
  1383. align 4
  1384. wio_reset:
  1385.  
  1386.         push    eax
  1387.         add     edx, WIO_RESET
  1388.         in      ax, dx
  1389.         pop     eax
  1390.         sub     edx, WIO_RESET
  1391.  
  1392.         ret
  1393.  
  1394.  
  1395.  
  1396. ; ecx - index
  1397. ; return:
  1398. ; eax - data
  1399. align 4
  1400. dwio_read_csr:
  1401.  
  1402.         add     edx, DWIO_RAP
  1403.         mov     eax, ecx
  1404.         out     dx, eax
  1405.         add     edx, DWIO_RDP - DWIO_RAP
  1406.         in      eax, dx
  1407.         and     eax, 0xffff
  1408.         sub     edx, DWIO_RDP
  1409.  
  1410.         ret
  1411.  
  1412.  
  1413. ; ecx - index
  1414. ; eax - data
  1415. align 4
  1416. dwio_write_csr:
  1417.  
  1418.         add     edx, DWIO_RAP
  1419.         xchg    eax, ecx
  1420.         out     dx, eax
  1421.         add     edx, DWIO_RDP - DWIO_RAP
  1422.         xchg    eax, ecx
  1423.         out     dx, eax
  1424.         sub     edx, DWIO_RDP
  1425.  
  1426.         ret
  1427.  
  1428. ; ecx - index
  1429. ; return:
  1430. ; eax - data
  1431. align 4
  1432. dwio_read_bcr:
  1433.  
  1434.         add     edx, DWIO_RAP
  1435.         mov     eax, ecx
  1436.         out     dx, eax
  1437.         add     edx, DWIO_BDP - DWIO_RAP
  1438.         in      eax, dx
  1439.         and     eax, 0xffff
  1440.         sub     edx, DWIO_BDP
  1441.  
  1442.         ret
  1443.  
  1444.  
  1445. ; ecx - index
  1446. ; eax - data
  1447. align 4
  1448. dwio_write_bcr:
  1449.  
  1450.         add     edx, DWIO_RAP
  1451.         xchg    eax, ecx
  1452.         out     dx, eax
  1453.         add     edx, DWIO_BDP - DWIO_RAP
  1454.         xchg    eax, ecx
  1455.         out     dx, eax
  1456.         sub     edx, DWIO_BDP
  1457.  
  1458.         ret
  1459.  
  1460. align 4
  1461. dwio_read_rap:
  1462.  
  1463.         add     edx, DWIO_RAP
  1464.         in      eax, dx
  1465.         and     eax, 0xffff
  1466.         sub     edx, DWIO_RAP
  1467.  
  1468.         ret
  1469.  
  1470.  
  1471. ; eax - val
  1472. align 4
  1473. dwio_write_rap:
  1474.  
  1475.         add     edx, DWIO_RAP
  1476.         out     dx, eax
  1477.         sub     edx, DWIO_RAP
  1478.  
  1479.         ret
  1480.  
  1481. align 4
  1482. dwio_reset:
  1483.  
  1484.         push    eax
  1485.         add     edx, DWIO_RESET
  1486.         in      eax, dx
  1487.         pop     eax
  1488.         sub     edx, DWIO_RESET
  1489.  
  1490.         ret
  1491.  
  1492.  
  1493. align 4
  1494. mdio_read:
  1495.  
  1496.         and     ecx, 0x1f
  1497.         mov     ax, [ebx + device.phy]
  1498.         and     ax, 0x1f
  1499.         shl     ax, 5
  1500.         or      ax, cx
  1501.  
  1502.         mov     ecx, BCR_MIIADDR
  1503.         call    [ebx + device.write_bcr]
  1504.  
  1505.         mov     ecx, BCR_MIIDATA
  1506.         call    [ebx + device.read_bcr]
  1507.  
  1508.         ret
  1509.  
  1510.  
  1511. align 4
  1512. mdio_write:
  1513.  
  1514.         push    eax
  1515.         and     ecx, 0x1f
  1516.         mov     ax, [ebx + device.phy]
  1517.         and     ax, 0x1f
  1518.         shl     ax, 5
  1519.         or      ax, cx
  1520.  
  1521.         mov     ecx, BCR_MIIADDR
  1522.         call    [ebx + device.write_bcr]
  1523.  
  1524.         pop     eax
  1525.         mov     ecx, BCR_MIIDATA
  1526.         call    [ebx + device.write_bcr]
  1527.  
  1528.         ret
  1529.  
  1530.  
  1531. align 4
  1532. check_media:
  1533.  
  1534.         DEBUGF  1, "check_media\n"
  1535.  
  1536.         test    [ebx + device.mii], 1
  1537.         jnz     mii_link_ok
  1538.  
  1539.         mov     ecx, BCR_LED0
  1540.         call    [ebx + device.read_bcr]
  1541.         cmp     eax, 0xc0
  1542.  
  1543.         DEBUGF  2, "link status=0x%x\n", ax
  1544.  
  1545.         ret
  1546.  
  1547.  
  1548.  
  1549. ; End of code
  1550.  
  1551.  
  1552. data fixups
  1553. end data
  1554.  
  1555. include '../peimport.inc'
  1556.  
  1557. my_service    db 'PCNET32',0            ; max 16 chars include zero
  1558.  
  1559. device_l2     db "PCnet/PCI 79C970",0
  1560. device_l4     db "PCnet/PCI II 79C970A",0
  1561. device_l5     db "PCnet/FAST 79C971",0
  1562. device_l6     db "PCnet/FAST+ 79C972",0
  1563. device_l7     db "PCnet/FAST III 79C973",0
  1564. device_l8     db "PCnet/Home 79C978",0
  1565. device_l9     db "PCnet/FAST III 79C975",0
  1566.  
  1567. options_mapping:
  1568. dd PORT_ASEL                            ; 0 Auto-select
  1569. dd PORT_AUI                             ; 1 BNC/AUI
  1570. dd PORT_AUI                             ; 2 AUI/BNC
  1571. dd PORT_ASEL                            ; 3 not supported
  1572. dd PORT_10BT or PORT_FD                 ; 4 10baseT-FD
  1573. dd PORT_ASEL                            ; 5 not supported
  1574. dd PORT_ASEL                            ; 6 not supported
  1575. dd PORT_ASEL                            ; 7 not supported
  1576. dd PORT_ASEL                            ; 8 not supported
  1577. dd PORT_MII                             ; 9 MII 10baseT
  1578. dd PORT_MII or PORT_FD                  ; 10 MII 10baseT-FD
  1579. dd PORT_MII                             ; 11 MII (autosel)
  1580. dd PORT_10BT                            ; 12 10BaseT
  1581. dd PORT_MII or PORT_100                 ; 13 MII 100BaseTx
  1582. dd PORT_MII or PORT_100 or PORT_FD      ; 14 MII 100BaseTx-FD
  1583. dd PORT_ASEL                            ; 15 not supported
  1584.  
  1585. include_debug_strings                                   ; All data wich FDO uses will be included here
  1586.  
  1587.  
  1588. align 4
  1589. devices     dd 0
  1590. device_list rd MAX_DEVICES                              ; This list contains all pointers to device structures the driver is handling
  1591.