Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.sbin / pccard / pccardd / pccardd.c
1 /*
2  * Copyright (c) 1995 Andrew McRae.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  *    derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #ifndef lint
28 static const char rcsid[] =
29   "$FreeBSD: src/usr.sbin/pccard/pccardd/pccardd.c,v 1.6.2.6 2001/08/02 18:51:38 imp Exp $";
30 #endif /* not lint */
31
32 #include <signal.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <sys/socket.h>
39 #include <sys/un.h>
40 #include <sys/stat.h>
41 #define EXTERN
42 #include "cardd.h"
43
44 char   *config_file = "/etc/defaults/pccard.conf";
45 static char *pid_file = "/var/run/pccardd.pid";
46
47 /*
48  * pathname of UNIX-domain socket
49  */
50 static char     *socket_name = "/var/tmp/.pccardd";
51 static char     *sock = 0;
52 static int      server_sock;
53
54 /* SIGHUP signal handler */
55 static void
56 restart(void)
57 {
58         bitstr_t bit_decl(io_inuse, IOPORTS);
59         bitstr_t bit_decl(mem_inuse, MEMBLKS);
60         int     irq_inuse[16];
61         int     i;
62         struct sockaddr_un sun;
63
64         bit_nclear(io_inuse, 0, IOPORTS-1);
65         bit_nclear(mem_inuse, 0, MEMBLKS-1);
66         bzero(irq_inuse, sizeof(irq_inuse));
67
68         /* compare the initial and current state of resource pool */
69         for (i = 0; i < IOPORTS; i++) {
70                 if (bit_test(io_init, i) == 1 && bit_test(io_avail, i) == 0) {
71                         if (debug_level >= 1) {
72                                 logmsg("io 0x%x seems to be in use\n", i);
73                         }
74                         bit_set(io_inuse, i);
75                 }
76         }
77         for (i = 0; i < MEMBLKS; i++) {
78                 if (bit_test(mem_init, i) == 1 && bit_test(mem_avail, i) == 0) {
79                         if (debug_level >= 1) {
80                                 logmsg("mem 0x%x seems to be in use\n", i);
81                         }
82                         bit_set(mem_inuse, i);
83                 }
84         }
85         for (i = 0; i < 16; i++) {
86                 if (irq_init[i] == 1 && pool_irq[i] == 0) {
87                         if (debug_level >= 1) {
88                                 logmsg("irq %d seems to be in use\n", i);
89                         }
90                         irq_inuse[i] = 1;
91                 }
92         }
93
94         readfile(config_file);
95
96         /* reflect used resources to managed resource pool */
97         for (i = 0; i < IOPORTS; i++) {
98                 if (bit_test(io_inuse, i) == 1) {
99                         bit_clear(io_avail, i);
100                 }
101         }
102         for (i = 0; i < MEMBLKS; i++) {
103                 if (bit_test(mem_inuse, i) == 1) {
104                         bit_clear(mem_avail, i);
105                 }
106         }
107         for (i = 0; i < 16; i++) {
108                 if (irq_inuse[i] == 1) {
109                         pool_irq[i] = 0;
110                 }
111         }
112         close(server_sock);
113         if ((server_sock = socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0)
114                 die("socket failed");
115         bzero(&sun, sizeof(sun));
116         sun.sun_family = AF_UNIX;
117         if (sock) {
118                 socket_name = sock;
119         }
120         strcpy(sun.sun_path, socket_name);
121         slen = SUN_LEN(&sun);
122         (void)unlink(socket_name);
123         if (bind(server_sock, (struct sockaddr *) & sun, slen) < 0)
124                 die("bind failed");
125         chown(socket_name, 0, 5);       /* XXX - root.operator */
126         chmod(socket_name, 0660);
127         set_socket(server_sock);
128 }
129
130 /* SIGTERM/SIGINT signal handler */
131 static void
132 term(int sig)
133 {
134         logmsg("pccardd terminated: signal %d received", sig);
135         (void)unlink(pid_file);
136         exit(0);
137 }
138
139 static void
140 write_pid()
141 {
142         FILE *fp = fopen(pid_file, "w");
143
144         if (fp) {
145                 fprintf(fp, "%d\n", getpid());
146                 fclose(fp);
147         }
148 }
149
150 int doverbose = 0;
151 /*
152  *      mainline code for cardd
153  */
154 int
155 main(int argc, char *argv[])
156 {
157         struct slot *sp;
158         int count, dodebug = 0;
159         int delay = 0;
160         int irq_arg[16];
161         int irq_specified = 0;
162         int i;
163         struct sockaddr_un sun;
164 #define COM_OPTS        ":Idvf:s:i:z"
165
166         bzero(irq_arg, sizeof(irq_arg));
167         use_kern_irq = 1;
168         debug_level = 0;
169         pccard_init_sleep = 5000000;
170         cards = last_card = 0;
171         while ((count = getopt(argc, argv, COM_OPTS)) != -1) {
172                 switch (count) {
173                 case 'I':
174                         use_kern_irq = 0;
175                         break;
176                 case 'd':
177                         setbuf(stdout, 0);
178                         setbuf(stderr, 0);
179                         dodebug = 1;
180                         break;
181                 case 'v':
182                         doverbose = 1;
183                         break;
184                 case 'f':
185                         config_file = optarg;
186                         break;
187                 case 'i':
188                         /* configure available irq */
189                         if (sscanf(optarg, "%d", &i) != 1) {
190                                 fprintf(stderr, "%s: -i number\n", argv[0]);
191                                 exit(1);
192                         }
193                         irq_arg[i] = 1;
194                         irq_specified = 1;
195                         break;
196                 case 's':
197                         sock = optarg;
198                         break;
199                 case 'z':
200                         delay = 1;
201                         break;
202                 case ':':
203                         die("no config file argument");
204                         break;
205                 case '?':
206                         die("illegal option");
207                         break;
208                 }
209         }
210 #ifdef  DEBUG
211         dodebug = 1;
212 #endif
213         io_avail = bit_alloc(IOPORTS);  /* Only supports ISA ports */
214         io_init  = bit_alloc(IOPORTS);
215
216         /* Mem allocation done in MEMUNIT units. */
217         mem_avail = bit_alloc(MEMBLKS);
218         mem_init  = bit_alloc(MEMBLKS);
219         readfile(config_file);
220         if (irq_specified) {
221                 bcopy(irq_arg, pool_irq, sizeof(irq_arg));
222                 bcopy(irq_arg, irq_init, sizeof(irq_arg));
223         }
224         if (doverbose)
225                 dump_config_file();
226         log_setup();
227         if (!dodebug && !delay)
228                 if (daemon(0, 0))
229                         die("fork failed");
230         slots = readslots();
231         if (slots == 0)
232                 die("no PC-CARD slots");
233         if (delay)
234                 if (daemon(0, 0))
235                         die("fork failed");
236         logmsg("pccardd started", NULL);
237         write_pid();
238
239         if ((server_sock = socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0)
240                 die("socket failed");
241         bzero(&sun, sizeof(sun));
242         sun.sun_family = AF_UNIX;
243         if (sock) {
244                 socket_name = sock;
245         }
246         strcpy(sun.sun_path, socket_name);
247         slen = SUN_LEN(&sun);
248         (void)unlink(socket_name);
249         if (bind(server_sock, (struct sockaddr *) & sun, slen) < 0)
250                 die("bind failed");
251         chown(socket_name, 0, 5);       /* XXX - root.operator */
252         chmod(socket_name, 0660);
253         set_socket(server_sock);
254
255         (void)signal(SIGINT, dodebug ? term : SIG_IGN);
256         (void)signal(SIGTERM, term);
257         (void)signal(SIGHUP, (void (*)(int))restart);
258
259         for (;;) {
260                 fd_set  rmask, emask;
261                 FD_ZERO(&emask);
262                 FD_ZERO(&rmask);
263                 for (sp = slots; sp; sp = sp->next)
264                         FD_SET(sp->fd, &emask);
265                 FD_SET(server_sock, &rmask);
266                 count = select(32, &rmask, 0, &emask, 0);
267                 if (count == -1) {
268                         logerr("select");
269                         continue;
270                 }
271                 if (count) {
272                         for (sp = slots; sp; sp = sp->next)
273                                 if (FD_ISSET(sp->fd, &emask))
274                                         slot_change(sp);
275                         if (FD_ISSET(server_sock, &rmask))
276                                 process_client();
277                 }
278         }
279 }