Subversion Repositories Kolibri OS

Rev

Rev 1257 | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  ETHERNET.INC                                                   ;;
  7. ;;                                                                 ;;
  8. ;;  Ethernet network layer for KolibriOS                           ;;
  9. ;;                                                                 ;;
  10. ;;    Written by hidnplayr@kolibrios.org                           ;;
  11. ;;                                                                 ;;
  12. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  13. ;;             Version 2, June 1991                                ;;
  14. ;;                                                                 ;;
  15. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  16.  
  17. $Revision: 1259 $
  18.  
  19. MAX_ETH_DEVICES         equ MAX_NET_DEVICES
  20. ETH_QUEUE_SIZE          equ 16
  21.  
  22. struct  ETH_FRAME
  23.         .DstMAC         dp  ?  ; destination MAC-address [6 bytes]
  24.         .SrcMAC         dp  ?  ; source MAC-address [6 bytes]
  25.         .Type           dw  ?  ; type of the upper-layer protocol [2 bytes]
  26.         .Data:                 ; data [46-1500 bytes]
  27. ends
  28.  
  29. struct  ETH_DEVICE
  30.         .unload         dd ?
  31.         .reset          dd ?
  32.         .transmit       dd ?
  33.         .set_MAC        dd ?
  34.         .get_MAC        dd ?
  35.         .set_mode       dd ?
  36.         .get_mode       dd ?
  37.  
  38.         .bytes_tx       dq ?
  39.         .bytes_rx       dq ?
  40.         .packets_tx     dd ?
  41.         .packets_rx     dd ?
  42.         .mode           dd ?  ; This dword contains cable status (10mbit/100mbit, full/half duplex, auto negotiation or not,..)
  43.         .name           dd ?
  44.         .mac            dp ?
  45. ends                          ; the rest of the device struct depends on the type of device
  46.  
  47.  
  48. align 4
  49. iglobal
  50.  
  51.         ETH_BROADCAST   dp  0xffffffffffff
  52. endg
  53.  
  54. align 4
  55. uglobal
  56.  
  57.         ETH_RUNNING     dd  ?
  58.         ETH_DRV_LIST    rd  MAX_ETH_DEVICES
  59.         ETH_IN_QUEUE    rd  3*ETH_QUEUE_SIZE+3
  60. if QUEUE_BEFORE_SENDING
  61.         ETH_OUT_QUEUE   rd  3*ETH_QUEUE_SIZE+3
  62. end if
  63. endg
  64.  
  65.  
  66. ;-----------------------------------------------------------------
  67. ;
  68. ; ETH_init
  69. ;
  70. ;  This function resets all ethernet variables
  71. ;
  72. ;  IN:  /
  73. ;  OUT: /
  74. ;
  75. ;-----------------------------------------------------------------
  76. align 4
  77. ETH_init:
  78.  
  79.         xor     eax, eax
  80.         mov     edi, ETH_RUNNING
  81.         mov     ecx, (1+MAX_ETH_DEVICES)
  82.         rep     stosd
  83.  
  84.         init_queue ETH_IN_QUEUE
  85.  
  86. if QUEUE_BEFORE_SENDING
  87.         init_queue ETH_OUT_QUEUE
  88. end if
  89.  
  90.         ret
  91.  
  92.  
  93. ;-----------------------------------------------------------------
  94. ;
  95. ; ETH_Add_Device:
  96. ;
  97. ;  This function is called by ethernet drivers,
  98. ;  to register each running ethernet device to the kernel
  99. ;
  100. ;  IN:  Pointer to device structure in ebx
  101. ;  OUT: Device num in eax, -1 on error
  102. ;
  103. ;-----------------------------------------------------------------
  104. align 4
  105. ETH_add_device:
  106.  
  107.         DEBUGF  1,"ETH_Add_Device: %x ", ebx
  108.  
  109.         mov     eax, [ETH_RUNNING]
  110.         cmp     eax, MAX_ETH_DEVICES
  111.         jge     .error
  112.  
  113.         test    eax, eax
  114.         jnz     .notfirst
  115.         mov     dword [ETH_IN_QUEUE], eax
  116. if QUEUE_BEFORE_SENDING
  117.         mov     dword [ETH_OUT_QUEUE], eax
  118. end if
  119.       .notfirst:
  120.  
  121.         mov     eax, ebx
  122.         mov     ecx, MAX_ETH_DEVICES      ; We need to check whole list because a device may be removed without re-organizing list
  123.         mov     edi, ETH_DRV_LIST
  124.  
  125.         repne   scasd                     ; See if device is already in the list
  126.         jz      .error
  127.  
  128.         xor     eax, eax
  129.         mov     ecx, MAX_ETH_DEVICES
  130.         mov     edi, ETH_DRV_LIST
  131.  
  132.         repne   scasd                     ; Find empty spot in the list
  133.         jnz     .error
  134.  
  135.         sub     edi, 4
  136.         mov     [edi], ebx                ; add device to list
  137.  
  138.         sub     edi, ETH_DRV_LIST         ; edi = 4*device num       Calculate device number in eax
  139.         mov     eax, edi                  ; edx = 4*device num
  140.         shr     eax, 2
  141.  
  142.         inc     [ETH_RUNNING]             ; Indicate that one more ethernet device is up and running
  143.  
  144.         DEBUGF  1,"- succes: %u\n",eax
  145.         ret
  146.  
  147.        .error:
  148.         or      eax, -1
  149.         DEBUGF  1,"- fail\n"
  150.         ret
  151.  
  152.  
  153.  
  154.  
  155. ;-----------------------------------------------------------------
  156. ;
  157. ; ETH_Remove_Device:
  158. ;
  159. ;  This function is called by ethernet drivers,
  160. ;  to unregister ethernet devices from the kernel
  161. ;
  162. ;  IN:  Pointer to device structure in ebx
  163. ;  OUT: eax: -1 on error
  164. ;
  165. ;-----------------------------------------------------------------
  166. align 4
  167. ETH_remove_device:
  168.  
  169.         cmp     [ETH_RUNNING], 0
  170.         je      .error
  171.  
  172.         mov     eax, ebx
  173.         mov     ecx, MAX_ETH_DEVICES
  174.         mov     edi, ETH_DRV_LIST
  175.  
  176.         repne   scasd
  177.         jnz     .error
  178.  
  179.         xor     eax, eax
  180.         mov     dword [edi-4], eax
  181.  
  182.         dec     [ETH_RUNNING]
  183.         jnz     .notlast
  184.  
  185.         mov     dword [ETH_IN_QUEUE], ETH_QUEUE_SIZE
  186. if QUEUE_BEFORE_SENDING
  187.         mov     dword [ETH_OUT_QUEUE], ETH_QUEUE_SIZE
  188. end if
  189.  
  190.   .notlast:
  191.         ret
  192.  
  193.   .error:
  194.         or      eax, -1
  195.         ret
  196.  
  197.  
  198.  
  199. ;-----------------------------------------------------------------
  200. ;
  201. ; ETH_Receiver:
  202. ;
  203. ;  This function is called by ethernet drivers,
  204. ;  It pushes the received ethernet packets onto the eth_in_queue
  205. ;
  206. ;  IN:  [esp]   = Pointer to buffer
  207. ;       [esp-4] = size of buffer
  208. ;       ebx     = pointer to eth_device
  209. ;  OUT: /
  210. ;
  211. ;-----------------------------------------------------------------
  212. align 4
  213. ETH_receiver:
  214.  
  215.         DEBUGF  1,"ETH_Receiver: "
  216.         push    ebx
  217.         mov     esi, esp
  218.         add_to_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .fail
  219.         DEBUGF  1,"Queued packet successfully\n"
  220.         add     esp, 4*3
  221.  
  222.         ret
  223.  
  224.   .fail:
  225.         DEBUGF  1,"ETH_IN_QUEUE is full!\n"
  226.         add     esp, 4
  227.         call    kernel_free
  228.         add     esp, 4
  229.  
  230.         ret
  231.  
  232.  
  233.  
  234. ;-----------------------------------------------------------------
  235. ;
  236. ; ETH_Handler:
  237. ;
  238. ;  Handles all queued eth packets (called from kernel's main_loop)
  239. ;
  240. ;  IN:  /
  241. ;  OUT: /
  242. ;
  243. ;-----------------------------------------------------------------
  244. align 4
  245. ETH_handler:
  246.  
  247.         get_from_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .gohome
  248.  
  249.         push    ETH_handler
  250.  
  251.         lodsd
  252.         mov     ebx, eax
  253.         lodsd
  254.         mov     ecx, eax
  255.         lodsd
  256.         xchg    eax, ecx
  257.         push    ecx
  258.         push    eax
  259.  
  260.         DEBUGF  1,"ETH_Handler - size: %u\n", ecx
  261.         cmp     ecx, 60    ; check packet length
  262.         jl      .dump
  263.         sub     ecx, ETH_FRAME.Data
  264.  
  265.         lea     edx, [eax + ETH_FRAME.Data]
  266.         mov     ax , [eax + ETH_FRAME.Type]
  267.  
  268.         cmp     ax, ETHER_IPv4
  269.         je      IPv4_handler
  270.  
  271.         cmp     ax, ETHER_ARP
  272.         je      ARP_handler
  273.  
  274.         DEBUGF  1,"Unknown ethernet packet type %x\n", ax
  275.  
  276.   .dump:
  277.         DEBUGF  1,"Dumping packet\n"
  278.         call    kernel_free
  279.         add     esp, 4
  280.  
  281.   .gohome:
  282.         ret                             ; return to get more from queue / to caller
  283.  
  284.  
  285.  
  286. ;-----------------------------------------------------------------
  287. ;
  288. ; ETH_sender:
  289. ;
  290. ;  This function sends an ethernet packet to the correct driver.
  291. ;
  292. ;  IN:  Pointer to buffer in [esp]
  293. ;       size of buffer in [esp+4]
  294. ;       pointer to device struct in ebx
  295. ;  OUT: /
  296. ;
  297. ;-----------------------------------------------------------------
  298. align 4
  299. ETH_sender:
  300. if QUEUE_BEFORE_SENDING
  301.         DEBUGF  1,"ETH_Sender: queuing for device: %x, %u bytes\n", [esp], [esp + 4]
  302.  
  303.         push    ebx
  304.         mov     esi, esp
  305.         add_to_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .fail
  306.         DEBUGF  1,"Queued packet successfully\n"
  307.         add     esp, 3*4
  308.  
  309.         ret
  310.  
  311.   .fail:
  312.         DEBUGF  1,"ETH_OUT_QUEUE is full!\n"
  313.         add     esp, 4
  314.         call    kernel_free
  315.         add     esp, 4
  316.  
  317.         ret
  318.  
  319.  
  320.  
  321. ;-----------------------------------------------------------------
  322. ;
  323. ; ETH_send_queued:
  324. ;
  325. ;  IN:  /
  326. ;  OUT: /
  327. ;
  328. ;-----------------------------------------------------------------
  329. align 4
  330. ETH_send_queued:
  331.  
  332.         get_from_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .gohome
  333.  
  334.         push    ETH_send_queued                 ; this will cause the procedure to check for more packets
  335.                                                 ; when a single packet is handled
  336.  
  337.         mov     ebx, [esi]
  338.         pushd   [esi + 8]
  339.         pushd   [esi + 4]
  340.  
  341.         DEBUGF  1,"dequeued packet for device %x\n", ebx
  342. end if
  343.         call    [ebx+ETH_DEVICE.transmit]       ; we will return to get_from_queue macro after transmitting packet
  344.         call    kernel_free
  345.         add     esp, 4 ; pop (balance stack)
  346.  
  347.   .gohome:
  348.         ret
  349.  
  350.  
  351. ;-----------------------------------------------------------------
  352. ;
  353. ; ETH_struc2dev
  354. ;
  355. ; IN: pointer to device struct in ebx
  356. ;
  357. ; OUT: edi is -1 on error, device number otherwise
  358. ;
  359. ;-----------------------------------------------------------------
  360. align 4
  361. ETH_struc2dev:
  362.         push    eax ecx
  363.  
  364.         mov     eax, ebx
  365.         mov     ecx, MAX_ETH_DEVICES
  366.         mov     edi, ETH_DRV_LIST
  367.  
  368.         repne   scasd
  369.         jnz     .error
  370.  
  371.         sub     edi, ETH_DRV_LIST+4
  372.         shr     edi, 2
  373.  
  374.         pop     ecx eax
  375.         ret
  376.   .error:
  377.         or      edi, -1
  378.         pop     ecx eax
  379.  
  380.         ret
  381.  
  382.  
  383. ;-----------------------------------------------------------------
  384. ;
  385. ; ETH_create_packet
  386. ;
  387. ; IN: pointer to source mac in eax
  388. ;     pointer to destination mac in ebx
  389. ;     packet size in ecx
  390. ;     device number in edx
  391. ;     protocol in di
  392. ;
  393. ; OUT: edi is -1 on error, pointer to buffer otherwise
  394. ;      eax points to buffer start
  395. ;      ebx is pointer to device structure
  396. ;      ecx is unchanged (packet size of embedded data)
  397. ;      edx is size of complete buffer
  398. ;      esi points to procedure wich needs to be called to send packet
  399. ;
  400. ;-----------------------------------------------------------------
  401. align 4
  402. ETH_create_packet:
  403.  
  404.         DEBUGF 1,"Creating Ethernet Packet (size=%u): \n", ecx
  405.  
  406.         cmp     ecx, 1500
  407.         jg      .exit
  408.  
  409.         push    ecx di eax ebx edx
  410.  
  411.         add     ecx, ETH_FRAME.Data
  412.         push    ecx
  413.         push    ecx
  414.         call    kernel_alloc
  415.         test    eax, eax
  416.         jz      .pop_exit
  417.  
  418.         pop     ecx
  419.         pop     edx
  420.  
  421.         mov     edi, eax
  422.         pop     esi
  423.         movsd
  424.         movsw
  425.         pop     esi
  426.         movsd
  427.         movsw
  428.         pop     ax
  429.         stosw
  430.  
  431.         lea     eax, [edi - ETH_FRAME.Data]  ; Set eax to buffer start
  432.         mov     edx, ecx                     ; Set ebx to complete buffer size
  433.         pop     ecx
  434.         mov     esi, ETH_sender
  435.  
  436.         xor     ebx, ebx                        ;;;; TODO: Fixme
  437.         mov     ebx, [ETH_DRV_LIST + ebx]
  438.  
  439.         cmp     edx, 46 + ETH_FRAME.Data    ; If data size is less then 46, add padding bytes
  440.         jg      .continue
  441.         mov     edx, 46 + ETH_FRAME.Data
  442.        .continue:
  443.  
  444.         DEBUGF 1,"done: %x size:%u device:%x\n", eax, edx, ebx
  445.         ret
  446.  
  447.   .pop_exit:
  448.         DEBUGF 1,"Out of ram space!!\n"
  449.         add     esp, 18
  450.         or      edi,-1
  451.         ret
  452.  
  453.   .exit:
  454.         DEBUGF 1,"Packet too large!\n"
  455.         or      edi, -1
  456.         ret
  457.  
  458.  
  459.  
  460. ;-----------------------------------------------------------------
  461. ;
  462. ; ETH_API
  463. ;
  464. ; This function is called by system function 75
  465. ;
  466. ; IN:  subfunction number in bl
  467. ;      device number in bh
  468. ;      ecx, edx, .. depends on subfunction
  469. ;
  470. ; OUT:
  471. ;
  472. ;-----------------------------------------------------------------
  473. align 4
  474. ETH_API:
  475.  
  476.         movzx   eax, bh
  477.         shl     eax, 2
  478.  
  479.         test    bl, bl
  480.         jz      .packets_tx     ; 0
  481.         dec     bl
  482.         jz      .packets_rx     ; 1
  483.         dec     bl
  484.         jz      .bytes_tx       ; 2
  485.         dec     bl
  486.         jz      .bytes_rx       ; 3
  487.         dec     bl
  488.         jz      .read_mac       ; 4
  489.         dec     bl
  490.         jz      .write_mac      ; 5
  491.         dec     bl
  492.         jz      .in_queue       ; 6
  493.         dec     bl
  494.         jz      .out_queue      ; 7
  495.  
  496. .error:
  497.         mov     eax, -1
  498.         ret
  499.  
  500. .packets_tx:
  501.         add     eax, ETH_DRV_LIST
  502.         mov     eax, dword [eax]
  503.         mov     eax, dword [eax + ETH_DEVICE.packets_tx]
  504.  
  505.         ret
  506.  
  507. .packets_rx:
  508.         add     eax, ETH_DRV_LIST
  509.         mov     eax, dword [eax]
  510.         mov     eax, dword [eax + ETH_DEVICE.packets_rx]
  511.         ret
  512.  
  513. .bytes_tx:
  514.         add     eax, ETH_DRV_LIST
  515.         mov     eax, dword [eax]
  516.         mov     ebx, dword [eax + ETH_DEVICE.bytes_tx + 4]
  517.         mov     eax, dword [eax + ETH_DEVICE.bytes_tx]
  518.         mov     [esp+20+4], ebx                         ; TODO: fix this ugly code
  519.         ret
  520.  
  521. .bytes_rx:
  522.         add     eax, ETH_DRV_LIST
  523.         mov     eax, dword [eax]
  524.         mov     ebx, dword [eax + ETH_DEVICE.bytes_rx + 4]
  525.         mov     eax, dword [eax + ETH_DEVICE.bytes_rx]
  526.         mov     [esp+20+4], ebx                         ; TODO: fix this ugly code
  527.         ret
  528.  
  529.  
  530. .read_mac:
  531.         add     eax, ETH_DRV_LIST
  532.         mov     eax, [eax]
  533. ;        push    eax
  534. ;        call    dword [eax + ETH_DEVICE.get_MAC]
  535. ;        pop     eax
  536.         movzx   ebx, word [eax + ETH_DEVICE.mac]
  537.         mov     eax, dword [eax + ETH_DEVICE.mac + 2]
  538.         mov     [esp+20+4], ebx                         ; TODO: fix this ugly code
  539.         ret
  540.  
  541. .write_mac:
  542.         push    ecx
  543.         push    dx
  544.         add     eax, ETH_DRV_LIST
  545.         mov     eax, [eax]
  546.         mov     eax, dword [eax + ETH_DEVICE.set_MAC]
  547.         call    eax
  548.         ret
  549.  
  550. .in_queue:
  551.         add     eax, ETH_IN_QUEUE
  552.         mov     eax, [eax + queue.size]
  553.         ret
  554.  
  555. .out_queue:
  556. if QUEUE_BEFORE_SENDING
  557.         add     eax, ETH_OUT_QUEUE
  558.         mov     eax, [eax + queue.size]
  559. else
  560.         mov     eax, -1
  561. end if
  562.         ret