Subversion Repositories Kolibri OS

Rev

Rev 7251 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2021. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  Broadcom NetXtreme 57xx driver for KolibriOS                   ;;
  7. ;;                                                                 ;;
  8. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  9. ;;             Version 2, June 1991                                ;;
  10. ;;                                                                 ;;
  11. ;; Broadcom's programmers's manual for the BCM57xx                 ;;
  12. ;; http://www.broadcom.com/collateral/pg/57XX-PG105-R.pdf          ;;
  13. ;;                                                                 ;;
  14. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  15.  
  16. format PE DLL native
  17. entry START
  18.  
  19.         CURRENT_API             = 0x0200
  20.         COMPATIBLE_API          = 0x0100
  21.         API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
  22.  
  23. ; configureable area
  24.  
  25.         MAX_DEVICES             = 16
  26.  
  27.         __DEBUG__               = 1
  28.         __DEBUG_LEVEL__         = 2
  29.  
  30.         TX_RING_SIZE            = 128   ; Number of packets in send ring buffer
  31.         RX_RING_SIZE            = 128   ; Number of packets in receive ring buffer
  32.  
  33. ; end configureable area
  34.  
  35. section '.flat' readable writable executable
  36.  
  37. include '../proc32.inc'
  38. include '../struct.inc'
  39. include '../macros.inc'
  40. include '../fdo.inc'
  41. include '../netdrv.inc'
  42.  
  43. if (bsr TX_RING_SIZE)>(bsf TX_RING_SIZE)
  44.   display 'TX_RING_SIZE must be a power of two'
  45.   err
  46. end if
  47.  
  48. if (bsr RX_RING_SIZE)>(bsf RX_RING_SIZE)
  49.   display 'RX_RING_SIZE must be a power of two'
  50.   err
  51. end if
  52.  
  53. struct  device          ETH_DEVICE
  54.  
  55.         mmio_addr       dd ?
  56.         pci_bus         dd ?
  57.         pci_dev         dd ?
  58.         irq_line        db ?
  59.  
  60.         cur_tx          dd ?
  61.         last_tx         dd ?
  62.  
  63.         rb 0x100 - ($ and 0xff) ; align 256
  64.         rx_desc         rd 256/8
  65.  
  66.         rb 0x100 - ($ and 0xff) ; align 256
  67.         tx_desc         rd 256/8
  68.  
  69. ends
  70.  
  71.  
  72. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  73. ;;                        ;;
  74. ;; proc START             ;;
  75. ;;                        ;;
  76. ;; (standard driver proc) ;;
  77. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  78.  
  79. proc START c, reason:dword, cmdline:dword
  80.  
  81.         cmp     [reason], DRV_ENTRY
  82.         jne     .fail
  83.  
  84.         DEBUGF  1,"Loading driver\n"
  85.         invoke  RegService, my_service, service_proc
  86.         ret
  87.  
  88.   .fail:
  89.         xor     eax, eax
  90.         ret
  91.  
  92. endp
  93.  
  94.  
  95.  
  96. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  97. ;;                        ;;
  98. ;; proc SERVICE_PROC      ;;
  99. ;;                        ;;
  100. ;; (standard driver proc) ;;
  101. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  102.  
  103. proc service_proc stdcall, ioctl:dword
  104.  
  105.         mov     edx, [ioctl]
  106.         mov     eax, [edx + IOCTL.io_code]
  107.  
  108. ;------------------------------------------------------
  109.  
  110.         cmp     eax, 0 ;SRV_GETVERSION
  111.         jne     @F
  112.  
  113.         cmp     [edx + IOCTL.out_size], 4
  114.         jb      .fail
  115.         mov     eax, [edx + IOCTL.output]
  116.         mov     [eax], dword API_VERSION
  117.  
  118.         xor     eax, eax
  119.         ret
  120.  
  121. ;------------------------------------------------------
  122.   @@:
  123.         cmp     eax, 1 ;SRV_HOOK
  124.         jne     .fail
  125.  
  126.         cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
  127.         jb      .fail
  128.  
  129.         mov     eax, [edx + IOCTL.input]
  130.         cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
  131.         jne     .fail                                   ; other types arent supported for this card yet
  132.  
  133. ; check if the device is already listed
  134.  
  135.         mov     esi, device_list
  136.         mov     ecx, [devices]
  137.         test    ecx, ecx
  138.         jz      .firstdevice
  139.  
  140. ;        mov     eax, [edx + IOCTL.input]                      ; get the pci bus and device numbers
  141.         mov     ax, [eax+1]                             ;
  142.   .nextdevice:
  143.         mov     ebx, [esi]
  144.         cmp     al, byte [ebx + device.pci_bus]
  145.         jne     .next
  146.         cmp     ah, byte [ebx + device.pci_dev]
  147.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  148.   .next:
  149.         add     esi, 4
  150.         loop    .nextdevice
  151.  
  152.  
  153. ; This device doesnt have its own eth_device structure yet, lets create one
  154.   .firstdevice:
  155.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  156.         jae     .fail
  157.  
  158.         allocate_and_clear ebx, sizeof.device, .fail      ; Allocate the buffer for device structure
  159.  
  160. ; Fill in the direct call addresses into the struct
  161.  
  162.         mov     [ebx + device.reset], reset
  163.         mov     [ebx + device.transmit], transmit
  164.         mov     [ebx + device.unload], unload
  165.         mov     [ebx + device.name], my_service
  166.  
  167. ; save the pci bus and device numbers
  168.  
  169.         mov     eax, [edx + IOCTL.input]
  170.         movzx   ecx, byte [eax+1]
  171.         mov     [ebx + device.pci_bus], ecx
  172.         movzx   ecx, byte [eax+2]
  173.         mov     [ebx + device.pci_dev], ecx
  174.  
  175. ; Now, it's time to find the base mmio addres of the PCI device
  176.  
  177.         stdcall PCI_find_mmio, [ebx + device.pci_bus], [ebx + device.pci_dev]
  178.         test    eax, eax
  179.         jz      .destroy
  180.  
  181. ; Create virtual mapping of the physical memory
  182.  
  183.         invoke  MapIoMem, eax, 10000h, PG_SW+PG_NOCACHE
  184.         mov     [ebx + device.mmio_addr], eax
  185.  
  186. ; We've found the mmio address, find IRQ now
  187.  
  188.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
  189.         mov     [ebx + device.irq_line], al
  190.  
  191.         DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  192.         [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.mmio_addr]:8
  193.  
  194. ; Ok, the eth_device structure is ready, let's probe the device
  195.         call    probe                                                   ; this function will output in eax
  196.         test    eax, eax
  197.         jnz     .err                                                    ; If an error occured, exit
  198.  
  199.         mov     eax, [devices]                                          ; Add the device structure to our device list
  200.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  201.         inc     [devices]                                               ;
  202.  
  203.         mov     [ebx + device.type], NET_TYPE_ETH
  204.         invoke  NetRegDev
  205.  
  206.         cmp     eax, -1
  207.         je      .destroy
  208.  
  209.         ret
  210.  
  211. ; If the device was already loaded, find the device number and return it in eax
  212.  
  213.   .find_devicenum:
  214.         DEBUGF  1,"Trying to find device number of already registered device\n"
  215.         invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  216.                                                                         ; into a device number in edi
  217.         mov     eax, edi                                                ; Application wants it in eax instead
  218.         DEBUGF  1,"Kernel says: %u\n", eax
  219.         ret
  220.  
  221. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  222.  
  223.   .destroy:
  224.         ; todo: reset device into virgin state
  225.  
  226.   .err:
  227.         invoke  KernelFree, ebx
  228.  
  229.   .fail:
  230.         or      eax, -1
  231.         ret
  232.  
  233. ;------------------------------------------------------
  234. endp
  235.  
  236.  
  237. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  238. ;;                                                                        ;;
  239. ;;        Actual Hardware dependent code starts here                      ;;
  240. ;;                                                                        ;;
  241. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  242.  
  243. unload:
  244.         ; TODO: (in this particular order)
  245.         ;
  246.         ; - Stop the device
  247.         ; - Detach int handler
  248.         ; - Remove device from local list (device_list)
  249.         ; - call unregister function in kernel
  250.         ; - Remove all allocated structures and buffers the card used
  251.  
  252.         or      eax, -1
  253.  
  254. ret
  255.  
  256.  
  257.  
  258. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  259. ;;
  260. ;;  probe: enables the device (if it really is BCM57XX)
  261. ;;
  262. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  263.  
  264. probe:
  265.  
  266.         DEBUGF  1,"Probe\n"
  267.  
  268. ; Make the device a bus master
  269.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
  270.         or      al, PCI_CMD_MASTER + PCI_CMD_MMIO + PCI_CMD_PIO
  271.         invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
  272.  
  273.         ; TODO: validate the device
  274.  
  275. reset:
  276.  
  277.         DEBUGF  1,"Reset\n"
  278.  
  279.         movzx   eax, [ebx + device.irq_line]
  280.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  281.         invoke  AttachIntHandler, eax, int_handler, ebx
  282.         test    eax, eax
  283.         jnz     @f
  284.         DEBUGF  1,"\nCould not attach int handler!\n"
  285. ;        or      eax, -1
  286. ;        ret
  287.   @@:
  288.  
  289.         call    read_mac
  290.  
  291. ; Set the mtu, kernel will be able to send now
  292.         mov     [ebx + device.mtu], 1514
  293.  
  294. ; Set link state to unknown
  295.         mov     [ebx + device.state], ETH_LINK_UNKNOWN
  296.  
  297.         ret
  298.  
  299.  
  300.  
  301.  
  302. align 4
  303. read_mac:
  304.  
  305.         DEBUGF  1,"Read MAC\n"
  306.  
  307.         mov     esi, [ebx + device.mmio_addr]
  308.         lea     edi, [ebx + device.mac]
  309.         movsd
  310.         movsw
  311.  
  312.   .mac_ok:
  313.         DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
  314.         [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,[ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
  315.  
  316.         ret
  317.  
  318.  
  319. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  320. ;;                                         ;;
  321. ;; Transmit                                ;;
  322. ;;                                         ;;
  323. ;; In: pointer to device structure in ebx  ;;
  324. ;; Out: eax = 0 on success                 ;;
  325. ;;                                         ;;
  326. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  327. align 16
  328. proc transmit stdcall bufferptr, buffersize
  329.  
  330.         spin_lock_irqsave
  331.  
  332.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [buffersize]
  333.         mov     eax, [bufferptr]
  334.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  335.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  336.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  337.         [eax+13]:2,[eax+12]:2
  338.  
  339.         cmp     [buffersize], 1514
  340.         ja      .error
  341.         cmp     [buffersize], 60
  342.         jb      .error
  343.  
  344. ; Program the descriptor
  345.  
  346. ;        test   [something], STILL_BUSY?
  347. ;        jnz    .overrun
  348.  
  349. ; TODO: Program the descriptor
  350.  
  351. ; Update stats
  352.         inc     [ebx + device.packets_tx]
  353.         mov     eax, [buffersize]
  354.         add     dword[ebx + device.bytes_tx], eax
  355.         adc     dword[ebx + device.bytes_tx + 4], 0
  356.  
  357.         DEBUGF  1,"Transmit OK\n"
  358.         spin_unlock_irqrestore
  359.         xor     eax, eax
  360.         ret
  361.  
  362.   .error:
  363.         DEBUGF  2, "TX packet error\n"
  364.         inc     [ebx + device.packets_tx_err]
  365.         invoke  NetFree, [bufferptr]
  366.  
  367.         spin_unlock_irqrestore
  368.         or      eax, -1
  369.         ret
  370.  
  371.   .overrun:
  372.         DEBUGF  2, "TX overrun\n"
  373.         inc     [ebx + device.packets_tx_ovr]
  374.         invoke  NetFree, [bufferptr]
  375.  
  376.         spin_unlock_irqrestore
  377.         or      eax, -1
  378.         ret
  379.  
  380. endp
  381.  
  382.  
  383. ;;;;;;;;;;;;;;;;;;;;;;;
  384. ;;                   ;;
  385. ;; Interrupt handler ;;
  386. ;;                   ;;
  387. ;;;;;;;;;;;;;;;;;;;;;;;
  388. align 16
  389. int_handler:
  390.  
  391.         push    ebx esi edi
  392.  
  393.         mov     ebx, [esp+4*4]
  394.         DEBUGF  1,"INT for 0x%x\n", ebx
  395.  
  396. ; TODO? if we are paranoid, we can check that the value from ebx is present in the current device_list
  397.  
  398.         mov     edi, [ebx + device.mmio_addr]
  399. ;        mov     eax, [edi + REG_ICR]
  400.         test    eax, eax
  401.         jz      .nothing
  402.  
  403.         DEBUGF  1,"Status: %x ", eax
  404.  
  405. ; TODO: handle interrupts
  406.  
  407.         pop     edi esi ebx
  408.         xor     eax, eax
  409.         inc     eax
  410.  
  411.         ret
  412.  
  413.   .nothing:
  414.         pop     edi esi ebx
  415.         xor     eax, eax
  416.  
  417.         ret
  418.  
  419.  
  420.  
  421.  
  422. ; End of code
  423.  
  424. data fixups
  425. end data
  426.  
  427. include '../peimport.inc'
  428.  
  429. my_service      db 'BCM57XX',0                   ; max 16 chars include zero
  430.  
  431. include_debug_strings                           ; All data wich FDO uses will be included here
  432.  
  433. align 4
  434. devices         dd 0
  435. device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
  436.  
  437.  
  438.