1 /* libbdev - asynchronous call structure management */ 2 3 #include <minix/drivers.h> 4 #include <minix/bdev.h> 5 #include <assert.h> 6 7 #include "const.h" 8 #include "type.h" 9 #include "proto.h" 10 11 static bdev_call_t *calls[NR_CALLS]; 12 bdev_call_alloc(int count)13bdev_call_t *bdev_call_alloc(int count) 14 { 15 /* Allocate a call structure. 16 */ 17 bdev_call_t *call; 18 bdev_id_t id; 19 20 for (id = 0; id < NR_CALLS; id++) 21 if (calls[id] == NULL) 22 break; 23 24 if (id == NR_CALLS) 25 return NULL; 26 27 call = malloc(sizeof(bdev_call_t) + 28 sizeof(call->gvec[0]) * (count - 1) + 29 sizeof(call->vec[0]) * count); 30 31 if (call == NULL) 32 return NULL; 33 34 call->id = id; 35 call->vec = (iovec_t *) &call->gvec[count]; 36 37 calls[id] = call; 38 39 return call; 40 } 41 bdev_call_free(bdev_call_t * call)42void bdev_call_free(bdev_call_t *call) 43 { 44 /* Free a call structure. 45 */ 46 47 assert(calls[call->id] == call); 48 49 calls[call->id] = NULL; 50 51 free(call); 52 } 53 bdev_call_get(bdev_id_t id)54bdev_call_t *bdev_call_get(bdev_id_t id) 55 { 56 /* Retrieve a call structure by request number. 57 */ 58 59 if (id < 0 || id >= NR_CALLS) 60 return NULL; 61 62 return calls[id]; 63 } 64 bdev_call_find(dev_t dev)65bdev_call_t *bdev_call_find(dev_t dev) 66 { 67 /* Find the first asynchronous request for the given device, if any. 68 */ 69 bdev_id_t id; 70 71 for (id = 0; id < NR_CALLS; id++) 72 if (calls[id] != NULL && calls[id]->dev == dev) 73 return calls[id]; 74 75 return NULL; 76 } 77 bdev_call_iter_maj(dev_t dev,bdev_call_t * call,bdev_call_t ** next)78bdev_call_t *bdev_call_iter_maj(dev_t dev, bdev_call_t *call, 79 bdev_call_t **next) 80 { 81 /* Iterate over all asynchronous requests for a major device. This function 82 * must be safe even if the returned call structure is freed. 83 */ 84 bdev_id_t id; 85 int major; 86 87 major = major(dev); 88 89 /* If this is the first invocation, find the first match. Otherwise, take the 90 * call we found to be next in the last invocation, which may be NULL. 91 */ 92 if (call == NULL) { 93 for (id = 0; id < NR_CALLS; id++) 94 if (calls[id] != NULL && major(calls[id]->dev) == major) 95 break; 96 97 if (id == NR_CALLS) 98 return NULL; 99 100 call = calls[id]; 101 } else { 102 if ((call = *next) == NULL) 103 return NULL; 104 } 105 106 /* Look for the next match, if any. */ 107 *next = NULL; 108 109 for (id = call->id + 1; id < NR_CALLS; id++) { 110 if (calls[id] != NULL && major(calls[id]->dev) == major) { 111 *next = calls[id]; 112 113 break; 114 } 115 } 116 117 return call; 118 } 119