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