Subversion Repositories Kolibri OS

Rev

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

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