Subversion Repositories Kolibri OS

Rev

Rev 4470 | Rev 4582 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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