Subversion Repositories Kolibri OS

Rev

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

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