|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved.
25: *
26: * Config.c - Config server.
27: *
28: * HISTORY
29: * 11-Apr-91 Doug Mitchell at NeXT
30: * Created.
31: */
32:
33: #import <bsd/sys/types.h>
34: #import <bsd/libc.h>
35: #import <mach/mach_types.h>
36: #import <driverkit/userConfigServer.h>
37: #import <driverkit/generalFuncs.h>
38: #import "ConfigPrivate.h"
39: #import "ConfigUtils.h"
40: #import "ConfigScan.h"
41: #import <mach/kern_return.h>
42: #import <mach/mach.h>
43: #import <servers/netname.h>
44: #import <mach/message.h>
45: #import <mach/mach_error.h>
46: #import <mach/cthreads.h>
47: #import <kernserv/queue.h>
48: #import <mach/notify.h>
49: #import <syslog.h>
50: #ifdef DEBUG
51: #import "ConfigUfs.h"
52: #endif DEBUG
53:
54: /*
55: * prototypes for private functions.
56: */
57: static void usage(char **argv);
58: static void server_loop();
59: boolean_t Config_server(msg_header_t *inp, msg_header_t *outp);
60: static void config_port_death(msg_header_t *inp);
61:
62: /*
63: * Static variables.
64: */
65: static port_t config_port; // we advertise this for all takers
66: static port_set_name_t config_port_set; // the set on which we listen
67: port_t device_master_port; // used to communicate with kernel
68: port_t notify_port; // that's ours
69: static boolean_t config_in_progress; // prevents hazardous operations
70: // during initial config
71: queue_head_t driver_list; // list of driver_entry_t's
72: mutex_t driver_list_lock; // protects driver_list during initial
73: // config
74: condition_t driver_list_cond;
75: boolean_t driver_list_locked;
76:
77: extern port_t device_master_self();
78:
79: /*
80: * User-specified variables.
81: */
82: int verbose = 0;
83:
84: void main(int argc, char **argv)
85: {
86: int arg;
87: kern_return_t krtn;
88: cthread_t server_thread;
89:
90: if(argc < 1)
91: usage(argv);
92: for(arg=1; arg<argc; arg++) {
93: switch(argv[arg][0]) {
94: case 'v':
95: verbose++;
96: break;
97: default:
98: usage(argv);
99: }
100: }
101:
102: #ifdef DDM_DEBUG
103: IOInitDDM(200, "ConfigXpr");
104: IOSetDDMMask(XPR_CONFIG_INDEX,
105: XPR_CONFIG | XPR_SERVER | XPR_COMMON | XPR_ERR);
106: #endif DDM_DEBUG
107:
108: /*
109: * Initialize global state.
110: */
111: queue_init(&driver_list);
112: driver_list_lock = mutex_alloc();
113: driver_list_cond = condition_alloc();
114: config_in_progress = TRUE;
115:
116: /*
117: * Set up various ports and start the server thread before initial
118: * autoconfig so device drivers have a place to send messages.
119: *
120: * config_port is how we advertise our exported services to all.
121: */
122: krtn = port_allocate(task_self(), &config_port);
123: if(krtn) {
124: mach_error("port_allocate", krtn);
125: exit(1);
126: }
127: krtn = port_set_allocate(task_self(), &config_port_set);
128: if(krtn) {
129: mach_error("port_set_allocate", krtn);
130: exit(1);
131: }
132: krtn = port_set_add(task_self(), config_port_set, config_port);
133: if(krtn) {
134: mach_error("port_set_add", krtn);
135: exit(1);
136: }
137:
138: /*
139: * we get port death notification on notify_port.
140: */
141: krtn = port_allocate(task_self(), ¬ify_port);
142: if(krtn) {
143: mach_error("port_allocate", krtn);
144: exit(1);
145: }
146: krtn = task_set_notify_port(task_self(), notify_port);
147: if(krtn) {
148: mach_error("task_set_notify_port", krtn);
149: exit(1);
150: }
151: krtn = port_set_add(task_self(), config_port_set, notify_port);
152: if(krtn) {
153: mach_error("port_set_add", krtn);
154: exit(1);
155: }
156: krtn = netname_check_in(name_server_port,
157: CONFIG_SERVER_NAME,
158: task_self(),
159: config_port);
160: if(krtn) {
161: mach_error("netname_check_in", krtn);
162: exit(1);
163: }
164: device_master_port = device_master_self();
165: if(device_master_port == PORT_NULL) {
166: syslog(LOG_ERR, "Config: Can't get device_master_port\n");
167: exit(1);
168: }
169:
170: server_thread = cthread_fork((cthread_fn_t)server_loop, (any_t)0);
171:
172: /*
173: * Do initial autoconfig.
174: */
175: config_scan(SCAN_ALL, IO_NULL_SLOT_ID, IO_NULL_DEVICE_TYPE);
176:
177: /*
178: * We're done; let the server_thread take it from here.
179: */
180: config_in_progress = FALSE;
181: cthread_exit(0);
182: }
183:
184: static void usage(char **argv)
185: {
186: printf("usage: %s [options]\n", argv[0]);
187: printf("Options:\n");
188: printf("\tv verbose mode\n");
189: exit(1);
190: }
191:
192:
193: /*
194: * Main server loop. This thread starts running before autoconfiguration
195: * takes place to allow servicing of IORegisterDriver() calls during
196: * autoconfig. The config_in_progress flag prevents us from servicing any
197: * hazardous calls during this time - like IORescanDriver(). Such calls will
198: * return a IO_CNF_BUSY status.
199: */
200: static void server_loop()
201: {
202: msg_header_t *inp, *outp;
203: kern_return_t krtn;
204: boolean_t return_msg;
205:
206: inp = (msg_header_t *)malloc(MSG_SIZE_MAX);
207: outp = (msg_header_t *)malloc(MSG_SIZE_MAX);
208: while (1) {
209: inp->msg_local_port = config_port_set;
210: inp->msg_size = MSG_SIZE_MAX;
211: krtn = msg_receive(inp, MSG_OPTION_NONE, 0);
212: if(krtn) {
213: mach_error("msg_receive", krtn);
214: continue;
215: }
216: xpr_server("msg_id %d received\n", inp->msg_id, 2,3,4,5);
217: return_msg = FALSE;
218: if(inp->msg_local_port == config_port) {
219: Config_server(inp, outp);
220: return_msg = TRUE;
221: }
222: else if(inp->msg_local_port == notify_port) {
223: config_port_death(inp);
224: }
225: else {
226: printf("Config server_loop: Bogus msg_local_port\n");
227: }
228:
229: if(return_msg) {
230: /*
231: * Return message to client. We don't deal with
232: * backed up port queues for now.
233: */
234: krtn = msg_send(outp, SEND_TIMEOUT, 0);
235: if(krtn) {
236: mach_error("msg_receive", krtn);
237: continue;
238: }
239: }
240: }
241: /* NOT REACHED */
242: }
243:
244: /*
245: * Handle port death notification. The only ports we're interested in are
246: * driver_ports.
247: */
248: static void config_port_death(msg_header_t *inp)
249: {
250: notification_t *msgp = (notification_t *)inp;
251: driver_entry_t *driver_entry;
252: queue_head_t dev_list;
253: dev_entry_t *dev_entry;
254: IOReturn drtn;
255:
256: /*
257: * FIXME: use NOTIFY_PORT_DESTOYED??
258: */
259: if(inp->msg_id != NOTIFY_PORT_DELETED) {
260: xpr_server("config_port_death: weird msg_id (%d)\n",
261: inp->msg_id, 2,3,4,5);
262: return;
263: }
264: xpr_server("config_port_death: port %d\n", msgp->notify_port, 2,3,4,5);
265: get_driver_list_lock();
266: driver_entry = get_driver_entry(
267: SK_DRIVER_PORT,
268: msgp->notify_port,
269: DEV_NUM_NULL,
270: FID_NULL,
271: IO_NULL_DEVICE_TYPE,
272: IO_NULL_SLOT_ID,
273: NULL);
274: release_driver_list_lock();
275: if(driver_entry == NULL) {
276: xpr_server("config_port_death: not sig port\n",
277: 1,2,3,4,5);
278: return;
279: }
280: driver_entry->driver_port = PORT_NULL;
281:
282: /*
283: * Shut down all devices associated with this driver.
284: * First, move all of this driver's dev_entry's to our local
285: * queue.
286: */
287: queue_init(&dev_list);
288: while(!queue_empty(&driver_entry->dev_list)) {
289: dev_entry = (dev_entry_t *)
290: queue_first(&driver_entry->dev_list);
291: queue_remove(&driver_entry->dev_list,
292: dev_entry,
293: dev_entry_t *,
294: link);
295: queue_enter(&dev_list,
296: dev_entry,
297: dev_entry_t *,
298: link);
299: }
300:
301: /*
302: * For each device, destroy the associated device port, then
303: * create a new one for the same physical device.
304: */
305: while(!queue_empty(&dev_list)) {
306: dev_entry = (dev_entry_t *)queue_first(&dev_list);
307: queue_remove(&dev_list,
308: dev_entry,
309: dev_entry_t *,
310: link);
311: if(dev_entry->dev_port) {
312: drtn = _IODestroyDevicePort(device_master_port,
313: dev_entry->dev_port);
314: if(drtn) {
315: xpr_common("config_port_death: "
316: "_IODestroyDevicePort() returned %s\n",
317: IOFindNameForValue(drtn, dev_returns),
318: 2,3,4,5);
319: /* but keep going... */
320: }
321: }
322: create_dev_entry(driver_entry,
323: dev_entry->dev_number,
324: dev_entry->dev_type,
325: dev_entry->slot_id);
326:
327: /*
328: * Our dev_entry is a useless copy...
329: */
330: free(dev_entry);
331: }
332:
333: /*
334: * Now restart the driver.
335: */
336: xpr_server("config_port_death: restarting driver %s\n",
337: IOCopyString(driver_entry->filename), 2,3,4,5);
338: if(exec_driver(driver_entry) != IO_CNF_SUCCESS) {
339: /*
340: * Couldn't exec this driver. Remove from driver_list.
341: */
342: get_driver_list_lock();
343: free_driver_entry(driver_entry);
344: release_driver_list_lock();
345: }
346: }
347:
348: /*
349: * These functions are called out from the mig-generated Config_server.
350: */
351:
352: /*
353: * Each driver which we exec calls this exactly once. The purpose is to
354: * register a driver_port for the driver's driver_entry so we can detect the
355: * death of the driver.
356: */
357: IOConfigReturn _IORegisterDriver(
358: port_t dev_config_port,
359: port_t driver_sig_port,
360: port_t driver_port)
361: {
362: driver_entry_t *driver_entry;
363: IOConfigReturn rtn = IO_CNF_SUCCESS;
364:
365: xpr_server("driver_register driver_port %d\n", driver_port, 2,3,4,5);
366: get_driver_list_lock();
367:
368: /*
369: * Make sure that this is a new registration for a device we
370: * know about.
371: */
372: driver_entry = get_driver_entry(
373: SK_SIG_PORT,
374: driver_sig_port,
375: DEV_NUM_NULL,
376: FID_NULL,
377: IO_NULL_DEVICE_TYPE,
378: IO_NULL_SLOT_ID,
379: NULL);
380: if(driver_entry == NULL) {
381: xpr_server("device_register: BAD driver_sig_port\n",
382: 1,2,3,4,5);
383: rtn = IO_CNF_NOT_REGISTERED;
384: goto done;
385: }
386: if(driver_entry->driver_port != PORT_NULL) {
387: xpr_server("device_register: REDUNDANT REGISTRATION\n",
388: 1,2,3,4,5);
389: rtn = IO_CNF_REGISTERED;
390: goto done;
391: }
392: driver_entry->driver_port = driver_port;
393: done:
394: release_driver_list_lock();
395: return rtn;
396: }
397:
398: /*
399: * Release all state associated with specified driver. Can only be called
400: * by drivers we exec.
401: */
402: IOConfigReturn _IODeleteDriver(
403: port_t dev_config_port,
404: port_t driver_sig_port)
405: {
406: driver_entry_t *driver_entry;
407: IOConfigReturn rtn = IO_CNF_SUCCESS;
408:
409: xpr_server("driver_delete\n", 1,2,3,4,5);
410:
411: get_driver_list_lock();
412: driver_entry = get_driver_entry(
413: SK_SIG_PORT,
414: driver_sig_port,
415: DEV_NUM_NULL,
416: FID_NULL,
417: IO_NULL_DEVICE_TYPE,
418: IO_NULL_SLOT_ID,
419: NULL);
420: if(driver_entry == NULL) {
421: xpr_server("driver_delete: BAD driver_sig_port\n",
422: 1,2,3,4,5);
423: rtn = IO_CNF_NOT_REGISTERED;
424: goto done;
425: }
426:
427: rtn = free_driver_entry(driver_entry);
428: done:
429: release_driver_list_lock();
430: return rtn;
431: }
432:
433: #if SUPPORT_DEVICE_DELETE
434: /*
435: * Release state associated with one device. Can only be called
436: * by drivers we exec.
437: *
438: * FIXME:
439: * problem - a driver deletes some ports via device_delete(), then crashes.
440: * On restart, should it have access to all of the dev_ports it initially
441: * had? Currently it won't because Config did device_destroy()'s on the
442: * dev_ports. Those dev_entry's will be missing from the driver_entry's
443: * dev_list...
444: *
445: * Also, how to assign a deleted device to another driver if the deletor
446: * keeps running? A config_scan() will just add it to that driver's
447: * dev_list and since that driver's already running, it won't get exec'd.
448: *
449: * SO...for now we don't support device_delete().
450: */
451: IOConfigReturn _IODeleteDevice(
452: port_t dev_config_port,
453: port_t driver_sig_port,
454: dev_port_t dev_port)
455: {
456: driver_entry_t *driver_entry;
457: dev_entry_t *dev_entry;
458: IOConfigReturn rtn = IO_CNF_SUCCESS;
459:
460: xpr_server("device_delete\n", 1,2,3,4,5);
461: get_driver_list_lock();
462: driver_entry = get_driver_entry(
463: SK_DEV_PORT,
464: dev_port,
465: DEV_NUM_NULL,
466: FID_NULL,
467: IO_NULL_DEVICE_TYPE,
468: IO_NULL_SLOT_ID,
469: &dev_entry);
470: if(driver_entry == NULL) {
471: rtn = IO_CNF_NOT_REGISTERED;
472: goto done;
473: }
474: if(dev_entry == NULL) {
475: /*
476: * Huh? This should not happen...
477: */
478: rtn = IO_CNF_NOT_REGISTERED;
479: goto done;
480: }
481: if(driver_entry->driver_sig_port != driver_sig_port) {
482: rtn = IO_CNF_NOT_REGISTERED;
483: goto done;
484: }
485: rtn = free_dev_entry(dev_entry);
486: done:
487: release_driver_list_lock();
488: xpr_server("device_delete: returning %s\n",
489: reg_text(*rtn, config_returns), 2,3,4,5);
490: return rtn;
491: }
492:
493: #endif SUPPORT_DEVICE_DELETE
494:
495: /*
496: * Do a complete rescan of all potential devices. Exec drivers for the
497: * devices which we don't currently have registered drivers. This can be
498: * called by anyone who can get dev_config_port. We return Busy status if
499: * initial config is still in progress.
500: */
501: IOConfigReturn _IORescanDriver(
502: port_t dev_config_port)
503: {
504: IOConfigReturn rtn;
505:
506: xpr_server("driver_rescan\n", 1,2,3,4,5);
507: if(config_in_progress) {
508: return(IO_CNF_BUSY);
509: }
510: rtn = config_scan(SCAN_ALL, IO_NULL_SLOT_ID, IO_NULL_DEVICE_TYPE);
511: return rtn;
512: }
513:
514: /*
515: * Attempt to start a driver for device specified by slot_id and dev_type.
516: * This can be called by anyone who can get dev_config_port. We return
517: * Busy status if initial config is still in progress.
518: */
519: IOConfigReturn _IOConfigDevice(
520: port_t dev_config_port,
521: IOSlotId slot_id,
522: IODeviceType dev_type)
523: {
524: IOConfigReturn rtn;
525:
526: xpr_server("driver_config\n", 1,2,3,4,5);
527: if(config_in_progress) {
528: return(IO_CNF_BUSY);
529: }
530: rtn = config_scan(SCAN_ONE, slot_id, dev_type);
531: return rtn;
532: }
533:
534: #ifdef DEBUG
535:
536: /*
537: * For debugging new drivers. Delete state associated with specified slot_id
538: * and device_type.
539: */
540: IOConfigReturn _IODeleteDeviceByType(
541: port_t configPort,
542: IOSlotId slot_id,
543: IODeviceType device_type)
544: {
545: IOConfigReturn rtn;
546: driver_entry_t *driver_entry;
547: dev_entry_t *dev_entry;
548:
549: xpr_server("IODeleteDeviceByType: slot_id 0x%x device_type 0x%x\n",
550: slot_id, device_type, 3,4,5);
551:
552: /*
553: * Get driver_entry associated with this slotId and deviceType.
554: */
555: get_driver_list_lock();
556: driver_entry = get_driver_entry(
557: SK_DEV_INDEX,
558: PORT_NULL,
559: DEV_NUM_NULL,
560: FID_NULL,
561: device_type,
562: slot_id,
563: &dev_entry);
564: if(driver_entry == NULL) {
565: rtn = IO_CNF_NOT_FOUND;
566: goto done;
567: }
568:
569: rtn = free_driver_entry(driver_entry);
570: done:
571: release_driver_list_lock();
572: return rtn;
573:
574: }
575: #endif DEBUG
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.