Subversion Repositories Kolibri OS

Rev

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