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