;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2015-2017. All rights reserved. ;; ;; Distributed under terms of the GNU General Public License ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; format PE DLL native 0.05 entry START DEBUG = 1 __DEBUG__ = 1 __DEBUG_LEVEL__ = 1 ; 1 = verbose, 2 = errors only API_VERSION = 0 ;debug STRIDE = 4 ;size of row in devices table SRV_GETVERSION = 0 section '.flat' code readable writable executable include '../proc32.inc' include '../struct.inc' include '../macros.inc' include '../peimport.inc' include '../fdo.inc' GPIO_PORT_CONFIG_ADDR = 0xF100 GPIO_DATA_ADDR = 0xF200 ADC_ADDR = 0xFE00 proc START c, state:dword, cmdline:dword cmp [state], 1 jne .exit .entry: push esi DEBUGF 1,"Loading vortex86EX GPIO driver\n" call detect pop esi test eax, eax jz .fail ; Set crossbar base address register in southbridge invoke PciWrite16, [bus], [dev], 0x64, 0x0A00 or 1 ; Set GPIO base address register in southbridge invoke PciWrite16, [bus], [dev], 0x62, GPIO_PORT_CONFIG_ADDR or 1 DEBUGF 1,"Setting up ADC\n" ; Enable ADC invoke PciRead32, [bus], [dev], 0xBC and eax, not (1 shl 28) invoke PciWrite32, [bus], [dev], 0xBC, eax ; Set ADC base address mov ebx, [dev] inc ebx invoke PciRead16, [bus], ebx, 0xDE or ax, 0x02 invoke PciWrite16, [bus], ebx, 0xDE, eax invoke PciWrite32, [bus], ebx, 0xE0, 0x00500000 or ADC_ADDR ; set up ADC mov dx, ADC_ADDR + 1 xor al, al out dx, al ; Empty FIFO @@: mov dx, ADC_ADDR + 2 ; Status register in al, dx test al, 0x01 ; FIFO ready jz @f mov dx, ADC_ADDR + 4 in ax, dx jmp @r @@: ; Enable GPIO0-9 mov dx, GPIO_PORT_CONFIG_ADDR + 0 ; General-Purpose I/O Data & Direction Decode Enable mov eax, 0x000001ff out dx, eax mov ecx, 10 ; 10 GPIO ports total mov dx, GPIO_PORT_CONFIG_ADDR + 4 ; General-Purpose I/O Port0 Data & Direction Decode Address mov ax, GPIO_DATA_ADDR .gpio_init: ; Set GPIO data port base address out dx, ax add ax, 2 add dx, 2 ; Set GPIO direction base address out dx, ax add ax, 2 add dx, 2 ; loop dec ecx jnz .gpio_init ; Set GPIO0 pin 0-7 as output mov al, 0xff mov dx, GPIO_DATA_ADDR + 0*4 + 2 out dx, al invoke RegService, my_service, service_proc ret .fail: .exit: xor eax, eax ret endp proc service_proc stdcall, ioctl:dword mov ebx, [ioctl] mov eax, [ebx+IOCTL.io_code] cmp eax, SRV_GETVERSION jne @F mov eax, [ebx+IOCTL.output] cmp [ebx+IOCTL.out_size], 4 jne .fail mov dword [eax], API_VERSION xor eax, eax ret @@: cmp eax, 1 ; read GPIO P0 jne .no_gpioread mov dx, GPIO_DATA_ADDR + 0x00 in al, dx ret .no_gpioread: cmp eax, 2 ; write GPIO P0 jne .no_gpiowrite mov eax, [ebx + IOCTL.input] mov dx, GPIO_DATA_ADDR + 0x00 out dx, al xor eax, eax ret .no_gpiowrite: cmp eax, 3 ; read single ADC channel jne .no_adcread mov ecx, [ebx + IOCTL.input] cmp ecx, 8 jae .fail mov dx, ADC_ADDR + 1 mov al, 1 shl 3 ; Power down ADC out dx, al mov dx, ADC_ADDR + 0 ; AUX channel select register mov al, 1 shl ax, cl out dx, al mov dx, ADC_ADDR + 1 mov al, 1 shl 0 ; Single shot, no interrupts, start out dx, al mov dx, ADC_ADDR + 2 @@: in al, dx test al, 1 shl 0 ; data ready? jz @r mov dx, ADC_ADDR + 4 in ax, dx ; read the data from the FIFO and return to user call ret .no_adcread: .fail: or eax, -1 ret endp proc detect push ebx invoke GetPCIList mov ebx, eax .next_dev: mov eax, [eax+PCIDEV.fd] cmp eax, ebx jz .err mov edx, [eax+PCIDEV.vendor_device_id] mov esi, devices @@: cmp dword [esi], 0 jz .next_dev cmp edx, [esi] jz .found add esi, STRIDE jmp @B .found: movzx ebx, [eax+PCIDEV.devfn] mov [dev], ebx movzx ebx, [eax+PCIDEV.bus] mov [bus], ebx xor eax, eax inc eax pop ebx ret .err: DEBUGF 1,"Could not find vortex86EX south bridge!\n" xor eax, eax pop ebx ret endp DEVICE_ID = 6011h VENDOR_ID = 17F3h ;all initialized data place here align 4 devices dd (DEVICE_ID shl 16)+VENDOR_ID dd 0 ;terminator my_service db '86DUINO-GPIO',0 ;max 16 chars include zero include_debug_strings ; All data wich FDO uses will be included here dev dd ? bus dd ? align 4 data fixups end data