Subversion Repositories Kolibri OS

Rev

Rev 8897 | Rev 8910 | 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      .error
  1020.         cmp     [esi + NET_BUFF.length], 60
  1021.         jb      .error
  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     .overrun
  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.         popf
  1062.         xor     eax, eax
  1063.         ret
  1064.  
  1065.   .error:
  1066.         DEBUGF  2, "TX packet error\n"
  1067.         inc     [ebx + device.packets_tx_err]
  1068.         invoke  NetFree, [bufferptr]
  1069.  
  1070.         popf
  1071.         or      eax, -1
  1072.         ret
  1073.  
  1074.   .overrun:
  1075.         DEBUGF  2, "TX overrun\n"
  1076.         inc     [ebx + device.packets_tx_ovr]
  1077.         invoke  NetFree, [bufferptr]
  1078.  
  1079.         popf
  1080.         or      eax, -1
  1081.         ret
  1082.  
  1083. endp
  1084.  
  1085.  
  1086. ;;;;;;;;;;;;;;;;;;;;;;;
  1087. ;;                   ;;
  1088. ;; Interrupt handler ;;
  1089. ;;                   ;;
  1090. ;;;;;;;;;;;;;;;;;;;;;;;
  1091.  
  1092. align 4
  1093. int_handler:
  1094.  
  1095.         push    ebx esi edi
  1096.  
  1097.         DEBUGF  1,"INT\n"
  1098.  
  1099. ; find pointer of device wich made IRQ occur
  1100.  
  1101.         mov     ecx, [devices]
  1102.         test    ecx, ecx
  1103.         jz      .nothing
  1104.         mov     esi, device_list
  1105.   .nextdevice:
  1106.         mov     ebx, [esi]
  1107.         mov     edx, [ebx + device.io_addr]
  1108.         push    ecx
  1109.         xor     ecx, ecx                        ; CSR0
  1110.         call    [ebx + device.read_csr]         ; get IRQ reason
  1111.         call    [ebx + device.write_csr]        ; write it back to ACK
  1112.         pop     ecx
  1113.         test    ax, CSR_RINT or CSR_TINT
  1114.         jnz     .got_it
  1115.   .continue:
  1116.         add     esi, 4
  1117.         dec     ecx
  1118.         jnz     .nextdevice
  1119.   .nothing:
  1120.         pop     edi esi ebx
  1121.         xor     eax, eax
  1122.  
  1123.         ret
  1124.  
  1125.   .got_it:
  1126.         DEBUGF  1,"Device: %x status: %x\n", ebx, eax:4
  1127.  
  1128.         push    ax
  1129.         test    ax, CSR_RINT
  1130.         jz      .not_receive
  1131.  
  1132.         push    ebx
  1133.   .rx_loop:
  1134.         pop     ebx
  1135.         push    ebx
  1136.         mov     eax, [ebx + device.cur_rx]
  1137.         shl     eax, 4
  1138.         lea     edi, [ebx + device.rx_ring]
  1139.         add     edi, eax                        ; edi now points to current rx ring entry
  1140.  
  1141.         mov     ax, [edi + descriptor.status]
  1142.         DEBUGF  1,"RX packet status: %x\n", eax:4
  1143.  
  1144.         test    ax, RXSTAT_OWN                  ; If this bit is set, the controller OWN's the packet, if not, we do
  1145.         jnz     .rx_done
  1146. ; Both Start of packet and End of packet bits should be set, we dont support multi frame packets
  1147.         test    ax, RXSTAT_ENP
  1148.         jz      .rx_drop
  1149.         test    ax, RXSTAT_STP
  1150.         jz      .rx_drop
  1151.  
  1152.         movzx   ecx, [edi + descriptor.msg_length]      ; get packet length in ecx
  1153.         sub     ecx, 4                                  ; We dont need the CRC
  1154.         DEBUGF  1,"Got %u bytes\n", ecx
  1155.  
  1156. ; Set pointers for ETH_input
  1157.         push    .rx_loop                                ; return address
  1158.         mov     eax, [edi + descriptor.virtual]
  1159.         push    eax                                     ; packet address
  1160.         mov     [eax + NET_BUFF.length], ecx
  1161.         mov     [eax + NET_BUFF.device], ebx
  1162.         mov     [eax + NET_BUFF.offset], NET_BUFF.data
  1163.  
  1164. ; Update stats
  1165.         add     dword[ebx + device.bytes_rx], ecx
  1166.         adc     dword[ebx + device.bytes_rx + 4], 0
  1167.         inc     [ebx + device.packets_rx]
  1168.  
  1169. ; now allocate a new buffer
  1170.         invoke  NetAlloc, PKT_BUF_SZ+NET_BUFF.data      ; Allocate a buffer for the next packet
  1171.         test    eax, eax
  1172.         jz      .rx_overrun
  1173.         mov     [edi + descriptor.virtual], eax         ; set virtual address
  1174.         invoke  GetPhysAddr
  1175.         add     eax, NET_BUFF.data
  1176.         mov     [edi + descriptor.base], eax            ; and physical address
  1177.         mov     [edi + descriptor.status], RXSTAT_OWN   ; give it back to PCnet controller
  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.   .rx_overrun:
  1185.         add     esp, 4+4
  1186.         DEBUGF  2,"RX FIFO overrun\n"
  1187.         inc     [ebx + device.packets_rx_ovr]
  1188.         jmp     .rx_next
  1189.  
  1190.   .rx_drop:
  1191.         DEBUGF  2,"Dropping incoming packet\n"
  1192.         inc     [ebx + device.packets_rx_drop]
  1193.  
  1194.   .rx_next:
  1195.         mov     [edi + descriptor.status], RXSTAT_OWN   ; give it back to PCnet controller
  1196.  
  1197.         inc     [ebx + device.cur_rx]                   ; set next receive descriptor
  1198.         and     [ebx + device.cur_rx], RX_RING_SIZE - 1
  1199.         jmp     .rx_loop
  1200.  
  1201.   .rx_done:
  1202.         pop     ebx
  1203.  
  1204.   .not_receive:
  1205.         pop     ax
  1206.  
  1207.         test    ax, CSR_TINT
  1208.         jz      .not_transmit
  1209.  
  1210.   .tx_loop:
  1211.         lea     edi, [ebx + device.tx_ring]
  1212.         mov     eax, [ebx + device.last_tx]
  1213.         shl     eax, 4
  1214.         add     edi, eax
  1215.  
  1216.         test    [edi + descriptor.status], TXCTL_OWN
  1217.         jnz     .not_transmit
  1218.  
  1219.         mov     eax, [edi + descriptor.virtual]
  1220.         test    eax, eax
  1221.         jz      .not_transmit
  1222.  
  1223.         mov     [edi + descriptor.virtual], 0
  1224.  
  1225.         DEBUGF  1,"Removing packet %x from memory\n", eax
  1226.  
  1227.         invoke  NetFree, eax
  1228.  
  1229.         inc     [ebx + device.last_tx]
  1230.         and     [ebx + device.last_tx], TX_RING_SIZE - 1
  1231.         jmp     .tx_loop
  1232.  
  1233.   .not_transmit:
  1234.         pop     edi esi ebx
  1235.         xor     eax, eax
  1236.         inc     eax
  1237.  
  1238.         ret
  1239.  
  1240.  
  1241.  
  1242.  
  1243. ;;;;;;;;;;;;;;;;;;;;;;;
  1244. ;;                   ;;
  1245. ;; Write MAC address ;;
  1246. ;;                   ;;
  1247. ;;;;;;;;;;;;;;;;;;;;;;;
  1248.  
  1249. align 4
  1250. write_mac:      ; in: mac pushed onto stack (as 3 words)
  1251.  
  1252.         DEBUGF  1,"Writing MAC: %x-%x-%x-%x-%x-%x\n",\
  1253.         [esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
  1254.  
  1255.         mov     edx, [ebx + device.io_addr]
  1256.         add     dx, 2
  1257.         xor     eax, eax
  1258.  
  1259.         mov     ecx, CSR_PAR0
  1260.        @@:
  1261.         pop     ax
  1262.         call    [ebx + device.write_csr]
  1263.         inc     ecx
  1264.         cmp     ecx, CSR_PAR2
  1265.         jb      @r
  1266.  
  1267. ; Notice this procedure does not ret, but continues to read_mac instead.
  1268.  
  1269. ;;;;;;;;;;;;;;;;;;;;;;
  1270. ;;                  ;;
  1271. ;; Read MAC address ;;
  1272. ;;                  ;;
  1273. ;;;;;;;;;;;;;;;;;;;;;;
  1274. align 4
  1275. read_mac:
  1276.         DEBUGF  1,"Reading MAC\n"
  1277.  
  1278.         mov     edx, [ebx + device.io_addr]
  1279.         lea     edi, [ebx + device.mac]
  1280.         in      ax, dx
  1281.         stosw
  1282.  
  1283.         inc     dx
  1284.         inc     dx
  1285.         in      ax, dx
  1286.         stosw
  1287.  
  1288.         inc     dx
  1289.         inc     dx
  1290.         in      ax, dx
  1291.         stosw
  1292.  
  1293.         DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
  1294.         [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,\
  1295.         [ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
  1296.  
  1297.         ret
  1298.  
  1299. align 4
  1300. switch_to_wio:
  1301.  
  1302.         DEBUGF  1,"Switching to 16-bit mode\n"
  1303.  
  1304.         mov     [ebx + device.read_csr], wio_read_csr
  1305.         mov     [ebx + device.write_csr], wio_write_csr
  1306.         mov     [ebx + device.read_bcr], wio_read_bcr
  1307.         mov     [ebx + device.write_bcr], wio_write_bcr
  1308.         mov     [ebx + device.read_rap], wio_read_rap
  1309.         mov     [ebx + device.write_rap], wio_write_rap
  1310.         mov     [ebx + device.sw_reset], wio_reset
  1311.  
  1312.         ret
  1313.  
  1314. align 4
  1315. switch_to_dwio:
  1316.  
  1317.         DEBUGF  1,"Switching to 32-bit mode\n"
  1318.  
  1319.         mov     [ebx + device.read_csr], dwio_read_csr
  1320.         mov     [ebx + device.write_csr], dwio_write_csr
  1321.         mov     [ebx + device.read_bcr], dwio_read_bcr
  1322.         mov     [ebx + device.write_bcr], dwio_write_bcr
  1323.         mov     [ebx + device.read_rap], dwio_read_rap
  1324.         mov     [ebx + device.write_rap], dwio_write_rap
  1325.         mov     [ebx + device.sw_reset], dwio_reset
  1326.  
  1327.         ret
  1328.  
  1329.  
  1330. ; ecx - index
  1331. ; return:
  1332. ; eax - data
  1333. align 4
  1334. wio_read_csr:
  1335.  
  1336.         add     edx, WIO_RAP
  1337.         mov     ax, cx
  1338.         out     dx, ax
  1339.         add     edx, WIO_RDP - WIO_RAP
  1340.         in      ax, dx
  1341.         and     eax, 0xffff
  1342.         sub     edx, WIO_RDP
  1343.  
  1344.         ret
  1345.  
  1346.  
  1347. ; eax - data
  1348. ; ecx - index
  1349. align 4
  1350. wio_write_csr:
  1351.  
  1352.         add     edx, WIO_RAP
  1353.         xchg    eax, ecx
  1354.         out     dx, ax
  1355.         xchg    eax, ecx
  1356.         add     edx, WIO_RDP - WIO_RAP
  1357.         out     dx, ax
  1358.         sub     edx, WIO_RDP
  1359.  
  1360.         ret
  1361.  
  1362.  
  1363. ; ecx - index
  1364. ; return:
  1365. ; eax - data
  1366. align 4
  1367. wio_read_bcr:
  1368.  
  1369.         add     edx, WIO_RAP
  1370.         mov     ax, cx
  1371.         out     dx, ax
  1372.         add     edx, WIO_BDP - WIO_RAP
  1373.         in      ax, dx
  1374.         and     eax, 0xffff
  1375.         sub     edx, WIO_BDP
  1376.  
  1377.         ret
  1378.  
  1379.  
  1380. ; eax - data
  1381. ; ecx - index
  1382. align 4
  1383. wio_write_bcr:
  1384.  
  1385.         add     edx, WIO_RAP
  1386.         xchg    eax, ecx
  1387.         out     dx, ax
  1388.         xchg    eax, ecx
  1389.         add     edx, WIO_BDP - WIO_RAP
  1390.         out     dx, ax
  1391.         sub     edx, WIO_BDP
  1392.  
  1393.         ret
  1394.  
  1395. align 4
  1396. wio_read_rap:
  1397.  
  1398.         add     edx, WIO_RAP
  1399.         in      ax, dx
  1400.         and     eax, 0xffff
  1401.         sub     edx, WIO_RAP
  1402.  
  1403.         ret
  1404.  
  1405. ; eax - val
  1406. align 4
  1407. wio_write_rap:
  1408.  
  1409.         add     edx, WIO_RAP
  1410.         out     dx, ax
  1411.         sub     edx, WIO_RAP
  1412.  
  1413.         ret
  1414.  
  1415. align 4
  1416. wio_reset:
  1417.  
  1418.         push    eax
  1419.         add     edx, WIO_RESET
  1420.         in      ax, dx
  1421.         pop     eax
  1422.         sub     edx, WIO_RESET
  1423.  
  1424.         ret
  1425.  
  1426.  
  1427.  
  1428. ; ecx - index
  1429. ; return:
  1430. ; eax - data
  1431. align 4
  1432. dwio_read_csr:
  1433.  
  1434.         add     edx, DWIO_RAP
  1435.         mov     eax, ecx
  1436.         out     dx, eax
  1437.         add     edx, DWIO_RDP - DWIO_RAP
  1438.         in      eax, dx
  1439.         and     eax, 0xffff
  1440.         sub     edx, DWIO_RDP
  1441.  
  1442.         ret
  1443.  
  1444.  
  1445. ; ecx - index
  1446. ; eax - data
  1447. align 4
  1448. dwio_write_csr:
  1449.  
  1450.         add     edx, DWIO_RAP
  1451.         xchg    eax, ecx
  1452.         out     dx, eax
  1453.         add     edx, DWIO_RDP - DWIO_RAP
  1454.         xchg    eax, ecx
  1455.         out     dx, eax
  1456.         sub     edx, DWIO_RDP
  1457.  
  1458.         ret
  1459.  
  1460. ; ecx - index
  1461. ; return:
  1462. ; eax - data
  1463. align 4
  1464. dwio_read_bcr:
  1465.  
  1466.         add     edx, DWIO_RAP
  1467.         mov     eax, ecx
  1468.         out     dx, eax
  1469.         add     edx, DWIO_BDP - DWIO_RAP
  1470.         in      eax, dx
  1471.         and     eax, 0xffff
  1472.         sub     edx, DWIO_BDP
  1473.  
  1474.         ret
  1475.  
  1476.  
  1477. ; ecx - index
  1478. ; eax - data
  1479. align 4
  1480. dwio_write_bcr:
  1481.  
  1482.         add     edx, DWIO_RAP
  1483.         xchg    eax, ecx
  1484.         out     dx, eax
  1485.         add     edx, DWIO_BDP - DWIO_RAP
  1486.         xchg    eax, ecx
  1487.         out     dx, eax
  1488.         sub     edx, DWIO_BDP
  1489.  
  1490.         ret
  1491.  
  1492. align 4
  1493. dwio_read_rap:
  1494.  
  1495.         add     edx, DWIO_RAP
  1496.         in      eax, dx
  1497.         and     eax, 0xffff
  1498.         sub     edx, DWIO_RAP
  1499.  
  1500.         ret
  1501.  
  1502.  
  1503. ; eax - val
  1504. align 4
  1505. dwio_write_rap:
  1506.  
  1507.         add     edx, DWIO_RAP
  1508.         out     dx, eax
  1509.         sub     edx, DWIO_RAP
  1510.  
  1511.         ret
  1512.  
  1513. align 4
  1514. dwio_reset:
  1515.  
  1516.         push    eax
  1517.         add     edx, DWIO_RESET
  1518.         in      eax, dx
  1519.         pop     eax
  1520.         sub     edx, DWIO_RESET
  1521.  
  1522.         ret
  1523.  
  1524.  
  1525. align 4
  1526. mdio_read:
  1527.  
  1528.         and     ecx, 0x1f
  1529.         mov     ax, [ebx + device.phy]
  1530.         and     ax, 0x1f
  1531.         shl     ax, 5
  1532.         or      ax, cx
  1533.  
  1534.         mov     ecx, BCR_MIIADDR
  1535.         call    [ebx + device.write_bcr]
  1536.  
  1537.         mov     ecx, BCR_MIIDATA
  1538.         call    [ebx + device.read_bcr]
  1539.  
  1540.         ret
  1541.  
  1542.  
  1543. align 4
  1544. mdio_write:
  1545.  
  1546.         push    eax
  1547.         and     ecx, 0x1f
  1548.         mov     ax, [ebx + device.phy]
  1549.         and     ax, 0x1f
  1550.         shl     ax, 5
  1551.         or      ax, cx
  1552.  
  1553.         mov     ecx, BCR_MIIADDR
  1554.         call    [ebx + device.write_bcr]
  1555.  
  1556.         pop     eax
  1557.         mov     ecx, BCR_MIIDATA
  1558.         call    [ebx + device.write_bcr]
  1559.  
  1560.         ret
  1561.  
  1562.  
  1563. align 4
  1564. check_media:
  1565.  
  1566.         DEBUGF  1, "check_media\n"
  1567.  
  1568.         test    [ebx + device.mii], 1
  1569.         jnz     mii_link_ok
  1570.  
  1571.         mov     ecx, BCR_LED0
  1572.         call    [ebx + device.read_bcr]
  1573.         cmp     eax, 0xc0
  1574.  
  1575.         DEBUGF  2, "link status=0x%x\n", ax
  1576.  
  1577.         ret
  1578.  
  1579.  
  1580.  
  1581. ; End of code
  1582.  
  1583.  
  1584. data fixups
  1585. end data
  1586.  
  1587. include '../peimport.inc'
  1588.  
  1589. my_service    db 'PCNET32',0            ; max 16 chars include zero
  1590.  
  1591. device_l2     db "PCnet/PCI 79C970",0
  1592. device_l4     db "PCnet/PCI II 79C970A",0
  1593. device_l5     db "PCnet/FAST 79C971",0
  1594. device_l6     db "PCnet/FAST+ 79C972",0
  1595. device_l7     db "PCnet/FAST III 79C973",0
  1596. device_l8     db "PCnet/Home 79C978",0
  1597. device_l9     db "PCnet/FAST III 79C975",0
  1598.  
  1599. options_mapping:
  1600. dd PORT_ASEL                            ; 0 Auto-select
  1601. dd PORT_AUI                             ; 1 BNC/AUI
  1602. dd PORT_AUI                             ; 2 AUI/BNC
  1603. dd PORT_ASEL                            ; 3 not supported
  1604. dd PORT_10BT or PORT_FD                 ; 4 10baseT-FD
  1605. dd PORT_ASEL                            ; 5 not supported
  1606. dd PORT_ASEL                            ; 6 not supported
  1607. dd PORT_ASEL                            ; 7 not supported
  1608. dd PORT_ASEL                            ; 8 not supported
  1609. dd PORT_MII                             ; 9 MII 10baseT
  1610. dd PORT_MII or PORT_FD                  ; 10 MII 10baseT-FD
  1611. dd PORT_MII                             ; 11 MII (autosel)
  1612. dd PORT_10BT                            ; 12 10BaseT
  1613. dd PORT_MII or PORT_100                 ; 13 MII 100BaseTx
  1614. dd PORT_MII or PORT_100 or PORT_FD      ; 14 MII 100BaseTx-FD
  1615. dd PORT_ASEL                            ; 15 not supported
  1616.  
  1617. include_debug_strings                                   ; All data wich FDO uses will be included here
  1618.  
  1619.  
  1620. align 4
  1621. devices     dd 0
  1622. device_list rd MAX_DEVICES                              ; This list contains all pointers to device structures the driver is handling
  1623.