Subversion Repositories Kolibri OS

Rev

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