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