Subversion Repositories Kolibri OS

Rev

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