Subversion Repositories Kolibri OS

Rev

Rev 5866 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2020. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;  PCMCIA aka cardbus driver for KolibriOS                     ;;
  7. ;;  Written by hidnplayr@gmail.com                              ;;
  8. ;;                                                              ;;
  9. ;;  Many credits go to Paolo Franchetti for his HWTEST program  ;;
  10. ;;  (https://sites.google.com/site/pfranz73/) from which large  ;;
  11. ;;  parts of code have been borrowed.                           ;;
  12. ;;                                                              ;;
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14.  
  15. ; This module detects and initialises all Cardbus/pc-card/PCMCIA cards.
  16.  
  17. ; WARNING: Cards must be inserted before the driver starts, and shouldn't be removed.
  18. ; This module doesn't handle insertions and removals.
  19.  
  20. ; TODO:
  21. ;
  22. ; Use GetPCIList instead of reading directly from PCI bus to detect bridge.
  23. ; (See #5544 agp.asm for example).
  24. ; Export a function in kernel to re-scan PCI device list (fix 'dirty hack').
  25. ; Fix bugs (currently not working on all PCMCIA bridges).
  26.  
  27. format PE DLL native
  28. entry START
  29.  
  30.         CURRENT_API             = 0x0200
  31.         COMPATIBLE_API          = 0x0100
  32.         API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
  33.  
  34.         CARDBUS_IO_BASE         = 0x1400
  35.         CARDBUS_IO_SIZE         = 0x100
  36.         CARDBUS_IRQ             = 0x0A
  37.  
  38.         __DEBUG__               = 1
  39.         __DEBUG_LEVEL__         = 1
  40.  
  41. section '.flat' readable writable executable
  42.  
  43. include '../proc32.inc'
  44. include '../struct.inc'
  45. include '../macros.inc'
  46. include '../pci.inc'
  47. include '../fdo.inc'
  48.  
  49. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  50. ;;                        ;;
  51. ;; proc START             ;;
  52. ;;                        ;;
  53. ;; (standard driver proc) ;;
  54. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  55.  
  56. proc START c, reason:dword, cmdline:dword
  57.  
  58.         cmp     [reason], DRV_ENTRY
  59.         jne     .fail
  60.  
  61.         DEBUGF  1, "Loading cardbus driver\n"
  62.         invoke  RegService, my_service, service_proc
  63.  
  64.         call    detect
  65.  
  66.         ret
  67.  
  68.   .fail:
  69.         xor     eax, eax
  70.         ret
  71.  
  72. endp
  73.  
  74.  
  75.  
  76. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  77. ;;                        ;;
  78. ;; proc SERVICE_PROC      ;;
  79. ;;                        ;;
  80. ;; (standard driver proc) ;;
  81. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  82.  
  83. proc service_proc stdcall, ioctl:dword
  84.  
  85.         mov     edx, [ioctl]
  86.         mov     eax, [edx + IOCTL.io_code]
  87.  
  88. ;------------------------------------------------------
  89.  
  90.         cmp     eax, 0 ;SRV_GETVERSION
  91.         jne     .fail
  92.  
  93.         cmp     [edx + IOCTL.out_size], 4
  94.         jb      .fail
  95.         mov     eax, [edx + IOCTL.output]
  96.         mov     [eax], dword API_VERSION
  97.  
  98.         xor     eax, eax
  99.         ret
  100.  
  101.   .fail:
  102.         or      eax, -1
  103.         ret
  104.  
  105. endp
  106.  
  107. align 4
  108. proc detect
  109.  
  110.            locals
  111.              last_bus dd ?
  112.              card_bus dd ?
  113.              bus      dd ?
  114.              devfn    dd ?
  115.            endl
  116.  
  117.         DEBUGF  1, "Searching for cardbus bridges...\n"
  118.  
  119.         xor     eax, eax
  120.         mov     [bus], eax
  121.         inc     eax
  122.         invoke  PciApi
  123.         cmp     eax, -1
  124.         je      .err
  125.         mov     [last_bus], eax
  126.  
  127.         inc     eax
  128.         mov     [card_bus], eax
  129.  
  130.   .next_bus:
  131.         and     [devfn], 0
  132.   .next_dev:
  133.         invoke  PciRead32, [bus], [devfn], PCI_header.vendor_id
  134.         test    eax, eax
  135.         jz      .next
  136.         cmp     eax, -1
  137.         je      .next
  138.  
  139.         invoke  PciRead16, [bus], [devfn], PCI_header.subclass  ; class & subclass
  140.         cmp     ax, 0x0607
  141.         je      .found
  142.  
  143.   .next:
  144.         test    [devfn], 7
  145.         jnz     .next_fn
  146.         invoke  PciRead8, [bus], [devfn], PCI_header.header_type
  147.         test    al, al
  148.         js      .next_fn
  149.         or      [devfn], 7
  150.  
  151.   .next_fn:
  152.         inc     [devfn]
  153.         cmp     [devfn], 256
  154.         jb      .next_dev
  155.         mov     eax, [bus]
  156.         inc     eax
  157.         mov     [bus], eax
  158.         cmp     eax, [last_bus]
  159.         jna     .next_bus
  160.  
  161.         DEBUGF  1, "Search complete\n"
  162.         xor     eax, eax
  163.         inc     eax
  164.         ret
  165.  
  166.   .found:
  167.         DEBUGF  1, "Found cardbus bridge: bus=0x%x, dev=0x%x\n", [bus], [devfn]
  168.  
  169.         invoke  PciRead8, [bus], [devfn], PCI_header.header_type
  170.         and     al, not 0x80                                            ; Mask the multifunction device bit
  171.         DEBUGF  1, "Header type=0x%x\n", eax:2
  172.         cmp     al, 2
  173.         jne     .next
  174.  
  175. ; Write PCI and cardbus numbers
  176.  
  177.         invoke  PciRead32, [bus], [devfn], PCI_header02.pci_bus_nr      ; PCcard latency settings + Card bus number, PCI bus number
  178.         and     eax, 0xff000000                                         ; Keep original latency setting, clear the rest
  179.         mov     al, byte[bus]
  180.         mov     ah, byte[card_bus]
  181.         mov     ebx, [card_bus]         ; sub bus nr???
  182.         shl     ebx, 16
  183.         or      eax, ebx
  184.         DEBUGF  1, "Latency, bus,.. 0x%x\n", eax
  185.         invoke  PciWrite32, [bus], [devfn], PCI_header02.pci_bus_nr, eax
  186.  
  187. ; set ExCA legacy mode base
  188.  
  189.         invoke  PciWrite32, [bus], [devfn], 0x44, 1
  190.  
  191. ; Enable power
  192.  
  193.         invoke  PciRead8, [bus], [devfn], 0x14                  ; get capabilities offset
  194.         movzx   eax, al                                         ; (A0 for TI bridges)
  195.         DEBUGF  1, "Capabilities offset=0x%x\n", eax:2
  196.         add     al, 4                                           ; Power management control/status
  197.         invoke  PciWrite16, [bus], [devfn], eax, 0x0100         ; Enable PME signaling, power state=D0
  198.  
  199. ; Enable Bus master, io space, memory space
  200.  
  201.         invoke  PciWrite16, [bus], [devfn], PCI_header02.command, 0x0007
  202.  
  203. ; Write CardBus Socket/ExCA base address
  204.  
  205.         mov     eax, 0x7f000000
  206.         push    eax
  207.         invoke  PciWrite32, [bus], [devfn], PCI_header02.base_addr, eax ; base is 4 Kbyte aligned
  208.         pop     ebx
  209.         invoke  MapIoMem, ebx, 4096, PG_SW+PG_NOCACHE
  210.         mov     ecx, eax
  211.  
  212. ; Check if a card is present in the socket
  213.  
  214.         mov     eax, [ecx + 8]                                  ; Socket present state register
  215.         DEBUGF  1, "Socket present state reg: 0x%x\n", eax
  216.         and     al, 10110110b                                   ; NotACard | CBCard | 16bitCard | CDetect1 | CDetect2
  217.         cmp     al, 00100000b                                   ; Check for inserted cardbus card
  218.         je      .CardbusInserted
  219.  
  220. ; No card found... set PCI command back to 0
  221.  
  222.         invoke  PciWrite16, [bus], [devfn], PCI_header02.command, 0  ; To avoid conflicts with other sockets
  223.         DEBUGF  1, "Cardbus KO\n"
  224.         jmp     .next
  225.  
  226.   .CardbusInserted:
  227.         DEBUGF  1, "Card inserted\n"
  228.         ;mov     word[ecx + 0x802], 0x00F9       ; Assert reset, output enable, vcc=vpp=3.3V
  229.         mov     dword[ecx + 0x10], 0x33         ; Request 3.3V for Vcc and Vpp (Control register)
  230.         ;push    ecx
  231.         ;mov     esi, 1
  232.         ;invoke  Sleep
  233.         ;pop     ecx
  234.         ;mov     byte[ecx + 0x803], 0x40         ; stop reset
  235.         mov     dword[ecx + 0xC], 0x4000        ; force Card CV test (Force register)   ;;; WHY???
  236.         DEBUGF  1, "Resetting card\n"
  237.  
  238. ; Next power up test can be deferred until before writing to Bridge control PCI reg 0x3E
  239.   .waitpower:                                   ; For TI, you can check that bits 8-11 in PCI reg 80h are all 0
  240.         test    dword[ecx + 8], 1 shl 3         ; Test PWRCYCLE bit
  241.         jz      .waitpower                      ; Wait for power to go up
  242.  
  243.         DEBUGF  1, "Interface is powered up\n"
  244.  
  245. ; Write MemBase-Limit 0 and 1, then IOBase-Limit 0 and 1
  246. ; mem0 space limit = base => size is 4 kilobytes
  247. ; set to 0 the second interval (mem1 and IO1)
  248. ; IO0: size is 256 bytes
  249.  
  250.         invoke  PciWrite32, [bus], [devfn], PCI_header02.mbar_0, 0x7EFFF000
  251.         invoke  PciWrite32, [bus], [devfn], PCI_header02.mlimit_0, 0x7EFFF000
  252.         invoke  PciWrite32, [bus], [devfn], PCI_header02.mbar_1, 0
  253.         invoke  PciWrite32, [bus], [devfn], PCI_header02.mlimit_1, 0
  254.         invoke  PciWrite32, [bus], [devfn], PCI_header02.iobar_0, CARDBUS_IO
  255.         invoke  PciWrite32, [bus], [devfn], PCI_header02.iolimit_0, CARDBUS_IO + 0xFC
  256.         invoke  PciWrite32, [bus], [devfn], PCI_header02.iobar_1, 0
  257.         invoke  PciWrite32, [bus], [devfn], PCI_header02.iolimit_1, 0
  258.         invoke  PciWrite8, [bus], [devfn], PCI_header02.interrupt_line, CARDBUS_IRQ     ; IRQ line
  259.         invoke  PciRead16, [bus], [devfn], PCI_header02.bridge_ctrl                     ; Bridge control
  260.         or      ax, 0x0700                                      ; Enable write posting, both memory windows prefetchable
  261.         invoke  PciWrite16, [bus], [devfn], PCI_header02.bridge_ctrl, eax
  262.         DEBUGF  1, "Write posting enabled\n"
  263.  
  264.  
  265.         DEBUGF  1, "Bridge PCI registers:\n"
  266. rept    17 reg
  267. {
  268.         invoke  PciRead32, [bus], [devfn], 4*(reg-1)
  269.         DEBUGF  1, "0x%x\n", eax
  270. }
  271.  
  272.         inc     byte[0x80009021]                                ; LAST PCI bus count in kernel (dirty HACK!)
  273.  
  274.  
  275.         mov     ecx, 100
  276.   .waitactive:
  277.         push    ecx
  278.         invoke  PciRead32, [card_bus], 0, PCI_header.vendor_id         ; Check if the card is awake yet
  279.         inc     eax
  280.         jnz     .got_it
  281.         mov     esi, 2
  282.         invoke  Sleep
  283.         pop     ecx
  284.         dec     ecx
  285.         jnz     .waitactive
  286.  
  287.         DEBUGF  1, "Timeout!\n"
  288.         ; TODO: disable card/bridge again ?
  289.         jmp     .next
  290.  
  291.   .got_it:
  292.         pop     eax
  293.         DEBUGF  1, "Card is enabled!\n"
  294.  
  295.         invoke  PciWrite32, [card_bus], 0, PCI_header02.base_addr, CARDBUS_IO       ; Supposing it's IO space that is needed
  296.         invoke  PciWrite8, [card_bus], 0, PCI_header02.interrupt_line, 0xC                      ; FIXME
  297.         invoke  PciWrite16, [card_bus], 0, PCI_header02.command, PCI_CMD_PIO or PCI_CMD_MMIO
  298.  
  299.         DEBUGF  1, "done\n"
  300.  
  301.         jmp     .next
  302.  
  303.   .err:
  304.         DEBUGF  1, "Error\n"
  305.         xor     eax, eax
  306.  
  307.         ret
  308.  
  309. endp
  310.  
  311.  
  312. ; End of code
  313.  
  314. data fixups
  315. end data
  316.  
  317. include '../peimport.inc'
  318.  
  319. my_service      db 'CARDBUS',0                  ; max 16 chars include zero
  320.  
  321. include_debug_strings                           ; All data wich FDO uses will be included here