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 19 static status_t mem_open(const char*, uint32, void**); 20 static status_t mem_close(void*); 21 static status_t mem_free(void*); 22 static status_t mem_read(void*, off_t, void*, size_t*); 23 static status_t mem_write(void*, off_t, const void*, size_t*); 24 25 static area_id mem_map_target(off_t position, size_t length, uint32 protection, 26 void **virtualAddress); 27 28 static const char* mem_name[] = { 29 DEVICE_NAME, 30 #ifdef PUBLISH_DEV_MEM 31 DRIVER_NAME, 32 #endif 33 NULL 34 }; 35 36 37 device_hooks mem_hooks = { 38 mem_open, 39 mem_close, 40 mem_free, 41 NULL, /*mem_control,*/ 42 mem_read, 43 mem_write, 44 }; 45 46 int32 api_version = B_CUR_DRIVER_API_VERSION; 47 48 status_t 49 init_hardware(void) 50 { 51 return B_OK; 52 } 53 54 55 status_t 56 init_driver(void) 57 { 58 return B_OK; 59 } 60 61 62 void 63 uninit_driver(void) 64 { 65 } 66 67 68 const char** 69 publish_devices(void) 70 { 71 return mem_name; 72 } 73 74 75 device_hooks* 76 find_device(const char* name) 77 { 78 return &mem_hooks; 79 } 80 81 82 status_t 83 mem_open(const char* name, uint32 flags, void** cookie) 84 { 85 // not really needed. 86 *cookie = NULL; 87 return B_OK; 88 } 89 90 91 status_t 92 mem_close(void* cookie) 93 { 94 return B_OK; 95 } 96 97 98 status_t 99 mem_free(void* cookie) 100 { 101 return B_OK; 102 } 103 104 105 status_t 106 mem_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 129 status_t 130 mem_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 153 area_id 154 mem_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