1 /* 2 * Copyright 2005, Oscar Lesta. All rights reserved. 3 * Copyright 2018, Haiku, Inc. All rights reserved. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include <Drivers.h> 9 #include <KernelExport.h> 10 #include <ISA.h> 11 #include <PCI.h> 12 13 #if defined(__i386__) || defined(__x86_64__) 14 #include <thread.h> 15 #endif 16 17 #include "poke.h" 18 19 /* 20 TODO: maintain a list of mapped areas in the cookie 21 and only allow unmapping them, and clean them up on free. 22 */ 23 24 static status_t poke_open(const char*, uint32, void**); 25 static status_t poke_close(void*); 26 static status_t poke_free(void*); 27 static status_t poke_control(void*, uint32, void*, size_t); 28 static status_t poke_read(void*, off_t, void*, size_t*); 29 static status_t poke_write(void*, off_t, const void*, size_t*); 30 31 32 static const char* poke_name[] = { 33 "misc/" POKE_DEVICE_NAME, 34 NULL 35 }; 36 37 38 device_hooks poke_hooks = { 39 poke_open, 40 poke_close, 41 poke_free, 42 poke_control, 43 poke_read, 44 poke_write, 45 }; 46 47 int32 api_version = B_CUR_DRIVER_API_VERSION; 48 49 isa_module_info* isa; 50 pci_module_info* pci; 51 52 53 status_t 54 init_hardware(void) 55 { 56 return B_OK; 57 } 58 59 60 status_t 61 init_driver(void) 62 { 63 if (get_module(B_ISA_MODULE_NAME, (module_info**)&isa) < B_OK) 64 return ENOSYS; 65 66 if (get_module(B_PCI_MODULE_NAME, (module_info**)&pci) < B_OK) { 67 put_module(B_ISA_MODULE_NAME); 68 return ENOSYS; 69 } 70 71 return B_OK; 72 } 73 74 75 void 76 uninit_driver(void) 77 { 78 put_module(B_ISA_MODULE_NAME); 79 put_module(B_PCI_MODULE_NAME); 80 } 81 82 83 const char** 84 publish_devices(void) 85 { 86 return poke_name; 87 } 88 89 90 device_hooks* 91 find_device(const char* name) 92 { 93 return &poke_hooks; 94 } 95 96 97 // #pragma mark - 98 99 100 status_t 101 poke_open(const char* name, uint32 flags, void** cookie) 102 { 103 *cookie = NULL; 104 105 if (getuid() != 0 && geteuid() != 0) 106 return EPERM; 107 108 #if defined(__i386__) || defined(__x86_64__) 109 /* on x86, raise the IOPL so that outb/inb will work */ 110 iframe* frame = x86_get_user_iframe(); 111 int iopl = 3; 112 frame->flags &= ~X86_EFLAGS_IO_PRIVILEG_LEVEL; 113 frame->flags |= (iopl << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT) 114 & X86_EFLAGS_IO_PRIVILEG_LEVEL; 115 #endif 116 117 return B_OK; 118 } 119 120 121 status_t 122 poke_close(void* cookie) 123 { 124 return B_OK; 125 } 126 127 128 status_t 129 poke_free(void* cookie) 130 { 131 #if defined(__i386__) || defined(__x86_64__) 132 iframe* frame = x86_get_user_iframe(); 133 int iopl = 0; 134 frame->flags &= ~X86_EFLAGS_IO_PRIVILEG_LEVEL; 135 frame->flags |= (iopl << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT) 136 & X86_EFLAGS_IO_PRIVILEG_LEVEL; 137 #endif 138 139 return B_OK; 140 } 141 142 143 status_t 144 poke_control(void* cookie, uint32 op, void* arg, size_t length) 145 { 146 switch (op) { 147 case POKE_PORT_READ: 148 { 149 status_t result = B_OK; 150 port_io_args ioctl; 151 if (user_memcpy(&ioctl, arg, sizeof(port_io_args)) != B_OK) 152 return B_BAD_ADDRESS; 153 if (ioctl.signature != POKE_SIGNATURE) 154 return B_BAD_VALUE; 155 156 switch (ioctl.size) { 157 case 1: 158 ioctl.value = isa->read_io_8(ioctl.port); 159 break; 160 case 2: 161 ioctl.value = isa->read_io_16(ioctl.port); 162 break; 163 case 4: 164 ioctl.value = isa->read_io_32(ioctl.port); 165 break; 166 default: 167 result = B_BAD_VALUE; 168 } 169 170 if (user_memcpy(arg, &ioctl, sizeof(port_io_args)) != B_OK) 171 return B_BAD_ADDRESS; 172 return result; 173 } 174 175 case POKE_PORT_WRITE: 176 { 177 status_t result = B_OK; 178 port_io_args ioctl; 179 if (user_memcpy(&ioctl, arg, sizeof(port_io_args)) != B_OK) 180 return B_BAD_ADDRESS; 181 if (ioctl.signature != POKE_SIGNATURE) 182 return B_BAD_VALUE; 183 184 switch (ioctl.size) { 185 case 1: 186 isa->write_io_8(ioctl.port, ioctl.value); 187 break; 188 case 2: 189 isa->write_io_16(ioctl.port, ioctl.value); 190 break; 191 case 4: 192 isa->write_io_32(ioctl.port, ioctl.value); 193 break; 194 default: 195 result = B_BAD_VALUE; 196 } 197 198 return result; 199 } 200 201 case POKE_PORT_INDEXED_READ: 202 { 203 port_io_args ioctl; 204 if (user_memcpy(&ioctl, arg, sizeof(port_io_args)) != B_OK) 205 return B_BAD_ADDRESS; 206 if (ioctl.signature != POKE_SIGNATURE) 207 return B_BAD_VALUE; 208 209 isa->write_io_8(ioctl.port, ioctl.size); 210 ioctl.value = isa->read_io_8(ioctl.port + 1); 211 212 if (user_memcpy(arg, &ioctl, sizeof(port_io_args)) != B_OK) 213 return B_BAD_ADDRESS; 214 return B_OK; 215 } 216 217 case POKE_PORT_INDEXED_WRITE: 218 { 219 port_io_args ioctl; 220 if (user_memcpy(&ioctl, arg, sizeof(port_io_args)) != B_OK) 221 return B_BAD_ADDRESS; 222 if (ioctl.signature != POKE_SIGNATURE) 223 return B_BAD_VALUE; 224 225 isa->write_io_8(ioctl.port, ioctl.size); 226 isa->write_io_8(ioctl.port + 1, ioctl.value); 227 return B_OK; 228 } 229 230 case POKE_PCI_READ_CONFIG: 231 { 232 pci_io_args ioctl; 233 if (user_memcpy(&ioctl, arg, sizeof(pci_io_args)) != B_OK) 234 return B_BAD_ADDRESS; 235 if (ioctl.signature != POKE_SIGNATURE) 236 return B_BAD_VALUE; 237 238 ioctl.value = pci->read_pci_config(ioctl.bus, ioctl.device, 239 ioctl.function, ioctl.offset, ioctl.size); 240 if (user_memcpy(arg, &ioctl, sizeof(pci_io_args)) != B_OK) 241 return B_BAD_ADDRESS; 242 return B_OK; 243 } 244 245 case POKE_PCI_WRITE_CONFIG: 246 { 247 pci_io_args ioctl; 248 if (user_memcpy(&ioctl, arg, sizeof(pci_io_args)) != B_OK) 249 return B_BAD_ADDRESS; 250 if (ioctl.signature != POKE_SIGNATURE) 251 return B_BAD_VALUE; 252 253 pci->write_pci_config(ioctl.bus, ioctl.device, ioctl.function, 254 ioctl.offset, ioctl.size, ioctl.value); 255 return B_OK; 256 } 257 258 case POKE_GET_NTH_PCI_INFO: 259 { 260 pci_info_args ioctl; 261 if (user_memcpy(&ioctl, arg, sizeof(pci_info_args)) != B_OK) 262 return B_BAD_ADDRESS; 263 if (ioctl.signature != POKE_SIGNATURE) 264 return B_BAD_VALUE; 265 266 pci_info info; 267 ioctl.status = pci->get_nth_pci_info(ioctl.index, &info); 268 269 if (user_memcpy(ioctl.info, &info, sizeof(pci_info)) != B_OK) 270 return B_BAD_ADDRESS; 271 if (user_memcpy(arg, &ioctl, sizeof(pci_info_args)) != B_OK) 272 return B_BAD_ADDRESS; 273 return B_OK; 274 } 275 276 case POKE_GET_PHYSICAL_ADDRESS: 277 { 278 mem_map_args ioctl; 279 if (user_memcpy(&ioctl, arg, sizeof(mem_map_args)) != B_OK) 280 return B_BAD_ADDRESS; 281 physical_entry table; 282 status_t result; 283 284 if (ioctl.signature != POKE_SIGNATURE) 285 return B_BAD_VALUE; 286 287 result = get_memory_map(ioctl.address, ioctl.size, &table, 1); 288 ioctl.physical_address = table.address; 289 ioctl.size = table.size; 290 if (user_memcpy(arg, &ioctl, sizeof(mem_map_args)) != B_OK) 291 return B_BAD_ADDRESS; 292 return result; 293 } 294 295 case POKE_MAP_MEMORY: 296 { 297 mem_map_args ioctl; 298 if (user_memcpy(&ioctl, arg, sizeof(mem_map_args)) != B_OK) 299 return B_BAD_ADDRESS; 300 if (ioctl.signature != POKE_SIGNATURE) 301 return B_BAD_VALUE; 302 303 char name[B_OS_NAME_LENGTH]; 304 if (user_strlcpy(name, ioctl.name, B_OS_NAME_LENGTH) != B_OK) 305 return B_BAD_ADDRESS; 306 307 ioctl.area = map_physical_memory(name, 308 (addr_t)ioctl.physical_address, ioctl.size, ioctl.flags, 309 ioctl.protection, (void**)&ioctl.address); 310 311 if (user_memcpy(arg, &ioctl, sizeof(mem_map_args)) != B_OK) 312 return B_BAD_ADDRESS; 313 return ioctl.area; 314 } 315 316 case POKE_UNMAP_MEMORY: 317 { 318 mem_map_args ioctl; 319 if (user_memcpy(&ioctl, arg, sizeof(mem_map_args)) != B_OK) 320 return B_BAD_ADDRESS; 321 if (ioctl.signature != POKE_SIGNATURE) 322 return B_BAD_VALUE; 323 324 return delete_area(ioctl.area); 325 } 326 } 327 328 return B_BAD_VALUE; 329 } 330 331 332 status_t 333 poke_read(void* cookie, off_t position, void* buffer, size_t* numBytes) 334 { 335 *numBytes = 0; 336 return B_NOT_ALLOWED; 337 } 338 339 340 status_t 341 poke_write(void* cookie, off_t position, const void* buffer, size_t* numBytes) 342 { 343 *numBytes = 0; 344 return B_NOT_ALLOWED; 345 } 346