xref: /haiku/src/add-ons/kernel/drivers/disk/virtual/nbd/nbd.c (revision 4d1cc41eb3a998c0661334fa5c4a3baa4ae5461f)
1 /*
2  * Copyright 2006-2007, François Revol. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 /*
7 	nbd driver for Haiku
8 
9 	Maps BEOS/IMAGE.BE files as virtual partitions.
10 */
11 
12 #include <KernelExport.h>
13 #include <Drivers.h>
14 #include <Errors.h>
15 #include <ksocket.h>
16 
17 #include "nbd.h"
18 
19 #define MAX_NBDS 4
20 #define DEVICE_PREFIX "disk/virtual/nbd/"
21 #define DEVICE_FMT DEVICE_PREFIX "%2d/raw"
22 #define DEVICE_NAME_MAX 32
23 #define MAX_REQ_SIZE (32*1024*1024)
24 
25 struct nbd_request_entry {
26 	struct nbd_request_entry *next;
27 	struct nbd_request req;
28 	bool r; /* is read */
29 	size_t len;
30 	void *buffer; /* write: ptr to passed buffer; read: ptr to malloc()ed extra */
31 };
32 
33 struct nbd_device {
34 	//lock
35 	vint32 refcnt;
36 	uint64 req; /* next ID for requests */
37 	int sock;
38 	thread_id postoffice;
39 	uint64 size;
40 	struct nbd_request_entry *reqs;
41 };
42 
43 typedef struct cookie {
44 	struct nbd_device *dev;
45 
46 } cookie_t;
47 
48 /* data=NULL on read */
49 status_t nbd_alloc_request(struct nbd_device, struct nbd_request_entry **req, size_t len, const char *data);
50 status_t nbd_post_request(struct nbd_device, uint64 handle, struct nbd_request_entry **req);
51 status_t nbd_dequeue_request(struct nbd_device, uint64 handle, struct nbd_request_entry **req);
52 status_t nbd_free_request(struct nbd_device, struct nbd_request_entry *req);
53 
54 #pragma mark ==== request manager ====
55 
56 
57 #pragma mark ==== nbd handler ====
58 
59 int32 postoffice(void *arg)
60 {
61 	struct nbd_device *dev = (struct nbd_device *)arg;
62 	int sock = dev->sock;
63 
64 
65 
66 	return 0;
67 }
68 
69 #pragma mark ==== device hooks ====
70 
71 status_t nbd_open(const char *name, uint32 flags, cookie_t **cookie) {
72 	(void)name; (void)flags;
73 	*cookie = (void*)malloc(sizeof(cookie_t));
74 	if (*cookie == NULL) {
75 		dprintf("nbd_open : error allocating cookie\n");
76 		goto err0;
77 	}
78 	memset(*cookie, 0, sizeof(cookie_t));
79 	return B_OK;
80 err0:
81 	return B_ERROR;
82 }
83 
84 status_t nbd_close(void *cookie) {
85 	(void)cookie;
86 	return B_OK;
87 }
88 
89 status_t nbd_free(cookie_t *cookie) {
90 	free(cookie);
91 	return B_OK;
92 }
93 
94 status_t nbd_control(cookie_t *cookie, uint32 op, void *data, size_t len) {
95 	switch (op) {
96 	case B_GET_DEVICE_SIZE: /* this one is broken anyway... */
97 		if (data) {
98 			*(size_t *)data = (size_t)cookie->dev->size;
99 			return B_OK;
100 		}
101 		return EINVAL;
102 	case B_SET_DEVICE_SIZE: /* broken */
103 		return EINVAL;
104 	case B_SET_NONBLOCKING_IO:
105 		return EINVAL;
106 	case B_SET_BLOCKING_IO:
107 		return B_OK;
108 	case B_GET_READ_STATUS:
109 	case B_GET_WRITE_STATUS:
110 		if (data) {
111 			*(bool *)data = false;
112 			return B_OK;
113 		}
114 		return EINVAL;
115 	case B_GET_GEOMETRY:
116 	case B_GET_BIOS_GEOMETRY:
117 		if (data) {
118 			device_geometry *geom = (device_geometry *)data;
119 			geom->bytes_per_sector = 256;
120 			geom->sectors_per_track = 1;
121 			geom->cylinder_count = cookie->dev->size / 256;
122 			geom->head_count = 1;
123 			geom->device_type = B_DISK;
124 			geom->removable = false;
125 			geom->read_only = false; // XXX
126 			geom->write_once = false;
127 			return B_OK;
128 		}
129 		return EINVAL;
130 	case B_GET_MEDIA_STATUS:
131 		if (data) {
132 			*(status_t *)data = B_OK;
133 			return B_OK;
134 		}
135 		return EINVAL;
136 
137 	case B_EJECT_DEVICE:
138 	case B_LOAD_MEDIA:
139 		return ENOSYS;
140 	case B_FLUSH_DRIVE_CACHE: /* wait for request list to be empty ? */
141 	default:
142 		return ENOSYS;
143 	}
144 	return B_NOT_ALLOWED;
145 }
146 
147 status_t nbd_read(cookie_t *cookie, off_t position, void *data, size_t *numbytes) {
148 	*numbytes = 0;
149 	return B_NOT_ALLOWED;
150 }
151 
152 status_t nbd_write(cookie_t *cookie, off_t position, const void *data, size_t *numbytes) {
153 	(void)cookie; (void)position; (void)data; (void)numbytes;
154 	*numbytes = 0;
155 	return EIO;
156 }
157 
158 device_hooks nbd_hooks={
159 	(device_open_hook)nbd_open,
160 	nbd_close,
161 	(device_free_hook)nbd_free,
162 	(device_control_hook)nbd_control,
163 	(device_read_hook)nbd_read,
164 	(device_write_hook)nbd_write,
165 	NULL,
166 	NULL,
167 	NULL,
168 	NULL
169 };
170 
171 
172 #pragma mark ==== driver hooks ====
173 
174 static const char *nbd_name[MAX_NBDS+1] = {
175 	NULL
176 };
177 
178 status_t
179 init_hardware (void)
180 {
181 	return B_OK;
182 }
183 
184 status_t
185 init_driver (void)
186 {
187 	int i;
188 	// load settings
189 	for (i = 0; i < MAX_NBDS; i++) {
190 		nbd_name[i] = malloc(DEVICE_NAME_MAX);
191 		if (nbd_name[i] == NULL)
192 			break;
193 		sprintf(nbd_name[i], DEVICE_FMT, i);
194 	}
195 	nbd_name[i] = NULL;
196 	return B_OK;
197 }
198 
199 void
200 uninit_driver (void)
201 {
202 	int i;
203 	for (i = 0; i < MAX_NBDS; i++) {
204 		free(nbd_name[i]);
205 	}
206 }
207 
208 const char**
209 publish_devices()
210 {
211 	return nbd_name;
212 }
213 
214 device_hooks*
215 find_device(const char* name)
216 {
217 	return &nbd_hooks;
218 }
219