1 /* 2 * Copyright 2012, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ithamar R. Adema <ithamar@upgrade-android.com> 7 */ 8 9 10 #include <string.h> 11 #include <stdlib.h> 12 #include <stdio.h> 13 #include <ctype.h> 14 15 #include <drivers/device_manager.h> 16 #include <drivers/KernelExport.h> 17 #include <drivers/Drivers.h> 18 #include <kernel/OS.h> 19 20 21 //#define TRACE_NORFLASH 22 #ifdef TRACE_NORFLASH 23 #define TRACE(x...) dprintf("nor: " x) 24 #else 25 #define TRACE(x...) 26 #endif 27 28 29 #define NORFLASH_DEVICE_MODULE_NAME "drivers/disk/norflash/device_v1" 30 #define NORFLASH_DRIVER_MODULE_NAME "drivers/disk/norflash/driver_v1" 31 32 33 #define NORFLASH_ADDR 0x00000000 34 35 36 struct nor_driver_info { 37 device_node *node; 38 size_t blocksize; 39 size_t totalsize; 40 41 area_id id; 42 void *mapped; 43 }; 44 45 46 static device_manager_info *sDeviceManager; 47 48 49 static status_t 50 nor_init_device(void *_info, void **_cookie) 51 { 52 TRACE("init_device\n"); 53 nor_driver_info *info = (nor_driver_info*)_info; 54 55 info->mapped = NULL; 56 info->blocksize = 128 * 1024; 57 info->totalsize = info->blocksize * 256; 58 59 info->id = map_physical_memory("NORFlash", NORFLASH_ADDR, info->totalsize, B_ANY_KERNEL_ADDRESS, B_READ_AREA, &info->mapped); 60 if (info->id < 0) 61 return info->id; 62 63 *_cookie = info; 64 return B_OK; 65 } 66 67 68 static void 69 nor_uninit_device(void *_cookie) 70 { 71 TRACE("uninit_device\n"); 72 nor_driver_info *info = (nor_driver_info*)_cookie; 73 if (info) 74 delete_area(info->id); 75 } 76 77 78 static status_t 79 nor_open(void *deviceCookie, const char *path, int openMode, 80 void **_cookie) 81 { 82 TRACE("open(%s)\n", path); 83 *_cookie = deviceCookie; 84 return B_OK; 85 } 86 87 88 static status_t 89 nor_close(void *_cookie) 90 { 91 TRACE("close()\n"); 92 return B_OK; 93 } 94 95 96 static status_t 97 nor_free(void *_cookie) 98 { 99 TRACE("free()\n"); 100 return B_OK; 101 } 102 103 104 static status_t 105 nor_ioctl(void *cookie, uint32 op, void *buffer, size_t length) 106 { 107 nor_driver_info *info = (nor_driver_info*)cookie; 108 TRACE("ioctl(%ld,%lu)\n", op, length); 109 110 switch (op) { 111 case B_GET_GEOMETRY: 112 { 113 device_geometry *deviceGeometry = (device_geometry*)buffer; 114 deviceGeometry->removable = false; 115 deviceGeometry->bytes_per_sector = info->blocksize; 116 deviceGeometry->sectors_per_track = info->totalsize / info->blocksize; 117 deviceGeometry->cylinder_count = 1; 118 deviceGeometry->head_count = 1; 119 deviceGeometry->device_type = B_DISK; 120 deviceGeometry->removable = false; 121 deviceGeometry->read_only = true; 122 deviceGeometry->write_once = false; 123 return B_OK; 124 } 125 break; 126 127 case B_GET_DEVICE_NAME: 128 strlcpy((char*)buffer, "NORFlash", length); 129 break; 130 } 131 132 return B_ERROR; 133 } 134 135 136 static status_t 137 nor_read(void *_cookie, off_t position, void *data, size_t *numbytes) 138 { 139 nor_driver_info *info = (nor_driver_info*)_cookie; 140 TRACE("read(%Ld,%lu)\n", position, *numbytes); 141 142 if (position + *numbytes > info->totalsize) 143 *numbytes = info->totalsize - (position + *numbytes); 144 145 memcpy(data, info->mapped + position, *numbytes); 146 147 return B_OK; 148 } 149 150 151 static status_t 152 nor_write(void *_cookie, off_t position, const void *data, size_t *numbytes) 153 { 154 TRACE("write(%Ld,%lu)\n", position, *numbytes); 155 *numbytes = 0; 156 return B_ERROR; 157 } 158 159 160 static float 161 nor_supports_device(device_node *parent) 162 { 163 TRACE("supports_device\n"); 164 return 0.6; 165 } 166 167 168 static status_t 169 nor_register_device(device_node *node) 170 { 171 TRACE("register_device\n"); 172 // ready to register 173 device_attr attrs[] = { 174 { NULL } 175 }; 176 177 return sDeviceManager->register_node(node, NORFLASH_DRIVER_MODULE_NAME, 178 attrs, NULL, NULL); 179 } 180 181 182 static status_t 183 nor_init_driver(device_node *node, void **cookie) 184 { 185 TRACE("init_driver\n"); 186 187 nor_driver_info *info = (nor_driver_info*)malloc(sizeof(nor_driver_info)); 188 if (info == NULL) 189 return B_NO_MEMORY; 190 191 memset(info, 0, sizeof(*info)); 192 193 info->node = node; 194 195 *cookie = info; 196 return B_OK; 197 } 198 199 200 static void 201 nor_uninit_driver(void *_cookie) 202 { 203 TRACE("uninit_driver\n"); 204 nor_driver_info *info = (nor_driver_info*)_cookie; 205 free(info); 206 } 207 208 209 static status_t 210 nor_register_child_devices(void *_cookie) 211 { 212 TRACE("register_child_devices\n"); 213 nor_driver_info *info = (nor_driver_info*)_cookie; 214 status_t status; 215 216 status = sDeviceManager->publish_device(info->node, "disk/nor/0/raw", 217 NORFLASH_DEVICE_MODULE_NAME); 218 219 return status; 220 } 221 222 223 struct device_module_info sNORFlashDiskDevice = { 224 { 225 NORFLASH_DEVICE_MODULE_NAME, 226 0, 227 NULL 228 }, 229 230 nor_init_device, 231 nor_uninit_device, 232 NULL, //nor_remove, 233 234 nor_open, 235 nor_close, 236 nor_free, 237 nor_read, 238 nor_write, 239 NULL, // nor_io, 240 nor_ioctl, 241 242 NULL, // select 243 NULL, // deselect 244 }; 245 246 247 248 struct driver_module_info sNORFlashDiskDriver = { 249 { 250 NORFLASH_DRIVER_MODULE_NAME, 251 0, 252 NULL 253 }, 254 255 nor_supports_device, 256 nor_register_device, 257 nor_init_driver, 258 nor_uninit_driver, 259 nor_register_child_devices, 260 NULL, // rescan 261 NULL, // removed 262 }; 263 264 265 module_dependency module_dependencies[] = { 266 { B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&sDeviceManager }, 267 { } 268 }; 269 270 271 module_info *modules[] = { 272 (module_info*)&sNORFlashDiskDriver, 273 (module_info*)&sNORFlashDiskDevice, 274 NULL 275 }; 276