Subversion Repositories Kolibri OS

Rev

Rev 5005 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2014. 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], size in [esp+8], pointer to device struct in ebx
  669. ;***************************************************************************
  670.  
  671. proc transmit stdcall buffer_ptr, buffer_size
  672.  
  673.         pushf
  674.         cli
  675.  
  676.         mov     esi, [buffer_ptr]
  677.         mov     ecx, [buffer_size]
  678.         DEBUGF  1, "Transmitting packet, buffer:%x, size:%u\n", esi, ecx
  679.         DEBUGF  1, "To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  680.         [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
  681.  
  682.         cmp     ecx, ETH_FRAME_LEN
  683.         ja      .err            ; packet is too long
  684.         cmp     ecx, ETH_ZLEN
  685.         jb      .err            ; packet is too short
  686.  
  687.         movzx   edi, [ebx + device.tx_start]
  688.         shl     edi, 8
  689.         push    cx
  690.         call    PIO_write
  691.         pop     cx
  692.  
  693.         set_io  [ebx + device.io_addr], 0
  694. ;        set_io  [ebx + device.io_addr], P0_COMMAND
  695.         mov     al, CMD_PS0 + CMD_RD2 + CMD_STA
  696.         out     dx, al
  697.  
  698.         set_io  [ebx + device.io_addr], P0_TPSR
  699.         mov     al, [ebx + device.tx_start]
  700.         out     dx, al
  701.  
  702.         set_io  [ebx + device.io_addr], P0_TBCR0
  703.         mov     al, cl
  704.         out     dx, al
  705.  
  706.         set_io  [ebx + device.io_addr], P0_TBCR1
  707.         mov     al, ch
  708.         out     dx, al
  709.  
  710.         set_io  [ebx + device.io_addr], P0_COMMAND
  711.         mov     al, CMD_PS0 + CMD_TXP + CMD_RD2 + CMD_STA
  712.         out     dx, al
  713.  
  714.         DEBUGF  1, "Packet Sent!\n"
  715.  
  716.         inc     [ebx + device.packets_tx]
  717.         mov     eax, [buffer_size]
  718.         add     dword[ebx + device.bytes_tx], eax
  719.         adc     dword[ebx + device.bytes_tx + 4], 0
  720.  
  721.         invoke  KernelFree, [buffer_ptr]
  722.         popf
  723.         xor     eax, eax
  724.         ret
  725.  
  726.   .err:
  727.         DEBUGF  2, "Transmit error!\n"
  728.         invoke  KernelFree, [buffer_ptr]
  729.         popf
  730.         or      eax, -1
  731.         ret
  732.  
  733. endp
  734.  
  735.  
  736.  
  737. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  738. ;
  739. ; Interrupt handler
  740. ;
  741. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  742.  
  743. align 4
  744. int_handler:
  745.  
  746.         push    ebx esi edi
  747.         DEBUGF  1, "INT\n"
  748.  
  749. ; find pointer of device wich made INT occur
  750.  
  751.         mov     ecx, [devices]
  752.         test    ecx, ecx
  753.         jz      .nothing
  754.         mov     esi, device_list
  755.   .nextdevice:
  756.         mov     ebx, [esi]
  757.  
  758.         set_io  [ebx + device.io_addr], 0
  759. ;        set_io  [ebx + device.io_addr], P0_COMMAND
  760.         mov     al, CMD_PS0
  761.         out     dx, al
  762.  
  763.         set_io  [ebx + device.io_addr], P0_ISR
  764.         in      al, dx
  765.         test    al, al
  766.         jnz     .got_it
  767.   .continue:
  768.         add     esi, 4
  769.         dec     ecx
  770.         jnz     .nextdevice
  771.   .nothing:
  772.         pop     edi esi ebx
  773.         xor     eax, eax
  774.  
  775.         ret
  776.  
  777.   .got_it:
  778.         DEBUGF  1, "Device=%x status=%x\n", ebx, eax:2
  779.  
  780.         push    ebx
  781.   .rx_loop:
  782.         test    al, ISR_PRX     ; packet received ok ?
  783.         jz      .no_rx
  784.         test    [ebx + device.flags], FLAG_PIO
  785.         jz      .no_rx          ; FIXME: Only PIO mode supported for now
  786.  
  787. ; allocate a buffer
  788.         invoke  KernelAlloc, ETH_FRAME_LEN
  789.         test    eax, eax
  790.         jz      .rx_fail_2
  791.  
  792. ; Push return address and packet ptr to stack
  793.         pushd   .no_rx
  794.         pushd   0               ; Reserve some space for the packet size
  795.         push    eax
  796.  
  797. ; read offset for current packet from device
  798.         set_io  [ebx + device.io_addr], 0
  799.         set_io  [ebx + device.io_addr], P0_BOUND        ; boundary ptr is offset to next packet we need to read.
  800.         in      al, dx
  801.         inc     al
  802.         cmp     al, [ebx + device.memsize]
  803.         jb      @f
  804.         mov     al, [ebx + device.rx_start]
  805.        @@:
  806.         mov     ch, al
  807.  
  808.         set_io  [ebx + device.io_addr], P0_COMMAND
  809.         mov     al, CMD_PS1
  810.         out     dx, al
  811.         set_io  [ebx + device.io_addr], P1_CURR
  812.         in      al, dx                          ; get current page in cl
  813.         mov     cl, al
  814.  
  815.         set_io  [ebx + device.io_addr], P1_COMMAND
  816.         mov     al, CMD_PS0
  817.         out     dx, al
  818.  
  819.         cmp     cl, [ebx + device.memsize]
  820.         jb      @f
  821.         mov     cl, [ebx + device.rx_start]
  822.        @@:
  823.  
  824.         cmp     cl, ch
  825.         je      .rx_fail
  826.         movzx   esi, ch                         ; we are using 256 byte pages
  827.         shl     esi, 8                          ; esi now holds the offset for current packet
  828.  
  829. ; Get packet header in ecx
  830.         push    ecx                             ; reserve 4 bytes on stack to put packet header in
  831.         mov     edi, esp
  832.         mov     cx, 4
  833.         call    PIO_read
  834.         mov     ecx, [esp]
  835.  
  836. ; check if packet is ok
  837.         test    ecx, RSTAT_PRX
  838.         jz      .rx_fail_3
  839.  
  840. ; calculate packet length in ecx
  841.         shr     ecx, 16
  842.         sub     ecx, 4                          ; CRC doesnt count as data byte
  843.         mov     [esp + 8], ecx
  844.  
  845. ; check if packet size is ok
  846.         cmp     ecx, ETH_ZLEN
  847.         jb      .rx_fail_3
  848.         cmp     ecx, ETH_FRAME_LEN
  849.         ja      .rx_fail_3
  850.  
  851. ; update stats
  852.         DEBUGF  1, "Received %u bytes\n", ecx
  853.         add     dword[ebx + device.bytes_rx], ecx
  854.         adc     dword[ebx + device.bytes_rx + 4], 0
  855.         inc     [ebx + device.packets_rx]
  856.  
  857. ; update read and write pointers
  858.         add     esi, 4
  859.         mov     edi, [esp + 4]
  860.  
  861. ; now check if we can read all data at once (if we cross the end boundary, we need to wrap back to the beginning)
  862.         xor     eax, eax
  863.         mov     ah, [ebx + device.memsize]
  864.         sub     eax, esi
  865.         cmp     ecx, eax                ; eax = number of bytes till end of buffer, ecx = bytes we need to read
  866.         jbe     .no_wrap
  867.  
  868. ; Read first part
  869.         sub     ecx, eax
  870.         push    ecx
  871.         mov     ecx, eax
  872.         call    PIO_read                ; Read the data
  873.  
  874. ; update pointers for second read
  875.         add     edi, ecx
  876.         pop     ecx
  877.         movzx   esi, [ebx + device.rx_start]
  878.         shl     esi, 8
  879.  
  880. ; now read second part (or only part)
  881.   .no_wrap:
  882.         call    PIO_read                ; Read the data
  883.  
  884. ; update boundary pointer
  885.         pop     eax
  886.         mov     al, ah
  887.         cmp     al, [ebx + device.rx_start]
  888.         jne     @f
  889.         mov     al, [ebx + device.memsize]
  890.        @@:
  891.         set_io  [ebx + device.io_addr], 0
  892.         set_io  [ebx + device.io_addr], P0_BOUND
  893.         dec     al
  894.         out     dx, al
  895.  
  896. ; now send the data to the kernel
  897.         jmp     [Eth_input]
  898.  
  899.   .rx_fail_3:
  900.         add     esp, 4
  901.   .rx_fail:
  902.         add     esp, 12
  903.   .rx_fail_2:
  904.         DEBUGF  2, "Error on receive\n"
  905.   .no_rx:
  906.         pop     ebx
  907.         DEBUGF  1, "done\n"
  908.  
  909.         set_io  [ebx + device.io_addr], 0
  910.         set_io  [ebx + device.io_addr], P0_ISR
  911.         mov     al, 0xff
  912.         out     dx, al
  913.  
  914.         pop     edi esi ebx
  915.  
  916.         ret
  917.  
  918.  
  919. ;;;;;;;;;;;;;;;;;;;;;;;
  920. ;;                   ;;
  921. ;; Write MAC address ;;
  922. ;;                   ;;
  923. ;;;;;;;;;;;;;;;;;;;;;;;
  924.  
  925. align 4
  926. write_mac:      ; in: mac on stack (6 bytes)
  927.  
  928.         DEBUGF  1, "Writing MAC\n"
  929.  
  930.         set_io  [ebx + device.io_addr], 0
  931.         mov     al, CMD_PS1; + CMD_RD2 + CMD_STP
  932.         out     dx, al
  933.  
  934.         set_io  [ebx + device.io_addr], P1_PAR0
  935.         mov     esi, esp
  936.         mov     cx, 6
  937.  @@:
  938.         lodsb
  939.         out     dx, al
  940.         inc     dx
  941.         loopw   @r
  942.  
  943.         add     esp, 6
  944.  
  945. ; Notice this procedure does not ret, but continues to read_mac instead.
  946.  
  947. ;;;;;;;;;;;;;;;;;;;;;;
  948. ;;                  ;;
  949. ;; Read MAC address ;;
  950. ;;                  ;;
  951. ;;;;;;;;;;;;;;;;;;;;;;
  952.  
  953. read_mac:
  954.  
  955.         DEBUGF  1, "Reading MAC\n"
  956.  
  957.         xor     esi, esi
  958.         mov     cx, 16
  959.         sub     esp, 16
  960.         mov     edi, esp
  961.         call    PIO_read
  962.  
  963.         mov     esi, esp
  964.         add     esp, 16
  965.         lea     edi, [ebx + device.mac]
  966.         mov     ecx, 6
  967.   .loop:
  968.         movsb
  969.         test    [ebx + device.flags], FLAG_16BIT
  970.         jz      .8bit
  971.         inc     esi
  972.   .8bit:
  973.         loop    .loop
  974.         DEBUGF  1, "MAC=%x-%x-%x-%x-%x-%x\n",\
  975.         [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
  976.  
  977.         ret
  978.  
  979.  
  980. ;***************************************************************************
  981. ;
  982. ;   PIO_read
  983. ;
  984. ;   Description
  985. ;       Read a frame from the ethernet card via Programmed I/O
  986. ;      src in si
  987. ;      cnt in cx
  988. ;       dst in edi
  989. ;***************************************************************************
  990. PIO_read:
  991.  
  992.         DEBUGF  1, "PIO Read from %x to %x, %u bytes ", si, edi, cx
  993.  
  994. ; stop DMA + start
  995.         set_io  [ebx + device.io_addr], 0
  996. ;        set_io  [ebx + device.io_addr], P0_COMMAND
  997.         mov     al, CMD_RD2 + CMD_STA
  998.         out     dx, al
  999.  
  1000. ; Request confirmation of end of DMA transfer
  1001.         set_io  [ebx + device.io_addr], P0_ISR
  1002.         mov     al, ISR_RDC
  1003.         out     dx, al
  1004.  
  1005. ; set length of data we're interested in
  1006.         set_io  [ebx + device.io_addr], P0_RBCR0
  1007.         mov     al, cl
  1008.         out     dx, al
  1009.         set_io  [ebx + device.io_addr], P0_RBCR1
  1010.         mov     al, ch
  1011.         out     dx, al
  1012.  
  1013. ; set offset of what we want to read
  1014.         set_io  [ebx + device.io_addr], P0_RSAR0
  1015.         mov     ax, si
  1016.         out     dx, al
  1017.         set_io  [ebx + device.io_addr], P0_RSAR1
  1018.         shr     ax, 8
  1019.         out     dx, al
  1020.  
  1021. ; start DMA read
  1022.         set_io  [ebx + device.io_addr], P0_COMMAND
  1023.         mov     al, CMD_RD0 + CMD_STA
  1024.         out     dx, al
  1025.  
  1026.         set_io  [ebx + device.io_addr], NE_ASIC
  1027.         test    [ebx + device.flags], FLAG_16BIT
  1028.         jz      .8bits
  1029.         DEBUGF  1, "(16-bit mode)\n"
  1030.         shr     cx, 1   ; note that if the number was odd, carry flag will be set
  1031.         pushf
  1032.   .16bits:
  1033.         in      ax, dx
  1034.         stosw
  1035.         loopw   .16bits
  1036.         popf
  1037.         jnc     wait_dma_done
  1038.         in      al, dx
  1039.         stosb
  1040.         jmp     wait_dma_done
  1041.  
  1042.   .8bits:
  1043.         DEBUGF  1, "(8-bit mode)\n"
  1044.   .8bits_:
  1045.         in      al, dx
  1046.         stosb
  1047.         loopw   .8bits_
  1048.         jmp     wait_dma_done
  1049.  
  1050.  
  1051.  
  1052.  
  1053. ;***************************************************************************
  1054. ;
  1055. ;   PIO_write
  1056. ;
  1057. ;   Description
  1058. ;       writes a frame to the ethernet card via Programmed I/O
  1059. ;      dst in di
  1060. ;      cnt in cx
  1061. ;       src in esi
  1062. ;***************************************************************************
  1063. PIO_write:
  1064.  
  1065.         DEBUGF  1, "Eth PIO Write from %x to %x, %u bytes ", esi, di, cx
  1066.  
  1067. ; Stop DMA + start
  1068.         set_io  [ebx + device.io_addr], 0
  1069. ;        set_io  [ebx + device.io_addr], P0_COMMAND
  1070.         mov     al, CMD_RD2 + CMD_STA
  1071.         out     dx, al
  1072.  
  1073. ; Request confirmation of end of DMA transfer
  1074.         set_io  [ebx + device.io_addr], P0_ISR
  1075.         mov     al, ISR_RDC
  1076.         out     dx, al
  1077.  
  1078. ; Program number of bytes we want to write
  1079.         set_io  [ebx + device.io_addr], P0_RBCR0
  1080.         mov     al, cl
  1081.         out     dx, al
  1082.         set_io  [ebx + device.io_addr], P0_RBCR1
  1083.         mov     al, ch
  1084.         out     dx, al
  1085.  
  1086. ; Program where we want to write
  1087.         mov     ax, di
  1088.         set_io  [ebx + device.io_addr], P0_RSAR0
  1089.         out     dx, al
  1090.         shr     ax, 8
  1091.         set_io  [ebx + device.io_addr], P0_RSAR1
  1092.         out     dx, al
  1093.  
  1094. ; Set the DMA to write
  1095.         set_io  [ebx + device.io_addr], P0_COMMAND
  1096.         mov     al, CMD_RD1 + CMD_STA
  1097.         out     dx, al
  1098.  
  1099.         set_io  [ebx + device.io_addr], NE_ASIC
  1100.         test    [ebx + device.flags], FLAG_16BIT
  1101.         jz      .8_bit
  1102.         DEBUGF  1, "(16-bit mode)\n"
  1103.         shr     cx, 1   ; note that if the number was odd, carry flag will be set
  1104.         pushf           ; save the flags for later
  1105.   .16bit:
  1106.         lodsw
  1107.         out     dx, ax
  1108.         loopw   .16bit
  1109.         popf
  1110.         jnc     wait_dma_done
  1111.         lodsb
  1112.         out     dx, al
  1113.         jmp     wait_dma_done
  1114.  
  1115.   .8_bit:
  1116.         DEBUGF  1, "(8-bit mode)\n"
  1117.   .8_bit_:
  1118.         lodsb
  1119.         out     dx, al
  1120.         loopw   .8_bit_
  1121.         jmp     wait_dma_done
  1122.  
  1123.  
  1124.  
  1125. wait_dma_done:
  1126.  
  1127.         set_io  [ebx + device.io_addr], 0
  1128.         set_io  [ebx + device.io_addr], P0_ISR
  1129.   .dmawait:
  1130.         in      al, dx
  1131.         test    al, ISR_RDC             ; Remote DMA Complete
  1132.         jz      .dmawait
  1133. ;        and     al, not ISR_RDC
  1134. ;        out     dx, al                  ; clear the bit
  1135.  
  1136.         ret
  1137.  
  1138.  
  1139.  
  1140. ; End of code
  1141.  
  1142.  
  1143. data fixups
  1144. end data
  1145.  
  1146. include '../peimport.inc'
  1147.  
  1148. my_service      db 'RTL8029', 0                 ; max 16 chars include zero
  1149.  
  1150. ;sz_8029         db 'Realtek 8029', 0
  1151. ;sz_8019         db 'Realtek 8019', 0
  1152. ;sz_8019as       db 'Realtek 8019AS', 0
  1153. ;sz_ne2k         db 'ne2000', 0
  1154. ;sz_dp8390       db 'DP8390', 0
  1155.  
  1156. include_debug_strings                           ; All data wich FDO uses will be included here
  1157.  
  1158. align 4
  1159. devices       dd 0
  1160. device_list   rd MAX_DEVICES                    ; This list contains all pointers to device structures the driver is handling
  1161.  
  1162.  
  1163.  
  1164.  
  1165.  
  1166.