Subversion Repositories Kolibri OS

Rev

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