Subversion Repositories Kolibri OS

Rev

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

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