1 /* $Id: elsa_ser.c,v 2.14.2.3 2004/02/11 13:21:33 keil Exp $
2  *
3  * stuff for the serial modem on ELSA cards
4  *
5  * This software may be used and distributed according to the terms
6  * of the GNU General Public License, incorporated herein by reference.
7  *
8  */
9 
10 #include <linux/serial.h>
11 #include <linux/serial_reg.h>
12 #include <linux/slab.h>
13 
14 #define MAX_MODEM_BUF	256
15 #define WAKEUP_CHARS	(MAX_MODEM_BUF / 2)
16 #define RS_ISR_PASS_LIMIT 256
17 #define BASE_BAUD (1843200 / 16)
18 
19 //#define SERIAL_DEBUG_OPEN 1
20 //#define SERIAL_DEBUG_INTR 1
21 //#define SERIAL_DEBUG_FLOW 1
22 #undef SERIAL_DEBUG_OPEN
23 #undef SERIAL_DEBUG_INTR
24 #undef SERIAL_DEBUG_FLOW
25 #undef SERIAL_DEBUG_REG
26 //#define SERIAL_DEBUG_REG 1
27 
28 #ifdef SERIAL_DEBUG_REG
29 static u_char deb[32];
30 const char *ModemIn[] = {"RBR", "IER", "IIR", "LCR", "MCR", "LSR", "MSR", "SCR"};
31 const char *ModemOut[] = {"THR", "IER", "FCR", "LCR", "MCR", "LSR", "MSR", "SCR"};
32 #endif
33 
34 static char *MInit_1 = "AT&F&C1E0&D2\r\0";
35 static char *MInit_2 = "ATL2M1S64=13\r\0";
36 static char *MInit_3 = "AT+FCLASS=0\r\0";
37 static char *MInit_4 = "ATV1S2=128X1\r\0";
38 static char *MInit_5 = "AT\\V8\\N3\r\0";
39 static char *MInit_6 = "ATL0M0&G0%E1\r\0";
40 static char *MInit_7 = "AT%L1%M0%C3\r\0";
41 
42 static char *MInit_speed28800 = "AT%G0%B28800\r\0";
43 
44 static char *MInit_dialout = "ATs7=60 x1 d\r\0";
45 static char *MInit_dialin = "ATs7=60 x1 a\r\0";
46 
47 
serial_in(struct IsdnCardState * cs,int offset)48 static inline unsigned int serial_in(struct IsdnCardState *cs, int offset)
49 {
50 #ifdef SERIAL_DEBUG_REG
51 	u_int val = inb(cs->hw.elsa.base + 8 + offset);
52 	debugl1(cs, "in   %s %02x", ModemIn[offset], val);
53 	return (val);
54 #else
55 	return inb(cs->hw.elsa.base + 8 + offset);
56 #endif
57 }
58 
serial_inp(struct IsdnCardState * cs,int offset)59 static inline unsigned int serial_inp(struct IsdnCardState *cs, int offset)
60 {
61 #ifdef SERIAL_DEBUG_REG
62 #ifdef ELSA_SERIAL_NOPAUSE_IO
63 	u_int val = inb(cs->hw.elsa.base + 8 + offset);
64 	debugl1(cs, "inp  %s %02x", ModemIn[offset], val);
65 #else
66 	u_int val = inb_p(cs->hw.elsa.base + 8 + offset);
67 	debugl1(cs, "inP  %s %02x", ModemIn[offset], val);
68 #endif
69 	return (val);
70 #else
71 #ifdef ELSA_SERIAL_NOPAUSE_IO
72 	return inb(cs->hw.elsa.base + 8 + offset);
73 #else
74 	return inb_p(cs->hw.elsa.base + 8 + offset);
75 #endif
76 #endif
77 }
78 
serial_out(struct IsdnCardState * cs,int offset,int value)79 static inline void serial_out(struct IsdnCardState *cs, int offset, int value)
80 {
81 #ifdef SERIAL_DEBUG_REG
82 	debugl1(cs, "out  %s %02x", ModemOut[offset], value);
83 #endif
84 	outb(value, cs->hw.elsa.base + 8 + offset);
85 }
86 
serial_outp(struct IsdnCardState * cs,int offset,int value)87 static inline void serial_outp(struct IsdnCardState *cs, int offset,
88 			       int value)
89 {
90 #ifdef SERIAL_DEBUG_REG
91 #ifdef ELSA_SERIAL_NOPAUSE_IO
92 	debugl1(cs, "outp %s %02x", ModemOut[offset], value);
93 #else
94 	debugl1(cs, "outP %s %02x", ModemOut[offset], value);
95 #endif
96 #endif
97 #ifdef ELSA_SERIAL_NOPAUSE_IO
98 	outb(value, cs->hw.elsa.base + 8 + offset);
99 #else
100 	outb_p(value, cs->hw.elsa.base + 8 + offset);
101 #endif
102 }
103 
104 /*
105  * This routine is called to set the UART divisor registers to match
106  * the specified baud rate for a serial port.
107  */
change_speed(struct IsdnCardState * cs,int baud)108 static void change_speed(struct IsdnCardState *cs, int baud)
109 {
110 	int	quot = 0, baud_base;
111 	unsigned cval, fcr = 0;
112 
113 
114 	/* byte size and parity */
115 	cval = 0x03;
116 	/* Determine divisor based on baud rate */
117 	baud_base = BASE_BAUD;
118 	quot = baud_base / baud;
119 	/* If the quotient is ever zero, default to 9600 bps */
120 	if (!quot)
121 		quot = baud_base / 9600;
122 
123 	/* Set up FIFO's */
124 	if ((baud_base / quot) < 2400)
125 		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
126 	else
127 		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
128 	serial_outp(cs, UART_FCR, fcr);
129 	/* CTS flow control flag and modem status interrupts */
130 	cs->hw.elsa.IER &= ~UART_IER_MSI;
131 	cs->hw.elsa.IER |= UART_IER_MSI;
132 	serial_outp(cs, UART_IER, cs->hw.elsa.IER);
133 
134 	debugl1(cs, "modem quot=0x%x", quot);
135 	serial_outp(cs, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
136 	serial_outp(cs, UART_DLL, quot & 0xff);		/* LS of divisor */
137 	serial_outp(cs, UART_DLM, quot >> 8);		/* MS of divisor */
138 	serial_outp(cs, UART_LCR, cval);		/* reset DLAB */
139 	serial_inp(cs, UART_RX);
140 }
141 
mstartup(struct IsdnCardState * cs)142 static int mstartup(struct IsdnCardState *cs)
143 {
144 	int retval = 0;
145 
146 	/*
147 	 * Clear the FIFO buffers and disable them
148 	 * (they will be reenabled in change_speed())
149 	 */
150 	serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT));
151 
152 	/*
153 	 * At this point there's no way the LSR could still be 0xFF;
154 	 * if it is, then bail out, because there's likely no UART
155 	 * here.
156 	 */
157 	if (serial_inp(cs, UART_LSR) == 0xff) {
158 		retval = -ENODEV;
159 		goto errout;
160 	}
161 
162 	/*
163 	 * Clear the interrupt registers.
164 	 */
165 	(void) serial_inp(cs, UART_RX);
166 	(void) serial_inp(cs, UART_IIR);
167 	(void) serial_inp(cs, UART_MSR);
168 
169 	/*
170 	 * Now, initialize the UART
171 	 */
172 	serial_outp(cs, UART_LCR, UART_LCR_WLEN8);	/* reset DLAB */
173 
174 	cs->hw.elsa.MCR = 0;
175 	cs->hw.elsa.MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
176 	serial_outp(cs, UART_MCR, cs->hw.elsa.MCR);
177 
178 	/*
179 	 * Finally, enable interrupts
180 	 */
181 	cs->hw.elsa.IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
182 	serial_outp(cs, UART_IER, cs->hw.elsa.IER);	/* enable interrupts */
183 
184 	/*
185 	 * And clear the interrupt registers again for luck.
186 	 */
187 	(void)serial_inp(cs, UART_LSR);
188 	(void)serial_inp(cs, UART_RX);
189 	(void)serial_inp(cs, UART_IIR);
190 	(void)serial_inp(cs, UART_MSR);
191 
192 	cs->hw.elsa.transcnt = cs->hw.elsa.transp = 0;
193 	cs->hw.elsa.rcvcnt = cs->hw.elsa.rcvp = 0;
194 
195 	/*
196 	 * and set the speed of the serial port
197 	 */
198 	change_speed(cs, BASE_BAUD);
199 	cs->hw.elsa.MFlag = 1;
200 errout:
201 	return retval;
202 }
203 
204 /*
205  * This routine will shutdown a serial port; interrupts are disabled, and
206  * DTR is dropped if the hangup on close termio flag is on.
207  */
mshutdown(struct IsdnCardState * cs)208 static void mshutdown(struct IsdnCardState *cs)
209 {
210 
211 #ifdef SERIAL_DEBUG_OPEN
212 	printk(KERN_DEBUG"Shutting down serial ....");
213 #endif
214 
215 	/*
216 	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
217 	 * here so the queue might never be waken up
218 	 */
219 
220 	cs->hw.elsa.IER = 0;
221 	serial_outp(cs, UART_IER, 0x00);	/* disable all intrs */
222 	cs->hw.elsa.MCR &= ~UART_MCR_OUT2;
223 
224 	/* disable break condition */
225 	serial_outp(cs, UART_LCR, serial_inp(cs, UART_LCR) & ~UART_LCR_SBC);
226 
227 	cs->hw.elsa.MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);
228 	serial_outp(cs, UART_MCR, cs->hw.elsa.MCR);
229 
230 	/* disable FIFO's */
231 	serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT));
232 	serial_inp(cs, UART_RX);    /* read data port to reset things */
233 
234 #ifdef SERIAL_DEBUG_OPEN
235 	printk(" done\n");
236 #endif
237 }
238 
239 static inline int
write_modem(struct BCState * bcs)240 write_modem(struct BCState *bcs) {
241 	int ret = 0;
242 	struct IsdnCardState *cs = bcs->cs;
243 	int count, len, fp;
244 
245 	if (!bcs->tx_skb)
246 		return 0;
247 	if (bcs->tx_skb->len <= 0)
248 		return 0;
249 	len = bcs->tx_skb->len;
250 	if (len > MAX_MODEM_BUF - cs->hw.elsa.transcnt)
251 		len = MAX_MODEM_BUF - cs->hw.elsa.transcnt;
252 	fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp;
253 	fp &= (MAX_MODEM_BUF - 1);
254 	count = len;
255 	if (count > MAX_MODEM_BUF - fp) {
256 		count = MAX_MODEM_BUF - fp;
257 		skb_copy_from_linear_data(bcs->tx_skb,
258 					  cs->hw.elsa.transbuf + fp, count);
259 		skb_pull(bcs->tx_skb, count);
260 		cs->hw.elsa.transcnt += count;
261 		ret = count;
262 		count = len - count;
263 		fp = 0;
264 	}
265 	skb_copy_from_linear_data(bcs->tx_skb,
266 				  cs->hw.elsa.transbuf + fp, count);
267 	skb_pull(bcs->tx_skb, count);
268 	cs->hw.elsa.transcnt += count;
269 	ret += count;
270 
271 	if (cs->hw.elsa.transcnt &&
272 	    !(cs->hw.elsa.IER & UART_IER_THRI)) {
273 		cs->hw.elsa.IER |= UART_IER_THRI;
274 		serial_outp(cs, UART_IER, cs->hw.elsa.IER);
275 	}
276 	return (ret);
277 }
278 
279 static inline void
modem_fill(struct BCState * bcs)280 modem_fill(struct BCState *bcs) {
281 
282 	if (bcs->tx_skb) {
283 		if (bcs->tx_skb->len) {
284 			write_modem(bcs);
285 			return;
286 		} else {
287 			if (test_bit(FLG_LLI_L1WAKEUP, &bcs->st->lli.flag) &&
288 			    (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
289 				u_long	flags;
290 				spin_lock_irqsave(&bcs->aclock, flags);
291 				bcs->ackcnt += bcs->hw.hscx.count;
292 				spin_unlock_irqrestore(&bcs->aclock, flags);
293 				schedule_event(bcs, B_ACKPENDING);
294 			}
295 			dev_kfree_skb_any(bcs->tx_skb);
296 			bcs->tx_skb = NULL;
297 		}
298 	}
299 	if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
300 		bcs->hw.hscx.count = 0;
301 		test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
302 		write_modem(bcs);
303 	} else {
304 		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
305 		schedule_event(bcs, B_XMTBUFREADY);
306 	}
307 }
308 
receive_chars(struct IsdnCardState * cs,int * status)309 static inline void receive_chars(struct IsdnCardState *cs,
310 				 int *status)
311 {
312 	unsigned char ch;
313 	struct sk_buff *skb;
314 
315 	do {
316 		ch = serial_in(cs, UART_RX);
317 		if (cs->hw.elsa.rcvcnt >= MAX_MODEM_BUF)
318 			break;
319 		cs->hw.elsa.rcvbuf[cs->hw.elsa.rcvcnt++] = ch;
320 #ifdef SERIAL_DEBUG_INTR
321 		printk("DR%02x:%02x...", ch, *status);
322 #endif
323 		if (*status & (UART_LSR_BI | UART_LSR_PE |
324 			       UART_LSR_FE | UART_LSR_OE)) {
325 
326 #ifdef SERIAL_DEBUG_INTR
327 			printk("handling exept....");
328 #endif
329 		}
330 		*status = serial_inp(cs, UART_LSR);
331 	} while (*status & UART_LSR_DR);
332 	if (cs->hw.elsa.MFlag == 2) {
333 		if (!(skb = dev_alloc_skb(cs->hw.elsa.rcvcnt)))
334 			printk(KERN_WARNING "ElsaSER: receive out of memory\n");
335 		else {
336 			skb_put_data(skb, cs->hw.elsa.rcvbuf,
337 				     cs->hw.elsa.rcvcnt);
338 			skb_queue_tail(&cs->hw.elsa.bcs->rqueue, skb);
339 		}
340 		schedule_event(cs->hw.elsa.bcs, B_RCVBUFREADY);
341 	} else {
342 		char tmp[128];
343 		char *t = tmp;
344 
345 		t += sprintf(t, "modem read cnt %d", cs->hw.elsa.rcvcnt);
346 		QuickHex(t, cs->hw.elsa.rcvbuf, cs->hw.elsa.rcvcnt);
347 		debugl1(cs, "%s", tmp);
348 	}
349 	cs->hw.elsa.rcvcnt = 0;
350 }
351 
transmit_chars(struct IsdnCardState * cs,int * intr_done)352 static inline void transmit_chars(struct IsdnCardState *cs, int *intr_done)
353 {
354 	int count;
355 
356 	debugl1(cs, "transmit_chars: p(%x) cnt(%x)", cs->hw.elsa.transp,
357 		cs->hw.elsa.transcnt);
358 
359 	if (cs->hw.elsa.transcnt <= 0) {
360 		cs->hw.elsa.IER &= ~UART_IER_THRI;
361 		serial_out(cs, UART_IER, cs->hw.elsa.IER);
362 		return;
363 	}
364 	count = 16;
365 	do {
366 		serial_outp(cs, UART_TX, cs->hw.elsa.transbuf[cs->hw.elsa.transp++]);
367 		if (cs->hw.elsa.transp >= MAX_MODEM_BUF)
368 			cs->hw.elsa.transp = 0;
369 		if (--cs->hw.elsa.transcnt <= 0)
370 			break;
371 	} while (--count > 0);
372 	if ((cs->hw.elsa.transcnt < WAKEUP_CHARS) && (cs->hw.elsa.MFlag == 2))
373 		modem_fill(cs->hw.elsa.bcs);
374 
375 #ifdef SERIAL_DEBUG_INTR
376 	printk("THRE...");
377 #endif
378 	if (intr_done)
379 		*intr_done = 0;
380 	if (cs->hw.elsa.transcnt <= 0) {
381 		cs->hw.elsa.IER &= ~UART_IER_THRI;
382 		serial_outp(cs, UART_IER, cs->hw.elsa.IER);
383 	}
384 }
385 
386 
rs_interrupt_elsa(struct IsdnCardState * cs)387 static void rs_interrupt_elsa(struct IsdnCardState *cs)
388 {
389 	int status, iir, msr;
390 	int pass_counter = 0;
391 
392 #ifdef SERIAL_DEBUG_INTR
393 	printk(KERN_DEBUG "rs_interrupt_single(%d)...", cs->irq);
394 #endif
395 
396 	do {
397 		status = serial_inp(cs, UART_LSR);
398 		debugl1(cs, "rs LSR %02x", status);
399 #ifdef SERIAL_DEBUG_INTR
400 		printk("status = %x...", status);
401 #endif
402 		if (status & UART_LSR_DR)
403 			receive_chars(cs, &status);
404 		if (status & UART_LSR_THRE)
405 			transmit_chars(cs, NULL);
406 		if (pass_counter++ > RS_ISR_PASS_LIMIT) {
407 			printk("rs_single loop break.\n");
408 			break;
409 		}
410 		iir = serial_inp(cs, UART_IIR);
411 		debugl1(cs, "rs IIR %02x", iir);
412 		if ((iir & 0xf) == 0) {
413 			msr = serial_inp(cs, UART_MSR);
414 			debugl1(cs, "rs MSR %02x", msr);
415 		}
416 	} while (!(iir & UART_IIR_NO_INT));
417 #ifdef SERIAL_DEBUG_INTR
418 	printk("end.\n");
419 #endif
420 }
421 
422 extern int open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs);
423 extern void modehscx(struct BCState *bcs, int mode, int bc);
424 extern void hscx_l2l1(struct PStack *st, int pr, void *arg);
425 
426 static void
close_elsastate(struct BCState * bcs)427 close_elsastate(struct BCState *bcs)
428 {
429 	modehscx(bcs, 0, bcs->channel);
430 	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
431 		if (bcs->hw.hscx.rcvbuf) {
432 			if (bcs->mode != L1_MODE_MODEM)
433 				kfree(bcs->hw.hscx.rcvbuf);
434 			bcs->hw.hscx.rcvbuf = NULL;
435 		}
436 		skb_queue_purge(&bcs->rqueue);
437 		skb_queue_purge(&bcs->squeue);
438 		if (bcs->tx_skb) {
439 			dev_kfree_skb_any(bcs->tx_skb);
440 			bcs->tx_skb = NULL;
441 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
442 		}
443 	}
444 }
445 
446 static void
modem_write_cmd(struct IsdnCardState * cs,u_char * buf,int len)447 modem_write_cmd(struct IsdnCardState *cs, u_char *buf, int len) {
448 	int count, fp;
449 	u_char *msg = buf;
450 
451 	if (!len)
452 		return;
453 	if (len > (MAX_MODEM_BUF - cs->hw.elsa.transcnt)) {
454 		return;
455 	}
456 	fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp;
457 	fp &= (MAX_MODEM_BUF - 1);
458 	count = len;
459 	if (count > MAX_MODEM_BUF - fp) {
460 		count = MAX_MODEM_BUF - fp;
461 		memcpy(cs->hw.elsa.transbuf + fp, msg, count);
462 		cs->hw.elsa.transcnt += count;
463 		msg += count;
464 		count = len - count;
465 		fp = 0;
466 	}
467 	memcpy(cs->hw.elsa.transbuf + fp, msg, count);
468 	cs->hw.elsa.transcnt += count;
469 	if (cs->hw.elsa.transcnt &&
470 	    !(cs->hw.elsa.IER & UART_IER_THRI)) {
471 		cs->hw.elsa.IER |= UART_IER_THRI;
472 		serial_outp(cs, UART_IER, cs->hw.elsa.IER);
473 	}
474 }
475 
476 static void
modem_set_init(struct IsdnCardState * cs)477 modem_set_init(struct IsdnCardState *cs) {
478 	int timeout;
479 
480 #define RCV_DELAY 20
481 	modem_write_cmd(cs, MInit_1, strlen(MInit_1));
482 	timeout = 1000;
483 	while (timeout-- && cs->hw.elsa.transcnt)
484 		udelay(1000);
485 	debugl1(cs, "msi tout=%d", timeout);
486 	mdelay(RCV_DELAY);
487 	modem_write_cmd(cs, MInit_2, strlen(MInit_2));
488 	timeout = 1000;
489 	while (timeout-- && cs->hw.elsa.transcnt)
490 		udelay(1000);
491 	debugl1(cs, "msi tout=%d", timeout);
492 	mdelay(RCV_DELAY);
493 	modem_write_cmd(cs, MInit_3, strlen(MInit_3));
494 	timeout = 1000;
495 	while (timeout-- && cs->hw.elsa.transcnt)
496 		udelay(1000);
497 	debugl1(cs, "msi tout=%d", timeout);
498 	mdelay(RCV_DELAY);
499 	modem_write_cmd(cs, MInit_4, strlen(MInit_4));
500 	timeout = 1000;
501 	while (timeout-- && cs->hw.elsa.transcnt)
502 		udelay(1000);
503 	debugl1(cs, "msi tout=%d", timeout);
504 	mdelay(RCV_DELAY);
505 	modem_write_cmd(cs, MInit_5, strlen(MInit_5));
506 	timeout = 1000;
507 	while (timeout-- && cs->hw.elsa.transcnt)
508 		udelay(1000);
509 	debugl1(cs, "msi tout=%d", timeout);
510 	mdelay(RCV_DELAY);
511 	modem_write_cmd(cs, MInit_6, strlen(MInit_6));
512 	timeout = 1000;
513 	while (timeout-- && cs->hw.elsa.transcnt)
514 		udelay(1000);
515 	debugl1(cs, "msi tout=%d", timeout);
516 	mdelay(RCV_DELAY);
517 	modem_write_cmd(cs, MInit_7, strlen(MInit_7));
518 	timeout = 1000;
519 	while (timeout-- && cs->hw.elsa.transcnt)
520 		udelay(1000);
521 	debugl1(cs, "msi tout=%d", timeout);
522 	mdelay(RCV_DELAY);
523 }
524 
525 static void
modem_set_dial(struct IsdnCardState * cs,int outgoing)526 modem_set_dial(struct IsdnCardState *cs, int outgoing) {
527 	int timeout;
528 #define RCV_DELAY 20
529 
530 	modem_write_cmd(cs, MInit_speed28800, strlen(MInit_speed28800));
531 	timeout = 1000;
532 	while (timeout-- && cs->hw.elsa.transcnt)
533 		udelay(1000);
534 	debugl1(cs, "msi tout=%d", timeout);
535 	mdelay(RCV_DELAY);
536 	if (outgoing)
537 		modem_write_cmd(cs, MInit_dialout, strlen(MInit_dialout));
538 	else
539 		modem_write_cmd(cs, MInit_dialin, strlen(MInit_dialin));
540 	timeout = 1000;
541 	while (timeout-- && cs->hw.elsa.transcnt)
542 		udelay(1000);
543 	debugl1(cs, "msi tout=%d", timeout);
544 	mdelay(RCV_DELAY);
545 }
546 
547 static void
modem_l2l1(struct PStack * st,int pr,void * arg)548 modem_l2l1(struct PStack *st, int pr, void *arg)
549 {
550 	struct BCState *bcs = st->l1.bcs;
551 	struct sk_buff *skb = arg;
552 	u_long flags;
553 
554 	if (pr == (PH_DATA | REQUEST)) {
555 		spin_lock_irqsave(&bcs->cs->lock, flags);
556 		if (bcs->tx_skb) {
557 			skb_queue_tail(&bcs->squeue, skb);
558 		} else {
559 			bcs->tx_skb = skb;
560 			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
561 			bcs->hw.hscx.count = 0;
562 			write_modem(bcs);
563 		}
564 		spin_unlock_irqrestore(&bcs->cs->lock, flags);
565 	} else if (pr == (PH_ACTIVATE | REQUEST)) {
566 		test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
567 		st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
568 		set_arcofi(bcs->cs, st->l1.bc);
569 		mstartup(bcs->cs);
570 		modem_set_dial(bcs->cs, test_bit(FLG_ORIG, &st->l2.flag));
571 		bcs->cs->hw.elsa.MFlag = 2;
572 	} else if (pr == (PH_DEACTIVATE | REQUEST)) {
573 		test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
574 		bcs->cs->dc.isac.arcofi_bc = st->l1.bc;
575 		arcofi_fsm(bcs->cs, ARCOFI_START, &ARCOFI_XOP_0);
576 		wait_event_interruptible(bcs->cs->dc.isac.arcofi_wait,
577 				 bcs->cs->dc.isac.arcofi_state == ARCOFI_NOP);
578 		bcs->cs->hw.elsa.MFlag = 1;
579 	} else {
580 		printk(KERN_WARNING "ElsaSer: unknown pr %x\n", pr);
581 	}
582 }
583 
584 static int
setstack_elsa(struct PStack * st,struct BCState * bcs)585 setstack_elsa(struct PStack *st, struct BCState *bcs)
586 {
587 
588 	bcs->channel = st->l1.bc;
589 	switch (st->l1.mode) {
590 	case L1_MODE_HDLC:
591 	case L1_MODE_TRANS:
592 		if (open_hscxstate(st->l1.hardware, bcs))
593 			return (-1);
594 		st->l2.l2l1 = hscx_l2l1;
595 		break;
596 	case L1_MODE_MODEM:
597 		bcs->mode = L1_MODE_MODEM;
598 		if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
599 			bcs->hw.hscx.rcvbuf = bcs->cs->hw.elsa.rcvbuf;
600 			skb_queue_head_init(&bcs->rqueue);
601 			skb_queue_head_init(&bcs->squeue);
602 		}
603 		bcs->tx_skb = NULL;
604 		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
605 		bcs->event = 0;
606 		bcs->hw.hscx.rcvidx = 0;
607 		bcs->tx_cnt = 0;
608 		bcs->cs->hw.elsa.bcs = bcs;
609 		st->l2.l2l1 = modem_l2l1;
610 		break;
611 	}
612 	st->l1.bcs = bcs;
613 	setstack_manager(st);
614 	bcs->st = st;
615 	setstack_l1_B(st);
616 	return (0);
617 }
618 
619 static void
init_modem(struct IsdnCardState * cs)620 init_modem(struct IsdnCardState *cs) {
621 
622 	cs->bcs[0].BC_SetStack = setstack_elsa;
623 	cs->bcs[1].BC_SetStack = setstack_elsa;
624 	cs->bcs[0].BC_Close = close_elsastate;
625 	cs->bcs[1].BC_Close = close_elsastate;
626 	if (!(cs->hw.elsa.rcvbuf = kmalloc(MAX_MODEM_BUF,
627 					   GFP_ATOMIC))) {
628 		printk(KERN_WARNING
629 		       "Elsa: No modem mem hw.elsa.rcvbuf\n");
630 		return;
631 	}
632 	if (!(cs->hw.elsa.transbuf = kmalloc(MAX_MODEM_BUF,
633 					     GFP_ATOMIC))) {
634 		printk(KERN_WARNING
635 		       "Elsa: No modem mem hw.elsa.transbuf\n");
636 		kfree(cs->hw.elsa.rcvbuf);
637 		cs->hw.elsa.rcvbuf = NULL;
638 		return;
639 	}
640 	if (mstartup(cs)) {
641 		printk(KERN_WARNING "Elsa: problem startup modem\n");
642 	}
643 	modem_set_init(cs);
644 }
645 
646 static void
release_modem(struct IsdnCardState * cs)647 release_modem(struct IsdnCardState *cs) {
648 
649 	cs->hw.elsa.MFlag = 0;
650 	if (cs->hw.elsa.transbuf) {
651 		if (cs->hw.elsa.rcvbuf) {
652 			mshutdown(cs);
653 			kfree(cs->hw.elsa.rcvbuf);
654 			cs->hw.elsa.rcvbuf = NULL;
655 		}
656 		kfree(cs->hw.elsa.transbuf);
657 		cs->hw.elsa.transbuf = NULL;
658 	}
659 }
660