Subversion Repositories Kolibri OS

Rev

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