Misc. changes by Pedro.

This commit is contained in:
Fritz Elfert 1996-06-20 19:21:44 +00:00
parent e728f3abbb
commit 91580dd520
6 changed files with 120 additions and 150 deletions

View File

@ -59,7 +59,8 @@ void cb_out_1(struct pcbit_dev * dev, struct pcbit_chan* chan,
* - kfree when msg has been sent
*/
if ((len = capi_conn_req(cbdata->data.setup.CalledPN, &skb)) < 0)
if ((len = capi_conn_req(cbdata->data.setup.CalledPN, &skb,
chan->proto)) < 0)
{
printk("capi_conn_req failed\n");
return;

View File

@ -58,7 +58,7 @@
*
*/
int capi_conn_req(const char * calledPN, struct sk_buff **skb)
int capi_conn_req(const char * calledPN, struct sk_buff **skb, int proto)
{
ushort len;
@ -80,6 +80,9 @@ int capi_conn_req(const char * calledPN, struct sk_buff **skb)
len = 18 + strlen(calledPN);
if (proto == ISDN_PROTO_L2_TRANS)
len++;
if ((*skb = dev_alloc_skb(len)) == NULL) {
printk(KERN_WARNING "capi_conn_req: alloc_skb failed\n");
@ -89,11 +92,21 @@ int capi_conn_req(const char * calledPN, struct sk_buff **skb)
/* InfoElmMask */
*((ushort*) skb_put(*skb, 2)) = AppInfoMask;
/* Bearer Capability - Mandatory*/
*(skb_put(*skb, 1)) = 2; /* BC0.Length */
*(skb_put(*skb, 1)) = 0x88; /* BC0.Octect3 - Digital Information */
*(skb_put(*skb, 1)) = 0x90; /* BC0.Octect4 - */
if (proto == ISDN_PROTO_L2_TRANS)
{
/* Bearer Capability - Mandatory*/
*(skb_put(*skb, 1)) = 3; /* BC0.Length */
*(skb_put(*skb, 1)) = 0x80; /* Speech */
*(skb_put(*skb, 1)) = 0x10; /* Circuit Mode */
*(skb_put(*skb, 1)) = 0x23; /* A-law */
}
else
{
/* Bearer Capability - Mandatory*/
*(skb_put(*skb, 1)) = 2; /* BC0.Length */
*(skb_put(*skb, 1)) = 0x88; /* Digital Information */
*(skb_put(*skb, 1)) = 0x90; /* BC0.Octect4 */
}
/* Bearer Capability - Optional*/
*(skb_put(*skb, 1)) = 0; /* BC1.Length = 0 */
@ -220,16 +233,19 @@ int capi_select_proto_req(struct pcbit_chan *chan, struct sk_buff **skb,
*(skb_put(*skb, 1)) = 0x05; /* LAPB */
break;
case ISDN_PROTO_L2_HDLC:
#ifdef DEBUG
printk(KERN_DEBUG "HDLC\n"); /* HDLC */
#endif
*(skb_put(*skb, 1)) = 0x02;
break;
case ISDN_PROTO_L2_TRANS:
/*
* Voice (a-law)
*/
*(skb_put(*skb, 1)) = 0x06;
break;
default:
#ifdef DEBUG
printk(KERN_DEBUG "Transparent\n");
#endif
*(skb_put(*skb, 1)) = 0x03;
*(skb_put(*skb, 1)) = 0x03;
break;
}

View File

@ -22,7 +22,8 @@
#define AppInfoMask REQ_CAUSE|REQ_DISPLAY|REQ_USER_TO_USER
/* Connection Setup */
extern int capi_conn_req(const char * calledPN, struct sk_buff **buf);
extern int capi_conn_req(const char * calledPN, struct sk_buff **buf,
int proto);
extern int capi_decode_conn_conf(struct pcbit_chan * chan, struct sk_buff *skb,
int *complete);

View File

@ -11,6 +11,14 @@
* PCBIT-D interface with isdn4linux
*/
/*
* Fixes:
*
* Nuno Grilo <l38486@alfa.ist.utl.pt>
* fixed msn_list NULL pointer dereference.
*
*/
#define __NO_VERSION__
#include <linux/module.h>
@ -109,7 +117,7 @@ int pcbit_init_dev(int board, int mem_base, int irq)
dev->b2->id = 1;
dev->qdelivery.next = 0;
dev->qdelivery.next = NULL;
dev->qdelivery.sync = 0;
dev->qdelivery.routine = pcbit_deliver;
dev->qdelivery.data = dev;
@ -152,8 +160,8 @@ int pcbit_init_dev(int board, int mem_base, int irq)
dev_if->channels = 2;
dev_if->features = ISDN_FEATURE_P_EURO | ISDN_FEATURE_L3_TRANS |
ISDN_FEATURE_L2_HDLC;
dev_if->features = (ISDN_FEATURE_P_EURO | ISDN_FEATURE_L3_TRANS |
ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L2_TRANS );
dev_if->writebuf_skb = pcbit_xmit;
dev_if->writebuf = NULL;
@ -1051,7 +1059,8 @@ static void pcbit_clear_msn(struct pcbit_dev *dev)
static void pcbit_set_msn(struct pcbit_dev *dev, char *list)
{
struct msn_entry *ptr, *back;
struct msn_entry *ptr;
struct msn_entry *back = NULL;
char *cp, *sp;
int len;
@ -1070,7 +1079,8 @@ static void pcbit_set_msn(struct pcbit_dev *dev, char *list)
return;
}
for (back=dev->msn_list; back->next; back=back->next);
if (dev->msn_list)
for (back=dev->msn_list; back->next; back=back->next);
sp = list;
@ -1128,10 +1138,3 @@ static int pcbit_check_msn(struct pcbit_dev *dev, char *msn)
return 0;
}

View File

@ -288,15 +288,10 @@ void pcbit_fsm_event(struct pcbit_dev *dev, struct pcbit_chan *chan,
save_flags(flags);
cli();
if (chan->fsm_timer.function) {
del_timer(&chan->fsm_timer);
chan->fsm_timer.function = NULL;
}
for (action = fsm_table; action->init != 0xff; action++)
if (action->init == chan->fsm_state && action->event == event)
break;
if (action->init == 0xff) {
@ -305,6 +300,11 @@ void pcbit_fsm_event(struct pcbit_dev *dev, struct pcbit_chan *chan,
return;
}
if (chan->fsm_timer.function) {
del_timer(&chan->fsm_timer);
chan->fsm_timer.function = NULL;
}
chan->fsm_state = action->final;
pcbit_state_change(dev, chan, action->init, event, action->final);

View File

@ -58,16 +58,7 @@
/*
* task queue struct
*/
struct tq_struct *tq_delivery=NULL;
static void do_pcbit_bh(task_queue *list)
{
run_task_queue(list);
}
struct tq_struct run_delivery= {
0, 0, (void *)(void *) do_pcbit_bh, &tq_delivery,
};
/*
@ -87,7 +78,6 @@ void pcbit_deliver(void * data);
static void pcbit_transmit(struct pcbit_dev * dev);
static void pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack);
static void pcbit_frame_read(struct pcbit_dev * dev, unsigned char read_seq);
static void pcbit_l2_error(struct pcbit_dev *dev);
static void pcbit_l2_active_conf(struct pcbit_dev *dev, u_char info);
@ -95,11 +85,10 @@ static void pcbit_l2_err_recover(unsigned long data);
static void pcbit_firmware_bug(struct pcbit_dev * dev);
static void pcbit_sched_delivery(struct pcbit_dev *dev)
static __inline__ void pcbit_sched_delivery(struct pcbit_dev *dev)
{
queue_task_irq_off(&dev->qdelivery, &tq_delivery);
queue_task_irq_off(&run_delivery, &tq_immediate);
mark_bh(IMMEDIATE_BH);
queue_task(&dev->qdelivery, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}
@ -195,12 +184,11 @@ static void pcbit_transmit(struct pcbit_dev * dev)
unacked = (dev->send_seq + (8 - dev->unack_seq) ) & 0x07;
save_flags(flags);
cli();
if (dev->free > 16 && dev->write_queue && unacked < 7) {
save_flags(flags);
cli();
if (!dev->w_busy)
dev->w_busy = 1;
else
@ -209,11 +197,12 @@ static void pcbit_transmit(struct pcbit_dev * dev)
return;
}
restore_flags(flags);
frame = dev->write_queue;
free = dev->free;
restore_flags(flags);
if (frame->copied == 0) {
/* Type 0 frame */
@ -311,12 +300,15 @@ static void pcbit_transmit(struct pcbit_dev * dev)
dev->w_busy = 0;
restore_flags(flags);
}
#ifdef DEBUG
else
{
restore_flags(flags);
#ifdef DEBUG
printk(KERN_DEBUG "unacked %d free %d write_queue %s\n",
unacked, dev->free, dev->write_queue ? "not empty" :
"empty");
"empty");
#endif
}
}
@ -334,29 +326,31 @@ void pcbit_deliver(void * data)
save_flags(flags);
cli();
/* get frame from queue */
if (!(frame=dev->read_queue)) {
while((frame=dev->read_queue))
{
dev->read_queue = frame->next;
restore_flags(flags);
return;
msg.cpu = 0;
msg.proc = 0;
msg.cmd = frame->skb->data[2];
msg.scmd = frame->skb->data[3];
frame->refnum = *((ushort*) frame->skb->data + 4);
frame->msg = *((ulong*) &msg);
skb_pull(frame->skb, 6);
pcbit_l3_receive(dev, frame->msg, frame->skb, frame->hdr_len,
frame->refnum);
kfree(frame);
save_flags(flags);
cli();
}
dev->read_queue = frame->next;
restore_flags(flags);
msg.cpu = 0;
msg.proc = 0;
msg.cmd = frame->skb->data[2];
msg.scmd = frame->skb->data[3];
frame->refnum = *((ushort*) frame->skb->data + 4);
frame->msg = *((ulong*) &msg);
skb_pull(frame->skb, 6);
pcbit_l3_receive(dev, frame->msg, frame->skb, frame->hdr_len,
frame->refnum);
kfree(frame);
restore_flags(flags);
}
/*
@ -517,8 +511,7 @@ static void pcbit_receive(struct pcbit_dev * dev)
}
else
dev->read_queue = frame;
pcbit_sched_delivery(dev);
restore_flags(flags);
}
@ -572,7 +565,6 @@ void pcbit_irq_handler(int interrupt, void * devptr, struct pt_regs *regs)
{
struct pcbit_dev * dev;
u_char info, ack_seq, read_seq;
u_char ack_int = 1;
dev = (struct pcbit_dev *) devptr;
@ -618,33 +610,27 @@ void pcbit_irq_handler(int interrupt, void * devptr, struct pt_regs *regs)
read_seq = (info & 0x07U);
dev->interrupt = 0;
sti();
/*
* Bottom Half
* Runs with ints enabled
*/
if (read_seq != dev->rcv_seq)
{
pcbit_frame_read(dev, read_seq);
ack_int = 0;
while (read_seq != dev->rcv_seq)
{
pcbit_receive(dev);
dev->rcv_seq = (dev->rcv_seq + 1) % 8;
}
pcbit_sched_delivery(dev);
}
if (ack_seq != dev->unack_seq)
{
pcbit_recv_ack(dev, ack_seq);
ack_int = 0;
}
if (ack_int)
{
info = 0;
info |= dev->rcv_seq << 3;
info |= dev->send_seq;
info = dev->rcv_seq << 3;
info |= dev->send_seq;
writeb(info, dev->sh_mem + BANK4);
}
writeb(info, dev->sh_mem + BANK4);
}
@ -685,17 +671,19 @@ static void pcbit_l2_err_recover(unsigned long data)
del_timer(&dev->error_recover_timer);
if (dev->w_busy || dev->r_busy)
{
init_timer(&dev->error_recover_timer);
dev->error_recover_timer.expires = jiffies + ERRTIME;
add_timer(&dev->error_recover_timer);
return;
}
{
init_timer(&dev->error_recover_timer);
dev->error_recover_timer.expires = jiffies + ERRTIME;
add_timer(&dev->error_recover_timer);
return;
}
dev->w_busy = dev->r_busy = 1;
if (dev->read_frame) {
if (dev->read_frame->skb) {
if (dev->read_frame)
{
if (dev->read_frame->skb)
{
dev->read_frame->skb->free = 1;
kfree_skb(dev->read_frame->skb, FREE_READ);
}
@ -704,7 +692,8 @@ static void pcbit_l2_err_recover(unsigned long data)
}
if (dev->write_queue) {
if (dev->write_queue)
{
frame = dev->write_queue;
#ifdef FREE_ON_ERROR
dev->write_queue = dev->write_queue->next;
@ -775,14 +764,20 @@ static void pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack)
{
if (dev->send_seq > dev->unack_seq)
if (ack <= dev->unack_seq || ack > dev->send_seq)
if (ack <= dev->unack_seq || ack > dev->send_seq)
{
printk("layer 2 ack unacceptable - dev %d", dev->id);
printk(KERN_DEBUG
"layer 2 ack unacceptable - dev %d",
dev->id);
pcbit_l2_error(dev);
}
else
if (ack > dev->send_seq && ack <= dev->unack_seq) {
printk("layer 2 ack unacceptable - dev %d", dev->id);
if (ack > dev->send_seq && ack <= dev->unack_seq)
{
printk(KERN_DEBUG
"layer 2 ack unacceptable - dev %d",
dev->id);
pcbit_l2_error(dev);
}
@ -805,55 +800,9 @@ static void pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack)
if (dev->send_seq == lsend_seq)
break;
count++;
}
if (!count) {
u_char info;
info = 0;
info |= dev->rcv_seq << 3;
info |= dev->send_seq;
writeb(info, dev->sh_mem + BANK4);
}
count++;
}
}
else
printk(KERN_DEBUG "recv_ack: unacked = 0\n");
}
static void pcbit_frame_read(struct pcbit_dev * dev, unsigned char read_seq)
{
unsigned long flags;
int busy;
u_char info;
save_flags(flags);
cli();
if (!(busy=dev->r_busy))
dev->r_busy = 1;
restore_flags(flags);
if (busy)
return;
while (read_seq != dev->rcv_seq) {
pcbit_receive(dev);
dev->rcv_seq = (dev->rcv_seq + 1) % 8;
}
dev->r_busy = 0;
info = 0;
info |= dev->rcv_seq << 3;
info |= dev->send_seq;
writeb(info, dev->sh_mem + BANK4);
}