xref: /haiku/src/add-ons/kernel/drivers/disk/norflash/norflash.cpp (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
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 #define SIZE_IN_BLOCKS	256
35 
36 /* Hide the start of NOR since U-Boot lives there */
37 #define HIDDEN_BLOCKS	2
38 
39 struct nor_driver_info {
40 	device_node *node;
41 	size_t blocksize;
42 	size_t totalsize;
43 
44 	area_id id;
45 	uint8 *mapped;
46 };
47 
48 
49 static device_manager_info *sDeviceManager;
50 
51 
52 static status_t
53 nor_init_device(void *_info, void **_cookie)
54 {
55 	TRACE("init_device\n");
56 	nor_driver_info *info = (nor_driver_info*)_info;
57 
58 	info->mapped = NULL;
59 	info->blocksize = 128 * 1024;
60 	info->totalsize = (SIZE_IN_BLOCKS - HIDDEN_BLOCKS) * info->blocksize;
61 
62 	info->id = map_physical_memory("NORFlash", NORFLASH_ADDR, info->totalsize, B_ANY_KERNEL_ADDRESS, B_READ_AREA, (void **)&info->mapped);
63 	if (info->id < 0)
64 		return info->id;
65 
66 	info->mapped += HIDDEN_BLOCKS * info->blocksize;
67 
68 
69 	*_cookie = info;
70 	return B_OK;
71 }
72 
73 
74 static void
75 nor_uninit_device(void *_cookie)
76 {
77 	TRACE("uninit_device\n");
78 	nor_driver_info *info = (nor_driver_info*)_cookie;
79 	if (info)
80 		delete_area(info->id);
81 }
82 
83 
84 static status_t
85 nor_open(void *deviceCookie, const char *path, int openMode,
86 	void **_cookie)
87 {
88 	TRACE("open(%s)\n", path);
89 	*_cookie = deviceCookie;
90 	return B_OK;
91 }
92 
93 
94 static status_t
95 nor_close(void *_cookie)
96 {
97 	TRACE("close()\n");
98 	return B_OK;
99 }
100 
101 
102 static status_t
103 nor_free(void *_cookie)
104 {
105 	TRACE("free()\n");
106 	return B_OK;
107 }
108 
109 
110 static status_t
111 nor_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
112 {
113 	nor_driver_info *info = (nor_driver_info*)cookie;
114 	TRACE("ioctl(%ld,%lu)\n", op, length);
115 
116 	switch (op) {
117 		case B_GET_GEOMETRY:
118 		{
119 			device_geometry *deviceGeometry = (device_geometry*)buffer;
120 			deviceGeometry->removable = false;
121 			deviceGeometry->bytes_per_sector = info->blocksize;
122 			deviceGeometry->sectors_per_track = info->totalsize / info->blocksize;
123 			deviceGeometry->cylinder_count = 1;
124 			deviceGeometry->head_count = 1;
125 			deviceGeometry->device_type = B_DISK;
126 			deviceGeometry->removable = false;
127 			deviceGeometry->read_only = true;
128 			deviceGeometry->write_once = false;
129 			return B_OK;
130 		}
131 		break;
132 
133 		case B_GET_DEVICE_NAME:
134 			strlcpy((char*)buffer, "NORFlash", length);
135 			break;
136 	}
137 
138 	return B_ERROR;
139 }
140 
141 
142 static status_t
143 nor_read(void *_cookie, off_t position, void *data, size_t *numbytes)
144 {
145 	nor_driver_info *info = (nor_driver_info*)_cookie;
146 	TRACE("read(%lld,%lu)\n", position, *numbytes);
147 
148 	position += HIDDEN_BLOCKS * info->blocksize;
149 
150 	if (position + *numbytes > info->totalsize)
151 		*numbytes = info->totalsize - (position + *numbytes);
152 
153 	memcpy(data, info->mapped + position, *numbytes);
154 
155 	return B_OK;
156 }
157 
158 
159 static status_t
160 nor_write(void *_cookie, off_t position, const void *data, size_t *numbytes)
161 {
162 	TRACE("write(%lld,%lu)\n", position, *numbytes);
163 	*numbytes = 0;
164 	return B_ERROR;
165 }
166 
167 
168 static float
169 nor_supports_device(device_node *parent)
170 {
171 	const char *bus;
172 	TRACE("supports_device\n");
173 
174 	if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
175 		return B_ERROR;
176 
177 	if (strcmp(bus, "generic"))
178 		return 0.0;
179 
180 	return 1.0;
181 }
182 
183 
184 static status_t
185 nor_register_device(device_node *node)
186 {
187 	TRACE("register_device\n");
188 	// ready to register
189 	device_attr attrs[] = {
190 		{ NULL }
191 	};
192 
193 	return sDeviceManager->register_node(node, NORFLASH_DRIVER_MODULE_NAME,
194 		attrs, NULL, NULL);
195 }
196 
197 
198 static status_t
199 nor_init_driver(device_node *node, void **cookie)
200 {
201 	TRACE("init_driver\n");
202 
203 	nor_driver_info *info = (nor_driver_info*)malloc(sizeof(nor_driver_info));
204 	if (info == NULL)
205 		return B_NO_MEMORY;
206 
207 	memset(info, 0, sizeof(*info));
208 
209 	info->node = node;
210 
211 	*cookie = info;
212 	return B_OK;
213 }
214 
215 
216 static void
217 nor_uninit_driver(void *_cookie)
218 {
219 	TRACE("uninit_driver\n");
220 	nor_driver_info *info = (nor_driver_info*)_cookie;
221 	free(info);
222 }
223 
224 
225 static status_t
226 nor_register_child_devices(void *_cookie)
227 {
228 	TRACE("register_child_devices\n");
229 	nor_driver_info *info = (nor_driver_info*)_cookie;
230 	status_t status;
231 
232 	status = sDeviceManager->publish_device(info->node, "disk/nor/0/raw",
233 		NORFLASH_DEVICE_MODULE_NAME);
234 
235 	return status;
236 }
237 
238 
239 struct device_module_info sNORFlashDiskDevice = {
240 	{
241 		NORFLASH_DEVICE_MODULE_NAME,
242 		0,
243 		NULL
244 	},
245 
246 	nor_init_device,
247 	nor_uninit_device,
248 	NULL, //nor_remove,
249 
250 	nor_open,
251 	nor_close,
252 	nor_free,
253 	nor_read,
254 	nor_write,
255 	NULL,	// nor_io,
256 	nor_ioctl,
257 
258 	NULL,	// select
259 	NULL,	// deselect
260 };
261 
262 
263 
264 struct driver_module_info sNORFlashDiskDriver = {
265 	{
266 		NORFLASH_DRIVER_MODULE_NAME,
267 		0,
268 		NULL
269 	},
270 
271 	nor_supports_device,
272 	nor_register_device,
273 	nor_init_driver,
274 	nor_uninit_driver,
275 	nor_register_child_devices,
276 	NULL,	// rescan
277 	NULL,	// removed
278 };
279 
280 
281 module_dependency module_dependencies[] = {
282 	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&sDeviceManager },
283 	{ }
284 };
285 
286 
287 module_info *modules[] = {
288 	(module_info*)&sNORFlashDiskDriver,
289 	(module_info*)&sNORFlashDiskDevice,
290 	NULL
291 };
292