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
36struct 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
46static device_manager_info *sDeviceManager;
47
48
49static status_t
50nor_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
68static void
69nor_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
78static status_t
79nor_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
88static status_t
89nor_close(void *_cookie)
90{
91	TRACE("close()\n");
92	return B_OK;
93}
94
95
96static status_t
97nor_free(void *_cookie)
98{
99	TRACE("free()\n");
100	return B_OK;
101}
102
103
104static status_t
105nor_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
136static status_t
137nor_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
151static status_t
152nor_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
160static float
161nor_supports_device(device_node *parent)
162{
163	TRACE("supports_device\n");
164	return 0.6;
165}
166
167
168static status_t
169nor_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
182static status_t
183nor_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
200static void
201nor_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
209static status_t
210nor_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
223struct 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
248struct 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
265module_dependency module_dependencies[] = {
266	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&sDeviceManager },
267	{ }
268};
269
270
271module_info *modules[] = {
272	(module_info*)&sNORFlashDiskDriver,
273	(module_info*)&sNORFlashDiskDevice,
274	NULL
275};
276