Subversion Repositories Kolibri OS

Rev

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