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