FreeBASIC  0.91.0
sys_portio.c
Go to the documentation of this file.
1 /* ports I/O functions */
2 
3 #include "../fb.h"
4 #include "fb_private_console.h"
5 #include "fbportio.h"
6 #include <windows.h>
7 #include <winioctl.h>
8 
9 #ifdef HOST_X86
10 
11 #include "fbportio_inline.h"
12 
13 static int inited = FALSE;
14 
15 static void remove_driver( void )
16 {
17  SC_HANDLE manager, service;
18  SERVICE_STATUS status;
19 
20  manager = OpenSCManager( NULL, NULL, GENERIC_ALL );
21  if( manager ) {
22  service = OpenService( manager, "fbportio", SERVICE_ALL_ACCESS );
23  if( service ) {
24  ControlService( service, SERVICE_CONTROL_STOP, &status );
25  DeleteService( service );
26  CloseServiceHandle( service );
27  }
28  CloseServiceHandle( manager );
29  }
30 }
31 
32 static SC_HANDLE install_driver( SC_HANDLE manager )
33 {
34  SC_HANDLE service = NULL;
35  char driver_filename[MAX_PATH];
36 
37  remove_driver( );
38 
39  if( GetSystemDirectory( driver_filename, MAX_PATH ) ) {
40  strncat( driver_filename, "\\Drivers\\fbportio.sys", MAX_PATH - strlen( driver_filename ) - 1 );
41  driver_filename[MAX_PATH-1] = '\0';
42 
43  FILE *f = fopen( driver_filename, "wb" );
44  fwrite( fbportio_driver, FBPORTIO_DRIVER_SIZE, 1, f );
45  fclose( f );
46 
47  service = CreateService( manager, "fbportio", "fbportio",
48  SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
49  "System32\\Drivers\\fbportio.sys", NULL, NULL, NULL, NULL, NULL );
50  }
51  return service;
52 }
53 
54 static void start_driver( void )
55 {
56  SC_HANDLE manager, service;
57 
58  manager = OpenSCManager( NULL, NULL, GENERIC_ALL );
59  if( !manager )
60  manager = OpenSCManager( NULL, NULL, GENERIC_READ );
61  if( manager ) {
62  service = OpenService( manager, "fbportio", SERVICE_ALL_ACCESS );
63  if( (!service ) || (!StartService( service, 0, NULL ) ) ) {
64  if( service )
65  CloseServiceHandle( service );
66  service = install_driver( manager );
67  StartService( service, 0, NULL );
68  }
69  CloseServiceHandle( service );
70  CloseServiceHandle( manager );
71  }
72 }
73 
74 static int init_ports( void )
75 {
76  OSVERSIONINFO ver_info;
77  HANDLE driver;
78  DWORD pid, bytes_written;
79  WORD driver_version;
80  int status, started = FALSE;
81 
82  memset( &ver_info, 0, sizeof(OSVERSIONINFO) );
83  ver_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
84  if ( !GetVersionEx( (OSVERSIONINFO *)&ver_info ) )
85  return FALSE;
86  switch (ver_info.dwPlatformId) {
87 
88  case VER_PLATFORM_WIN32_WINDOWS:
89  break;
90 
91  case VER_PLATFORM_WIN32_NT:
92  do {
93  driver = CreateFile( "\\\\.\\fbportio", GENERIC_READ | GENERIC_WRITE, 0, NULL,
94  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
95  if( driver == INVALID_HANDLE_VALUE ) {
96  if( !started ) {
97  start_driver( );
98  started = TRUE;
99  }
100  else
101  return FALSE;
102  }
103  else {
104  if( !DeviceIoControl( driver, IOCTL_GET_VERSION, NULL, 0, &driver_version, 2, &bytes_written, NULL ) ||
105  ( driver_version != FBPORTIO_VERSION ) ) {
106  /* Not our driver or an old version of it; reinstall */
107  CloseHandle( driver );
108  remove_driver( );
109  start_driver( );
110  started = TRUE;
111  driver = INVALID_HANDLE_VALUE;
112  }
113  else
114  break;
115  }
116  } while( driver == INVALID_HANDLE_VALUE );
117 
118  /* Ok, we got our driver loaded; grant I/O ports access to our own process */
119  pid = GetCurrentProcessId( );
120  status = DeviceIoControl( driver, IOCTL_GRANT_IOPM, &pid, 4, NULL, 0, &bytes_written, NULL );
121  CloseHandle( driver );
122 
123  /* Give up our timeslice to ensure process kernel state is updated */
124  Sleep(1);
125 
126  if( !status )
127  return FALSE;
128  break;
129  }
130 
131  return TRUE;
132 }
133 
134 int fb_hIn( unsigned short port )
135 {
136  unsigned char value;
137 
138  if( !inited )
139  inited = init_ports( );
140  if( !inited )
142 
143  __asm__ volatile ("inb %1, %0" : "=a" (value) : "d" (port));
144 
145  return (int)value;
146 }
147 
148 int fb_hOut( unsigned short port, unsigned char value )
149 {
150  if( !inited )
151  inited = init_ports( );
152  if( !inited )
154 
155  __asm__ volatile ("outb %0, %1" : : "a" (value), "d" (port));
156 
157  return FB_RTERROR_OK;
158 }
159 
160 #else
161 
162 int fb_hIn( unsigned short port )
163 {
165 }
166 
167 int fb_hOut( unsigned short port, unsigned char value )
168 {
170 }
171 
172 #endif