Subversion Repositories Kolibri OS

Rev

Rev 5074 | Rev 5363 | 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_header.vendor_id
  125.         test    eax, eax
  126.         jz      .next
  127.         cmp     eax, -1
  128.         je      .next
  129.  
  130.         invoke  PciRead16, [bus], [devfn], PCI_header.subclass  ; class & subclass
  131.         cmp     ax, 0x0607
  132.         je      .found
  133.  
  134.   .next:
  135.         test    [devfn], 7
  136.         jnz     .next_fn
  137.         invoke  PciRead8, [bus], [devfn], PCI_header.header_type
  138.         test    al, al
  139.         js      .next_fn
  140.         or      [devfn], 7
  141.  
  142.   .next_fn:
  143.         inc     [devfn]
  144.         cmp     [devfn], 256
  145.         jb      .next_dev
  146.         mov     eax, [bus]
  147.         inc     eax
  148.         mov     [bus], eax
  149.         cmp     eax, [last_bus]
  150.         jna     .next_bus
  151.  
  152.         DEBUGF  1, "Search complete\n"
  153.         xor     eax, eax
  154.         inc     eax
  155.         ret
  156.  
  157.   .found:
  158.         DEBUGF  1, "Found cardbus bridge: bus=0x%x, dev=0x%x\n", [bus], [devfn]
  159.  
  160.         invoke  PciRead8, [bus], [devfn], PCI_header.header_type
  161.         and     al, not 0x80                                            ; Mask the multifunction device bit
  162.         DEBUGF  1, "Header type=0x%x\n", eax:2
  163.         cmp     al, 2
  164.         jne     .next
  165.  
  166. ; Write PCI and cardbus numbers
  167.  
  168.         invoke  PciRead32, [bus], [devfn], PCI_header02.pci_bus_nr      ; PCcard latency settings + Card bus number, PCI bus number
  169.         and     eax, 0xff000000                                         ; Keep original latency setting, clear the rest
  170.         mov     al, byte[bus]
  171.         mov     ah, byte[card_bus]
  172.         mov     ebx, [card_bus]
  173.         shl     ebx, 16
  174.         or      eax, ebx
  175.         DEBUGF  1, "Latency, bus,.. 0x%x\n", eax
  176.         invoke  PciWrite32, [bus], [devfn], PCI_header02.pci_bus_nr, eax
  177.  
  178. ; set ExCA legacy mode base
  179.  
  180.         invoke  PciWrite32, [bus], [devfn], 0x44, 1
  181.  
  182. ; Enable power
  183.  
  184.         invoke  PciRead8, [bus], [devfn], 0x14                  ; get capabilities offset
  185.         movzx   eax, al                                         ; (A0 for TI bridges)
  186.         DEBUGF  1, "Capabilities offset=0x%x\n", eax:2
  187.         add     al, 4                                           ; Power management control/status
  188.         invoke  PciWrite16, [bus], [devfn], eax, 0x0100         ; Enable PME signaling, power state=D0
  189.  
  190. ; Enable Bus master, io space, memory space
  191.  
  192.         invoke  PciWrite16, [bus], [devfn], PCI_header02.command, 0x0007
  193.  
  194. ; Write CardBus Socket/ExCA base address
  195.  
  196.         mov     eax, 0x7f000000
  197.         push    eax
  198.         invoke  PciWrite32, [bus], [devfn], PCI_header02.base_addr, eax ; base is 4 Kbyte aligned
  199.         pop     ebx
  200.         invoke  MapIoMem, ebx, 4096, 0x1b
  201.         mov     ecx, eax
  202.  
  203. ; Check if a card is present in the socket
  204.  
  205.         mov     eax, [ecx + 8]                                  ; Socket present state register
  206.         DEBUGF  1, "Socket present state reg: 0x%x\n", eax
  207.         and     al, 10110110b                                   ; NotACard | CBCard | 16bitCard | CDetect1 | CDetect2
  208.         cmp     al, 00100000b                                   ; Check for inserted cardbus card
  209.         je      .CardbusInserted
  210.  
  211. ; No card found... set PCI command back to 0
  212.  
  213.         invoke  PciWrite16, [bus], [devfn], PCI_header02.command, 0  ; To avoid conflicts with other sockets
  214.         DEBUGF  1, "Cardbus KO\n"
  215.         jmp     .next
  216.  
  217.   .CardbusInserted:
  218.         DEBUGF  1, "Card inserted\n"
  219.         ;mov     word[ecx + 0x802], 0x00F9       ; Assert reset, output enable, vcc=vpp=3.3V
  220.         mov     dword[ecx + 0x10], 0x33         ; Request 3.3V for Vcc and Vpp (Control register)
  221.         ;push    ecx
  222.         ;mov     esi, 10
  223.         ;invoke  Sleep
  224.         ;pop     ecx
  225.         ;mov     byte[ecx + 0x803], 0x40         ; stop reset
  226.         mov     dword[ecx + 0xC], 0x4000        ; force Card CV test (Force register)   ;;; WHY???
  227.         DEBUGF  1, "Resetting card\n"
  228.  
  229. ; Next power up test can be deferred until before writing to Bridge control PCI reg 0x3E
  230.   .waitpower:                                   ; For TI, you can check that bits 8-11 in PCI reg 80h are all 0
  231.         test    dword[ecx + 8], 1 shl 3         ; Test PWRCYCLE bit
  232.         jz      .waitpower                      ; Wait for power to go up
  233.  
  234.         DEBUGF  1, "Interface is powered up\n"
  235.  
  236. ; Write MemBase-Limit 0 and 1, then IOBase-Limit 0 and 1
  237. ; mem0 space limit = base => size is 4 kilobytes
  238. ; set to 0 the second interval (mem1 and IO1)
  239. ; IO0: size is 256 bytes
  240.  
  241. irp     regvalue,   0x7efff000, 0x7effffff, 0x7effe000, 0x7effe000, CARDBUS_IO, CARDBUS_IO + 0xFF, 0, 0
  242. {
  243. common
  244.         reg = 0x1C
  245. forward
  246.         invoke  PciWrite32, [bus], [devfn], reg, regvalue
  247.         DEBUGF  1, "Writing 0x%x to 0x%x\n", regvalue, reg
  248.         reg = reg + 4
  249. }
  250.  
  251.         invoke  PciWrite8, [bus], [devfn], PCI_header02.interrupt_line, 0xc    ; IRQ line
  252.  
  253.         invoke  PciRead16, [bus], [devfn], PCI_header02.bridge_ctrl                 ; Bridge control
  254.         or      ax, 0x0700                                      ; Enable write posting, both memory windows prefetchable
  255.         invoke  PciWrite16, [bus], [devfn], PCI_header02.bridge_ctrl, eax
  256.         DEBUGF  1, "Write posting enabled\n"
  257.  
  258.  
  259.         DEBUGF  1, "Bridge PCI registers:\n"
  260. rept    17 reg
  261. {
  262.         invoke  PciRead32, [bus], [devfn], 4*(reg-1)
  263.         DEBUGF  1, "0x%x\n", eax
  264. }
  265.  
  266.         inc     byte[0x80009021]                                ; LAST PCI bus count in kernel (dirty HACK!)
  267.  
  268.  
  269.         mov     ecx, 100
  270.   .waitactive:
  271.         push    ecx
  272.         invoke  PciRead32, [card_bus], 0, PCI_header02.vendor_id         ; Check if the card is awake yet
  273.         inc     eax
  274.         jnz     .got_it
  275.         mov     esi, 2
  276.         invoke  Sleep
  277.         pop     ecx
  278.         dec     ecx
  279.         jnz     .waitactive
  280.  
  281.         DEBUGF  1, "Timeout!\n"
  282.         ; TODO: disable card/bridge again ?
  283.         jmp     .next
  284.  
  285.   .got_it:
  286.         pop     eax
  287.         DEBUGF  1, "Card is enabled!\n"
  288.  
  289.         invoke  PciWrite32, [card_bus], 0, PCI_header02.base_addr, CARDBUS_IO       ; Supposing it's IO space that is needed
  290.         invoke  PciWrite8, [card_bus], 0, PCI_header02.interrupt_line, 0xC                      ; FIXME
  291.         invoke  PciWrite16, [card_bus], 0, PCI_header02.command, PCI_CMD_PIO or PCI_CMD_MMIO
  292.  
  293.         DEBUGF  1, "done\n"
  294.  
  295.         jmp     .next
  296.  
  297.   .err:
  298.         DEBUGF  1, "Error\n"
  299.         xor     eax, eax
  300.  
  301.         ret
  302.  
  303. endp
  304.  
  305.  
  306. ; End of code
  307.  
  308. data fixups
  309. end data
  310.  
  311. include '../peimport.inc'
  312.  
  313. my_service      db 'CARDBUS',0                  ; max 16 chars include zero
  314.  
  315. include_debug_strings                           ; All data wich FDO uses will be included here