1/*
2 * Copyright (c) 1997, 2000 Hellmuth Michaelis. 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 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 *---------------------------------------------------------------------------
26 *
27 *	i4b daemon - controller state support routines
28 *	----------------------------------------------
29 *
30 *	$Id: controller.c,v 1.10 2009/04/16 05:56:32 lukem Exp $
31 *
32 * $FreeBSD$
33 *
34 *      last edit-date: [Mon Oct  9 14:37:34 2000]
35 *
36 *---------------------------------------------------------------------------*/
37
38#include <sys/types.h>
39#include <sys/mman.h>
40
41#include <fcntl.h>
42
43#include "isdnd.h"
44
45static int
46init_controller_state(int controller, const char *devnam, const char *cardname, int tei, int nbch);
47
48/*
49 * add a single controller
50 */
51void
52init_new_controller(int isdnif)
53{
54	msg_ctrl_info_req_t mcir;
55
56	memset(&mcir, 0, sizeof mcir);
57	mcir.controller = isdnif;
58
59	if ((ioctl(isdnfd, I4B_CTRL_INFO_REQ, &mcir)) < 0)
60		return;
61
62	if ((init_controller_state(isdnif, mcir.devname, mcir.cardname, mcir.tei, mcir.nbch)) == ERROR)
63	{
64		logit(LL_ERR, "init_new_controller: init_controller_state for controller %d failed", isdnif);
65		do_exit(1);
66	}
67}
68
69/*---------------------------------------------------------------------------*
70 *	init controller state array
71 *---------------------------------------------------------------------------*/
72void
73init_controller(void)
74{
75	int i;
76	int max = 0;
77	msg_ctrl_info_req_t mcir;
78
79	remove_all_ctrl_state();
80	for (i=0; i <= max; i++)
81	{
82		mcir.controller = i;
83
84		if ((ioctl(isdnfd, I4B_CTRL_INFO_REQ, &mcir)) < 0)
85			continue;
86
87		max = mcir.max_isdnif;
88
89		/* init controller tab */
90
91		if ((init_controller_state(i, mcir.devname, mcir.cardname, mcir.tei, mcir.nbch)) == ERROR)
92		{
93			logit(LL_ERR, "init_controller: init_controller_state for controller %d failed", i);
94			do_exit(1);
95		}
96	}
97	DBGL(DL_RCCF, (logit(LL_DBG, "init_controller: found %d ISDN controller(s)", max)));
98}
99
100/*--------------------------------------------------------------------------*
101 *	init controller state table entry
102 *--------------------------------------------------------------------------*/
103static int
104init_controller_state(int controller, const char *devnam, const char *cardname, int tei, int nbch)
105{
106	struct isdn_ctrl_state *ctrl;
107	int i;
108
109	ctrl = malloc(sizeof *ctrl);
110	if (ctrl == NULL) {
111		logit(LL_ERR, "init_controller_state: out of memory");
112		return(ERROR);
113	}
114
115	/* init controller state entry */
116
117	memset(ctrl, 0, sizeof *ctrl);
118	strncpy(ctrl->device_name,
119	    devnam,
120	    sizeof(ctrl->device_name)-1);
121	strncpy(ctrl->controller,
122	    cardname,
123	    sizeof(ctrl->controller)-1);
124	ctrl->isdnif = controller;
125	ctrl->protocol = PROTOCOL_DSS1;
126	ctrl->state = CTRL_UP;
127	ctrl->nbch = nbch;
128	for (i = 0; i < ctrl->nbch; i++)
129		ctrl->stateb[i] = CHAN_IDLE;
130	ctrl->freechans = MAX_CHANCTRL;
131	ctrl->tei = tei;
132	ctrl->l1stat = LAYER_IDLE;
133	ctrl->l2stat = LAYER_IDLE;
134	ctrl->firmware = NULL;
135	DBGL(DL_RCCF, (logit(LL_DBG, "init_controller_state: controller %d (%s) is %s",
136	   controller, devnam, cardname)));
137
138	/* add to list */
139	add_ctrl_state(ctrl);
140
141	return(GOOD);
142}
143
144/*--------------------------------------------------------------------------*
145 *	init active controller
146 *--------------------------------------------------------------------------*/
147void
148init_active_controller(void)
149{
150	struct isdn_ctrl_state *cst = NULL;
151	int ret, fd;
152	int i, numctrl;
153
154#if 0
155	/* XXX - replace by something useful */
156	int controller;
157	char cmdbuf[MAXPATHLEN+128];
158
159	for (controller = 0; controller < ncontroller; controller++)
160	{
161		if (isdn_ctrl_tab[controller].ctrl_type == CTRL_TINADD)
162		{
163			DBGL(DL_RCCF, (logit(LL_DBG, "init_active_controller, tina-dd %d: executing [%s %d]", unit, tinainitprog, unit)));
164
165			snprintf(cmdbuf, sizeof(cmdbuf), "%s %d", tinainitprog, unit);
166
167			if ((ret = system(cmdbuf)) != 0)
168			{
169				logit(LL_ERR, "init_active_controller, tina-dd %d: %s returned %d!", unit, tinainitprog, ret);
170				do_exit(1);
171			}
172		}
173	}
174#endif
175
176	numctrl = count_ctrl_states();
177	for (cst = get_first_ctrl_state(), i = 0;
178	    i < numctrl;
179	    cst = find_ctrl_state(i++)) {
180
181		/*
182		 *  Generic microcode loading. If a controller has
183		 *  defined a microcode file, load it using the
184		 *  I4B_CTRL_DOWNLOAD ioctl.
185		 */
186		if (cst->firmware != NULL) {
187			struct isdn_dr_prot idp;
188			struct isdn_download_request idr;
189
190			fd = open(cst->firmware, O_RDONLY);
191			if (fd < 0) {
192				logit(LL_ERR, "init_active_controller %d: "
193				    "open %s: %s!", cst->isdnif, cst->firmware,
194				    strerror(errno));
195				do_exit(1);
196			}
197
198			idp.bytecount = lseek(fd, 0, SEEK_END);
199			idp.microcode = mmap(0, idp.bytecount, PROT_READ,
200			    MAP_SHARED, fd, 0);
201			if (idp.microcode == MAP_FAILED) {
202				logit(LL_ERR, "init_active_controller %d: "
203				    "mmap %s: %s!", cst->isdnif, cst->firmware,
204				    strerror(errno));
205				do_exit(1);
206			}
207
208			DBGL(DL_RCCF, (logit(LL_DBG, "init_active_controller "
209			    "%d: loading firmware from [%s]", cst->isdnif,
210			    cst->firmware)));
211
212			idr.controller = cst->isdnif;
213			idr.numprotos = 1;
214			idr.protocols = &idp;
215
216			ret = ioctl(isdnfd, I4B_CTRL_DOWNLOAD, &idr,
217			    sizeof(idr));
218			if (ret) {
219				logit(LL_ERR, "init_active_controller %d: "
220				    "load %s: %s!", cst->isdnif, cst->firmware,
221				    strerror(errno));
222				do_exit(1);
223			}
224
225			munmap(idp.microcode, idp.bytecount);
226			close(fd);
227		}
228	}
229}
230
231void
232init_single_controller_protocol ( struct isdn_ctrl_state *ctrl )
233{
234	msg_prot_ind_t mpi;
235
236	memset(&mpi, 0, sizeof mpi);
237	mpi.controller = ctrl->isdnif;
238	mpi.protocol = ctrl->protocol;
239
240	if ((ioctl(isdnfd, I4B_PROT_IND, &mpi)) < 0)
241	{
242		logit(LL_ERR, "init_single_controller_protocol: ioctl I4B_PROT_IND failed: %s", strerror(errno));
243		do_exit(1);
244	}
245}
246
247/*--------------------------------------------------------------------------*
248 *	init controller D-channel ISDN protocol
249 *--------------------------------------------------------------------------*/
250void
251init_controller_protocol(void)
252{
253	struct isdn_ctrl_state *ctrl;
254
255	for (ctrl = get_first_ctrl_state(); ctrl; ctrl = NEXT_CTRL(ctrl))
256		init_single_controller_protocol(ctrl);
257}
258
259/*--------------------------------------------------------------------------*
260 *	set controller state to UP/DOWN
261 *--------------------------------------------------------------------------*/
262int
263set_controller_state(struct isdn_ctrl_state *ctrl, int state)
264{
265	if (ctrl == NULL) {
266		logit(LL_ERR, "set_controller_state: invalid controller");
267		return(ERROR);
268	}
269
270	if (state == CTRL_UP) {
271		ctrl->state = CTRL_UP;
272		DBGL(DL_CNST, (logit(LL_DBG, "set_controller_state: controller [%d] set UP!", ctrl->isdnif)));
273	}
274	else if (state == CTRL_DOWN)
275	{
276		ctrl->state = CTRL_DOWN;
277		DBGL(DL_CNST, (logit(LL_DBG, "set_controller_state: controller [%d] set DOWN!", ctrl->isdnif)));
278	}
279	else
280	{
281		logit(LL_ERR, "set_controller_state: invalid controller state [%d]!", state);
282		return(ERROR);
283	}
284	return(GOOD);
285}
286
287/*--------------------------------------------------------------------------*
288 *	get controller state
289 *--------------------------------------------------------------------------*/
290int
291get_controller_state(struct isdn_ctrl_state *ctrl)
292{
293	if (ctrl == NULL) {
294		logit(LL_ERR, "set_controller_state: invalid controller");
295		return(ERROR);
296	}
297	return (ctrl->state);
298}
299
300/*--------------------------------------------------------------------------*
301 *	decrement number of free channels for controller
302 *--------------------------------------------------------------------------*/
303int
304decr_free_channels(struct isdn_ctrl_state *ctrl)
305{
306	if (ctrl == NULL) {
307		logit(LL_ERR, "decr_free_channels: invalid controller!");
308		return(ERROR);
309	}
310	if (ctrl->freechans > 0)
311	{
312		ctrl->freechans--;
313		DBGL(DL_CNST, (logit(LL_DBG, "decr_free_channels: ctrl %d, now %d chan free", ctrl->isdnif, ctrl->freechans)));
314		return(GOOD);
315	}
316	else
317	{
318		logit(LL_ERR, "decr_free_channels: controller [%d] already 0 free chans!", ctrl->isdnif);
319		return(ERROR);
320	}
321}
322
323/*--------------------------------------------------------------------------*
324 *	increment number of free channels for controller
325 *--------------------------------------------------------------------------*/
326int
327incr_free_channels(struct isdn_ctrl_state *ctrl)
328{
329	if (ctrl == NULL) {
330		logit(LL_ERR, "incr_free_channels: invalid controller!");
331		return(ERROR);
332	}
333	if (ctrl->freechans < MAX_CHANCTRL)
334	{
335		ctrl->freechans++;
336		DBGL(DL_CNST, (logit(LL_DBG, "incr_free_channels: ctrl %d, now %d chan free", ctrl->isdnif, ctrl->freechans)));
337		return(GOOD);
338	}
339	else
340	{
341		logit(LL_ERR, "incr_free_channels: controller [%d] already 2 free chans!", ctrl->isdnif);
342		return(ERROR);
343	}
344}
345
346/*--------------------------------------------------------------------------*
347 *	get number of free channels for controller
348 *--------------------------------------------------------------------------*/
349int
350get_free_channels(struct isdn_ctrl_state *ctrl)
351{
352	if (ctrl == NULL) {
353		logit(LL_ERR, "get_free_channels: invalid controller!");
354		return(ERROR);
355	}
356	DBGL(DL_CNST, (logit(LL_DBG, "get_free_channels: ctrl %d, %d chan free", ctrl->isdnif, ctrl->freechans)));
357	return (ctrl->freechans);
358}
359
360/*--------------------------------------------------------------------------*
361 *	set channel state to busy
362 *--------------------------------------------------------------------------*/
363int
364set_channel_busy(struct isdn_ctrl_state *ctrl, int channel)
365{
366	if (ctrl == NULL) {
367		logit(LL_ERR, "set_channel_busy: invalid controller");
368		return(ERROR);
369	}
370
371	if (channel < 0 || channel >= ctrl->nbch)
372	{
373		DBGL(DL_CNST, (logit(LL_DBG, "set_channel_busy: controller [%d] invalid channel %d", ctrl->isdnif, channel)));
374		return(ERROR);
375	}
376
377	if (ctrl->stateb[channel] == CHAN_RUN)
378	{
379		DBGL(DL_CNST, (logit(LL_DBG, "set_channel_busy: controller [%d] channel B%d already busy!", ctrl->isdnif, channel)));
380	}
381	else
382	{
383		ctrl->stateb[channel] = CHAN_RUN;
384		DBGL(DL_CNST, (logit(LL_DBG, "set_channel_busy: controller [%d] channel B%d set to BUSY!", ctrl->isdnif, channel)));
385	}
386
387	return(GOOD);
388}
389
390/*--------------------------------------------------------------------------*
391 *	set channel state to idle
392 *--------------------------------------------------------------------------*/
393int
394set_channel_idle(struct isdn_ctrl_state *ctrl, int channel)
395{
396	if (ctrl == NULL) {
397		logit(LL_ERR, "set_channel_idle: invalid controller");
398		return(ERROR);
399	}
400
401	if (channel < 0 || channel >= ctrl->nbch)
402	{
403		DBGL(DL_CNST, (logit(LL_DBG, "set_channel_idle: controller [%d] invalid channel %d", ctrl->isdnif, channel)));
404		return(ERROR);
405	}
406
407	if (ctrl->stateb[channel] == CHAN_IDLE)
408	{
409		DBGL(DL_CNST, (logit(LL_DBG, "set_channel_idle: controller [%d] channel B%d already idle!", ctrl->isdnif, channel)));
410	}
411	else
412	{
413		ctrl->stateb[channel] = CHAN_IDLE;
414		DBGL(DL_CNST, (logit(LL_DBG, "set_channel_idle: controller [%d] channel B%d set to IDLE!", ctrl->isdnif, channel)));
415	}
416
417	return(GOOD);
418}
419
420/*--------------------------------------------------------------------------*
421 *	return channel state
422 *--------------------------------------------------------------------------*/
423int
424ret_channel_state(struct isdn_ctrl_state *ctrl, int channel)
425{
426	if (ctrl == NULL) {
427		logit(LL_ERR, "ret_channel_state: invalid controller!");
428		return(ERROR);
429	}
430
431	if (channel < 0 || channel >= ctrl->nbch) {
432		logit(LL_ERR, "ret_channel_state: controller [%d], invalid channel [%d]!", ctrl->isdnif, channel);
433		return(ERROR);
434	}
435	else
436	{
437		return (ctrl->stateb[channel]);
438	}
439}
440
441/* EOF */
442