Subversion Repositories Kolibri OS

Rev

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