Drop main() prototype. Syncs with NetBSD-8
[minix.git] / minix / lib / libbdev / driver.c
blob6c0a3deaec19ab08c614439251921e3d8cdd84d2
1 /* libbdev - driver endpoint management */
3 #include <minix/drivers.h>
4 #include <minix/bdev.h>
5 #include <minix/ds.h>
6 #include <assert.h>
8 #include "const.h"
9 #include "type.h"
10 #include "proto.h"
12 static struct {
13 endpoint_t endpt;
14 char label[DS_MAX_KEYLEN];
15 } driver_tab[NR_DEVICES];
17 void bdev_driver_init(void)
19 /* Initialize the driver table.
21 int i;
23 for (i = 0; i < NR_DEVICES; i++) {
24 driver_tab[i].endpt = NONE;
25 driver_tab[i].label[0] = '\0';
29 void bdev_driver_clear(dev_t dev)
31 /* Clear information about a driver.
33 int major;
35 major = major(dev);
37 assert(major >= 0 && major < NR_DEVICES);
39 driver_tab[major].endpt = NONE;
40 driver_tab[major].label[0] = '\0';
43 endpoint_t bdev_driver_set(dev_t dev, char *label)
45 /* Set the label for a driver, and retrieve the associated endpoint.
47 int major;
49 major = major(dev);
51 assert(major >= 0 && major < NR_DEVICES);
52 assert(strlen(label) < sizeof(driver_tab[major].label));
54 strlcpy(driver_tab[major].label, label, sizeof(driver_tab[major].label));
56 driver_tab[major].endpt = NONE;
58 return bdev_driver_update(dev);
61 endpoint_t bdev_driver_get(dev_t dev)
63 /* Return the endpoint for a driver, or NONE if we do not know its endpoint.
65 int major;
67 major = major(dev);
69 assert(major >= 0 && major < NR_DEVICES);
71 return driver_tab[major].endpt;
74 endpoint_t bdev_driver_update(dev_t dev)
76 /* Update the endpoint of a driver. The caller of this function already knows
77 * that the current endpoint may no longer be valid, and must be updated.
78 * Return the new endpoint upon success, and NONE otherwise.
80 endpoint_t endpt;
81 int r, major, nr_tries;
83 major = major(dev);
85 assert(major >= 0 && major < NR_DEVICES);
86 assert(driver_tab[major].label[0] != '\0');
88 /* Repeatedly retrieve the endpoint for the driver label, and see if it is a
89 * different, valid endpoint. If retrieval fails at first, we have to wait.
90 * We use polling, as opposed to a DS subscription, for a number of reasons:
91 * 1) DS supports only one subscription per process, and our main program may
92 * already have a subscription;
93 * 2) if we block on receiving a notification from DS, we cannot impose an
94 * upper bound on the retry time;
95 * 3) temporarily subscribing and then unsubscribing may cause leftover DS
96 * notifications, which the main program would then have to deal with.
97 * As of writing, unsubscribing from DS is not possible at all, anyway.
99 * In the normal case, the driver's label/endpoint mapping entry disappears
100 * completely for a short moment, before being replaced with the new mapping.
101 * Hence, failure to retrieve the entry at all does not constitute permanent
102 * failure. In fact, there is no way to determine reliably that a driver has
103 * failed permanently in the current approach. For this we simply rely on the
104 * retry limit.
106 for (nr_tries = 0; nr_tries < DS_NR_TRIES; nr_tries++) {
107 r = ds_retrieve_label_endpt(driver_tab[major].label, &endpt);
109 if (r == OK && endpt != NONE && endpt != driver_tab[major].endpt) {
110 driver_tab[major].endpt = endpt;
112 return endpt;
115 if (nr_tries < DS_NR_TRIES - 1)
116 micro_delay(DS_DELAY);
119 driver_tab[major].endpt = NONE;
121 return NONE;