Subversion Repositories Kolibri OS

Rev

Rev 5617 | 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-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.         rb 0x100-($ and 0xff)   ; align 256
  336.  
  337.         read_csr        dd ?
  338.         write_csr       dd ?
  339.         read_bcr        dd ?
  340.         write_bcr       dd ?
  341.         read_rap        dd ?
  342.         write_rap       dd ?
  343.         sw_reset        dd ?
  344.  
  345. ends
  346.  
  347. struct  descriptor
  348.  
  349.         base            dd ?
  350.         length          dw ?
  351.         status          dw ?
  352.         msg_length      dw ?
  353.         misc            dw ?
  354.         virtual         dd ?
  355.  
  356. ends
  357.  
  358.  
  359. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  360. ;;                        ;;
  361. ;; proc START             ;;
  362. ;;                        ;;
  363. ;; (standard driver proc) ;;
  364. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  365.  
  366. proc START c, reason:dword, cmdline:dword
  367.  
  368.         cmp     [reason], DRV_ENTRY
  369.         jne     .fail
  370.  
  371.         DEBUGF  2,"Loading driver\n"
  372.         invoke  RegService, my_service, service_proc
  373.         ret
  374.  
  375.   .fail:
  376.         xor eax, eax
  377.         ret
  378.  
  379. endp
  380.  
  381.  
  382. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  383. ;;                        ;;
  384. ;; proc SERVICE_PROC      ;;
  385. ;;                        ;;
  386. ;; (standard driver proc) ;;
  387. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  388.  
  389. align 4
  390. proc service_proc stdcall, ioctl:dword
  391.  
  392.         mov     edx, [ioctl]
  393.         mov     eax, [edx + IOCTL.io_code]
  394.  
  395. ;------------------------------------------------------
  396.  
  397.         cmp     eax, 0 ;SRV_GETVERSION
  398.         jne     @F
  399.  
  400.         cmp     [edx + IOCTL.out_size], 4
  401.         jb      .fail
  402.         mov     eax, [edx + IOCTL.output]
  403.         mov     [eax], dword API_VERSION
  404.  
  405.         xor     eax, eax
  406.         ret
  407.  
  408. ;------------------------------------------------------
  409.   @@:
  410.         cmp     eax, 1 ;SRV_HOOK
  411.         jne     .fail
  412.  
  413.         cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
  414.         jb      .fail
  415.  
  416.         mov     eax, [edx + IOCTL.input]
  417.         cmp     byte[eax], 1                            ; 1 means device number and bus number (pci) are given
  418.         jne     .fail                                   ; other types arent supported for this card yet
  419.  
  420. ; check if the device is already listed
  421.  
  422.         mov     ecx, [devices]
  423.         test    ecx, ecx
  424.         jz      .firstdevice
  425.  
  426.         mov     esi, device_list
  427. ;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
  428.         mov     ax, [eax+1]                             ;
  429.   .nextdevice:
  430.         mov     ebx, [esi]
  431.         cmp     al, byte[ebx + device.pci_bus]
  432.         jne     @f
  433.         cmp     ah, byte[ebx + device.pci_dev]
  434.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  435.        @@:
  436.         add     esi, 4
  437.         loop    .nextdevice
  438.  
  439. ; This device doesnt have its own eth_device structure yet, lets create one
  440.  
  441.   .firstdevice:
  442.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  443.         jae     .fail
  444.  
  445.         allocate_and_clear ebx, sizeof.device, .fail
  446.  
  447. ; Fill in the direct call addresses into the struct
  448.  
  449.         mov     [ebx + device.reset], reset
  450.         mov     [ebx + device.transmit], transmit
  451.         mov     [ebx + device.unload], unload
  452.         mov     [ebx + device.name], my_service
  453.  
  454. ; save the pci bus and device numbers
  455.  
  456.         mov     eax, [edx + IOCTL.input]
  457.         movzx   ecx, byte[eax+1]
  458.         mov     [ebx + device.pci_bus], ecx
  459.         movzx   ecx, byte[eax+2]
  460.         mov     [ebx + device.pci_dev], ecx
  461.  
  462. ; Now, it's time to find the base io addres of the PCI device
  463.  
  464.         stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
  465.         mov     [ebx + device.io_addr], eax
  466.  
  467. ; We've found the io address, find IRQ now
  468.  
  469.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
  470.         mov     [ebx + device.irq_line], al
  471.  
  472.         DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  473.         [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:4
  474.  
  475. ; Ok, the eth_device structure is ready, let's probe the device
  476. ; Because initialization fires IRQ, IRQ handler must be aware of this device
  477.         mov     eax, [devices]                                          ; Add the device structure to our device list
  478.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  479.         inc     [devices]                                               ;
  480.  
  481.         call    probe                                                   ; this function will output in eax
  482.         test    eax, eax
  483.         jnz     .destroy                                                ; If an error occured, exit
  484.  
  485.         mov     [ebx + device.type], NET_TYPE_ETH
  486.         invoke  NetRegDev
  487.         cmp     eax, -1
  488.         je      .destroy
  489.  
  490.         ret
  491.  
  492. ; If the device was already loaded, find the device number and return it in eax
  493.  
  494.   .find_devicenum:
  495.         DEBUGF  1,"Trying to find device number of already registered device\n"
  496.         invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  497.                                                                         ; into a device number in edi
  498.         mov     eax, edi                                                ; Application wants it in eax instead
  499.         DEBUGF  1,"Kernel says: %u\n", eax
  500.         ret
  501.  
  502. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  503.  
  504.   .destroy:
  505.         ; todo: reset device into virgin state
  506.         add     eax, NET_BUFF.data
  507.         dec     [devices]
  508.   .err:
  509.         DEBUGF  2,"Error, removing all data !\n"
  510.         invoke  KernelFree, ebx
  511.  
  512.   .fail:
  513.         or      eax, -1
  514.         ret
  515.  
  516. ;------------------------------------------------------
  517. endp
  518.  
  519.  
  520. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  521. ;;                                                                        ;;
  522. ;;        Actual Hardware dependent code starts here                      ;;
  523. ;;                                                                        ;;
  524. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  525.  
  526. align 4
  527. unload:
  528.         ; TODO: (in this particular order)
  529.         ;
  530.         ; - Stop the device
  531.         ; - Detach int handler
  532.         ; - Remove device from local list (device_list)
  533.         ; - call unregister function in kernel
  534.         ; - Remove all allocated structures and buffers the card used
  535.  
  536.         or      eax, -1
  537.         ret
  538.  
  539.  
  540. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  541. ;;
  542. ;;  probe: enables the device (if it really is a PCnet device)
  543. ;;
  544. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  545.  
  546. align 4
  547. probe:
  548.  
  549.         mov     edx, [ebx + device.io_addr]
  550.  
  551.         call    wio_reset
  552.  
  553.         xor     ecx, ecx
  554.         call    wio_read_csr
  555.         cmp     eax, 4
  556.         jne     .try_dwio
  557.  
  558.         ; Try Word I/O
  559.         mov     ax, 88
  560.         add     edx, WIO_RAP
  561.         out     dx, ax
  562.         nop
  563.         nop
  564.         in      ax, dx
  565.         sub     edx, WIO_RAP
  566.         cmp     ax, 88
  567.         jne     .try_dwio
  568.  
  569.         call    switch_to_wio
  570.  
  571.         jmp     .L1
  572.  
  573.   .try_dwio:
  574.         call    dwio_reset
  575.  
  576.         xor     ecx, ecx
  577.         call    dwio_read_csr
  578.         cmp     eax, 4
  579.         jne     .no_dev
  580.  
  581.         ; Try Dword I/O
  582.         add     edx, DWIO_RAP
  583.         mov     eax, 88
  584.         out     dx, eax
  585.         nop
  586.         nop
  587.         in      eax, dx
  588.         sub     edx, DWIO_RAP
  589.         and     eax, 0xffff
  590.         cmp     eax, 88
  591.         jne     .no_dev
  592.  
  593.         call    switch_to_dwio
  594.  
  595.         jmp     .L1
  596.  
  597.   .no_dev:
  598.         DEBUGF  2,"device not found!\n"
  599.         mov     eax, 1
  600.         ret
  601.  
  602.   .L1:
  603.         mov     ecx, CSR_CHIPID0
  604.         call    [ebx + device.read_csr]
  605.  
  606.         mov     esi, eax
  607.         shr     esi, 12
  608.  
  609.         and     ax, 0xfff
  610.         cmp     ax, 3
  611.         jne     .no_dev
  612.  
  613.         mov     ecx, CSR_CHIPID1
  614.         call    [ebx + device.read_csr]
  615.         shl     eax, 4
  616.         or      eax, esi
  617.         mov     [ebx + device.chip_version], ax
  618.  
  619.         mov     [ebx + device.fdx], 0
  620.         mov     [ebx + device.mii], 0
  621.         mov     [ebx + device.fset], 0
  622.         mov     [ebx + device.dxsuflo], 0
  623.         mov     [ebx + device.ltint], 0
  624.  
  625.         cmp     ax, 0x2420
  626.         je      .L2
  627.         cmp     ax, 0x2430
  628.         je      .L2
  629.  
  630.         mov     [ebx + device.fdx], 1
  631.  
  632.         cmp     ax, 0x2621
  633.         je      .L4
  634.         cmp     ax, 0x2623
  635.         je      .L5
  636.         cmp     ax, 0x2624
  637.         je      .L6
  638.         cmp     ax, 0x2625
  639.         je      .L7
  640.         cmp     ax, 0x2626
  641.         je      .L8
  642.         cmp     ax, 0x2627
  643.         je      .L9
  644.  
  645.         DEBUGF  2,"Invalid chip rev\n"
  646.         jmp     .no_dev
  647.   .L2:
  648.         mov     [ebx + device.name], device_l2
  649.         jmp     .L10
  650.   .L4:
  651.         mov     [ebx + device.name], device_l4
  652. ;        mov     [ebx + device.fdx], 1
  653.         jmp     .L10
  654.   .L5:
  655.         mov     [ebx + device.name], device_l5
  656. ;        mov     [ebx + device.fdx], 1
  657.         mov     [ebx + device.mii], 1
  658.         mov     [ebx + device.fset], 1
  659.         mov     [ebx + device.ltint], 1
  660.         jmp     .L10
  661.   .L6:
  662.         mov     [ebx + device.name], device_l6
  663. ;        mov     [ebx + device.fdx], 1
  664.         mov     [ebx + device.mii], 1
  665.         mov     [ebx + device.fset], 1
  666.         jmp     .L10
  667.   .L7:
  668.         mov     [ebx + device.name], device_l7
  669. ;        mov     [ebx + device.fdx], 1
  670.         mov     [ebx + device.mii], 1
  671.         jmp     .L10
  672.   .L8:
  673.         mov     [ebx + device.name], device_l8
  674. ;        mov     [ebx + device.fdx], 1
  675.         mov     ecx, CSR_RXPOLL
  676.         call    dword [ebx + device.read_bcr]
  677.         call    dword [ebx + device.write_bcr]
  678.         jmp     .L10
  679.   .L9:
  680.         mov     [ebx + device.name], device_l9
  681. ;        mov     [ebx + device.fdx], 1
  682.         mov     [ebx + device.mii], 1
  683.   .L10:
  684.         DEBUGF  1,"device name: %s\n", [ebx + device.name]
  685.  
  686.         cmp     [ebx + device.fset], 1
  687.         jne     .L11
  688.         mov     ecx, BCR_BUSCTL
  689.         call    [ebx + device.read_bcr]
  690.         or      eax, 0x800
  691.         call    [ebx + device.write_bcr]
  692.  
  693.         mov     ecx, CSR_DMACTL
  694. ;        call    [ebx + device.read_csr]
  695.         mov     eax, 0xc00
  696.         call    [ebx + device.write_csr]
  697.  
  698.         mov     [ebx + device.dxsuflo],1
  699.         mov     [ebx + device.ltint],1
  700.   .L11:
  701.  
  702. ; Make the device a bus master
  703.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
  704.         or      al, PCI_CMD_MASTER
  705.         invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
  706.  
  707.         mov     [ebx + device.options], PORT_ASEL
  708.         mov     [ebx + device.init_block.mode], MODE_RXD + MODE_TXD     ; disable receive and transmit
  709.         mov     [ebx + device.init_block.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
  710.  
  711.         mov     dword[ebx + device.init_block.filter], 0
  712.         mov     dword[ebx + device.init_block.filter+4], 0
  713.  
  714. align 4
  715. reset:
  716.  
  717. ; attach int handler
  718.  
  719.         movzx   eax, [ebx + device.irq_line]
  720.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  721.         invoke  AttachIntHandler, eax, int_handler, ebx
  722.         test    eax, eax
  723.         jnz     @f
  724.         DEBUGF  2,"Could not attach int handler!\n"
  725.         or      eax, -1
  726.         ret
  727.   @@:
  728.  
  729.         mov     edx, [ebx + device.io_addr]
  730.         call    [ebx + device.sw_reset]
  731.  
  732.         ; Switch pcnet32 to 32bit mode
  733.         mov     ecx, BCR_SSTYLE
  734.         mov     eax, 2
  735.         call    [ebx + device.write_bcr]
  736.  
  737.         ; set/reset autoselect bit
  738.         mov     ecx, BCR_MISCCFG
  739.         call    [ebx + device.read_bcr]
  740.         and     eax, not 2
  741.         test    [ebx + device.options], PORT_ASEL
  742.         jz      @f
  743.         or      eax, 2
  744.   @@:
  745.         call    [ebx + device.write_bcr]
  746.  
  747.         ; Handle full duplex setting
  748.         cmp     byte [ebx + device.full_duplex], 0
  749.         je      .duplex_ok
  750.         mov     ecx, BCR_DUPLEX
  751.         call    [ebx + device.read_bcr]
  752.         and     eax, not 3
  753.         test    [ebx + device.options], PORT_FD
  754.         jz      @f
  755.         or      eax, 1
  756.         cmp     [ebx + device.options], PORT_FD or PORT_AUI
  757.         jne     .set_duplex
  758.         or      eax, 2
  759.         jmp     .set_duplex
  760.   @@:
  761.         test    [ebx + device.options], PORT_ASEL
  762.         jz      .set_duplex
  763.         cmp     [ebx + device.chip_version], 0x2627
  764.         jne     .set_duplex
  765.         or      eax, 3
  766.   .set_duplex:
  767.         mov     ecx, BCR_DUPLEX
  768.         call    [ebx + device.write_bcr]
  769.   .duplex_ok:
  770.  
  771.         ; set/reset GPSI bit in test register
  772.         mov     ecx, 124
  773.         call    [ebx + device.read_csr]
  774.         mov     ecx, [ebx + device.options]
  775.         and     ecx, PORT_PORTSEL
  776.         cmp     ecx, PORT_GPSI
  777.         jne     @f
  778.         or      eax, 0x10
  779.   @@:
  780.         call    [ebx + device.write_csr]
  781.         cmp     [ebx + device.mii], 0
  782.         je      .L6
  783.         test    [ebx + device.options], PORT_ASEL
  784.         jnz     .L6
  785.         mov     ecx, BCR_MIICTL
  786.         call    [ebx + device.read_bcr]
  787.         and     eax, not 0x38
  788.         test    [ebx + device.options], PORT_FD
  789.         jz      @f
  790.         or      eax, 0x10
  791.   @@:
  792.         test    [ebx + device.options], PORT_100
  793.         jz      @f
  794.         or      eax, 0x08
  795.   @@:
  796.         call    [ebx + device.write_bcr]
  797.         jmp     .L9
  798.   .L6:
  799.         test    [ebx + device.options], PORT_ASEL
  800.         jz      .L9
  801.         mov     ecx, BCR_MIICTL
  802.         DEBUGF  1,"ASEL, enable auto-negotiation\n"
  803.         call    [ebx + device.read_bcr]
  804.         and     eax, not 0x98
  805.         or      eax, 0x20
  806.         call    [ebx + device.write_bcr]
  807.   .L9:
  808.         cmp     [ebx + device.ltint], 0
  809.         je      @f
  810.         mov     ecx, 5
  811.         call    [ebx + device.read_csr]
  812.         or      eax, (1 shl 14)
  813.         call    [ebx + device.write_csr]
  814.   @@:
  815.         mov     eax, [ebx + device.options]
  816.         and     eax, PORT_PORTSEL
  817.         shl     eax, 7
  818.         mov     [ebx + device.init_block.mode], ax
  819.         mov     dword [ebx + device.init_block.filter], -1
  820.         mov     dword [ebx + device.init_block.filter+4], -1
  821.  
  822.  
  823.  
  824. ;-----------------------------
  825.  
  826.         test    [ebx + device.mii], 1
  827.         jz      .no_mii
  828.  
  829.         mov     [ebx + device.phy], 0
  830.  
  831.   .mii_loop:
  832.         mov     ecx, MII_PHYSID1
  833.         call    mdio_read
  834.         cmp     ax, 0xffff
  835.         je      .next
  836.  
  837.         DEBUGF  1, "0x%x\n", ax
  838.  
  839.         mov     ecx, MII_PHYSID2
  840.         call    mdio_read
  841.         cmp     ax, 0xffff
  842.         je      .next
  843.  
  844.         DEBUGF  1, "0x%x\n", ax
  845.  
  846.         jmp     .got_phy
  847.  
  848.         cmp     [ebx + device.phy], 31
  849.         jne     .next
  850.         mov     ax, [ebx + device.chip_version]
  851.         inc     ax
  852.         and     ax, 0xfffe
  853.         cmp     ax, 0x2624              ; 79c971 & 79c972 have phantom phy at id 31
  854.         je      .got_phy
  855.  
  856.   .next:
  857.         inc     [ebx + device.phy]
  858.         cmp     [ebx + device.phy], MAX_PHYS
  859.         jb      .mii_loop
  860.  
  861.         DEBUGF  2, "No PHY found!\n"
  862.         or      eax, -1
  863.         ret
  864.  
  865.   .got_phy:
  866.         DEBUGF  1, "Found PHY at 0x%x\n", [ebx + device.phy]:4
  867.  
  868.   .no_mii:
  869.  
  870. ;-----------------------------------------------
  871.  
  872.         call    read_mac
  873.  
  874.         lea     esi, [ebx + device.mac]
  875.         lea     edi, [ebx + device.init_block.phys_addr]
  876.         movsd
  877.         movsw
  878.  
  879.         call    init_ring
  880.         test    eax, eax
  881.         jnz     .fail
  882.  
  883.         mov     edx, [ebx + device.io_addr]     ; init ring destroys edx
  884.  
  885.         lea     eax, [ebx + device.init_block]
  886.         invoke  GetPhysAddr
  887.         push    eax
  888.         and     eax, 0xffff
  889.         mov     ecx, CSR_IAB0
  890.         call    [ebx + device.write_csr]
  891.         pop     eax
  892.         shr     eax, 16
  893.         mov     ecx, CSR_IAB1
  894.         call    [ebx + device.write_csr]
  895.  
  896.         mov     ecx, CSR_TFEAT
  897.         mov     eax, 0x0915                     ; Auto TX PAD ?
  898.         call    [ebx + device.write_csr]
  899.  
  900. ; Set the interrupt mask
  901.         mov     ecx, CSR_IMR
  902.         mov     eax, IMR
  903.         call    [ebx + device.write_csr]
  904.  
  905. ; Initialise the device
  906.         xor     ecx, ecx
  907.         mov     eax, CSR_INIT
  908.         call    [ebx + device.write_csr]
  909.  
  910.         mov     esi, 100
  911. ;        xor     ecx, ecx
  912.   @@:
  913.         call    [ebx + device.read_csr]
  914.         test    ax, CSR_IDONE
  915.         jnz     @f
  916.  
  917.         dec     esi
  918.         jnz     @r
  919.         DEBUGF  2,"Initialize timeout!\n"
  920.   @@:
  921.  
  922. ; Start the device and enable interrupts
  923.         xor     ecx, ecx
  924.         mov     eax, CSR_START + CSR_INTEN
  925.         call    [ebx + device.write_csr]
  926.  
  927. ; Set the mtu, kernel will be able to send now
  928.         mov     [ebx + device.mtu], 1514
  929.  
  930. ; get link status
  931.         mov     [ebx + device.state], ETH_LINK_UNKNOWN
  932.  
  933.         call    check_media
  934.  
  935.         DEBUGF  1,"reset complete\n"
  936.         xor     eax, eax
  937.   .fail:
  938.         ret
  939.  
  940.  
  941. align 4
  942. init_ring:
  943.  
  944.         DEBUGF  1,"init ring\n"
  945.  
  946.         lea     edi, [ebx + device.rx_ring]
  947.         mov     eax, edi
  948.         invoke  GetPhysAddr
  949.         mov     [ebx + device.init_block.rx_ring_phys], eax
  950.         mov     ecx, RX_RING_SIZE
  951.   .rx_init:
  952.         push    ecx
  953.         invoke  NetAlloc, PKT_BUF_SZ+NET_BUFF.data
  954.         pop     ecx
  955.         test    eax, eax
  956.         jz      .out_of_mem
  957.         mov     [edi + descriptor.virtual], eax
  958.         invoke  GetPhysAddr
  959.         add     eax, NET_BUFF.data
  960.         mov     [edi + descriptor.base], eax
  961.         mov     [edi + descriptor.length], - PKT_BUF_SZ
  962.         mov     dword[edi + descriptor.msg_length], 0    ; also clears misc field
  963.         mov     [edi + descriptor.status], RXSTAT_OWN
  964.         add     edi, sizeof.descriptor
  965.         dec     ecx
  966.         jnz     .rx_init
  967.  
  968.         lea     edi, [ebx + device.tx_ring]
  969.         mov     eax, edi
  970.         invoke  GetPhysAddr
  971.         mov     [ebx + device.init_block.tx_ring_phys], eax
  972.         mov     ecx, TX_RING_SIZE
  973.   .tx_init:
  974.         mov     [edi + descriptor.status], 0
  975.         add     edi, sizeof.descriptor
  976.         dec     ecx
  977.         jnz     .tx_init
  978.  
  979.         mov     [ebx + device.init_block.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
  980.  
  981.         mov     [ebx + device.cur_tx], 0
  982.         mov     [ebx + device.last_tx], 0
  983.         mov     [ebx + device.cur_rx], 0
  984.  
  985.         xor     eax, eax
  986.         ret
  987.  
  988.   .out_of_mem:
  989.         DEBUGF  2,"Out of memory!\n"
  990.  
  991.         or      eax, -1
  992.         ret
  993.  
  994.  
  995.  
  996.  
  997. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  998. ;;                                         ;;
  999. ;; Transmit                                ;;
  1000. ;;                                         ;;
  1001. ;; In: pointer to device structure in ebx  ;;
  1002. ;;                                         ;;
  1003. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1004.  
  1005. proc transmit stdcall bufferptr
  1006.  
  1007.         pushf
  1008.         cli
  1009.  
  1010.         mov     esi, [bufferptr]
  1011.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
  1012.         lea     eax, [esi + NET_BUFF.data]
  1013.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  1014.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  1015.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  1016.         [eax+13]:2,[eax+12]:2
  1017.  
  1018.         cmp     [esi + NET_BUFF.length], 1514
  1019.         ja      .fail
  1020.         cmp     [esi + NET_BUFF.length], 60
  1021.         jb      .fail
  1022.  
  1023. ; check descriptor
  1024.         lea     edi, [ebx + device.tx_ring]
  1025.         mov     ecx, [ebx + device.cur_tx]
  1026.         shl     ecx, 4
  1027.         add     edi, ecx
  1028.  
  1029.         test    [edi + descriptor.status], TXCTL_OWN
  1030.         jnz     .fail
  1031. ; descriptor is free, use it
  1032.         mov     [edi + descriptor.virtual], esi
  1033.         mov     eax, esi
  1034.         add     eax, [eax + NET_BUFF.offset]
  1035.         invoke  GetPhysAddr
  1036.         mov     [edi + descriptor.base], eax
  1037. ; set length
  1038.         mov     eax, [esi + NET_BUFF.length]
  1039.         neg     eax
  1040.         mov     [edi + descriptor.length], ax
  1041. ; put to transfer queue
  1042.         mov     [edi + descriptor.status], TXCTL_OWN + TXCTL_STP + TXCTL_ENP
  1043.  
  1044. ; trigger an immediate send
  1045.         mov     edx, [ebx + device.io_addr]
  1046.         xor     ecx, ecx                        ; CSR0
  1047.         call    [ebx + device.read_csr]
  1048.         or      eax, CSR_TX
  1049.         call    [ebx + device.write_csr]
  1050.  
  1051. ; get next descriptor
  1052.         inc     [ebx + device.cur_tx]
  1053.         and     [ebx + device.cur_tx], TX_RING_SIZE - 1
  1054.  
  1055. ; Update stats
  1056.         inc     [ebx + device.packets_tx]
  1057.         mov     eax, [esi + NET_BUFF.length]
  1058.         add     dword[ebx + device.bytes_tx], eax
  1059.         adc     dword[ebx + device.bytes_tx + 4], 0
  1060.  
  1061.   .finish:
  1062.         popf
  1063.         xor     eax, eax
  1064.         ret
  1065.  
  1066.   .fail:
  1067.         DEBUGF  2, "Send failed\n"
  1068.         invoke  NetFree, [bufferptr]
  1069.         popf
  1070.         or      eax, -1
  1071.         ret
  1072.  
  1073. endp
  1074.  
  1075.  
  1076. ;;;;;;;;;;;;;;;;;;;;;;;
  1077. ;;                   ;;
  1078. ;; Interrupt handler ;;
  1079. ;;                   ;;
  1080. ;;;;;;;;;;;;;;;;;;;;;;;
  1081.  
  1082. align 4
  1083. int_handler:
  1084.  
  1085.         push    ebx esi edi
  1086.  
  1087.         DEBUGF  1,"INT\n"
  1088.  
  1089. ; find pointer of device wich made IRQ occur
  1090.  
  1091.         mov     ecx, [devices]
  1092.         test    ecx, ecx
  1093.         jz      .nothing
  1094.         mov     esi, device_list
  1095.   .nextdevice:
  1096.         mov     ebx, [esi]
  1097.         mov     edx, [ebx + device.io_addr]
  1098.         push    ecx
  1099.         xor     ecx, ecx                        ; CSR0
  1100.         call    [ebx + device.read_csr]         ; get IRQ reason
  1101.         call    [ebx + device.write_csr]        ; write it back to ACK
  1102.         pop     ecx
  1103.         test    ax, CSR_RINT or CSR_TINT
  1104.         jnz     .got_it
  1105.   .continue:
  1106.         add     esi, 4
  1107.         dec     ecx
  1108.         jnz     .nextdevice
  1109.   .nothing:
  1110.         pop     edi esi ebx
  1111.         xor     eax, eax
  1112.  
  1113.         ret
  1114.  
  1115.   .got_it:
  1116.         DEBUGF  1,"Device: %x status: %x\n", ebx, eax:4
  1117.  
  1118.         push    ax
  1119.         test    ax, CSR_RINT
  1120.         jz      .not_receive
  1121.  
  1122.         push    ebx
  1123.   .rx_loop:
  1124.         pop     ebx
  1125.         mov     eax, [ebx + device.cur_rx]
  1126.         shl     eax, 4
  1127.         lea     edi, [ebx + device.rx_ring]
  1128.         add     edi, eax                        ; edi now points to current rx ring entry
  1129.  
  1130.         mov     ax, [edi + descriptor.status]
  1131.         DEBUGF  1,"RX packet status: %x\n", eax:4
  1132.  
  1133.         test    ax, RXSTAT_OWN                  ; If this bit is set, the controller OWN's the packet, if not, we do
  1134.         jnz     .not_receive
  1135.  
  1136.         test    ax, RXSTAT_ENP
  1137.         jz      .not_receive
  1138.  
  1139.         test    ax, RXSTAT_STP
  1140.         jz      .not_receive
  1141.  
  1142.         movzx   ecx, [edi + descriptor.msg_length]      ; get packet length in ecx
  1143.         sub     ecx, 4                                  ; We dont need the CRC
  1144.         DEBUGF  1,"Got %u bytes\n", ecx
  1145.  
  1146. ; Set pointers for ETH_input
  1147.         push    ebx
  1148.  
  1149.         push    .rx_loop                                ; return address
  1150.         mov     eax, [edi + descriptor.virtual]
  1151.         push    eax                                     ; packet address
  1152.         mov     [eax + NET_BUFF.length], ecx
  1153.         mov     [eax + NET_BUFF.device], ebx
  1154.         mov     [eax + NET_BUFF.offset], NET_BUFF.data
  1155.  
  1156. ; Update stats
  1157.         add     dword[ebx + device.bytes_rx], ecx
  1158.         adc     dword[ebx + device.bytes_rx + 4], 0
  1159.         inc     [ebx + device.packets_rx]
  1160.  
  1161. ; now allocate a new buffer
  1162.         invoke  NetAlloc, PKT_BUF_SZ+NET_BUFF.data      ; Allocate a buffer for the next packet
  1163.         test    eax, eax
  1164.         jz      .out_of_mem
  1165.         mov     [edi + descriptor.virtual], eax         ; set virtual address
  1166.         invoke  GetPhysAddr
  1167.         add     eax, NET_BUFF.data
  1168.         mov     [edi + descriptor.base], eax            ; and physical address
  1169.         mov     [edi + descriptor.status], RXSTAT_OWN   ; give it back to PCnet controller
  1170.  
  1171.         inc     [ebx + device.cur_rx]                   ; set next receive descriptor
  1172.         and     [ebx + device.cur_rx], RX_RING_SIZE - 1
  1173.  
  1174.         jmp     [EthInput]
  1175.  
  1176.   .out_of_mem:
  1177.         DEBUGF  2,"Out of memory!\n"
  1178.  
  1179.         inc     [ebx + device.cur_rx]                   ; set next receive descriptor
  1180.         and     [ebx + device.cur_rx], RX_RING_SIZE - 1
  1181.  
  1182.         jmp     [EthInput]
  1183.  
  1184.   .not_receive:
  1185.         pop     ax
  1186.  
  1187.         test    ax, CSR_TINT
  1188.         jz      .not_transmit
  1189.  
  1190.   .tx_loop:
  1191.         lea     edi, [ebx + device.tx_ring]
  1192.         mov     eax, [ebx + device.last_tx]
  1193.         shl     eax, 4
  1194.         add     edi, eax
  1195.  
  1196.         test    [edi + descriptor.status], TXCTL_OWN
  1197.         jnz     .not_transmit
  1198.  
  1199.         mov     eax, [edi + descriptor.virtual]
  1200.         test    eax, eax
  1201.         jz      .not_transmit
  1202.  
  1203.         mov     [edi + descriptor.virtual], 0
  1204.  
  1205.         DEBUGF  1,"Removing packet %x from memory\n", eax
  1206.  
  1207.         invoke  NetFree, eax
  1208.  
  1209.         inc     [ebx + device.last_tx]
  1210.         and     [ebx + device.last_tx], TX_RING_SIZE - 1
  1211.         jmp     .tx_loop
  1212.  
  1213.   .not_transmit:
  1214.         pop     edi esi ebx
  1215.         xor     eax, eax
  1216.         inc     eax
  1217.  
  1218.         ret
  1219.  
  1220.  
  1221.  
  1222.  
  1223. ;;;;;;;;;;;;;;;;;;;;;;;
  1224. ;;                   ;;
  1225. ;; Write MAC address ;;
  1226. ;;                   ;;
  1227. ;;;;;;;;;;;;;;;;;;;;;;;
  1228.  
  1229. align 4
  1230. write_mac:      ; in: mac pushed onto stack (as 3 words)
  1231.  
  1232.         DEBUGF  1,"Writing MAC: %x-%x-%x-%x-%x-%x\n",\
  1233.         [esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
  1234.  
  1235.         mov     edx, [ebx + device.io_addr]
  1236.         add     dx, 2
  1237.         xor     eax, eax
  1238.  
  1239.         mov     ecx, CSR_PAR0
  1240.        @@:
  1241.         pop     ax
  1242.         call    [ebx + device.write_csr]
  1243.         inc     ecx
  1244.         cmp     ecx, CSR_PAR2
  1245.         jb      @r
  1246.  
  1247. ; Notice this procedure does not ret, but continues to read_mac instead.
  1248.  
  1249. ;;;;;;;;;;;;;;;;;;;;;;
  1250. ;;                  ;;
  1251. ;; Read MAC address ;;
  1252. ;;                  ;;
  1253. ;;;;;;;;;;;;;;;;;;;;;;
  1254. align 4
  1255. read_mac:
  1256.         DEBUGF  1,"Reading MAC\n"
  1257.  
  1258.         mov     edx, [ebx + device.io_addr]
  1259.         lea     edi, [ebx + device.mac]
  1260.         in      ax, dx
  1261.         stosw
  1262.  
  1263.         inc     dx
  1264.         inc     dx
  1265.         in      ax, dx
  1266.         stosw
  1267.  
  1268.         inc     dx
  1269.         inc     dx
  1270.         in      ax, dx
  1271.         stosw
  1272.  
  1273.         DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
  1274.         [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,\
  1275.         [ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
  1276.  
  1277.         ret
  1278.  
  1279. align 4
  1280. switch_to_wio:
  1281.  
  1282.         DEBUGF  1,"Switching to 16-bit mode\n"
  1283.  
  1284.         mov     [ebx + device.read_csr], wio_read_csr
  1285.         mov     [ebx + device.write_csr], wio_write_csr
  1286.         mov     [ebx + device.read_bcr], wio_read_bcr
  1287.         mov     [ebx + device.write_bcr], wio_write_bcr
  1288.         mov     [ebx + device.read_rap], wio_read_rap
  1289.         mov     [ebx + device.write_rap], wio_write_rap
  1290.         mov     [ebx + device.sw_reset], wio_reset
  1291.  
  1292.         ret
  1293.  
  1294. align 4
  1295. switch_to_dwio:
  1296.  
  1297.         DEBUGF  1,"Switching to 32-bit mode\n"
  1298.  
  1299.         mov     [ebx + device.read_csr], dwio_read_csr
  1300.         mov     [ebx + device.write_csr], dwio_write_csr
  1301.         mov     [ebx + device.read_bcr], dwio_read_bcr
  1302.         mov     [ebx + device.write_bcr], dwio_write_bcr
  1303.         mov     [ebx + device.read_rap], dwio_read_rap
  1304.         mov     [ebx + device.write_rap], dwio_write_rap
  1305.         mov     [ebx + device.sw_reset], dwio_reset
  1306.  
  1307.         ret
  1308.  
  1309.  
  1310. ; ecx - index
  1311. ; return:
  1312. ; eax - data
  1313. align 4
  1314. wio_read_csr:
  1315.  
  1316.         add     edx, WIO_RAP
  1317.         mov     ax, cx
  1318.         out     dx, ax
  1319.         add     edx, WIO_RDP - WIO_RAP
  1320.         in      ax, dx
  1321.         and     eax, 0xffff
  1322.         sub     edx, WIO_RDP
  1323.  
  1324.         ret
  1325.  
  1326.  
  1327. ; eax - data
  1328. ; ecx - index
  1329. align 4
  1330. wio_write_csr:
  1331.  
  1332.         add     edx, WIO_RAP
  1333.         xchg    eax, ecx
  1334.         out     dx, ax
  1335.         xchg    eax, ecx
  1336.         add     edx, WIO_RDP - WIO_RAP
  1337.         out     dx, ax
  1338.         sub     edx, WIO_RDP
  1339.  
  1340.         ret
  1341.  
  1342.  
  1343. ; ecx - index
  1344. ; return:
  1345. ; eax - data
  1346. align 4
  1347. wio_read_bcr:
  1348.  
  1349.         add     edx, WIO_RAP
  1350.         mov     ax, cx
  1351.         out     dx, ax
  1352.         add     edx, WIO_BDP - WIO_RAP
  1353.         in      ax, dx
  1354.         and     eax, 0xffff
  1355.         sub     edx, WIO_BDP
  1356.  
  1357.         ret
  1358.  
  1359.  
  1360. ; eax - data
  1361. ; ecx - index
  1362. align 4
  1363. wio_write_bcr:
  1364.  
  1365.         add     edx, WIO_RAP
  1366.         xchg    eax, ecx
  1367.         out     dx, ax
  1368.         xchg    eax, ecx
  1369.         add     edx, WIO_BDP - WIO_RAP
  1370.         out     dx, ax
  1371.         sub     edx, WIO_BDP
  1372.  
  1373.         ret
  1374.  
  1375. align 4
  1376. wio_read_rap:
  1377.  
  1378.         add     edx, WIO_RAP
  1379.         in      ax, dx
  1380.         and     eax, 0xffff
  1381.         sub     edx, WIO_RAP
  1382.  
  1383.         ret
  1384.  
  1385. ; eax - val
  1386. align 4
  1387. wio_write_rap:
  1388.  
  1389.         add     edx, WIO_RAP
  1390.         out     dx, ax
  1391.         sub     edx, WIO_RAP
  1392.  
  1393.         ret
  1394.  
  1395. align 4
  1396. wio_reset:
  1397.  
  1398.         push    eax
  1399.         add     edx, WIO_RESET
  1400.         in      ax, dx
  1401.         pop     eax
  1402.         sub     edx, WIO_RESET
  1403.  
  1404.         ret
  1405.  
  1406.  
  1407.  
  1408. ; ecx - index
  1409. ; return:
  1410. ; eax - data
  1411. align 4
  1412. dwio_read_csr:
  1413.  
  1414.         add     edx, DWIO_RAP
  1415.         mov     eax, ecx
  1416.         out     dx, eax
  1417.         add     edx, DWIO_RDP - DWIO_RAP
  1418.         in      eax, dx
  1419.         and     eax, 0xffff
  1420.         sub     edx, DWIO_RDP
  1421.  
  1422.         ret
  1423.  
  1424.  
  1425. ; ecx - index
  1426. ; eax - data
  1427. align 4
  1428. dwio_write_csr:
  1429.  
  1430.         add     edx, DWIO_RAP
  1431.         xchg    eax, ecx
  1432.         out     dx, eax
  1433.         add     edx, DWIO_RDP - DWIO_RAP
  1434.         xchg    eax, ecx
  1435.         out     dx, eax
  1436.         sub     edx, DWIO_RDP
  1437.  
  1438.         ret
  1439.  
  1440. ; ecx - index
  1441. ; return:
  1442. ; eax - data
  1443. align 4
  1444. dwio_read_bcr:
  1445.  
  1446.         add     edx, DWIO_RAP
  1447.         mov     eax, ecx
  1448.         out     dx, eax
  1449.         add     edx, DWIO_BDP - DWIO_RAP
  1450.         in      eax, dx
  1451.         and     eax, 0xffff
  1452.         sub     edx, DWIO_BDP
  1453.  
  1454.         ret
  1455.  
  1456.  
  1457. ; ecx - index
  1458. ; eax - data
  1459. align 4
  1460. dwio_write_bcr:
  1461.  
  1462.         add     edx, DWIO_RAP
  1463.         xchg    eax, ecx
  1464.         out     dx, eax
  1465.         add     edx, DWIO_BDP - DWIO_RAP
  1466.         xchg    eax, ecx
  1467.         out     dx, eax
  1468.         sub     edx, DWIO_BDP
  1469.  
  1470.         ret
  1471.  
  1472. align 4
  1473. dwio_read_rap:
  1474.  
  1475.         add     edx, DWIO_RAP
  1476.         in      eax, dx
  1477.         and     eax, 0xffff
  1478.         sub     edx, DWIO_RAP
  1479.  
  1480.         ret
  1481.  
  1482.  
  1483. ; eax - val
  1484. align 4
  1485. dwio_write_rap:
  1486.  
  1487.         add     edx, DWIO_RAP
  1488.         out     dx, eax
  1489.         sub     edx, DWIO_RAP
  1490.  
  1491.         ret
  1492.  
  1493. align 4
  1494. dwio_reset:
  1495.  
  1496.         push    eax
  1497.         add     edx, DWIO_RESET
  1498.         in      eax, dx
  1499.         pop     eax
  1500.         sub     edx, DWIO_RESET
  1501.  
  1502.         ret
  1503.  
  1504.  
  1505. align 4
  1506. mdio_read:
  1507.  
  1508.         and     ecx, 0x1f
  1509.         mov     ax, [ebx + device.phy]
  1510.         and     ax, 0x1f
  1511.         shl     ax, 5
  1512.         or      ax, cx
  1513.  
  1514.         mov     ecx, BCR_MIIADDR
  1515.         call    [ebx + device.write_bcr]
  1516.  
  1517.         mov     ecx, BCR_MIIDATA
  1518.         call    [ebx + device.read_bcr]
  1519.  
  1520.         ret
  1521.  
  1522.  
  1523. align 4
  1524. mdio_write:
  1525.  
  1526.         push    eax
  1527.         and     ecx, 0x1f
  1528.         mov     ax, [ebx + device.phy]
  1529.         and     ax, 0x1f
  1530.         shl     ax, 5
  1531.         or      ax, cx
  1532.  
  1533.         mov     ecx, BCR_MIIADDR
  1534.         call    [ebx + device.write_bcr]
  1535.  
  1536.         pop     eax
  1537.         mov     ecx, BCR_MIIDATA
  1538.         call    [ebx + device.write_bcr]
  1539.  
  1540.         ret
  1541.  
  1542.  
  1543. align 4
  1544. check_media:
  1545.  
  1546.         DEBUGF  1, "check_media\n"
  1547.  
  1548.         test    [ebx + device.mii], 1
  1549.         jnz     mii_link_ok
  1550.  
  1551.         mov     ecx, BCR_LED0
  1552.         call    [ebx + device.read_bcr]
  1553.         cmp     eax, 0xc0
  1554.  
  1555.         DEBUGF  2, "link status=0x%x\n", ax
  1556.  
  1557.         ret
  1558.  
  1559.  
  1560.  
  1561. ; End of code
  1562.  
  1563.  
  1564. data fixups
  1565. end data
  1566.  
  1567. include '../peimport.inc'
  1568.  
  1569. my_service    db 'PCNET32',0            ; max 16 chars include zero
  1570.  
  1571. device_l2     db "PCnet/PCI 79C970",0
  1572. device_l4     db "PCnet/PCI II 79C970A",0
  1573. device_l5     db "PCnet/FAST 79C971",0
  1574. device_l6     db "PCnet/FAST+ 79C972",0
  1575. device_l7     db "PCnet/FAST III 79C973",0
  1576. device_l8     db "PCnet/Home 79C978",0
  1577. device_l9     db "PCnet/FAST III 79C975",0
  1578.  
  1579. options_mapping:
  1580. dd PORT_ASEL                            ; 0 Auto-select
  1581. dd PORT_AUI                             ; 1 BNC/AUI
  1582. dd PORT_AUI                             ; 2 AUI/BNC
  1583. dd PORT_ASEL                            ; 3 not supported
  1584. dd PORT_10BT or PORT_FD                 ; 4 10baseT-FD
  1585. dd PORT_ASEL                            ; 5 not supported
  1586. dd PORT_ASEL                            ; 6 not supported
  1587. dd PORT_ASEL                            ; 7 not supported
  1588. dd PORT_ASEL                            ; 8 not supported
  1589. dd PORT_MII                             ; 9 MII 10baseT
  1590. dd PORT_MII or PORT_FD                  ; 10 MII 10baseT-FD
  1591. dd PORT_MII                             ; 11 MII (autosel)
  1592. dd PORT_10BT                            ; 12 10BaseT
  1593. dd PORT_MII or PORT_100                 ; 13 MII 100BaseTx
  1594. dd PORT_MII or PORT_100 or PORT_FD      ; 14 MII 100BaseTx-FD
  1595. dd PORT_ASEL                            ; 15 not supported
  1596.  
  1597. include_debug_strings                                   ; All data wich FDO uses will be included here
  1598.  
  1599.  
  1600. align 4
  1601. devices     dd 0
  1602. device_list rd MAX_DEVICES                              ; This list contains all pointers to device structures the driver is handling
  1603.