Subversion Repositories Kolibri OS

Rev

Rev 5363 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  RTL8029/ne2000 driver for KolibriOS                            ;;
  7. ;;                                                                 ;;
  8. ;;  based on RTL8029.asm driver for menuetos                       ;;
  9. ;;  and realtek8029.asm for SolarOS by Eugen Brasoveanu            ;;
  10. ;;                                                                 ;;
  11. ;;    Written by hidnplayr@kolibrios.org                           ;;
  12. ;;     with help from CleverMouse                                  ;;
  13. ;;                                                                 ;;
  14. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  15. ;;             Version 2, June 1991                                ;;
  16. ;;                                                                 ;;
  17. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  18.  
  19. format PE DLL native
  20. entry START
  21.  
  22.         CURRENT_API             = 0x0200
  23.         COMPATIBLE_API          = 0x0100
  24.         API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
  25.  
  26.         MAX_DEVICES             = 16
  27.  
  28.         DEBUG                   = 1
  29.         __DEBUG__               = 1
  30.         __DEBUG_LEVEL__         = 2             ; 1 = verbose, 2 = errors only
  31.  
  32. section '.flat' readable writable executable
  33.  
  34. include '../struct.inc'
  35. include '../macros.inc'
  36. include '../proc32.inc'
  37. include '../fdo.inc'
  38. include '../netdrv.inc'
  39.  
  40. struct  device          ETH_DEVICE
  41.  
  42.         io_addr         dd ?
  43.         irq_line        db ?
  44.         pci_bus         dd ?
  45.         pci_dev         dd ?
  46.  
  47.         flags           db ?
  48.         vendor          db ?
  49.  
  50.         memsize         db ?
  51.         rx_start        db ?
  52.         tx_start        db ?
  53.         bmem            dd ?
  54.         rmem            dd ?
  55.  
  56. ends
  57.  
  58.         P0_COMMAND              = 0x00
  59.         P0_PSTART               = 0x01
  60.         P0_PSTOP                = 0x02
  61.         P0_BOUND                = 0x03
  62.         P0_TSR                  = 0x04
  63.         P0_TPSR                 = 0x04
  64.         P0_TBCR0                = 0x05
  65.         P0_TBCR1                = 0x06
  66.         P0_ISR                  = 0x07
  67.         P0_RSAR0                = 0x08
  68.         P0_RSAR1                = 0x09
  69.         P0_RBCR0                = 0x0A
  70.         P0_RBCR1                = 0x0B
  71.         P0_RSR                  = 0x0C
  72.         P0_RCR                  = 0x0C
  73.         P0_TCR                  = 0x0D
  74.         P0_DCR                  = 0x0E
  75.         P0_IMR                  = 0x0F
  76.  
  77.         P1_COMMAND              = 0x00
  78.         P1_PAR0                 = 0x01
  79.         P1_PAR1                 = 0x02
  80.         P1_PAR2                 = 0x03
  81.         P1_PAR3                 = 0x04
  82.         P1_PAR4                 = 0x05
  83.         P1_PAR5                 = 0x06
  84.         P1_CURR                 = 0x07
  85.         P1_MAR0                 = 0x08
  86.  
  87.         CMD_PS0                 = 0x00          ; Page 0 select
  88.         CMD_PS1                 = 0x40          ; Page 1 select
  89.         CMD_PS2                 = 0x80          ; Page 2 select
  90.         CMD_RD2                 = 0x20          ; Remote DMA control
  91.         CMD_RD1                 = 0x10
  92.         CMD_RD0                 = 0x08
  93.         CMD_TXP                 = 0x04          ; transmit packet
  94.         CMD_STA                 = 0x02          ; start
  95.         CMD_STP                 = 0x01          ; stop
  96.  
  97.         CMD_RDMA_READ           = 001b shl 3
  98.         CMD_RDMA_WRITE          = 010b shl 3
  99.         CMD_RDMA_SEND_PACKET    = 011b shl 3
  100.         CMD_RDMA_ABORT          = 100b shl 3    ; really is 1xx, Abort/Complete Remote DMA
  101. ;        RDMA_MASK               = 111b shl 3    ; internal, mask
  102.  
  103.         RCR_MON                 = 0x20          ; monitor mode
  104.  
  105.         DCR_FT1                 = 0x40
  106.         DCR_LS                  = 0x08          ; Loopback select
  107.         DCR_WTS                 = 0x01          ; Word transfer select
  108.  
  109.         ISR_PRX                 = 0x01          ; successful recv
  110.         ISR_PTX                 = 0x02          ; successful xmit
  111.         ISR_RXE                 = 0x04          ; receive error
  112.         ISR_TXE                 = 0x08          ; transmit error
  113.         ISR_OVW                 = 0x10          ; Overflow
  114.         ISR_CNT                 = 0x20          ; Counter overflow
  115.         ISR_RDC                 = 0x40          ; Remote DMA complete
  116.         ISR_RST                 = 0x80          ; reset
  117.  
  118.         IRQ_MASK                = ISR_PRX ;+ ISR_PTX ;+ ISR_RDC + ISR_PTX + ISR_TXE
  119.  
  120.         RSTAT_PRX               = 1 shl 0       ; successful recv
  121.         RSTAT_CRC               = 1 shl 1       ; CRC error
  122.         RSTAT_FAE               = 1 shl 2       ; Frame alignment error
  123.         RSTAT_OVER              = 1 shl 3       ; FIFO overrun
  124.  
  125.         TXBUF_SIZE              = 6
  126.         RXBUF_END               = 32
  127.         PAGE_SIZE               = 256
  128.  
  129.         ETH_ZLEN                = 60
  130.         ETH_FRAME_LEN           = 1514
  131.  
  132.         FLAG_PIO                = 1 shl 0
  133.         FLAG_16BIT              = 1 shl 1
  134.  
  135.         VENDOR_NONE             = 0
  136.         VENDOR_WD               = 1
  137.         VENDOR_NOVELL           = 2
  138.         VENDOR_3COM             = 3
  139.  
  140.         NE_ASIC                 = 0x10
  141.         NE_RESET                = 0x0F          ; Used to reset card
  142.         NE_DATA                 = 0x00          ; Used to read/write NIC mem
  143.  
  144.         MEM_8k                  = 32
  145.         MEM_16k                 = 64
  146.         MEM_32k                 = 128
  147.  
  148.         ISA_MAX_ADDR            = 0x400
  149.  
  150.  
  151.  
  152. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  153. ;;                        ;;
  154. ;; proc START             ;;
  155. ;;                        ;;
  156. ;; (standard driver proc) ;;
  157. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  158.  
  159. proc START c, reason:dword, cmdline:dword
  160.  
  161.         cmp     [reason], DRV_ENTRY
  162.         jne     .fail
  163.  
  164.         DEBUGF  2,"Loading driver\n"
  165.         invoke  RegService, my_service, service_proc
  166.         ret
  167.  
  168.   .fail:
  169.         xor     eax, eax
  170.         ret
  171.  
  172. endp
  173.  
  174.  
  175. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  176. ;;                        ;;
  177. ;; proc SERVICE_PROC      ;;
  178. ;;                        ;;
  179. ;; (standard driver proc) ;;
  180. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  181.  
  182. align 4
  183. proc service_proc stdcall, ioctl:dword
  184.  
  185.         mov     edx, [ioctl]
  186.         mov     eax, [edx + IOCTL.io_code]
  187.  
  188. ;------------------------------------------------------
  189.                        ;---------------
  190.         cmp     eax, 0 ;SRV_GETVERSION
  191.         jne     @F     ;---------------
  192.  
  193.         cmp     [edx + IOCTL.out_size], 4
  194.         jb      .fail
  195.         mov     eax, [edx + IOCTL.output]
  196.         mov     [eax], dword API_VERSION
  197.  
  198.         xor     eax, eax
  199.         ret
  200.  
  201. ;------------------------------------------------------
  202.   @@:                  ;---------
  203.         cmp     eax, 1 ;SRV_HOOK
  204.         jne     @F     ;---------
  205.  
  206.         DEBUGF  1, "Checking if device is already listed..\n"
  207.  
  208.         mov     eax, [edx + IOCTL.input]
  209.  
  210.         cmp     [edx + IOCTL.inp_size], 3
  211.         jb      .fail
  212.         cmp     byte [eax], 1
  213.         je      .pci
  214.  
  215.         cmp     [edx + IOCTL.inp_size], 4
  216.         jb      .fail
  217.         cmp     byte [eax], 0
  218.         je      .isa
  219.  
  220.         jmp     .fail
  221.  
  222.   .pci:
  223.  
  224. ; check if the device is already listed
  225.  
  226.         mov     esi, device_list
  227.         mov     ecx, [devices]
  228.         test    ecx, ecx
  229.         jz      .firstdevice_pci
  230.  
  231.         mov     ax, [eax+1]                             ; get the pci bus and device numbers
  232.   .nextdevice:
  233.         mov     ebx, [esi]
  234.         cmp     al, byte[ebx + device.pci_bus]
  235.         jne     @f
  236.         cmp     ah, byte[ebx + device.pci_dev]
  237.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  238.        @@:
  239.         add     esi, 4
  240.         loop    .nextdevice
  241.  
  242.   .firstdevice_pci:
  243.         call    create_new_struct
  244.  
  245.         mov     eax, [edx + IOCTL.input]
  246.         movzx   ecx, byte[eax+1]
  247.         mov     [ebx + device.pci_bus], ecx
  248.         movzx   ecx, byte[eax+2]
  249.         mov     [ebx + device.pci_dev], ecx
  250.  
  251. ; Now, it's time to find the base io addres of the PCI device
  252.  
  253.         stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
  254.         mov     [ebx + device.io_addr], eax
  255.  
  256. ; We've found the io address, find IRQ now
  257.  
  258.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
  259.         mov     [ebx + device.irq_line], al
  260.         jmp     .hook
  261.  
  262.   .isa:
  263.         mov     esi, device_list
  264.         mov     ecx, [devices]
  265.         test    ecx, ecx
  266.         jz      .firstdevice_isa
  267.         movzx   edi, word [eax+1]
  268.         mov     al, [eax+3]
  269.   .nextdevice_isa:
  270.         mov     ebx, [esi]
  271.         cmp     edi, [ebx + device.io_addr]
  272.         jne     .maybenext
  273.         cmp     al, [ebx + device.irq_line]
  274.         je      find_device_num
  275.   .maybenext:
  276.         add     esi, 4
  277.         loop    .nextdevice_isa
  278.  
  279.  
  280.  
  281.   .firstdevice_isa:
  282.         call    create_new_struct
  283.  
  284.         mov     eax, [edx + IOCTL.input]
  285.         movzx   ecx, word[eax+1]
  286.         mov     [ebx + device.io_addr], ecx
  287.         mov     cl, [eax+3]
  288.         mov     [ebx + device.irq_line], cl
  289.  
  290.   .hook:
  291.         DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  292.         [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:8
  293.  
  294.         call    probe                                                   ; this function will output in eax
  295.         test    eax, eax
  296.         jnz     .err                                                    ; If an error occured, exit
  297.  
  298.         DEBUGF  2,"Initialised OK\n"
  299.  
  300.         mov     eax, [devices]
  301.         mov     [device_list+4*eax], ebx
  302.         inc     [devices]
  303.  
  304.         mov     [ebx + device.type], NET_TYPE_ETH
  305.         invoke  NetRegDev
  306.  
  307.         cmp     eax, -1
  308.         jz      .err
  309.         ret
  310.  
  311.  
  312. ; If the device was already loaded, find the device number and return it in eax
  313.  
  314.   .find_devicenum:
  315.         DEBUGF  1, "Trying to find device number of already registered device\n"
  316.         invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  317.                                                                         ; into a device number in edi
  318.         mov     eax, edi                                                ; Application wants it in eax instead
  319.         DEBUGF  1, "Kernel says: %u\n", eax
  320.         ret
  321.  
  322.   .err:
  323.         DEBUGF  2, "Failed, removing device structure\n"
  324.         invoke  KernelFree, ebx
  325.  
  326.         jmp     .fail
  327.  
  328. ;------------------------------------------------------
  329.   @@:
  330. .fail:
  331.         or      eax, -1
  332.         ret
  333.  
  334. ;------------------------------------------------------
  335. endp
  336.  
  337.  
  338. create_new_struct:
  339.  
  340.         cmp     [devices], MAX_DEVICES
  341.         jae     .fail
  342.  
  343.         allocate_and_clear ebx, sizeof.device, .fail    ; Allocate the buffer for device structure
  344.  
  345.         mov     [ebx + device.reset], reset
  346.         mov     [ebx + device.transmit], transmit
  347.         mov     [ebx + device.unload], unload
  348.         mov     [ebx + device.name], my_service
  349.  
  350.         ret
  351.  
  352.   .fail:
  353.         add     esp, 4                                  ; return to caller of 'hook'
  354.         or      eax, -1
  355.         ret
  356.  
  357. find_device_num:
  358.  
  359.         DEBUGF  1, "Trying to find device number of already registered device\n"
  360.         mov     ebx, eax
  361.         invoke  NetPtrToNum                             ; This kernel procedure converts a pointer to device struct in ebx
  362.                                                         ; into a device number in edi
  363.         mov     eax, edi                                ; Application wants it in eax instead
  364.         DEBUGF  1, "Kernel says: %u\n", eax
  365.         ret
  366.  
  367.  
  368. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  369. ;;                                                                        ;;
  370. ;;        Actual Hardware dependent code starts here                      ;;
  371. ;;                                                                        ;;
  372. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  373.  
  374.  
  375. unload:   ; TODO
  376.         or      eax, -1
  377.         ret
  378.  
  379.  
  380.  
  381. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  382. ;;
  383. ;;  probe: enables the device and clears the rx buffer
  384. ;;
  385. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  386.  
  387. probe:
  388.         mov     [ebx + device.vendor], VENDOR_NONE
  389.         mov     [ebx + device.bmem], 0
  390.  
  391.         DEBUGF  1, "Trying 16-bit mode\n"
  392.  
  393.         mov     [ebx + device.flags], FLAG_16BIT + FLAG_PIO
  394.         mov     [ebx + device.memsize], MEM_32k
  395.         mov     [ebx + device.tx_start], 64
  396.         mov     [ebx + device.rx_start], TXBUF_SIZE + 64
  397.  
  398.         set_io  [ebx + device.io_addr], 0
  399.         set_io  [ebx + device.io_addr], P0_DCR
  400.         mov     al, DCR_WTS + DCR_FT1 + DCR_LS  ; word transfer select +
  401.         out     dx, al
  402.  
  403.         set_io  [ebx + device.io_addr], P0_PSTART
  404.         mov     al, MEM_16k
  405.         out     dx, al
  406.  
  407.         set_io  [ebx + device.io_addr], P0_PSTOP
  408.         mov     al, MEM_32k
  409.         out     dx, al
  410.  
  411.         mov     esi, my_service
  412.         mov     di, 16384
  413.         mov     cx, 14
  414.         call    PIO_write
  415.  
  416.         mov     si, 16384
  417.         mov     cx, 14
  418.         sub     esp, 16
  419.         mov     edi, esp
  420.         call    PIO_read
  421.  
  422.         mov     esi, esp
  423.         add     esp, 16
  424.         mov     edi, my_service
  425.         mov     ecx, 13
  426.         repe    cmpsb
  427.         je      ep_set_vendor
  428.  
  429.         DEBUGF  1, "16-bit mode failed\n"
  430.         DEBUGF  1, "Trying 8-bit mode\n"
  431.  
  432.         mov     [ebx + device.flags], FLAG_PIO
  433.         mov     [ebx + device.memsize], MEM_16k
  434.         mov     [ebx + device.tx_start], 32
  435.         mov     [ebx + device.rx_start], TXBUF_SIZE + 32
  436.  
  437.         set_io  [ebx + device.io_addr], NE_ASIC + NE_RESET
  438.         in      al, dx
  439.         out     dx, al
  440.  
  441.         in      al, 0x84
  442.  
  443.         set_io  [ebx + device.io_addr], P0_COMMAND
  444.         mov     al, CMD_RD2 + CMD_STP
  445.         out     dx, al
  446.  
  447.         set_io  [ebx + device.io_addr], P0_RCR
  448.         mov     al, RCR_MON
  449.         out     dx, al
  450.  
  451.         set_io  [ebx + device.io_addr], P0_DCR
  452.         mov     al, DCR_FT1 + DCR_LS
  453.         out     dx, al
  454.  
  455.         set_io  [ebx + device.io_addr], P0_PSTART
  456.         mov     al, MEM_8k
  457.         out     dx, al
  458.  
  459.         set_io  [ebx + device.io_addr], P0_PSTOP
  460.         mov     al, MEM_16k
  461.         out     dx, al
  462.  
  463.         mov     esi, my_service
  464.         mov     di, 8192
  465.         mov     cx, 14
  466.         call    PIO_write
  467.  
  468.         mov     si, 8192
  469.         mov     cx, 14
  470.         sub     esp, 16
  471.         mov     edi, esp
  472.         call    PIO_read
  473.  
  474.         mov     esi, my_service
  475.         mov     edi, esp
  476.         add     esp, 16
  477.         mov     ecx, 13
  478.         repe    cmpsb
  479.         je      ep_set_vendor
  480.  
  481.         DEBUGF  2, "This is not a valid ne2000 device!\n"
  482.         or      eax, -1
  483.         ret
  484.  
  485.  
  486. ep_set_vendor:
  487.  
  488.         DEBUGF  1, "Mode ok\n"
  489.  
  490.         cmp     [ebx + device.io_addr], ISA_MAX_ADDR
  491.         jbe     .isa
  492.  
  493.         DEBUGF  1, "Card is using PCI bus\n"
  494.  
  495.         mov     [ebx + device.vendor], VENDOR_NOVELL  ;;; FIXME
  496.         jmp     ep_check_have_vendor
  497.  
  498.   .isa:
  499.         DEBUGF  1, "Card is using ISA bus\n"
  500.  
  501.         mov     [ebx + device.vendor], VENDOR_NOVELL
  502.  
  503. ep_check_have_vendor:
  504.  
  505.  
  506.         mov     al, [ebx + device.vendor]
  507.         cmp     al, VENDOR_NONE
  508. ;        je      exit
  509.  
  510.         cmp     al, VENDOR_3COM
  511.         je      reset
  512.  
  513.         mov     eax, [ebx + device.bmem]
  514.         mov     [ebx + device.rmem], eax
  515.  
  516. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  517. ;;
  518. ;;   reset: Place the chip into a virgin state
  519. ;;
  520. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  521.  
  522. reset:
  523.         DEBUGF  1, "Resetting device\n"
  524.  
  525. ; attach int handler
  526.         movzx   eax, [ebx + device.irq_line]
  527.         DEBUGF  1, "Attaching int handler to irq %x\n", eax:1
  528.         invoke  AttachIntHandler, eax, int_handler, ebx
  529.         test    eax, eax
  530.         jnz     @f
  531.         DEBUGF  2, "Could not attach int handler!\n"
  532.         or      eax, -1
  533.         ret
  534.        @@:
  535.  
  536. ; Stop card + DMA
  537.         set_io  [ebx + device.io_addr], 0
  538. ;        set_io  [ebx + device.io_addr], P0_COMMAND
  539.         mov     al, CMD_PS0 + CMD_RDMA_ABORT + CMD_STP
  540.         out     dx, al
  541.  
  542. ; initialize DCR
  543.         set_io  [ebx + device.io_addr], P0_DCR
  544.         mov     al, DCR_FT1 + DCR_LS
  545.         test    [ebx + device.flags], FLAG_16BIT
  546.         jz      @f
  547.         or      al, DCR_WTS                     ; word transfer select
  548.       @@:
  549.         out     dx, al
  550.  
  551. ; clear remote bytes count
  552.         set_io  [ebx + device.io_addr], P0_RBCR0
  553.         xor     al, al
  554.         out     dx, al
  555.  
  556.         set_io  [ebx + device.io_addr], P0_RBCR1
  557.         out     dx, al
  558.  
  559. ; initialize Receive configuration register (until all init is done)
  560.         set_io  [ebx + device.io_addr], P0_RCR
  561.         mov     al, 0x20        ; monitor mode
  562.         out     dx, al
  563.  
  564. ; transmit configuration register to monitor mode (until all ini is done)
  565.         set_io  [ebx + device.io_addr], P0_TCR
  566.         mov     al, 2           ; internal loopback
  567.         out     dx, al
  568.  
  569. ; clear interupt status
  570.         set_io  [ebx + device.io_addr], P0_ISR
  571.         mov     al, 0xff
  572.         out     dx, al
  573.  
  574. ; clear IRQ mask                        ;;;;; CHECKME ;;;;;
  575.         set_io  [ebx + device.io_addr], P0_IMR
  576.         xor     al, al
  577.         out     dx, al
  578.  
  579. ; set transmit pointer
  580.         set_io  [ebx + device.io_addr], P0_TPSR
  581.         mov     al, [ebx + device.tx_start]
  582.         out     dx, al
  583.  
  584. ; set pagestart pointer
  585.         set_io  [ebx + device.io_addr], P0_PSTART
  586.         mov     al, [ebx + device.rx_start]
  587.         out     dx, al
  588.  
  589. ; set pagestop pointer
  590.         set_io  [ebx + device.io_addr], P0_PSTOP
  591.         mov     al, [ebx + device.memsize]
  592.         out     dx, al
  593.  
  594. ; set boundary pointer
  595.         set_io  [ebx + device.io_addr], P0_BOUND
  596.         mov     al, [ebx + device.memsize]
  597.         dec     al
  598.         out     dx, al
  599.  
  600. ; set curr pointer
  601.         set_io  [ebx + device.io_addr], P0_COMMAND
  602.         mov     al, CMD_PS1 ;+ CMD_RD2 + CMD_STP ; page 1, stop mode
  603.         out     dx, al
  604.  
  605.         set_io  [ebx + device.io_addr], P1_CURR
  606.         mov     al, [ebx + device.rx_start]
  607.         out     dx, al
  608.  
  609.         set_io  [ebx + device.io_addr], P0_COMMAND
  610.         mov     al, CMD_PS0 ;+ CMD_RD2 + CMD_STA ; go to page 0, start mode
  611.         out     dx, al
  612.  
  613. ; Read MAC address and set it to registers
  614.         call    read_mac
  615.         push    .macret
  616.         sub     esp, 6
  617.         lea     esi, [ebx + device.mac]
  618.         mov     edi, esp
  619.         movsd
  620.         movsw
  621.         jmp     write_mac
  622.   .macret:
  623.  
  624. ; set IRQ mask
  625.         set_io  [ebx + device.io_addr], 0
  626.         set_io  [ebx + device.io_addr], P0_IMR
  627.         mov     al, IRQ_MASK
  628.         out     dx, al
  629.  
  630. ; start mode
  631.         set_io  [ebx + device.io_addr], P0_COMMAND
  632.         mov     al, CMD_STA
  633.         out     dx, al
  634.  
  635. ; clear transmit control register
  636.         set_io  [ebx + device.io_addr], P0_TCR
  637.         xor     al, al                  ; no loopback
  638.         out     dx, al
  639.  
  640. ; set receive control register ;;;;
  641.         set_io  [ebx + device.io_addr], P0_RCR
  642.         mov     al, 4                   ; accept broadcast
  643.         out     dx, al
  644.  
  645. ; clear packet/byte counters
  646.         xor     eax, eax
  647.         lea     edi, [ebx + device.bytes_tx]
  648.         mov     ecx, 6
  649.         rep     stosd
  650.  
  651. ; Set the mtu, kernel will be able to send now
  652.         mov     [ebx + device.mtu], ETH_FRAME_LEN
  653.  
  654. ; Set link state to unknown
  655.         mov     [ebx + device.state], ETH_LINK_UNKNOWN
  656.  
  657. ; Indicate that we have successfully reset the card
  658.         xor     eax, eax
  659.         DEBUGF  1, "Done!\n"
  660.  
  661.         ret
  662.  
  663.  
  664.  
  665. ;***************************************************************************
  666. ;   Function
  667. ;      transmit
  668. ; buffer in [esp+4], pointer to device struct in ebx
  669. ;***************************************************************************
  670.  
  671. proc transmit stdcall buffer_ptr
  672.  
  673.         pushf
  674.         cli
  675.  
  676.         mov     esi, [buffer_ptr]
  677.         mov     ecx, [esi + NET_BUFF.length]
  678.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", esi, ecx
  679.         lea     eax, [esi + NET_BUFF.data]
  680.         DEBUGF  1, "To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  681.         [esi+0]:2,[esi+1]:2,[esi+2]:2,[esi+3]:2,[esi+4]:2,[esi+5]:2,[esi+6]:2,[esi+7]:2,[esi+8]:2,[esi+9]:2,[esi+10]:2,[esi+11]:2,[esi+13]:2,[esi+12]:2
  682.  
  683.         cmp     ecx, ETH_FRAME_LEN
  684.         ja      .err            ; packet is too long
  685.         cmp     ecx, ETH_ZLEN
  686.         jb      .err            ; packet is too short
  687.  
  688.         movzx   edi, [ebx + device.tx_start]
  689.         shl     edi, 8
  690.         add     esi, [esi + NET_BUFF.offset]
  691.         push    ecx
  692.         call    PIO_write
  693.         pop     ecx
  694.  
  695.         set_io  [ebx + device.io_addr], 0
  696. ;        set_io  [ebx + device.io_addr], P0_COMMAND
  697.         mov     al, CMD_PS0 + CMD_RD2 + CMD_STA
  698.         out     dx, al
  699.  
  700.         set_io  [ebx + device.io_addr], P0_TPSR
  701.         mov     al, [ebx + device.tx_start]
  702.         out     dx, al
  703.  
  704.         set_io  [ebx + device.io_addr], P0_TBCR0
  705.         mov     al, cl
  706.         out     dx, al
  707.  
  708.         set_io  [ebx + device.io_addr], P0_TBCR1
  709.         mov     al, ch
  710.         out     dx, al
  711.  
  712.         set_io  [ebx + device.io_addr], P0_COMMAND
  713.         mov     al, CMD_PS0 + CMD_TXP + CMD_RD2 + CMD_STA
  714.         out     dx, al
  715.  
  716.         DEBUGF  1, "Packet Sent!\n"
  717.  
  718.         inc     [ebx + device.packets_tx]
  719.         add     dword[ebx + device.bytes_tx], ecx
  720.         adc     dword[ebx + device.bytes_tx + 4], 0
  721.  
  722.         invoke  NetFree, [buffer_ptr]
  723.         popf
  724.         xor     eax, eax
  725.         ret
  726.  
  727.   .err:
  728.         DEBUGF  2, "Transmit error!\n"
  729.         invoke  NetFree, [buffer_ptr]
  730.         popf
  731.         or      eax, -1
  732.         ret
  733.  
  734. endp
  735.  
  736.  
  737.  
  738. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  739. ;
  740. ; Interrupt handler
  741. ;
  742. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  743.  
  744. align 4
  745. int_handler:
  746.  
  747.         push    ebx esi edi
  748.         DEBUGF  1, "INT\n"
  749.  
  750. ; find pointer of device wich made INT occur
  751.  
  752.         mov     ecx, [devices]
  753.         test    ecx, ecx
  754.         jz      .nothing
  755.         mov     esi, device_list
  756.   .nextdevice:
  757.         mov     ebx, [esi]
  758.  
  759.         set_io  [ebx + device.io_addr], 0
  760. ;        set_io  [ebx + device.io_addr], P0_COMMAND
  761.         mov     al, CMD_PS0
  762.         out     dx, al
  763.  
  764.         set_io  [ebx + device.io_addr], P0_ISR
  765.         in      al, dx
  766.         test    al, al
  767.         jnz     .got_it
  768.   .continue:
  769.         add     esi, 4
  770.         dec     ecx
  771.         jnz     .nextdevice
  772.   .nothing:
  773.         pop     edi esi ebx
  774.         xor     eax, eax
  775.  
  776.         ret
  777.  
  778.   .got_it:
  779.         DEBUGF  1, "Device=%x status=%x\n", ebx, eax:2
  780.  
  781.         push    ebx
  782.   .rx_loop:
  783.         test    al, ISR_PRX     ; packet received ok ?
  784.         jz      .no_rx
  785.         test    [ebx + device.flags], FLAG_PIO
  786.         jz      .no_rx          ; FIXME: Only PIO mode supported for now
  787.  
  788. ; allocate a buffer
  789.         invoke  NetAlloc, ETH_FRAME_LEN+NET_BUFF.data
  790.         test    eax, eax
  791.         jz      .rx_fail_2
  792.  
  793. ; Push return address and packet ptr to stack
  794.         pushd   .no_rx
  795.         push    eax
  796.         mov     [eax + NET_BUFF.device], ebx
  797.         mov     [eax + NET_BUFF.offset], NET_BUFF.data
  798.  
  799. ; read offset for current packet from device
  800.         set_io  [ebx + device.io_addr], 0
  801.         set_io  [ebx + device.io_addr], P0_BOUND        ; boundary ptr is offset to next packet we need to read.
  802.         in      al, dx
  803.         inc     al
  804.         cmp     al, [ebx + device.memsize]
  805.         jb      @f
  806.         mov     al, [ebx + device.rx_start]
  807.        @@:
  808.         mov     ch, al
  809.  
  810.         set_io  [ebx + device.io_addr], P0_COMMAND
  811.         mov     al, CMD_PS1
  812.         out     dx, al
  813.         set_io  [ebx + device.io_addr], P1_CURR
  814.         in      al, dx                                  ; get current page in cl
  815.         mov     cl, al
  816.  
  817.         set_io  [ebx + device.io_addr], P1_COMMAND
  818.         mov     al, CMD_PS0
  819.         out     dx, al
  820.  
  821.         cmp     cl, [ebx + device.memsize]
  822.         jb      @f
  823.         mov     cl, [ebx + device.rx_start]
  824.        @@:
  825.  
  826.         cmp     cl, ch
  827.         je      .rx_fail
  828.         movzx   esi, ch                                 ; we are using 256 byte pages
  829.         shl     esi, 8                                  ; esi now holds the offset for current packet
  830.  
  831. ; Write packet header to frame header size field
  832.         push    ecx
  833.         mov     edi, esp
  834.         mov     cx, 4
  835.         call    PIO_read
  836.         mov     ecx, [esp]
  837.  
  838. ; check if packet is ok
  839.         test    ecx, RSTAT_PRX
  840.         jz      .rx_fail_3
  841.  
  842. ; calculate packet length in ecx
  843.         shr     ecx, 16
  844.         sub     ecx, 4                                  ; CRC doesnt count as data byte
  845.         mov     edi, [esp+4]
  846.         mov     [edi + NET_BUFF.length], ecx
  847.  
  848. ; check if packet size is ok
  849.         cmp     ecx, ETH_ZLEN
  850.         jb      .rx_fail_3
  851.         cmp     ecx, ETH_FRAME_LEN
  852.         ja      .rx_fail_3
  853.  
  854. ; update stats
  855.         DEBUGF  1, "Received %u bytes\n", ecx
  856.         add     dword[ebx + device.bytes_rx], ecx
  857.         adc     dword[ebx + device.bytes_rx + 4], 0
  858.         inc     [ebx + device.packets_rx]
  859.  
  860. ; update read and write pointers
  861.         add     esi, 4
  862.         add     edi, NET_BUFF.data
  863.  
  864. ; now check if we can read all data at once (if we cross the end boundary, we need to wrap back to the beginning)
  865.         xor     eax, eax
  866.         mov     ah, [ebx + device.memsize]
  867.         sub     eax, esi
  868.         cmp     ecx, eax                ; eax = number of bytes till end of buffer, ecx = bytes we need to read
  869.         jbe     .no_wrap
  870.  
  871. ; Read first part
  872.         sub     ecx, eax
  873.         push    ecx
  874.         mov     ecx, eax
  875.         call    PIO_read                ; Read the data
  876.  
  877. ; update pointers for second read
  878.         add     edi, ecx
  879.         pop     ecx
  880.         movzx   esi, [ebx + device.rx_start]
  881.         shl     esi, 8
  882.  
  883. ; now read second part (or only part)
  884.   .no_wrap:
  885.         call    PIO_read                ; Read the data
  886.  
  887. ; update boundary pointer
  888.         pop     eax
  889.         mov     al, ah
  890.         cmp     al, [ebx + device.rx_start]
  891.         jne     @f
  892.         mov     al, [ebx + device.memsize]
  893.        @@:
  894.         set_io  [ebx + device.io_addr], 0
  895.         set_io  [ebx + device.io_addr], P0_BOUND
  896.         dec     al
  897.         out     dx, al
  898.  
  899. ; now send the data to the kernel
  900.         jmp     [EthInput]
  901.  
  902.   .rx_fail_3:
  903.         add     esp, 4
  904.   .rx_fail:
  905.         add     esp, 12
  906.   .rx_fail_2:
  907.         DEBUGF  2, "Error on receive\n"
  908.   .no_rx:
  909.         pop     ebx
  910.         DEBUGF  1, "done\n"
  911.  
  912.         set_io  [ebx + device.io_addr], 0
  913.         set_io  [ebx + device.io_addr], P0_ISR
  914.         mov     al, 0xff
  915.         out     dx, al
  916.  
  917.         pop     edi esi ebx
  918.  
  919.         ret
  920.  
  921.  
  922. ;;;;;;;;;;;;;;;;;;;;;;;
  923. ;;                   ;;
  924. ;; Write MAC address ;;
  925. ;;                   ;;
  926. ;;;;;;;;;;;;;;;;;;;;;;;
  927.  
  928. align 4
  929. write_mac:      ; in: mac on stack (6 bytes)
  930.  
  931.         DEBUGF  1, "Writing MAC\n"
  932.  
  933.         set_io  [ebx + device.io_addr], 0
  934.         mov     al, CMD_PS1; + CMD_RD2 + CMD_STP
  935.         out     dx, al
  936.  
  937.         set_io  [ebx + device.io_addr], P1_PAR0
  938.         mov     esi, esp
  939.         mov     cx, 6
  940.  @@:
  941.         lodsb
  942.         out     dx, al
  943.         inc     dx
  944.         loopw   @r
  945.  
  946.         add     esp, 6
  947.  
  948. ; Notice this procedure does not ret, but continues to read_mac instead.
  949.  
  950. ;;;;;;;;;;;;;;;;;;;;;;
  951. ;;                  ;;
  952. ;; Read MAC address ;;
  953. ;;                  ;;
  954. ;;;;;;;;;;;;;;;;;;;;;;
  955.  
  956. read_mac:
  957.  
  958.         DEBUGF  1, "Reading MAC\n"
  959.  
  960.         xor     esi, esi
  961.         mov     cx, 16
  962.         sub     esp, 16
  963.         mov     edi, esp
  964.         call    PIO_read
  965.  
  966.         mov     esi, esp
  967.         add     esp, 16
  968.         lea     edi, [ebx + device.mac]
  969.         mov     ecx, 6
  970.   .loop:
  971.         movsb
  972.         test    [ebx + device.flags], FLAG_16BIT
  973.         jz      .8bit
  974.         inc     esi
  975.   .8bit:
  976.         loop    .loop
  977.         DEBUGF  1, "MAC=%x-%x-%x-%x-%x-%x\n",\
  978.         [ebx + device.mac]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,[ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
  979.  
  980.         ret
  981.  
  982.  
  983. ;***************************************************************************
  984. ;
  985. ;   PIO_read
  986. ;
  987. ;   Description
  988. ;       Read a frame from the ethernet card via Programmed I/O
  989. ;      src in si
  990. ;      cnt in cx
  991. ;       dst in edi
  992. ;***************************************************************************
  993. PIO_read:
  994.  
  995.         DEBUGF  1, "PIO Read from %x to %x, %u bytes ", si, edi, cx
  996.  
  997. ; stop DMA + start
  998.         set_io  [ebx + device.io_addr], 0
  999. ;        set_io  [ebx + device.io_addr], P0_COMMAND
  1000.         mov     al, CMD_RD2 + CMD_STA
  1001.         out     dx, al
  1002.  
  1003. ; Request confirmation of end of DMA transfer
  1004.         set_io  [ebx + device.io_addr], P0_ISR
  1005.         mov     al, ISR_RDC
  1006.         out     dx, al
  1007.  
  1008. ; set length of data we're interested in
  1009.         set_io  [ebx + device.io_addr], P0_RBCR0
  1010.         mov     al, cl
  1011.         out     dx, al
  1012.         set_io  [ebx + device.io_addr], P0_RBCR1
  1013.         mov     al, ch
  1014.         out     dx, al
  1015.  
  1016. ; set offset of what we want to read
  1017.         set_io  [ebx + device.io_addr], P0_RSAR0
  1018.         mov     ax, si
  1019.         out     dx, al
  1020.         set_io  [ebx + device.io_addr], P0_RSAR1
  1021.         shr     ax, 8
  1022.         out     dx, al
  1023.  
  1024. ; start DMA read
  1025.         set_io  [ebx + device.io_addr], P0_COMMAND
  1026.         mov     al, CMD_RD0 + CMD_STA
  1027.         out     dx, al
  1028.  
  1029.         set_io  [ebx + device.io_addr], NE_ASIC
  1030.         test    [ebx + device.flags], FLAG_16BIT
  1031.         jz      .8bits
  1032.         DEBUGF  1, "(16-bit mode)\n"
  1033.         shr     cx, 1   ; note that if the number was odd, carry flag will be set
  1034.         pushf
  1035.   .16bits:
  1036.         in      ax, dx
  1037.         stosw
  1038.         loopw   .16bits
  1039.         popf
  1040.         jnc     wait_dma_done
  1041.         in      al, dx
  1042.         stosb
  1043.         jmp     wait_dma_done
  1044.  
  1045.   .8bits:
  1046.         DEBUGF  1, "(8-bit mode)\n"
  1047.   .8bits_:
  1048.         in      al, dx
  1049.         stosb
  1050.         loopw   .8bits_
  1051.         jmp     wait_dma_done
  1052.  
  1053.  
  1054.  
  1055.  
  1056. ;***************************************************************************
  1057. ;
  1058. ;   PIO_write
  1059. ;
  1060. ;   Description
  1061. ;       writes a frame to the ethernet card via Programmed I/O
  1062. ;      dst in di
  1063. ;      cnt in cx
  1064. ;       src in esi
  1065. ;***************************************************************************
  1066. PIO_write:
  1067.  
  1068.         DEBUGF  1, "Eth PIO Write from %x to %x, %u bytes ", esi, di, cx
  1069.  
  1070. ; Stop DMA + start
  1071.         set_io  [ebx + device.io_addr], 0
  1072. ;        set_io  [ebx + device.io_addr], P0_COMMAND
  1073.         mov     al, CMD_RD2 + CMD_STA
  1074.         out     dx, al
  1075.  
  1076. ; Request confirmation of end of DMA transfer
  1077.         set_io  [ebx + device.io_addr], P0_ISR
  1078.         mov     al, ISR_RDC
  1079.         out     dx, al
  1080.  
  1081. ; Program number of bytes we want to write
  1082.         set_io  [ebx + device.io_addr], P0_RBCR0
  1083.         mov     al, cl
  1084.         out     dx, al
  1085.         set_io  [ebx + device.io_addr], P0_RBCR1
  1086.         mov     al, ch
  1087.         out     dx, al
  1088.  
  1089. ; Program where we want to write
  1090.         mov     ax, di
  1091.         set_io  [ebx + device.io_addr], P0_RSAR0
  1092.         out     dx, al
  1093.         shr     ax, 8
  1094.         set_io  [ebx + device.io_addr], P0_RSAR1
  1095.         out     dx, al
  1096.  
  1097. ; Set the DMA to write
  1098.         set_io  [ebx + device.io_addr], P0_COMMAND
  1099.         mov     al, CMD_RD1 + CMD_STA
  1100.         out     dx, al
  1101.  
  1102.         set_io  [ebx + device.io_addr], NE_ASIC
  1103.         test    [ebx + device.flags], FLAG_16BIT
  1104.         jz      .8_bit
  1105.         DEBUGF  1, "(16-bit mode)\n"
  1106.         shr     cx, 1   ; note that if the number was odd, carry flag will be set
  1107.         pushf           ; save the flags for later
  1108.   .16bit:
  1109.         lodsw
  1110.         out     dx, ax
  1111.         loopw   .16bit
  1112.         popf
  1113.         jnc     wait_dma_done
  1114.         lodsb
  1115.         out     dx, al
  1116.         jmp     wait_dma_done
  1117.  
  1118.   .8_bit:
  1119.         DEBUGF  1, "(8-bit mode)\n"
  1120.   .8_bit_:
  1121.         lodsb
  1122.         out     dx, al
  1123.         loopw   .8_bit_
  1124.         jmp     wait_dma_done
  1125.  
  1126.  
  1127.  
  1128. wait_dma_done:
  1129.  
  1130.         set_io  [ebx + device.io_addr], 0
  1131.         set_io  [ebx + device.io_addr], P0_ISR
  1132.   .dmawait:
  1133.         in      al, dx
  1134.         test    al, ISR_RDC             ; Remote DMA Complete
  1135.         jz      .dmawait
  1136. ;        and     al, not ISR_RDC
  1137. ;        out     dx, al                  ; clear the bit
  1138.  
  1139.         ret
  1140.  
  1141.  
  1142.  
  1143. ; End of code
  1144.  
  1145.  
  1146. data fixups
  1147. end data
  1148.  
  1149. include '../peimport.inc'
  1150.  
  1151. my_service      db 'RTL8029', 0                 ; max 16 chars include zero
  1152.  
  1153. ;sz_8029         db 'Realtek 8029', 0
  1154. ;sz_8019         db 'Realtek 8019', 0
  1155. ;sz_8019as       db 'Realtek 8019AS', 0
  1156. ;sz_ne2k         db 'ne2000', 0
  1157. ;sz_dp8390       db 'DP8390', 0
  1158.  
  1159. include_debug_strings                           ; All data wich FDO uses will be included here
  1160.  
  1161. align 4
  1162. devices       dd 0
  1163. device_list   rd MAX_DEVICES                    ; This list contains all pointers to device structures the driver is handling
  1164.  
  1165.  
  1166.  
  1167.  
  1168.  
  1169.