1/* $Id: hycapi.c,v 1.1.1.1 2008/10/15 03:26:34 james26_jang Exp $
2 *
3 * Linux driver for HYSDN cards, CAPI2.0-Interface.
4 *
5 * Author    Ulrich Albrecht <u.albrecht@hypercope.de> for Hypercope GmbH
6 * Copyright 2000 by Hypercope GmbH
7 *
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
10 *
11 */
12
13#include <linux/module.h>
14#include <linux/version.h>
15#include <linux/signal.h>
16#include <linux/kernel.h>
17#include <linux/skbuff.h>
18
19
20#define	VER_DRIVER	0
21#define	VER_CARDTYPE	1
22#define	VER_HWID	2
23#define	VER_SERIAL	3
24#define	VER_OPTION	4
25#define	VER_PROTO	5
26#define	VER_PROFILE	6
27#define	VER_CAPI	7
28
29#include "hysdn_defs.h"
30#include <linux/kernelcapi.h>
31
32static char hycapi_revision[]="$Revision: 1.1.1.1 $";
33
34unsigned int hycapi_enable = 0xffffffff;
35MODULE_PARM(hycapi_enable, "i");
36
37typedef struct _hycapi_appl {
38	unsigned int ctrl_mask;
39	capi_register_params rp;
40	struct sk_buff *listen_req[CAPI_MAXCONTR];
41} hycapi_appl;
42
43static hycapi_appl hycapi_applications[CAPI_MAXAPPL];
44
45static inline int _hycapi_appCheck(int app_id, int ctrl_no)
46{
47	if((ctrl_no <= 0) || (ctrl_no > CAPI_MAXCONTR) || (app_id <= 0) ||
48	   (app_id > CAPI_MAXAPPL))
49	{
50		printk(KERN_ERR "HYCAPI: Invalid request app_id %d for controller %d", app_id, ctrl_no);
51		return -1;
52	}
53	return ((hycapi_applications[app_id-1].ctrl_mask & (1 << (ctrl_no-1))) != 0);
54}
55
56struct capi_driver_interface *hy_di = NULL;
57
58/******************************
59Kernel-Capi callback reset_ctr
60******************************/
61
62void
63hycapi_reset_ctr(struct capi_ctr *ctrl)
64{
65#ifdef HYCAPI_PRINTFNAMES
66	printk(KERN_NOTICE "HYCAPI hycapi_reset_ctr\n");
67#endif
68	ctrl->reseted(ctrl);
69}
70
71/******************************
72Kernel-Capi callback remove_ctr
73******************************/
74
75void
76hycapi_remove_ctr(struct capi_ctr *ctrl)
77{
78	int i;
79	hycapictrl_info *cinfo = NULL;
80	hysdn_card *card = NULL;
81#ifdef HYCAPI_PRINTFNAMES
82	printk(KERN_NOTICE "HYCAPI hycapi_remove_ctr\n");
83#endif
84	if(!hy_di) {
85		printk(KERN_ERR "No capi_driver_interface set!");
86		return;
87	}
88	cinfo = (hycapictrl_info *)(ctrl->driverdata);
89	if(!cinfo) {
90		printk(KERN_ERR "No hycapictrl_info set!");
91		return;
92	}
93	card = cinfo->card;
94	ctrl->suspend_output(ctrl);
95	for(i=0; i<CAPI_MAXAPPL;i++) {
96		if(hycapi_applications[i].listen_req[ctrl->cnr-1]) {
97			kfree_skb(hycapi_applications[i].listen_req[ctrl->cnr-1]);
98			hycapi_applications[i].listen_req[ctrl->cnr-1] = NULL;
99		}
100	}
101	hy_di->detach_ctr(ctrl);
102	ctrl->driverdata = 0;
103	kfree(card->hyctrlinfo);
104
105
106	card->hyctrlinfo = NULL;
107}
108
109/***********************************************************
110
111Queue a CAPI-message to the controller.
112
113***********************************************************/
114
115static void
116hycapi_sendmsg_internal(struct capi_ctr *ctrl, struct sk_buff *skb)
117{
118	hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
119	hysdn_card *card = cinfo->card;
120
121	spin_lock_irq(&cinfo->lock);
122#ifdef HYCAPI_PRINTFNAMES
123	printk(KERN_NOTICE "hycapi_send_message\n");
124#endif
125	cinfo->skbs[cinfo->in_idx++] = skb;	/* add to buffer list */
126	if (cinfo->in_idx >= HYSDN_MAX_CAPI_SKB)
127		cinfo->in_idx = 0;	/* wrap around */
128	cinfo->sk_count++;		/* adjust counter */
129	if (cinfo->sk_count >= HYSDN_MAX_CAPI_SKB) {
130		/* inform upper layers we're full */
131		printk(KERN_ERR "HYSDN Card%d: CAPI-buffer overrun!\n",
132		       card->myid);
133		ctrl->suspend_output(ctrl);
134	}
135	cinfo->tx_skb = skb;
136	spin_unlock_irq(&cinfo->lock);
137	queue_task(&card->irq_queue, &tq_immediate);
138	mark_bh(IMMEDIATE_BH);
139}
140
141/***********************************************************
142hycapi_register_internal
143
144Send down the CAPI_REGISTER-Command to the controller.
145This functions will also be used if the adapter has been rebooted to
146re-register any applications in the private list.
147
148************************************************************/
149
150static void
151hycapi_register_internal(struct capi_ctr *ctrl, __u16 appl,
152			 capi_register_params *rp)
153{
154	char ExtFeatureDefaults[] = "49  /0/0/0/0,*/1,*/2,*/3,*/4,*/5,*/6,*/7,*/8,*/9,*";
155	hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
156	hysdn_card *card = cinfo->card;
157	struct sk_buff *skb;
158	__u16 len;
159	__u8 _command = 0xa0, _subcommand = 0x80;
160	__u16 MessageNumber = 0x0000;
161	__u16 MessageBufferSize = 0;
162	int slen = strlen(ExtFeatureDefaults);
163#ifdef HYCAPI_PRINTFNAMES
164	printk(KERN_NOTICE "hycapi_register_appl\n");
165#endif
166	MessageBufferSize = rp->level3cnt * rp->datablkcnt * rp->datablklen;
167
168	len = CAPI_MSG_BASELEN + 8 + slen + 1;
169	if (!(skb = alloc_skb(len, GFP_ATOMIC))) {
170		printk(KERN_ERR "HYSDN card%d: memory squeeze in hycapi_register_appl\n",
171		       card->myid);
172		return;
173	}
174	memcpy(skb_put(skb,sizeof(__u16)), &len, sizeof(__u16));
175	memcpy(skb_put(skb,sizeof(__u16)), &appl, sizeof(__u16));
176	memcpy(skb_put(skb,sizeof(__u8)), &_command, sizeof(_command));
177	memcpy(skb_put(skb,sizeof(__u8)), &_subcommand, sizeof(_subcommand));
178	memcpy(skb_put(skb,sizeof(__u16)), &MessageNumber, sizeof(__u16));
179	memcpy(skb_put(skb,sizeof(__u16)), &MessageBufferSize, sizeof(__u16));
180	memcpy(skb_put(skb,sizeof(__u16)), &(rp->level3cnt), sizeof(__u16));
181	memcpy(skb_put(skb,sizeof(__u16)), &(rp->datablkcnt), sizeof(__u16));
182	memcpy(skb_put(skb,sizeof(__u16)), &(rp->datablklen), sizeof(__u16));
183	memcpy(skb_put(skb,slen), ExtFeatureDefaults, slen);
184	hycapi_applications[appl-1].ctrl_mask |= (1 << (ctrl->cnr-1));
185	hycapi_send_message(ctrl, skb);
186}
187
188/************************************************************
189hycapi_restart_internal
190
191After an adapter has been rebootet, re-register all applications and
192send a LISTEN_REQ (if there has been such a thing )
193
194*************************************************************/
195
196static void hycapi_restart_internal(struct capi_ctr *ctrl)
197{
198	int i;
199	struct sk_buff *skb;
200#ifdef HYCAPI_PRINTFNAMES
201	printk(KERN_WARNING "HYSDN: hycapi_restart_internal");
202#endif
203	for(i=0; i<CAPI_MAXAPPL; i++) {
204		if(_hycapi_appCheck(i+1, ctrl->cnr) == 1) {
205			hycapi_register_internal(ctrl, i+1,
206						 &hycapi_applications[i].rp);
207			if(hycapi_applications[i].listen_req[ctrl->cnr-1]) {
208				skb = skb_copy(hycapi_applications[i].listen_req[ctrl->cnr-1], GFP_ATOMIC);
209				hycapi_sendmsg_internal(ctrl, skb);
210			}
211		}
212	}
213}
214
215/*************************************************************
216Register an application.
217Error-checking is done for CAPI-compliance.
218
219The application is recorded in the internal list.
220*************************************************************/
221
222void
223hycapi_register_appl(struct capi_ctr *ctrl, __u16 appl,
224		     capi_register_params *rp)
225{
226	int MaxLogicalConnections = 0, MaxBDataBlocks = 0, MaxBDataLen = 0;
227	hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
228	hysdn_card *card = cinfo->card;
229	int chk = _hycapi_appCheck(appl, ctrl->cnr);
230	if(chk < 0) {
231		return;
232	}
233	if(chk == 1) {
234		printk(KERN_INFO "HYSDN: apl %d allready registered\n", appl);
235		return;
236	}
237	MaxBDataBlocks = rp->datablkcnt > CAPI_MAXDATAWINDOW ? CAPI_MAXDATAWINDOW : rp->datablkcnt;
238	rp->datablkcnt = MaxBDataBlocks;
239	MaxBDataLen = rp->datablklen < 1024 ? 1024 : rp->datablklen ;
240	rp->datablklen = MaxBDataLen;
241
242	MaxLogicalConnections = rp->level3cnt;
243	if (MaxLogicalConnections < 0) {
244		MaxLogicalConnections = card->bchans * -MaxLogicalConnections;
245	}
246	if (MaxLogicalConnections == 0) {
247		MaxLogicalConnections = card->bchans;
248	}
249
250	rp->level3cnt = MaxLogicalConnections;
251	memcpy(&hycapi_applications[appl-1].rp,
252	       rp, sizeof(capi_register_params));
253
254/*        MOD_INC_USE_COUNT; */
255	ctrl->appl_registered(ctrl, appl);
256}
257
258/*********************************************************************
259
260hycapi_release_internal
261
262Send down a CAPI_RELEASE to the controller.
263*********************************************************************/
264
265static void hycapi_release_internal(struct capi_ctr *ctrl, __u16 appl)
266{
267	hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
268	hysdn_card *card = cinfo->card;
269	struct sk_buff *skb;
270	__u16 len;
271	__u8 _command = 0xa1, _subcommand = 0x80;
272	__u16 MessageNumber = 0x0000;
273#ifdef HYCAPI_PRINTFNAMES
274	printk(KERN_NOTICE "hycapi_release_appl\n");
275#endif
276	len = CAPI_MSG_BASELEN;
277	if (!(skb = alloc_skb(len, GFP_ATOMIC))) {
278		printk(KERN_ERR "HYSDN card%d: memory squeeze in hycapi_register_appl\n",
279		       card->myid);
280		return;
281	}
282	memcpy(skb_put(skb,sizeof(__u16)), &len, sizeof(__u16));
283	memcpy(skb_put(skb,sizeof(__u16)), &appl, sizeof(__u16));
284	memcpy(skb_put(skb,sizeof(__u8)), &_command, sizeof(_command));
285	memcpy(skb_put(skb,sizeof(__u8)), &_subcommand, sizeof(_subcommand));
286	memcpy(skb_put(skb,sizeof(__u16)), &MessageNumber, sizeof(__u16));
287	hycapi_send_message(ctrl, skb);
288	hycapi_applications[appl-1].ctrl_mask &= ~(1 << (ctrl->cnr-1));
289}
290
291/******************************************************************
292hycapi_release_appl
293
294Release the application from the internal list an remove it's
295registration at controller-level
296******************************************************************/
297
298void
299hycapi_release_appl(struct capi_ctr *ctrl, __u16 appl)
300{
301	int chk;
302
303	chk = _hycapi_appCheck(appl, ctrl->cnr);
304	if(chk<0) {
305		printk(KERN_ERR "HYCAPI: Releasing invalid appl %d on controller %d\n", appl, ctrl->cnr);
306		return;
307	}
308	if(hycapi_applications[appl-1].listen_req[ctrl->cnr-1]) {
309		kfree_skb(hycapi_applications[appl-1].listen_req[ctrl->cnr-1]);
310		hycapi_applications[appl-1].listen_req[ctrl->cnr-1] = NULL;
311	}
312	if(chk == 1)
313	{
314		hycapi_release_internal(ctrl, appl);
315	}
316	ctrl->appl_released(ctrl, appl);
317/*        MOD_DEC_USE_COUNT;  */
318}
319
320
321/**************************************************************
322Kill a single controller.
323**************************************************************/
324
325int hycapi_capi_release(hysdn_card *card)
326{
327	hycapictrl_info *cinfo = card->hyctrlinfo;
328	struct capi_ctr *ctrl;
329#ifdef HYCAPI_PRINTFNAMES
330	printk(KERN_NOTICE "hycapi_capi_release\n");
331#endif
332	if(cinfo) {
333		ctrl = cinfo->capi_ctrl;
334		hycapi_remove_ctr(ctrl);
335	}
336	return 0;
337}
338
339/**************************************************************
340hycapi_capi_stop
341
342Stop CAPI-Output on a card. (e.g. during reboot)
343***************************************************************/
344
345int hycapi_capi_stop(hysdn_card *card)
346{
347	hycapictrl_info *cinfo = card->hyctrlinfo;
348	struct capi_ctr *ctrl;
349#ifdef HYCAPI_PRINTFNAMES
350	printk(KERN_NOTICE "hycapi_capi_stop\n");
351#endif
352	if(cinfo) {
353		if(cinfo->capi_ctrl) {
354			ctrl = cinfo->capi_ctrl;
355/*			ctrl->suspend_output(ctrl); */
356			ctrl->reseted(ctrl);
357
358		} else {
359			printk(KERN_NOTICE "hycapi_capi_stop: cinfo but no capi_ctrl\n");
360		}
361	}
362	return 0;
363}
364
365/***************************************************************
366hycapi_send_message
367
368Send a message to the controller.
369
370Messages are parsed for their Command/Subcommand-type, and appropriate
371action's are performed.
372
373Note that we have to muck around with a 64Bit-DATA_REQ as there are
374firmware-releases that do not check the MsgLen-Indication!
375
376***************************************************************/
377
378void hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
379{
380	__u16 appl_id;
381	int _len, _len2;
382	__u8 msghead[64];
383
384	appl_id = CAPIMSG_APPID(skb->data);
385	switch(_hycapi_appCheck(appl_id, ctrl->cnr))
386	{
387		case 0:
388/*			printk(KERN_INFO "Need to register\n"); */
389			hycapi_register_internal(ctrl,
390						 appl_id,
391						 &(hycapi_applications[appl_id-1].rp));
392			break;
393		case 1:
394			break;
395		default:
396			printk(KERN_ERR "HYCAPI: Controller mixup!\n");
397			return;
398	}
399	switch(CAPIMSG_CMD(skb->data)) {
400		case CAPI_DISCONNECT_B3_RESP:
401			ctrl->free_ncci(ctrl, appl_id,
402					CAPIMSG_NCCI(skb->data));
403			break;
404		case CAPI_DATA_B3_REQ:
405			_len = CAPIMSG_LEN(skb->data);
406			if (_len > 22) {
407				_len2 = _len - 22;
408				memcpy(msghead, skb->data, 22);
409				memcpy(skb->data + _len2, msghead, 22);
410				skb_pull(skb, _len2);
411				CAPIMSG_SETLEN(skb->data, 22);
412			}
413			break;
414		case CAPI_LISTEN_REQ:
415			if(hycapi_applications[appl_id-1].listen_req[ctrl->cnr-1])
416			{
417				kfree_skb(hycapi_applications[appl_id-1].listen_req[ctrl->cnr-1]);
418				hycapi_applications[appl_id-1].listen_req[ctrl->cnr-1] = NULL;
419			}
420			if (!(hycapi_applications[appl_id-1].listen_req[ctrl->cnr-1] = skb_copy(skb, GFP_ATOMIC)))
421			{
422				printk(KERN_ERR "HYSDN: memory squeeze in private_listen\n");
423			}
424			break;
425		default:
426			break;
427	}
428	hycapi_sendmsg_internal(ctrl, skb);
429}
430
431/*********************************************************************
432hycapi_read_proc
433
434Informations provided in the /proc/capi-entries.
435
436*********************************************************************/
437
438int hycapi_read_proc(char *page, char **start, off_t off,
439		     int count, int *eof, struct capi_ctr *ctrl)
440{
441	hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
442	hysdn_card *card = cinfo->card;
443	int len = 0;
444	char *s;
445#ifdef HYCAPI_PRINTFNAMES
446	printk(KERN_NOTICE "hycapi_read_proc\n");
447#endif
448	len += sprintf(page+len, "%-16s %s\n", "name", cinfo->cardname);
449	len += sprintf(page+len, "%-16s 0x%x\n", "io", card->iobase);
450	len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
451
452	switch (card->brdtype) {
453		case BD_PCCARD:  s = "HYSDN Hycard"; break;
454		case BD_ERGO: s = "HYSDN Ergo2"; break;
455		case BD_METRO: s = "HYSDN Metro4"; break;
456		case BD_CHAMP2: s = "HYSDN Champ2";	break;
457		case BD_PLEXUS: s = "HYSDN Plexus30"; break;
458		default: s = "???"; break;
459	}
460	len += sprintf(page+len, "%-16s %s\n", "type", s);
461	if ((s = cinfo->version[VER_DRIVER]) != 0)
462		len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
463	if ((s = cinfo->version[VER_CARDTYPE]) != 0)
464		len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
465	if ((s = cinfo->version[VER_SERIAL]) != 0)
466		len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
467
468	len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
469
470	if (off+count >= len)
471		*eof = 1;
472	if (len < off)
473		return 0;
474	*start = page + off;
475	return ((count < len-off) ? count : len-off);
476}
477
478/**************************************************************
479hycapi_load_firmware
480
481This does NOT load any firmware, but the callback somehow is needed
482on capi-interface registration.
483
484**************************************************************/
485
486int hycapi_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
487{
488#ifdef HYCAPI_PRINTFNAMES
489	printk(KERN_NOTICE "hycapi_load_firmware\n");
490#endif
491	return 0;
492}
493
494
495char *hycapi_procinfo(struct capi_ctr *ctrl)
496{
497	hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
498#ifdef HYCAPI_PRINTFNAMES
499	printk(KERN_NOTICE "hycapi_proc_info\n");
500#endif
501	if (!cinfo)
502		return "";
503	sprintf(cinfo->infobuf, "%s %s 0x%x %d %s",
504		cinfo->cardname[0] ? cinfo->cardname : "-",
505		cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
506		cinfo->card ? cinfo->card->iobase : 0x0,
507		cinfo->card ? cinfo->card->irq : 0,
508		hycapi_revision
509		);
510	return cinfo->infobuf;
511}
512
513/******************************************************************
514hycapi_rx_capipkt
515
516Receive a capi-message.
517
518All B3_DATA_IND are converted to 64K-extension compatible format.
519New nccis are created if neccessary.
520*******************************************************************/
521
522void
523hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len)
524{
525	struct sk_buff *skb;
526	hycapictrl_info *cinfo = card->hyctrlinfo;
527	struct capi_ctr *ctrl;
528	__u16 ApplId;
529	__u16 MsgLen, info;
530	__u16 len2, CapiCmd;
531	__u32 CP64[2] = {0,0};
532#ifdef HYCAPI_PRINTFNAMES
533	printk(KERN_NOTICE "hycapi_rx_capipkt\n");
534#endif
535	if(!cinfo) {
536		return;
537	}
538	ctrl = cinfo->capi_ctrl;
539	if(!ctrl)
540	{
541		return;
542	}
543	if(len < CAPI_MSG_BASELEN) {
544		printk(KERN_ERR "HYSDN Card%d: invalid CAPI-message, lenght %d!\n",
545		       card->myid, len);
546		return;
547	}
548	MsgLen = CAPIMSG_LEN(buf);
549	ApplId = CAPIMSG_APPID(buf);
550	CapiCmd = CAPIMSG_CMD(buf);
551
552	if((CapiCmd == CAPI_DATA_B3_IND) && (MsgLen < 30)) {
553		len2 = len + (30 - MsgLen);
554		if (!(skb = alloc_skb(len2, GFP_ATOMIC))) {
555			printk(KERN_ERR "HYSDN Card%d: incoming packet dropped\n",
556			       card->myid);
557			return;
558		}
559		memcpy(skb_put(skb, MsgLen), buf, MsgLen);
560		memcpy(skb_put(skb, 2*sizeof(__u32)), CP64, 2* sizeof(__u32));
561		memcpy(skb_put(skb, len - MsgLen), buf + MsgLen,
562		       len - MsgLen);
563		CAPIMSG_SETLEN(skb->data, 30);
564	} else {
565		if (!(skb = alloc_skb(len, GFP_ATOMIC))) {
566			printk(KERN_ERR "HYSDN Card%d: incoming packet dropped\n",
567			       card->myid);
568			return;
569		}
570		memcpy(skb_put(skb, len), buf, len);
571	}
572	switch(CAPIMSG_CMD(skb->data))
573	{
574		case CAPI_CONNECT_B3_CONF:
575/* Check info-field for error-indication: */
576			info = CAPIMSG_U16(skb->data, 12);
577			switch(info)
578			{
579				case 0:
580					ctrl->new_ncci(ctrl, ApplId, CAPIMSG_NCCI(skb->data),
581						       hycapi_applications[ApplId-1].rp.datablkcnt);
582
583					break;
584				case 0x0001:
585					printk(KERN_ERR "HYSDN Card%d: NCPI not supported by current "
586					       "protocol. NCPI ignored.\n", card->myid);
587					break;
588				case 0x2001:
589					printk(KERN_ERR "HYSDN Card%d: Message not supported in"
590					       " current state\n", card->myid);
591					break;
592				case 0x2002:
593					printk(KERN_ERR "HYSDN Card%d: illegal PLCI\n", card->myid);
594					break;
595				case 0x2004:
596					printk(KERN_ERR "HYSDN Card%d: out of NCCI\n", card->myid);
597					break;
598				case 0x3008:
599					printk(KERN_ERR "HYSDN Card%d: NCPI not supported\n",
600					       card->myid);
601					break;
602				default:
603					printk(KERN_ERR "HYSDN Card%d: Info in CONNECT_B3_CONF: %d\n",
604					       card->myid, info);
605					break;
606			}
607			break;
608		case CAPI_CONNECT_B3_IND:
609			ctrl->new_ncci(ctrl, ApplId,
610				       CAPIMSG_NCCI(skb->data),
611				       hycapi_applications[ApplId-1].rp.datablkcnt);
612			break;
613		default:
614			break;
615	}
616	ctrl->handle_capimsg(ctrl, ApplId, skb);
617}
618
619/******************************************************************
620hycapi_tx_capiack
621
622Internally acknowledge a msg sent. This will remove the msg from the
623internal queue.
624
625*******************************************************************/
626
627void hycapi_tx_capiack(hysdn_card * card)
628{
629	hycapictrl_info *cinfo = card->hyctrlinfo;
630#ifdef HYCAPI_PRINTFNAMES
631	printk(KERN_NOTICE "hycapi_tx_capiack\n");
632#endif
633	if(!cinfo) {
634		return;
635	}
636	spin_lock_irq(&cinfo->lock);
637	kfree_skb(cinfo->skbs[cinfo->out_idx]);		/* free skb */
638	cinfo->skbs[cinfo->out_idx++] = NULL;
639	if (cinfo->out_idx >= HYSDN_MAX_CAPI_SKB)
640		cinfo->out_idx = 0;	/* wrap around */
641
642	if (cinfo->sk_count-- == HYSDN_MAX_CAPI_SKB)	/* dec usage count */
643		cinfo->capi_ctrl->resume_output(cinfo->capi_ctrl);
644	spin_unlock_irq(&cinfo->lock);
645}
646
647/***************************************************************
648hycapi_tx_capiget(hysdn_card *card)
649
650This is called when polling for messages to SEND.
651
652****************************************************************/
653
654struct sk_buff *
655hycapi_tx_capiget(hysdn_card *card)
656{
657	hycapictrl_info *cinfo = card->hyctrlinfo;
658	if(!cinfo) {
659		return (struct sk_buff *)NULL;
660	}
661	if (!cinfo->sk_count)
662		return (struct sk_buff *)NULL;	/* nothing available */
663
664	return (cinfo->skbs[cinfo->out_idx]);		/* next packet to send */
665}
666
667
668static struct capi_driver hycapi_driver = {
669	"hysdn",
670	"0.0",
671	hycapi_load_firmware,
672	hycapi_reset_ctr,
673	hycapi_remove_ctr,
674	hycapi_register_appl,
675	hycapi_release_appl,
676	hycapi_send_message,
677	hycapi_procinfo,
678	hycapi_read_proc,
679	0,	/* use standard driver_read_proc */
680	0, /* no add_card function */
681};
682
683
684/**********************************************************
685int hycapi_init()
686
687attach the capi-driver to the kernel-capi.
688
689***********************************************************/
690
691int hycapi_init()
692{
693	struct capi_driver *driver;
694	int i;
695	if(hy_di) {
696		printk(KERN_NOTICE "HyDI allready set\n");
697		return 0;
698	}
699	driver = &hycapi_driver;
700	printk(KERN_NOTICE "HYSDN: Attaching capi-driver\n");
701	hy_di = attach_capi_driver(driver);
702	if (!hy_di) {
703		printk(KERN_ERR "HYCAPI: failed to attach capi_driver\n");
704		return(-1);
705	}
706	for(i=0;i<CAPI_MAXAPPL;i++) {
707		memset(&(hycapi_applications[i]), 0, sizeof(hycapi_appl));
708	}
709	return(0);
710}
711
712/**************************************************************
713hycapi_cleanup(void)
714
715detach the capi-driver to the kernel-capi. Actually this should
716free some more ressources. Do that later.
717**************************************************************/
718
719void
720hycapi_cleanup(void)
721{
722	struct capi_driver *driver;
723	driver = &hycapi_driver;
724	if (!hy_di) {
725		printk(KERN_ERR "HYSDN: no capi-driver to detach (?)\n");
726		return;
727	}
728	printk(KERN_NOTICE "HYSDN: Detaching capi-driver\n");
729	detach_capi_driver(driver);
730	hy_di = 0;
731	return;
732}
733
734/********************************************************************
735hycapi_capi_create(hysdn_card *card)
736
737Attach the card with it's capi-ctrl.
738*********************************************************************/
739
740static void hycapi_fill_profile(hysdn_card *card)
741{
742	hycapictrl_info *cinfo = NULL;
743	struct capi_ctr *ctrl = NULL;
744	cinfo = card->hyctrlinfo;
745	if(!cinfo) return;
746	ctrl = cinfo->capi_ctrl;
747	if(!ctrl) return;
748	strcpy(ctrl->manu, "Hypercope");
749	ctrl->version.majorversion = 2;
750	ctrl->version.minorversion = 0;
751	ctrl->version.majormanuversion = 3;
752	ctrl->version.minormanuversion = 2;
753	ctrl->profile.ncontroller = card->myid;
754	ctrl->profile.nbchannel = card->bchans;
755	ctrl->profile.goptions = GLOBAL_OPTION_INTERNAL_CONTROLLER |
756		GLOBAL_OPTION_B_CHANNEL_OPERATION;
757	ctrl->profile.support1 =  B1_PROT_64KBIT_HDLC |
758		(card->faxchans ? B1_PROT_T30 : 0) |
759		B1_PROT_64KBIT_TRANSPARENT;
760	ctrl->profile.support2 = B2_PROT_ISO7776 |
761		(card->faxchans ? B2_PROT_T30 : 0) |
762		B2_PROT_TRANSPARENT;
763	ctrl->profile.support3 = B3_PROT_TRANSPARENT |
764		B3_PROT_T90NL |
765		(card->faxchans ? B3_PROT_T30 : 0) |
766		(card->faxchans ? B3_PROT_T30EXT : 0) |
767		B3_PROT_ISO8208;
768}
769
770int
771hycapi_capi_create(hysdn_card *card)
772{
773	hycapictrl_info *cinfo = NULL;
774	struct capi_ctr *ctrl = NULL;
775#ifdef HYCAPI_PRINTFNAMES
776	printk(KERN_NOTICE "hycapi_capi_create\n");
777#endif
778	if((hycapi_enable & (1 << card->myid)) == 0) {
779		return 1;
780	}
781	if (!card->hyctrlinfo) {
782		cinfo = (hycapictrl_info *) kmalloc(sizeof(hycapictrl_info), GFP_ATOMIC);
783		if (!cinfo) {
784			printk(KERN_WARNING "HYSDN: no memory for capi-ctrl.\n");
785			return -ENOMEM;
786		}
787		memset(cinfo, 0, sizeof(hycapictrl_info));
788		card->hyctrlinfo = cinfo;
789		cinfo->card = card;
790		spin_lock_init(&cinfo->lock);
791
792		switch (card->brdtype) {
793			case BD_PCCARD:  strcpy(cinfo->cardname,"HYSDN Hycard"); break;
794			case BD_ERGO: strcpy(cinfo->cardname,"HYSDN Ergo2"); break;
795			case BD_METRO: strcpy(cinfo->cardname,"HYSDN Metro4"); break;
796			case BD_CHAMP2: strcpy(cinfo->cardname,"HYSDN Champ2"); break;
797			case BD_PLEXUS: strcpy(cinfo->cardname,"HYSDN Plexus30"); break;
798			default: strcpy(cinfo->cardname,"HYSDN ???"); break;
799		}
800
801		cinfo->capi_ctrl = hy_di->attach_ctr(&hycapi_driver,
802						     cinfo->cardname, cinfo);
803		ctrl = cinfo->capi_ctrl;
804		if (!ctrl) {
805			printk(KERN_ERR "%s: attach controller failed.\n",
806			       hycapi_driver.name);
807			return -EBUSY;
808		}
809		/* fill in the blanks: */
810		hycapi_fill_profile(card);
811		ctrl->ready(ctrl);
812	} else {
813		/* resume output on stopped ctrl */
814		ctrl = card->hyctrlinfo->capi_ctrl;
815		if(ctrl) {
816			hycapi_fill_profile(card);
817			ctrl->ready(ctrl);
818			hycapi_restart_internal(ctrl);
819/*			ctrl->resume_output(ctrl); */
820		} else {
821			printk(KERN_WARNING "HYSDN: No ctrl???? How come?\n");
822		}
823	}
824	return 0;
825}
826