Subversion Repositories Kolibri OS

Rev

Rev 2863 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                  ;;
  3. ;; Copyright (C) KolibriOS team 2004-2010. All rights reserved.     ;;
  4. ;; Distributed under terms of the GNU General Public License        ;;
  5. ;;                                                                  ;;
  6. ;;  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. ; $Revision: 2935 $
  18.  
  19. format MS COFF
  20.  
  21.         API_VERSION             =   0x01000100
  22.  
  23.         DEBUG                   =   1
  24.         __DEBUG__               =   1
  25.         __DEBUG_LEVEL__         =   1
  26.  
  27.         MAX_DEVICES =   4
  28.         MAX_ETH_FRAME_SIZE =   1514
  29.  
  30. include 'proc32.inc'
  31. include 'imports.inc'
  32. include 'fdo.inc'
  33. include 'netdrv.inc'
  34.  
  35.  
  36. public START
  37. public service_proc
  38. public version
  39.  
  40.  
  41. virtual at ebx
  42.  
  43.         device:
  44.  
  45.         ETH_DEVICE
  46.  
  47. ; device specific
  48.  
  49.       .private:
  50.       .mode_            dw ?
  51.       .tlen_rlen        dw ?
  52.       .phys_addr        dp ?
  53.       .reserved         dw ?
  54.       .filter           dq ?
  55.       .rx_ring_phys     dd ?
  56.       .tx_ring_phys     dd ?
  57.  
  58.       .cur_rx           db ?
  59.       .cur_tx           db ?
  60.       .dirty_rx         dd ?
  61.       .dirty_tx         dd ?
  62.       .tx_full          db ?
  63.       .options          dd ?
  64.       .full_duplex      db ?
  65.       .chip_version     dd ?
  66.       .mii              db ?
  67.       .ltint            db ?
  68.       .dxsuflo          db ?
  69.       .fset             db ?
  70.       .fdx              db ?
  71.  
  72.       .rx_buffer        dd ?
  73.       .tx_buffer        dd ?
  74.  
  75.       .io_addr          dd ?
  76.       .irq_line         db ?
  77.       .pci_bus          db ?
  78.       .pci_dev          db ?
  79.  
  80.  
  81.       .access_read_csr          dd ?
  82.       .access_write_csr         dd ?
  83.       .access_read_bcr          dd ?
  84.       .access_write_bcr         dd ?
  85.       .access_read_rap          dd ?
  86.       .access_write_rap         dd ?
  87.       .access_reset             dd ?
  88.  
  89.       device_size       = $ - device
  90.  
  91. end virtual
  92.  
  93. struc buf_head {
  94.         .base           dd ?
  95.         .length         dw ?
  96.         .status         dw ?
  97.         .msg_length     dw ?
  98.         .misc           dw ?
  99.         .reserved       dd ?
  100.  
  101.         .size:
  102. }
  103.  
  104. virtual at 0
  105.  buf_head buf_head
  106. end virtual
  107.  
  108.         PCNET_PORT_AUI                =   0x00
  109.         PCNET_PORT_10BT               =   0x01
  110.         PCNET_PORT_GPSI               =   0x02
  111.         PCNET_PORT_MII                =   0x03
  112.         PCNET_PORT_PORTSEL            =   0x03
  113.         PCNET_PORT_ASEL               =   0x04
  114.         PCNET_PORT_100                =   0x40
  115.         PCNET_PORT_FD                 =   0x80
  116.  
  117.         PCNET_DMA_MASK                =   0xffffffff
  118.  
  119.         PCNET_LOG_TX_BUFFERS          =   2
  120.         PCNET_LOG_RX_BUFFERS          =   2
  121.  
  122.         PCNET_TX_RING_SIZE            =   4
  123.         PCNET_TX_RING_MOD_MASK        =   (PCNET_TX_RING_SIZE-1)
  124.         PCNET_TX_RING_LEN_BITS        =   (PCNET_LOG_TX_BUFFERS shl 12)
  125.  
  126.         PCNET_RX_RING_SIZE            =   4
  127.         PCNET_RX_RING_MOD_MASK        =   (PCNET_RX_RING_SIZE-1)
  128.         PCNET_RX_RING_LEN_BITS        =   (PCNET_LOG_RX_BUFFERS shl 4)
  129.  
  130.         PCNET_PKT_BUF_SZ              =   1544
  131.         PCNET_PKT_BUF_SZ_NEG          =   0xf9f8
  132.  
  133.         PCNET_WIO_RDP                 =   0x10
  134.         PCNET_WIO_RAP                 =   0x12
  135.         PCNET_WIO_RESET               =   0x14
  136.         PCNET_WIO_BDP                 =   0x16
  137.         PCNET_DWIO_RDP                =   0x10
  138.         PCNET_DWIO_RAP                =   0x14
  139.         PCNET_DWIO_RESET              =   0x18
  140.         PCNET_DWIO_BDP                =   0x1C
  141.         PCNET_TOTAL_SIZE              =   0x20
  142.  
  143. ; CSR registers
  144.  
  145.         PCNET_CSR_CSR                 =   0x00
  146.         PCNET_CSR_IAB0                =   0x01
  147.         PCNET_CSR_IAB1                =   0x02
  148.         PCNET_CSR_IMR                 =   0x03
  149.         PCNET_CSR_TFEAT               =   0x04
  150.         PCNET_CSR_EXTCTL1             =   0x05
  151.         PCNET_CSR_DTBLLEN             =   0x06
  152.         PCNET_CSR_EXTCTL2             =   0x07
  153.         PCNET_CSR_MAR0                =   0x08
  154.         PCNET_CSR_MAR1                =   0x09
  155.         PCNET_CSR_MAR2                =   0x0A
  156.         PCNET_CSR_MAR3                =   0x0B
  157.         PCNET_CSR_PAR0                =   0x0C
  158.         PCNET_CSR_PAR1                =   0x0D
  159.         PCNET_CSR_PAR2                =   0x0E
  160.         PCNET_CSR_MODE                =   0x0F
  161.         PCNET_CSR_RXADDR0             =   0x18
  162.         PCNET_CSR_RXADDR1             =   0x19
  163.         PCNET_CSR_TXADDR0             =   0x1E
  164.         PCNET_CSR_TXADDR1             =   0x1F
  165.         PCNET_CSR_TXPOLL              =   0x2F
  166.         PCNET_CSR_RXPOLL              =   0x31
  167.         PCNET_CSR_RXRINGLEN           =   0x4C
  168.         PCNET_CSR_TXRINGLEN           =   0x4E
  169.         PCNET_CSR_DMACTL              =   0x50
  170.         PCNET_CSR_BUSTIMER            =   0x52
  171.         PCNET_CSR_MEMERRTIMEO         =   0x64
  172.         PCNET_CSR_ONNOWMISC           =   0x74
  173.         PCNET_CSR_ADVFEAT             =   0x7A
  174.         PCNET_CSR_MACCFG              =   0x7D
  175.         PCNET_CSR_CHIPID0             =   0x58
  176.         PCNET_CSR_CHIPID1             =   0x59
  177.  
  178. ; Control and Status Register (CSR0)
  179.  
  180.         PCNET_CSR_INIT                =   1 shl 0
  181.         PCNET_CSR_START               =   1 shl 1
  182.         PCNET_CSR_STOP                =   1 shl 2
  183.         PCNET_CSR_TX                  =   1 shl 3
  184.         PCNET_CSR_TXON                =   1 shl 4
  185.         PCNET_CSR_RXON                =   1 shl 5
  186.         PCNET_CSR_INTEN               =   1 shl 6
  187.         PCNET_CSR_INTR                =   1 shl 7
  188.         PCNET_CSR_IDONE               =   1 shl 8
  189.         PCNET_CSR_TINT                =   1 shl 9
  190.         PCNET_CSR_RINT                =   1 shl 10
  191.         PCNET_CSR_MERR                =   1 shl 11
  192.         PCNET_CSR_MISS                =   1 shl 12
  193.         PCNET_CSR_CERR                =   1 shl 13
  194.  
  195. ; Interrupt masks and deferral control (CSR3)
  196.  
  197.         PCNET_IMR_BSWAP               =   0x0004
  198.         PCNET_IMR_ENMBA               =   0x0008  ; enable modified backoff alg
  199.         PCNET_IMR_DXMT2PD             =   0x0010
  200.         PCNET_IMR_LAPPEN              =   0x0020  ; lookahead packet processing enb
  201.         PCNET_IMR_DXSUFLO             =   0x0040  ; disable TX stop on underflow
  202.         PCNET_IMR_IDONE               =   0x0100
  203.         PCNET_IMR_TINT                =   0x0200
  204.         PCNET_IMR_RINT                =   0x0400
  205.         PCNET_IMR_MERR                =   0x0800
  206.         PCNET_IMR_MISS                =   0x1000
  207.  
  208.         PCNET_IMR                     =   PCNET_IMR_TINT+PCNET_IMR_RINT+PCNET_IMR_IDONE+PCNET_IMR_MERR+PCNET_IMR_MISS
  209.  
  210. ; Test and features control (CSR4)
  211.  
  212.         PCNET_TFEAT_TXSTRTMASK        =   0x0004
  213.         PCNET_TFEAT_TXSTRT            =   0x0008
  214.         PCNET_TFEAT_RXCCOFLOWM        =   0x0010  ; Rx collision counter oflow
  215.         PCNET_TFEAT_RXCCOFLOW         =   0x0020
  216.         PCNET_TFEAT_UINT              =   0x0040
  217.         PCNET_TFEAT_UINTREQ           =   0x0080
  218.         PCNET_TFEAT_MISSOFLOWM        =   0x0100
  219.         PCNET_TFEAT_MISSOFLOW         =   0x0200
  220.         PCNET_TFEAT_STRIP_FCS         =   0x0400
  221.         PCNET_TFEAT_PAD_TX            =   0x0800
  222.         PCNET_TFEAT_TXDPOLL           =   0x1000
  223.         PCNET_TFEAT_DMAPLUS           =   0x4000
  224.  
  225. ; Extended control and interrupt 1 (CSR5)
  226.  
  227.         PCNET_EXTCTL1_SPND            =   0x0001  ; suspend
  228.         PCNET_EXTCTL1_MPMODE          =   0x0002  ; magic packet mode
  229.         PCNET_EXTCTL1_MPENB           =   0x0004  ; magic packet enable
  230.         PCNET_EXTCTL1_MPINTEN         =   0x0008  ; magic packet interrupt enable
  231.         PCNET_EXTCTL1_MPINT           =   0x0010  ; magic packet interrupt
  232.         PCNET_EXTCTL1_MPPLBA          =   0x0020  ; magic packet phys. logical bcast
  233.         PCNET_EXTCTL1_EXDEFEN         =   0x0040  ; excessive deferral interrupt enb.
  234.         PCNET_EXTCTL1_EXDEF           =   0x0080  ; excessive deferral interrupt
  235.         PCNET_EXTCTL1_SINTEN          =   0x0400  ; system interrupt enable
  236.         PCNET_EXTCTL1_SINT            =   0x0800  ; system interrupt
  237.         PCNET_EXTCTL1_LTINTEN         =   0x4000  ; last TX interrupt enb
  238.         PCNET_EXTCTL1_TXOKINTD        =   0x8000  ; TX OK interrupt disable
  239.  
  240. ; RX/TX descriptor len (CSR6)
  241.  
  242.         PCNET_DTBLLEN_RLEN            =   0x0F00
  243.         PCNET_DTBLLEN_TLEN            =   0xF000
  244.  
  245. ; Extended control and interrupt 2 (CSR7)
  246.  
  247.         PCNET_EXTCTL2_MIIPDTINTE      =   0x0001
  248.         PCNET_EXTCTL2_MIIPDTINT       =   0x0002
  249.         PCNET_EXTCTL2_MCCIINTE        =   0x0004
  250.         PCNET_EXTCTL2_MCCIINT         =   0x0008
  251.         PCNET_EXTCTL2_MCCINTE         =   0x0010
  252.         PCNET_EXTCTL2_MCCINT          =   0x0020
  253.         PCNET_EXTCTL2_MAPINTE         =   0x0040
  254.         PCNET_EXTCTL2_MAPINT          =   0x0080
  255.         PCNET_EXTCTL2_MREINTE         =   0x0100
  256.         PCNET_EXTCTL2_MREINT          =   0x0200
  257.         PCNET_EXTCTL2_STINTE          =   0x0400
  258.         PCNET_EXTCTL2_STINT           =   0x0800
  259.         PCNET_EXTCTL2_RXDPOLL         =   0x1000
  260.         PCNET_EXTCTL2_RDMD            =   0x2000
  261.         PCNET_EXTCTL2_RXFRTG          =   0x4000
  262.         PCNET_EXTCTL2_FASTSPNDE       =   0x8000
  263.  
  264. ; Mode (CSR15)
  265.  
  266.         PCNET_MODE_RXD                =   0x0001  ; RX disable
  267.         PCNET_MODE_TXD                =   0x0002  ; TX disable
  268.         PCNET_MODE_LOOP               =   0x0004  ; loopback enable
  269.         PCNET_MODE_TXCRCD             =   0x0008
  270.         PCNET_MODE_FORCECOLL          =   0x0010
  271.         PCNET_MODE_RETRYD             =   0x0020
  272.         PCNET_MODE_INTLOOP            =   0x0040
  273.         PCNET_MODE_PORTSEL            =   0x0180
  274.         PCNET_MODE_RXVPAD             =   0x2000
  275.         PCNET_MODE_RXNOBROAD          =   0x4000
  276.         PCNET_MODE_PROMISC            =   0x8000
  277.  
  278. ; BCR (Bus Control Registers)
  279.  
  280.         PCNET_BCR_MMRA                =   0x00    ; Master Mode Read Active
  281.         PCNET_BCR_MMW                 =   0x01    ; Master Mode Write Active
  282.         PCNET_BCR_MISCCFG             =   0x02
  283.         PCNET_BCR_LED0                =   0x04
  284.         PCNET_BCR_LED1                =   0x05
  285.         PCNET_BCR_LED2                =   0x06
  286.         PCNET_BCR_LED3                =   0x07
  287.         PCNET_BCR_DUPLEX              =   0x09
  288.         PCNET_BCR_BUSCTL              =   0x12
  289.         PCNET_BCR_EECTL               =   0x13
  290.         PCNET_BCR_SSTYLE              =   0x14
  291.         PCNET_BCR_PCILAT              =   0x16
  292.         PCNET_BCR_PCISUBVENID         =   0x17
  293.         PCNET_BCR_PCISUBSYSID         =   0x18
  294.         PCNET_BCR_SRAMSIZE            =   0x19
  295.         PCNET_BCR_SRAMBOUND           =   0x1A
  296.         PCNET_BCR_SRAMCTL             =   0x1B
  297.         PCNET_BCR_MIICTL              =   0x20
  298.         PCNET_BCR_MIIADDR             =   0x21
  299.         PCNET_BCR_MIIDATA             =   0x22
  300.         PCNET_BCR_PCIVENID            =   0x23
  301.         PCNET_BCR_PCIPCAP             =   0x24
  302.         PCNET_BCR_DATA0               =   0x25
  303.         PCNET_BCR_DATA1               =   0x26
  304.         PCNET_BCR_DATA2               =   0x27
  305.         PCNET_BCR_DATA3               =   0x28
  306.         PCNET_BCR_DATA4               =   0x29
  307.         PCNET_BCR_DATA5               =   0x2A
  308.         PCNET_BCR_DATA6               =   0x2B
  309.         PCNET_BCR_DATA7               =   0x2C
  310.         PCNET_BCR_ONNOWPAT0           =   0x2D
  311.         PCNET_BCR_ONNOWPAT1           =   0x2E
  312.         PCNET_BCR_ONNOWPAT2           =   0x2F
  313.         PCNET_BCR_PHYSEL              =   0x31
  314.  
  315. ; RX status register
  316.  
  317.         PCNET_RXSTAT_BPE              =   0x0080  ; bus parity error
  318.         PCNET_RXSTAT_ENP              =   0x0100  ; end of packet
  319.         PCNET_RXSTAT_STP              =   0x0200  ; start of packet
  320.         PCNET_RXSTAT_BUFF             =   0x0400  ; buffer error
  321.         PCNET_RXSTAT_CRC              =   0x0800  ; CRC error
  322.         PCNET_RXSTAT_OFLOW            =   0x1000  ; rx overrun
  323.         PCNET_RXSTAT_FRAM             =   0x2000  ; framing error
  324.         PCNET_RXSTAT_ERR              =   0x4000  ; error summary
  325.         PCNET_RXSTAT_OWN              =   0x8000
  326.  
  327. ; TX status register
  328.  
  329.         PCNET_TXSTAT_TRC              =   0x0000000F      ; transmit retries
  330.         PCNET_TXSTAT_RTRY             =   0x04000000      ; retry
  331.         PCNET_TXSTAT_LCAR             =   0x08000000      ; lost carrier
  332.         PCNET_TXSTAT_LCOL             =   0x10000000      ; late collision
  333.         PCNET_TXSTAT_EXDEF            =   0x20000000      ; excessive deferrals
  334.         PCNET_TXSTAT_UFLOW            =   0x40000000      ; transmit underrun
  335.         PCNET_TXSTAT_BUFF             =   0x80000000      ; buffer error
  336.  
  337.         PCNET_TXCTL_OWN               =   0x80000000
  338.         PCNET_TXCTL_ERR               =   0x40000000      ; error summary
  339.         PCNET_TXCTL_ADD_FCS           =   0x20000000      ; add FCS to pkt
  340.         PCNET_TXCTL_MORE_LTINT        =   0x10000000
  341.         PCNET_TXCTL_ONE               =   0x08000000
  342.         PCNET_TXCTL_DEF               =   0x04000000
  343.         PCNET_TXCTL_STP               =   0x02000000
  344.         PCNET_TXCTL_ENP               =   0x01000000
  345.         PCNET_TXCTL_BPE               =   0x00800000
  346.         PCNET_TXCTL_MBO               =   0x0000F000
  347.         PCNET_TXCTL_BUFSZ             =   0x00000FFF
  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 PCnet driver\n"
  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.         jl      .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.         jl      .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.         jge     .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.         allocate_and_clear [device.tx_buffer], PCNET_RX_RING_SIZE * (PCNET_PKT_BUF_SZ + buf_head.size), .err
  471.         allocate_and_clear [device.rx_buffer], PCNET_TX_RING_SIZE * (PCNET_PKT_BUF_SZ + buf_head.size), .err
  472.  
  473. ; Ok, the eth_device structure is ready, let's probe the device
  474. ; Because initialization fires IRQ, IRQ handler must be aware of this device
  475.         mov     eax, [devices]                                        ; Add the device structure to our device list
  476.         mov     [device_list+4*eax], ebx                                 ; (IRQ handler uses this list to find device)
  477.         inc     [devices]                                             ;
  478.  
  479.         call    probe                                                   ; this function will output in eax
  480.         test    eax, eax
  481.         jnz     .destroy                                                        ; If an error occured, exit
  482.  
  483.         mov     [device.type], NET_TYPE_ETH
  484.         call    NetRegDev
  485.         cmp     eax, -1
  486.         je      .destroy
  487.  
  488.         ret
  489.  
  490. ; If the device was already loaded, find the device number and return it in eax
  491.  
  492.   .find_devicenum:
  493.         DEBUGF  1,"Trying to find device number of already registered device\n"
  494.         call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  495.                                                                         ; into a device number in edi
  496.         mov     eax, edi                                                ; Application wants it in eax instead
  497.         DEBUGF  1,"Kernel says: %u\n", eax
  498.         ret
  499.  
  500. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  501.  
  502.   .destroy:
  503.         ; todo: reset device into virgin state
  504.  
  505.         dec     [devices]
  506.   .err:
  507.         DEBUGF  1,"Error, removing all data !\n"
  508.         stdcall KernelFree, [device.rx_buffer]
  509.         stdcall KernelFree, [device.tx_buffer]
  510.         stdcall KernelFree, ebx
  511.  
  512.   .fail:
  513.         or      eax, -1
  514.         ret
  515.  
  516. ;------------------------------------------------------
  517. endp
  518.  
  519.  
  520. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  521. ;;                                                                        ;;
  522. ;;        Actual Hardware dependent code starts here                      ;;
  523. ;;                                                                        ;;
  524. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  525.  
  526. align 4
  527. unload:
  528.         ; TODO: (in this particular order)
  529.         ;
  530.         ; - Stop the device
  531.         ; - Detach int handler
  532.         ; - Remove device from local list (RTL8139_LIST)
  533.         ; - call unregister function in kernel
  534.         ; - Remove all allocated structures and buffers the card used
  535.  
  536.         or      eax,-1
  537.  
  538. ret
  539.  
  540.  
  541. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  542. ;;
  543. ;;  probe: enables the device (if it really is a PCnet device)
  544. ;;
  545. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  546.  
  547. align 4
  548. probe:
  549.         mov     edx, [device.io_addr]
  550.  
  551.         call    wio_reset
  552.  
  553.         xor     ecx, ecx
  554.         call    wio_read_csr
  555.         cmp     eax, 4
  556.         jne     .try_dwio
  557.  
  558.         ; Try Word I/O
  559.         mov     ax , 88
  560.         add     edx, PCNET_WIO_RAP
  561.         out     dx , ax
  562.         nop
  563.         nop
  564.         in      ax , dx
  565.         sub     edx, PCNET_WIO_RAP
  566.         cmp     ax , 88
  567.         jne     .try_dwio
  568.  
  569.         call    switch_to_wio
  570.  
  571.         jmp     .L1
  572.  
  573.   .try_dwio:
  574.         call    dwio_reset
  575.  
  576.         xor     ecx, ecx
  577.         call    dwio_read_csr
  578.         cmp     eax, 4
  579.         jne     .no_dev
  580.  
  581.         ; Try Dword I/O
  582.         add     edx, PCNET_DWIO_RAP
  583.         mov     eax, 88
  584.         out     dx , eax
  585.         nop
  586.         nop
  587.         in      eax, dx
  588.         sub     edx, PCNET_DWIO_RAP
  589.         and     eax, 0xffff
  590.         cmp     eax, 88
  591.         jne     .no_dev
  592.  
  593.         call    switch_to_dwio
  594.  
  595.         jmp     .L1
  596.  
  597.   .no_dev:
  598.         DEBUGF 1,"PCnet device not found!\n"
  599.         mov     eax, 1
  600.         ret
  601.   .L1:
  602.  
  603.         mov     ecx, PCNET_CSR_CHIPID0
  604.         call    [device.access_read_csr]
  605.         mov     esi, eax
  606.  
  607.         mov     ecx, PCNET_CSR_CHIPID1
  608.         call    [device.access_read_csr]
  609.         shl     eax, 16
  610.         or      eax, esi
  611.  
  612.         mov     ecx, eax
  613.         and     ecx, 0xfff
  614.         cmp     ecx, 3
  615.         jne     .no_dev
  616.  
  617.         shr     eax, 12
  618.         and     eax, 0xffff
  619.         mov     [device.chip_version], eax
  620.  
  621.         DEBUGF 1,"chip version ok\n"
  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     eax, 0x2420
  629.         je      .L2
  630.         cmp     eax, 0x2430
  631.         je      .L2
  632.  
  633.         mov     [device.fdx], 1
  634.  
  635.         cmp     eax, 0x2621
  636.         je      .L4
  637.         cmp     eax, 0x2623
  638.         je      .L5
  639.         cmp     eax, 0x2624
  640.         je      .L6
  641.         cmp     eax, 0x2625
  642.         je      .L7
  643.         cmp     eax, 0x2626
  644.         je      .L8
  645.         cmp     eax, 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, PCNET_CSR_RXPOLL
  679.         call    dword [device.access_read_bcr]
  680.         call    dword [device.access_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, PCNET_BCR_BUSCTL
  692.         call    [device.access_read_bcr]
  693.         or      eax, 0x800
  694.         call    [device.access_write_bcr]
  695.  
  696.         mov     ecx, PCNET_CSR_DMACTL
  697.         call    [device.access_read_csr]
  698. ;        and     eax, 0xc00
  699. ;        or      eax, 0xc00
  700.         mov     eax, 0xc00
  701.         call    [device.access_write_csr]
  702.  
  703.         mov     [device.dxsuflo],1
  704.         mov     [device.ltint],1
  705.   .L11:
  706.  
  707.         make_bus_master [device.pci_bus], [device.pci_dev]
  708.  
  709.         mov     eax, PCNET_PORT_ASEL
  710.         mov     [device.options], eax
  711.         mov     [device.mode_], word 0x0003
  712.         mov     [device.tlen_rlen], word (PCNET_TX_RING_LEN_BITS or PCNET_RX_RING_LEN_BITS)
  713.  
  714.         mov     dword [device.filter], 0
  715.         mov     dword [device.filter+4], 0
  716.  
  717.         mov     eax, PCNET_IMR
  718.         mov     ecx, PCNET_CSR_IMR                      ; Write interrupt mask
  719.         call    [device.access_write_csr]
  720.  
  721. align 4
  722. reset:
  723.  
  724. ; attach int handler
  725.  
  726.         movzx   eax, [device.irq_line]
  727.         DEBUGF  1,"Attaching int handler to irq %x\n",eax:1
  728.         stdcall AttachIntHandler, eax, int_handler, dword 0
  729.         test    eax, eax
  730.         jnz     @f
  731.         DEBUGF  1,"\nCould not attach int handler!\n"
  732. ;        or      eax, -1
  733. ;        ret
  734.   @@:
  735.  
  736.         mov     edx, [device.io_addr]
  737.         call    [device.access_reset]
  738.  
  739.         ; Switch pcnet32 to 32bit mode
  740.         mov     ecx, PCNET_BCR_SSTYLE
  741.         mov     eax, 2
  742.         call    [device.access_write_bcr]
  743.  
  744.         ; set/reset autoselect bit
  745.         mov     ecx, PCNET_BCR_MISCCFG
  746.         call    [device.access_read_bcr]
  747.         and     eax,not 2
  748.         test    [device.options], PCNET_PORT_ASEL
  749.         jz      .L1
  750.         or      eax, 2
  751.   .L1:
  752.         call    [device.access_write_bcr]
  753.  
  754.  
  755.         ; Handle full duplex setting
  756.         cmp     byte [device.full_duplex], 0
  757.         je      .L2
  758.         mov     ecx, PCNET_BCR_DUPLEX
  759.         call    [device.access_read_bcr]
  760.         and     eax, not 3
  761.         test    [device.options], PCNET_PORT_FD
  762.         jz      .L3
  763.         or      eax, 1
  764.         cmp     [device.options], PCNET_PORT_FD or PCNET_PORT_AUI
  765.         jne     .L4
  766.         or      eax, 2
  767.         jmp     .L4
  768.   .L3:
  769.         test    [device.options], PCNET_PORT_ASEL
  770.         jz      .L4
  771.         cmp     [device.chip_version], 0x2627
  772.         jne     .L4
  773.         or      eax, 3
  774.   .L4:
  775.         mov     ecx, PCNET_BCR_DUPLEX
  776.         call    [device.access_write_bcr]
  777.   .L2:
  778.  
  779.  
  780.         ; set/reset GPSI bit in test register
  781.         mov     ecx, 124
  782.         call    [device.access_read_csr]
  783.         mov     ecx, [device.options]
  784.         and     ecx, PCNET_PORT_PORTSEL
  785.         cmp     ecx, PCNET_PORT_GPSI
  786.         jne     .L5
  787.         or      eax, 0x10
  788.   .L5:
  789.         call    [device.access_write_csr]
  790.         cmp     [device.mii], 0
  791.         je      .L6
  792.         test    [device.options], PCNET_PORT_ASEL
  793.         jnz     .L6
  794.         mov     ecx, PCNET_BCR_MIICTL
  795.         call    [device.access_read_bcr]
  796.         and     eax,not 0x38
  797.         test    [device.options], PCNET_PORT_FD
  798.         jz      .L7
  799.         or      eax, 0x10
  800.   .L7:
  801.         test    [device.options], PCNET_PORT_100
  802.         jz      .L8
  803.         or      eax, 0x08
  804.   .L8:
  805.         call    [device.access_write_bcr]
  806.         jmp     .L9
  807. .L6:
  808.         test    [device.options], PCNET_PORT_ASEL
  809.         jz      .L9
  810.         mov     ecx, PCNET_BCR_MIICTL
  811.         DEBUGF 1,"ASEL, enable auto-negotiation\n"
  812.         call    [device.access_read_bcr]
  813.         and     eax, not 0x98
  814.         or      eax, 0x20
  815.         call    [device.access_write_bcr]
  816. .L9:
  817.         cmp     [device.ltint],0
  818.         je      .L10
  819.         mov     ecx,5
  820.         call    [device.access_read_csr]
  821.         or      eax,(1 shl 14)
  822.         call    [device.access_write_csr]
  823. .L10:
  824.         mov     eax,[device.options]
  825.         and     eax,PCNET_PORT_PORTSEL
  826.         shl     eax,7
  827.         mov     [device.mode_],ax
  828.         mov     dword [device.filter], -1
  829.         mov     dword [device.filter+4], -1
  830.  
  831.         call    read_mac
  832.  
  833.         lea     esi, [device.mac]
  834.         lea     edi, [device.phys_addr]
  835.         movsd
  836.         movsw
  837.  
  838.         call    init_ring
  839.  
  840.         lea     eax, [device.private]
  841.         GetRealAddr
  842.  
  843.         push    eax
  844.         and     eax, 0xffff
  845.         mov     ecx, 1
  846.         call    [device.access_write_csr]
  847.         pop     eax
  848.         shr     eax,16
  849.         mov     ecx,2
  850.         call    [device.access_write_csr]
  851.  
  852.         mov     ecx,4
  853.         mov     eax,0x0915
  854.         call    [device.access_write_csr]
  855.  
  856.         mov     ecx,0
  857.         mov     eax,1
  858.         call    [device.access_write_csr]
  859.  
  860.         mov     [device.tx_full],0
  861.         mov     [device.cur_rx],0
  862.         mov     [device.cur_tx],0
  863.         mov     [device.dirty_rx],0
  864.         mov     [device.dirty_tx],0
  865.  
  866.         mov     ecx,100
  867. .L11:
  868.         push    ecx
  869.         xor     ecx,ecx
  870.         call    [device.access_read_csr]
  871.         pop     ecx
  872.         test    ax,0x100
  873.         jnz     .L12
  874.         loop    .L11
  875. .L12:
  876.  
  877.         DEBUGF 1,"hardware reset\n"
  878.         xor     ecx, ecx
  879.         mov     eax, 0x0002
  880.         call    [device.access_write_csr]
  881.  
  882.         xor     ecx, ecx
  883.         call    [device.access_read_csr]
  884.  
  885.         xor     ecx, ecx
  886.         mov     eax, PCNET_CSR_INTEN or PCNET_CSR_START
  887.         call    [device.access_write_csr]
  888.  
  889. ; Set the mtu, kernel will be able to send now
  890.         mov     [device.mtu], 1514
  891.  
  892.         DEBUGF 1,"PCNET reset complete\n"
  893.         xor     eax, eax
  894.         ret
  895.  
  896.  
  897. align 4
  898. init_ring:
  899.  
  900.         mov     ecx, PCNET_RX_RING_SIZE
  901.         mov     edi, [device.rx_buffer]
  902.         mov     eax, edi
  903.         GetRealAddr
  904.         mov     [device.rx_ring_phys], eax
  905.         add     eax, PCNET_RX_RING_SIZE * buf_head.size
  906.   .rx_init:
  907.         mov     [edi + buf_head.base], eax
  908.         mov     [edi + buf_head.length], PCNET_PKT_BUF_SZ_NEG
  909.         mov     [edi + buf_head.status], 0x8000
  910.         and     dword [edi + buf_head.msg_length], 0
  911.         and     dword [edi + buf_head.reserved], 0
  912.         add     eax, PCNET_PKT_BUF_SZ
  913.         add     edi, buf_head.size
  914.         loop    .rx_init
  915.  
  916.         mov     ecx, PCNET_TX_RING_SIZE
  917.         mov     edi, [device.tx_buffer]
  918.         mov     eax, edi
  919.         GetRealAddr
  920.         mov     [device.tx_ring_phys], eax
  921.         add     eax, PCNET_TX_RING_SIZE * buf_head.size
  922.   .tx_init:
  923.         mov     [edi + buf_head.base], eax
  924.         and     dword [edi + buf_head.length], 0
  925.         and     dword [edi + buf_head.msg_length], 0
  926.         and     dword [edi + buf_head.reserved], 0
  927.         add     eax, PCNET_PKT_BUF_SZ
  928.         add     edi, buf_head.size
  929.         loop    .tx_init
  930.  
  931.         mov     [device.tlen_rlen], (PCNET_TX_RING_LEN_BITS or PCNET_RX_RING_LEN_BITS)
  932.  
  933.         ret
  934.  
  935.  
  936.  
  937.  
  938. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  939. ;;                                         ;;
  940. ;; Transmit                                ;;
  941. ;;                                         ;;
  942. ;; In: buffer pointer in [esp+4]           ;;
  943. ;;     size of buffer in [esp+8]           ;;
  944. ;;     pointer to device structure in ebx  ;;
  945. ;;                                         ;;
  946. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  947.  
  948. align 4
  949. transmit:
  950.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
  951.         mov     eax, [esp+4]
  952.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  953.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  954.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  955.         [eax+13]:2,[eax+12]:2
  956.  
  957.         cmp     dword [esp+8], 1514
  958.         jg      .nospace                        ; packet is too long
  959.         cmp     dword [esp+8], 60
  960.         jl      .nospace                        ; packet is too short
  961.  
  962. ; check descriptor
  963.         movzx   eax, [device.cur_tx]
  964.         imul    edi, eax, PCNET_PKT_BUF_SZ
  965.         shl     eax, 4
  966.         add     eax, [device.tx_buffer]
  967.         add     edi, [device.tx_buffer]
  968.         add     edi, PCNET_TX_RING_SIZE * buf_head.size
  969.  
  970.         test    byte [eax + buf_head.status + 1], 80h
  971.         jnz     .nospace
  972. ; descriptor is free, copy data
  973.         mov     esi, [esp+4]
  974.         mov     ecx, [esp+8]
  975.         mov     edx, ecx
  976.         shr     ecx, 2
  977.         and     edx, 3
  978.         rep     movsd
  979.         mov     ecx, edx
  980.         rep     movsb
  981. ; set length
  982.         mov     ecx, [esp+8]
  983.         neg     ecx
  984.         mov     [eax + buf_head.length], cx
  985. ; put to transfer queue
  986.         mov     [eax + buf_head.status], 0x8300
  987.  
  988. ; trigger an immediate send
  989.         xor     ecx, ecx         ; CSR0
  990.         call    [device.access_read_csr]
  991.         or      eax, PCNET_CSR_TX
  992.         call    [device.access_write_csr]
  993.  
  994. ; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
  995.         inc     [device.cur_tx]
  996.         and     [device.cur_tx], 3
  997.         DEBUGF  2," - Packet Sent! "
  998.  
  999. ; Update stats
  1000.         inc     [device.packets_tx]
  1001.         mov     eax, [esp+8]
  1002.         add     dword [device.bytes_tx], eax
  1003.         adc     dword [device.bytes_tx + 4], 0
  1004.  
  1005. .finish:
  1006.         DEBUGF  2," - Done!\n"
  1007.         stdcall KernelFree, [esp+4]
  1008.         xor     eax, eax
  1009.         ret     8
  1010.  
  1011. .nospace:
  1012.         DEBUGF  1, 'ERROR: no free transmit descriptors\n'
  1013.         stdcall KernelFree, [esp+4]
  1014.         or      eax, -1
  1015.         ret     8
  1016.  
  1017.  
  1018.  
  1019. ;;;;;;;;;;;;;;;;;;;;;;;
  1020. ;;                   ;;
  1021. ;; Interrupt handler ;;
  1022. ;;                   ;;
  1023. ;;;;;;;;;;;;;;;;;;;;;;;
  1024.  
  1025. align 4
  1026. int_handler:
  1027.  
  1028.         DEBUGF  1,"\n%s int\n", my_service
  1029.  
  1030. ; find pointer of device wich made IRQ occur
  1031.  
  1032.         mov     ecx, [devices]
  1033.         test    ecx, ecx
  1034.         jz      .nothing
  1035.         mov     esi, device_list
  1036.   .nextdevice:
  1037.         mov     ebx, [esi]
  1038.  
  1039.         mov     edx, [device.io_addr]     ; get IRQ reason
  1040.         push    ecx
  1041.         xor     ecx, ecx ; CSR0
  1042.         call    [device.access_read_csr]
  1043.         pop     ecx
  1044.         test    al, al
  1045.         js      .got_it
  1046.   .continue:
  1047.         add     esi, 4
  1048.         dec     ecx
  1049.         jnz     .nextdevice
  1050.   .nothing:
  1051.         ret                                         ; If no device was found, abort (The irq was probably for a device, not registered to this driver
  1052.  
  1053.   .got_it:
  1054.  
  1055.         DEBUGF  1,"Device: %x Status: %x ", ebx, eax:2
  1056.  
  1057. ;-------------------------------------------------------
  1058. ; Possible reasons:
  1059. ; initialization done - ignore
  1060. ; transmit done - ignore
  1061. ; packet received - handle
  1062. ; Clear ALL IRQ reasons.
  1063. ; N.B. One who wants to handle more than one reason must be ready
  1064. ; to two or more reasons in one IRQ.
  1065.         xor     ecx, ecx
  1066.         call    [device.access_write_csr]
  1067. ; Received packet ok?
  1068.  
  1069.         test    ax, PCNET_CSR_RINT
  1070.         jz      @f
  1071.  
  1072.         push    ebx
  1073. .receiver_test_loop:
  1074.         pop     ebx
  1075.         movzx   eax, [device.cur_rx]
  1076. ;        and     eax, PCNET_RX_RING_MOD_MASK
  1077.         mov     edi, eax
  1078.  
  1079.         imul    esi, eax, PCNET_PKT_BUF_SZ      ;
  1080.         add     esi, [device.rx_buffer]         ; esi now points to rx buffer
  1081.         add     esi, PCNET_RX_RING_SIZE * buf_head.size
  1082.  
  1083.         shl     edi, 4                          ; desc * 16 (16 is size of one ring entry)
  1084.         add     edi, [device.rx_buffer]     ; edi now points to current rx ring entry
  1085.  
  1086.         mov     cx , [edi + buf_head.status]
  1087.  
  1088.         test    cx , PCNET_RXSTAT_OWN           ; If this bit is set, the controller OWN's the packet, if not, we do
  1089.         jnz     .abort
  1090.  
  1091.         test    cx , PCNET_RXSTAT_ENP
  1092.         jz      .abort
  1093.  
  1094.         test    cx , PCNET_RXSTAT_STP
  1095.         jz      .abort
  1096.  
  1097.         movzx   ecx, [edi + buf_head.msg_length]        ; get packet length in ecx
  1098.         sub     ecx, 4                          ;
  1099.  
  1100.         push    ecx
  1101.         stdcall KernelAlloc, ecx                ; Allocate a buffer to put packet into
  1102.         pop     ecx
  1103.         test    eax, eax                        ; Test if we allocated succesfully
  1104.         jz      .abort                          ;
  1105.  
  1106. ; Update stats
  1107.         add     dword [device.bytes_rx], ecx
  1108.         adc     dword [device.bytes_rx + 4], 0
  1109.         inc     dword [device.packets_rx]
  1110.  
  1111.         push    ebx
  1112.         push    .receiver_test_loop             ;
  1113.         push    ecx                             ; for eth_receiver
  1114.         push    eax                             ;
  1115.  
  1116.         xchg    edi, eax
  1117.         push    ecx
  1118.         shr     ecx, 2
  1119.         cld
  1120.         rep     movsd
  1121.         pop     ecx
  1122.         and     ecx, 3
  1123.         rep     movsb
  1124.  
  1125. ;       mov     word [eax + buf_head.length], PCNET_PKT_BUF_SZ_NEG
  1126.         mov     word [eax + buf_head.status], PCNET_RXSTAT_OWN      ; Set OWN bit back to 1 (controller may write to tx-buffer again now)
  1127.  
  1128.         inc     [device.cur_rx]           ; update descriptor
  1129.         and     [device.cur_rx], 3        ;
  1130.  
  1131.         jmp     EthReceiver                     ; Send the copied packet to kernel
  1132.  
  1133.   .abort:
  1134.  
  1135.   @@:
  1136.  
  1137.         ret
  1138.  
  1139.  
  1140.  
  1141.  
  1142. ;;;;;;;;;;;;;;;;;;;;;;;
  1143. ;;                   ;;
  1144. ;; Write MAC address ;;
  1145. ;;                   ;;
  1146. ;;;;;;;;;;;;;;;;;;;;;;;
  1147.  
  1148. align 4
  1149. write_mac:      ; in: mac pushed onto stack (as 3 words)
  1150.  
  1151.         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
  1152.  
  1153.         mov     edx, [device.io_addr]
  1154.         add     dx, 2
  1155.         xor     eax, eax
  1156.  
  1157.         mov     ecx, PCNET_CSR_PAR0
  1158.        @@:
  1159.         pop     ax
  1160.         call    [device.access_write_csr]
  1161.         DEBUGF  1,"."
  1162.         inc     ecx
  1163.         cmp     ecx, PCNET_CSR_PAR2
  1164.         jl      @r
  1165.  
  1166.         DEBUGF  1,"\n"
  1167.  
  1168. ; Notice this procedure does not ret, but continues to read_mac instead.
  1169.  
  1170. ;;;;;;;;;;;;;;;;;;;;;;
  1171. ;;                  ;;
  1172. ;; Read MAC address ;;
  1173. ;;                  ;;
  1174. ;;;;;;;;;;;;;;;;;;;;;;
  1175. align 4
  1176. read_mac:
  1177.         DEBUGF  1,"Reading MAC"
  1178.  
  1179.         mov     edx, [device.io_addr]
  1180.         add     dx, 6
  1181.        @@:
  1182.         dec     dx
  1183.         dec     dx
  1184.         in      ax, dx
  1185.         push    ax
  1186.         DEBUGF  1,"."
  1187.         cmp     edx, [device.io_addr]
  1188.         jg      @r
  1189.  
  1190.         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
  1191.  
  1192.         lea     edi, [device.mac]
  1193.         pop     ax
  1194.         stosw
  1195.         pop     ax
  1196.         stosw
  1197.         pop     ax
  1198.         stosw
  1199.  
  1200.         ret
  1201.  
  1202. align 4
  1203. switch_to_wio:
  1204.  
  1205.         DEBUGF  1,"Switching to 16-bit mode\n"
  1206.  
  1207.         mov     [device.access_read_csr], wio_read_csr
  1208.         mov     [device.access_write_csr], wio_write_csr
  1209.         mov     [device.access_read_bcr], wio_read_bcr
  1210.         mov     [device.access_write_bcr], wio_write_bcr
  1211.         mov     [device.access_read_rap], wio_read_rap
  1212.         mov     [device.access_write_rap], wio_write_rap
  1213.         mov     [device.access_reset], wio_reset
  1214.  
  1215.         ret
  1216.  
  1217. align 4
  1218. switch_to_dwio:
  1219.  
  1220.         DEBUGF  1,"Switching to 32-bit mode\n"
  1221.  
  1222.         mov     [device.access_read_csr], dwio_read_csr
  1223.         mov     [device.access_write_csr], dwio_write_csr
  1224.         mov     [device.access_read_bcr], dwio_read_bcr
  1225.         mov     [device.access_write_bcr], dwio_write_bcr
  1226.         mov     [device.access_read_rap], dwio_read_rap
  1227.         mov     [device.access_write_rap], dwio_write_rap
  1228.         mov     [device.access_reset], dwio_reset
  1229.  
  1230.         ret
  1231.  
  1232.  
  1233. ; ecx - index
  1234. ; return:
  1235. ; eax - data
  1236. align 4
  1237. wio_read_csr:
  1238.  
  1239.         add     edx, PCNET_WIO_RAP
  1240.         mov     ax , cx
  1241.         out     dx , ax
  1242.         add     edx, PCNET_WIO_RDP - PCNET_WIO_RAP
  1243.         in      ax , dx
  1244.         and     eax, 0xffff
  1245.         sub     edx, PCNET_WIO_RDP
  1246.  
  1247.         ret
  1248.  
  1249.  
  1250. ; eax - data
  1251. ; ecx - index
  1252. align 4
  1253. wio_write_csr:
  1254.  
  1255.         add     edx, PCNET_WIO_RAP
  1256.         xchg    eax, ecx
  1257.         out     dx , ax
  1258.         xchg    eax, ecx
  1259.         add     edx, PCNET_WIO_RDP - PCNET_WIO_RAP
  1260.         out     dx , ax
  1261.         sub     edx, PCNET_WIO_RDP
  1262.  
  1263.         ret
  1264.  
  1265.  
  1266. ; ecx - index
  1267. ; return:
  1268. ; eax - data
  1269. align 4
  1270. wio_read_bcr:
  1271.  
  1272.         add     edx, PCNET_WIO_RAP
  1273.         mov     ax , cx
  1274.         out     dx , ax
  1275.         add     edx, PCNET_WIO_BDP - PCNET_WIO_RAP
  1276.         in      ax , dx
  1277.         and     eax, 0xffff
  1278.         sub     edx, PCNET_WIO_BDP
  1279.  
  1280.         ret
  1281.  
  1282.  
  1283. ; eax - data
  1284. ; ecx - index
  1285. align 4
  1286. wio_write_bcr:
  1287.  
  1288.         add     edx, PCNET_WIO_RAP
  1289.         xchg    eax, ecx
  1290.         out     dx , ax
  1291.         xchg    eax, ecx
  1292.         add     edx, PCNET_WIO_BDP - PCNET_WIO_RAP
  1293.         out     dx , ax
  1294.         sub     edx, PCNET_WIO_BDP
  1295.  
  1296.         ret
  1297.  
  1298. align 4
  1299. wio_read_rap:
  1300.  
  1301.         add     edx, PCNET_WIO_RAP
  1302.         in      ax , dx
  1303.         and     eax, 0xffff
  1304.         sub     edx, PCNET_WIO_RAP
  1305.  
  1306.         ret
  1307.  
  1308. ; eax - val
  1309. align 4
  1310. wio_write_rap:
  1311.  
  1312.         add     edx, PCNET_WIO_RAP
  1313.         out     dx , ax
  1314.         sub     edx, PCNET_WIO_RAP
  1315.  
  1316.         ret
  1317.  
  1318. align 4
  1319. wio_reset:
  1320.  
  1321.         push    eax
  1322.         add     edx, PCNET_WIO_RESET
  1323.         in      ax , dx
  1324.         pop     eax
  1325.         sub     edx, PCNET_WIO_RESET
  1326.  
  1327.         ret
  1328.  
  1329.  
  1330.  
  1331. ; ecx - index
  1332. ; return:
  1333. ; eax - data
  1334. align 4
  1335. dwio_read_csr:
  1336.  
  1337.         add     edx, PCNET_DWIO_RAP
  1338.         mov     eax, ecx
  1339.         out     dx , eax
  1340.         add     edx, PCNET_DWIO_RDP - PCNET_DWIO_RAP
  1341.         in      eax, dx
  1342.         and     eax, 0xffff
  1343.         sub     edx, PCNET_DWIO_RDP
  1344.  
  1345.         ret
  1346.  
  1347.  
  1348. ; ecx - index
  1349. ; eax - data
  1350. align 4
  1351. dwio_write_csr:
  1352.  
  1353.         add     edx, PCNET_DWIO_RAP
  1354.         xchg    eax, ecx
  1355.         out     dx , eax
  1356.         add     edx, PCNET_DWIO_RDP - PCNET_DWIO_RAP
  1357.         xchg    eax, ecx
  1358.         out     dx , eax
  1359.         sub     edx, PCNET_DWIO_RDP
  1360.  
  1361.         ret
  1362.  
  1363. ; ecx - index
  1364. ; return:
  1365. ; eax - data
  1366. align 4
  1367. dwio_read_bcr:
  1368.  
  1369.         add     edx, PCNET_DWIO_RAP
  1370.         mov     eax, ecx
  1371.         out     dx , eax
  1372.         add     edx, PCNET_DWIO_BDP - PCNET_DWIO_RAP
  1373.         in      eax, dx
  1374.         and     eax, 0xffff
  1375.         sub     edx, PCNET_DWIO_BDP
  1376.  
  1377.         ret
  1378.  
  1379.  
  1380. ; ecx - index
  1381. ; eax - data
  1382. align 4
  1383. dwio_write_bcr:
  1384.  
  1385.         add     edx, PCNET_DWIO_RAP
  1386.         xchg    eax, ecx
  1387.         out     dx , eax
  1388.         add     edx, PCNET_DWIO_BDP - PCNET_DWIO_RAP
  1389.         xchg    eax, ecx
  1390.         out     dx , eax
  1391.         sub     edx, PCNET_DWIO_BDP
  1392.  
  1393.         ret
  1394.  
  1395. align 4
  1396. dwio_read_rap:
  1397.  
  1398.         add     edx, PCNET_DWIO_RAP
  1399.         in      eax, dx
  1400.         and     eax, 0xffff
  1401.         sub     edx, PCNET_DWIO_RAP
  1402.  
  1403.         ret
  1404.  
  1405.  
  1406. ; eax - val
  1407. align 4
  1408. dwio_write_rap:
  1409.  
  1410.         add     edx, PCNET_DWIO_RAP
  1411.         out     dx , eax
  1412.         sub     edx, PCNET_DWIO_RAP
  1413.  
  1414.         ret
  1415.  
  1416. align 4
  1417. dwio_reset:
  1418.  
  1419.         push    eax
  1420.         add     edx, PCNET_DWIO_RESET
  1421.         in      eax, dx
  1422.         pop     eax
  1423.         sub     edx, PCNET_DWIO_RESET
  1424.  
  1425.         ret
  1426.  
  1427.  
  1428.  
  1429. ; End of code
  1430.  
  1431. align 4                                       ; Place all initialised data here
  1432.  
  1433. devices     dd 0
  1434. version       dd (5 shl 16) or (API_VERSION and 0xFFFF)
  1435. my_service    db 'PCnet',0                    ; max 16 chars include zero
  1436.  
  1437. device_l2     db "PCnet/PCI 79C970",0
  1438. device_l4     db "PCnet/PCI II 79C970A",0
  1439. device_l5     db "PCnet/FAST 79C971",0
  1440. device_l6     db "PCnet/FAST+ 79C972",0
  1441. device_l7     db "PCnet/FAST III 79C973",0
  1442. device_l8     db "PCnet/Home 79C978",0
  1443. device_l9     db "PCnet/FAST III 79C975",0
  1444.  
  1445. options_mapping:
  1446. dd PCNET_PORT_ASEL                                      ;  0 Auto-select
  1447. dd PCNET_PORT_AUI                                       ;  1 BNC/AUI
  1448. dd PCNET_PORT_AUI                                       ;  2 AUI/BNC
  1449. dd PCNET_PORT_ASEL                                      ;  3 not supported
  1450. dd PCNET_PORT_10BT or PCNET_PORT_FD                     ;  4 10baseT-FD
  1451. dd PCNET_PORT_ASEL                                      ;  5 not supported
  1452. dd PCNET_PORT_ASEL                                      ;  6 not supported
  1453. dd PCNET_PORT_ASEL                                      ;  7 not supported
  1454. dd PCNET_PORT_ASEL                                      ;  8 not supported
  1455. dd PCNET_PORT_MII                                       ;  9 MII 10baseT
  1456. dd PCNET_PORT_MII or PCNET_PORT_FD                      ; 10 MII 10baseT-FD
  1457. dd PCNET_PORT_MII                                       ; 11 MII (autosel)
  1458. dd PCNET_PORT_10BT                                      ; 12 10BaseT
  1459. dd PCNET_PORT_MII or PCNET_PORT_100                     ; 13 MII 100BaseTx
  1460. dd PCNET_PORT_MII or PCNET_PORT_100 or PCNET_PORT_FD    ; 14 MII 100BaseTx-FD
  1461. dd PCNET_PORT_ASEL                                      ; 15 not supported
  1462.  
  1463. include_debug_strings                                   ; All data wich FDO uses will be included here
  1464.  
  1465. section '.data' data readable writable align 16         ; place all uninitialized data place here
  1466.  
  1467. device_list rd MAX_DEVICES                                 ; This list contains all pointers to device structures the driver is handling
  1468.