Subversion Repositories Kolibri OS

Rev

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

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