Subversion Repositories Kolibri OS

Rev

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

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