Subversion Repositories Kolibri OS

Rev

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