Subversion Repositories Kolibri OS

Rev

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