1/* 2 * Copyright 2007, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5#include <Drivers.h> 6#include <KernelExport.h> 7#include <string.h> 8#include <unistd.h> 9#include <sys/types.h> 10 11#define DRIVER_NAME "mem" 12#define DEVICE_NAME "misc/mem" 13 14#define DEVMNT "/dev/" 15 16/* also publish /dev/mem */ 17#define PUBLISH_DEV_MEM 18 19static status_t mem_open(const char*, uint32, void**); 20static status_t mem_close(void*); 21static status_t mem_free(void*); 22static status_t mem_read(void*, off_t, void*, size_t*); 23static status_t mem_write(void*, off_t, const void*, size_t*); 24 25static area_id mem_map_target(off_t position, size_t length, uint32 protection, 26 void **virtualAddress); 27 28static const char* mem_name[] = { 29 DEVICE_NAME, 30#ifdef PUBLISH_DEV_MEM 31 DRIVER_NAME, 32#endif 33 NULL 34}; 35 36 37device_hooks mem_hooks = { 38 mem_open, 39 mem_close, 40 mem_free, 41 NULL, /*mem_control,*/ 42 mem_read, 43 mem_write, 44}; 45 46int32 api_version = B_CUR_DRIVER_API_VERSION; 47 48status_t 49init_hardware(void) 50{ 51 return B_OK; 52} 53 54 55status_t 56init_driver(void) 57{ 58 return B_OK; 59} 60 61 62void 63uninit_driver(void) 64{ 65} 66 67 68const char** 69publish_devices(void) 70{ 71 return mem_name; 72} 73 74 75device_hooks* 76find_device(const char* name) 77{ 78 return &mem_hooks; 79} 80 81 82status_t 83mem_open(const char* name, uint32 flags, void** cookie) 84{ 85 // not really needed. 86 *cookie = NULL; 87 return B_OK; 88} 89 90 91status_t 92mem_close(void* cookie) 93{ 94 return B_OK; 95} 96 97 98status_t 99mem_free(void* cookie) 100{ 101 return B_OK; 102} 103 104 105status_t 106mem_read(void* cookie, off_t position, void* buffer, size_t* numBytes) 107{ 108 void *virtualAddress; 109 area_id area; 110 111 /* check permissions */ 112 if (getuid() != 0 && geteuid() != 0) { 113 *numBytes = 0; 114 return EPERM; 115 } 116 117 area = mem_map_target(position, *numBytes, B_READ_AREA, &virtualAddress); 118 if (area < 0) { 119 *numBytes = 0; 120 return area; 121 } 122 123 memcpy(buffer, virtualAddress, *numBytes); 124 delete_area(area); 125 return B_OK; 126} 127 128 129status_t 130mem_write(void* cookie, off_t position, const void* buffer, size_t* numBytes) 131{ 132 void *virtualAddress; 133 area_id area; 134 135 /* check permissions */ 136 if (getuid() != 0 && geteuid() != 0) { 137 *numBytes = 0; 138 return EPERM; 139 } 140 141 area = mem_map_target(position, *numBytes, B_WRITE_AREA, &virtualAddress); 142 if (area < 0) { 143 *numBytes = 0; 144 return area; 145 } 146 147 memcpy(virtualAddress, buffer, *numBytes); 148 delete_area(area); 149 return B_OK; 150} 151 152 153area_id 154mem_map_target(off_t position, size_t length, uint32 protection, 155 void **virtualAddress) 156{ 157 area_id area; 158 phys_addr_t physicalAddress; 159 size_t offset; 160 size_t size; 161 162 /* SIZE_MAX actually but 2G should be enough anyway */ 163 if (length > SSIZE_MAX - B_PAGE_SIZE) 164 return EINVAL; 165 166 /* the first page address */ 167 physicalAddress = (phys_addr_t)position & ~((off_t)B_PAGE_SIZE - 1); 168 169 /* offset of target into it */ 170 offset = position - (off_t)physicalAddress; 171 172 /* size of the whole mapping (page rounded) */ 173 size = (offset + length + B_PAGE_SIZE - 1) & ~((size_t)B_PAGE_SIZE - 1); 174 area = map_physical_memory("mem_driver_temp", physicalAddress, size, 175 B_ANY_KERNEL_ADDRESS, protection, virtualAddress); 176 if (area < 0) 177 return area; 178 179 *virtualAddress += offset; 180 return area; 181} 182