Subversion Repositories Kolibri OS

Rev

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