Subversion Repositories Kolibri OS

Rev

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