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