Changes in uspace/srv/devman/main.c [f9b2cb4c:005ac3c] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/devman/main.c
rf9b2cb4c r005ac3c 49 49 #include <io/log.h> 50 50 #include <ipc/devman.h> 51 #include <ipc/driver.h> 51 52 #include <loc.h> 52 53 … … 65 66 dev_tree_t device_tree; 66 67 67 static void devman_ connection_device(ipc_callid_t iid, ipc_call_t *icall,68 void *arg)68 static void devman_forward(ipc_callid_t iid, ipc_call_t *icall, 69 bool drv_to_parent) 69 70 { 70 71 devman_handle_t handle = IPC_GET_ARG2(*icall); 72 devman_handle_t fwd_h; 73 fun_node_t *fun = NULL; 71 74 dev_node_t *dev = NULL; 72 75 73 fun _node_t *fun= find_fun_node(&device_tree, handle);74 if (fun == NULL) {76 fun = find_fun_node(&device_tree, handle); 77 if (fun == NULL) 75 78 dev = find_dev_node(&device_tree, handle); 76 }else {79 else { 77 80 fibril_rwlock_read_lock(&device_tree.rwlock); 78 79 81 dev = fun->dev; 80 82 if (dev != NULL) 81 83 dev_add_ref(dev); 82 83 84 fibril_rwlock_read_unlock(&device_tree.rwlock); 84 85 } 85 86 86 87 /* 87 88 * For a valid function to connect to we need a device. The root … … 96 97 goto cleanup; 97 98 } 98 99 if (fun == NULL ) {99 100 if (fun == NULL && !drv_to_parent) { 100 101 log_msg(LOG_DEFAULT, LVL_ERROR, NAME ": devman_forward error - cannot " 101 102 "connect to handle %" PRIun ", refers to a device.", … … 105 106 } 106 107 108 driver_t *driver = NULL; 109 107 110 fibril_rwlock_read_lock(&device_tree.rwlock); 108 111 109 /* Connect to the specified function */ 110 driver_t *driver = dev->drv; 112 if (drv_to_parent) { 113 /* Connect to parent function of a device (or device function). */ 114 if (dev->pfun->dev != NULL) 115 driver = dev->pfun->dev->drv; 116 117 fwd_h = dev->pfun->handle; 118 } else { 119 /* Connect to the specified function */ 120 driver = dev->drv; 121 fwd_h = handle; 122 } 111 123 112 124 fibril_rwlock_read_unlock(&device_tree.rwlock); … … 118 130 goto cleanup; 119 131 } 132 133 int method; 134 if (drv_to_parent) 135 method = DRIVER_DRIVER; 136 else 137 method = DRIVER_CLIENT; 120 138 121 139 if (!driver->sess) { … … 125 143 goto cleanup; 126 144 } 127 145 128 146 if (fun != NULL) { 129 147 log_msg(LOG_DEFAULT, LVL_DEBUG, … … 137 155 138 156 async_exch_t *exch = async_exchange_begin(driver->sess); 139 async_forward_fast(iid, exch, INTERFACE_DDF_CLIENT, handle, 0, IPC_FF_NONE);157 async_forward_fast(iid, exch, method, fwd_h, 0, IPC_FF_NONE); 140 158 async_exchange_end(exch); 141 159 … … 148 166 } 149 167 150 static void devman_connection_parent(ipc_callid_t iid, ipc_call_t *icall, 151 void *arg) 152 { 153 devman_handle_t handle = IPC_GET_ARG2(*icall); 154 dev_node_t *dev = NULL; 155 156 fun_node_t *fun = find_fun_node(&device_tree, handle); 157 if (fun == NULL) { 158 dev = find_dev_node(&device_tree, handle); 159 } else { 160 fibril_rwlock_read_lock(&device_tree.rwlock); 161 162 dev = fun->dev; 163 if (dev != NULL) 164 dev_add_ref(dev); 165 166 fibril_rwlock_read_unlock(&device_tree.rwlock); 167 } 168 169 /* 170 * For a valid function to connect to we need a device. The root 171 * function, for example, has no device and cannot be connected to. 172 * This means @c dev needs to be valid regardless whether we are 173 * connecting to a device or to a function. 174 */ 175 if (dev == NULL) { 176 log_msg(LOG_DEFAULT, LVL_ERROR, "IPC forwarding failed - no device or " 177 "function with handle %" PRIun " was found.", handle); 178 async_answer_0(iid, ENOENT); 179 goto cleanup; 180 } 181 182 driver_t *driver = NULL; 168 /** Function for handling connections from a client forwarded by the location 169 * service to the device manager. */ 170 static void devman_connection_loc(ipc_callid_t iid, ipc_call_t *icall) 171 { 172 service_id_t service_id = IPC_GET_ARG2(*icall); 173 fun_node_t *fun; 174 dev_node_t *dev; 175 devman_handle_t handle; 176 driver_t *driver; 177 178 fun = find_loc_tree_function(&device_tree, service_id); 183 179 184 180 fibril_rwlock_read_lock(&device_tree.rwlock); 185 181 186 /* Connect to parent function of a device (or device function). */ 187 if (dev->pfun->dev != NULL) 188 driver = dev->pfun->dev->drv; 189 190 devman_handle_t fun_handle = dev->pfun->handle; 191 192 fibril_rwlock_read_unlock(&device_tree.rwlock); 193 194 if (driver == NULL) { 195 log_msg(LOG_DEFAULT, LVL_ERROR, "IPC forwarding refused - " \ 196 "the device %" PRIun " is not in usable state.", handle); 197 async_answer_0(iid, ENOENT); 198 goto cleanup; 199 } 200 201 if (!driver->sess) { 202 log_msg(LOG_DEFAULT, LVL_ERROR, 203 "Could not forward to driver `%s'.", driver->name); 204 async_answer_0(iid, EINVAL); 205 goto cleanup; 206 } 207 208 if (fun != NULL) { 209 log_msg(LOG_DEFAULT, LVL_DEBUG, 210 "Forwarding request for `%s' function to driver `%s'.", 211 fun->pathname, driver->name); 212 } else { 213 log_msg(LOG_DEFAULT, LVL_DEBUG, 214 "Forwarding request for `%s' device to driver `%s'.", 215 dev->pfun->pathname, driver->name); 216 } 217 218 async_exch_t *exch = async_exchange_begin(driver->sess); 219 async_forward_fast(iid, exch, INTERFACE_DDF_DRIVER, fun_handle, 0, IPC_FF_NONE); 220 async_exchange_end(exch); 221 222 cleanup: 223 if (dev != NULL) 224 dev_del_ref(dev); 225 226 if (fun != NULL) 227 fun_del_ref(fun); 228 } 229 230 static void devman_forward(ipc_callid_t iid, ipc_call_t *icall, void *arg) 231 { 232 iface_t iface = IPC_GET_ARG1(*icall); 233 service_id_t service_id = IPC_GET_ARG2(*icall); 234 235 fun_node_t *fun = find_loc_tree_function(&device_tree, service_id); 236 237 fibril_rwlock_read_lock(&device_tree.rwlock); 238 239 if ((fun == NULL) || (fun->dev == NULL) || (fun->dev->drv == NULL)) { 240 log_msg(LOG_DEFAULT, LVL_WARN, "devman_forward(): function " 182 if (fun == NULL || fun->dev == NULL || fun->dev->drv == NULL) { 183 log_msg(LOG_DEFAULT, LVL_WARN, "devman_connection_loc(): function " 241 184 "not found.\n"); 242 185 fibril_rwlock_read_unlock(&device_tree.rwlock); … … 245 188 } 246 189 247 dev _node_t *dev= fun->dev;248 driver _t *driver= dev->drv;249 devman_handle_thandle = fun->handle;190 dev = fun->dev; 191 driver = dev->drv; 192 handle = fun->handle; 250 193 251 194 fibril_rwlock_read_unlock(&device_tree.rwlock); 252 195 253 196 async_exch_t *exch = async_exchange_begin(driver->sess); 254 async_forward_fast(iid, exch, iface, handle, 0, IPC_FF_NONE); 197 async_forward_fast(iid, exch, DRIVER_CLIENT, handle, 0, 198 IPC_FF_NONE); 255 199 async_exchange_end(exch); 256 200 257 201 log_msg(LOG_DEFAULT, LVL_DEBUG, 258 "Forwarding service request for `%s' function to driver `%s'.",202 "Forwarding loc service request for `%s' function to driver `%s'.", 259 203 fun->pathname, driver->name); 260 204 261 205 fun_del_ref(fun); 206 } 207 208 /** Function for handling connections to device manager. */ 209 static void devman_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 210 { 211 /* Select port. */ 212 switch ((sysarg_t) (IPC_GET_ARG1(*icall))) { 213 case DEVMAN_DRIVER: 214 devman_connection_driver(iid, icall); 215 break; 216 case DEVMAN_CLIENT: 217 devman_connection_client(iid, icall); 218 break; 219 case DEVMAN_CONNECT_TO_DEVICE: 220 /* Connect client to selected device. */ 221 devman_forward(iid, icall, false); 222 break; 223 case DEVMAN_CONNECT_FROM_LOC: 224 /* Someone connected through loc node. */ 225 devman_connection_loc(iid, icall); 226 break; 227 case DEVMAN_CONNECT_TO_PARENTS_DEVICE: 228 /* Connect client to selected device. */ 229 devman_forward(iid, icall, true); 230 break; 231 default: 232 /* No such interface */ 233 async_answer_0(iid, ENOENT); 234 } 262 235 } 263 236 … … 325 298 async_set_client_data_constructor(devman_client_data_create); 326 299 async_set_client_data_destructor(devman_client_data_destroy); 327 328 port_id_t port; 329 rc = async_create_port(INTERFACE_DDF_DRIVER, 330 devman_connection_driver, NULL, &port); 331 if (rc != EOK) 332 return rc; 333 334 rc = async_create_port(INTERFACE_DDF_CLIENT, 335 devman_connection_client, NULL, &port); 336 if (rc != EOK) 337 return rc; 338 339 rc = async_create_port(INTERFACE_DEVMAN_DEVICE, 340 devman_connection_device, NULL, &port); 341 if (rc != EOK) 342 return rc; 343 344 rc = async_create_port(INTERFACE_DEVMAN_PARENT, 345 devman_connection_parent, NULL, &port); 346 if (rc != EOK) 347 return rc; 348 349 async_set_fallback_port_handler(devman_forward, NULL); 300 async_set_client_connection(devman_connection); 350 301 351 302 if (!devman_init()) {
Note:
See TracChangeset
for help on using the changeset viewer.