extractedLnx/linux-2.5.9/drivers/isdn/icn/icn.c_icn_command.c
static int
icn_command(isdn_ctrl * c, icn_card * card)
{
ulong a;
ulong flags;
int i;
char cbuf[60];
isdn_ctrl cmd;
icn_cdef cdef;
switch (c->command) {
case ISDN_CMD_IOCTL:
memcpy(&a, c->parm.num, sizeof(ulong));
switch (c->arg) {
case ICN_IOCTL_SETMMIO:
if (dev.memaddr != (a & 0x0ffc000)) {
if (check_mem_region(a & 0x0ffc000, 0x4000)) {
printk(KERN_WARNING
"icn: memory at 0x%08lx in use.\n",
a & 0x0ffc000);
return -EINVAL;
}
icn_stopallcards();
save_flags(flags);
cli();
if (dev.mvalid) {
iounmap(dev.shmem);
release_mem_region(dev.memaddr, 0x4000);
}
dev.mvalid = 0;
dev.memaddr = a & 0x0ffc000;
restore_flags(flags);
printk(KERN_INFO
"icn: (%s) mmio set to 0x%08lx\n",
CID,
dev.memaddr);
}
break;
case ICN_IOCTL_GETMMIO:
return (long) dev.memaddr;
case ICN_IOCTL_SETPORT:
if (a == 0x300 || a == 0x310 || a == 0x320 || a == 0x330
|| a == 0x340 || a == 0x350 || a == 0x360 ||
a == 0x308 || a == 0x318 || a == 0x328 || a == 0x338
|| a == 0x348 || a == 0x358 || a == 0x368) {
if (card->port != (unsigned short) a) {
if (check_region((unsigned short) a, ICN_PORTLEN)) {
printk(KERN_WARNING
"icn: (%s) ports 0x%03x-0x%03x in use.\n",
CID, (int) a, (int) a + ICN_PORTLEN);
return -EINVAL;
}
icn_stopcard(card);
save_flags(flags);
cli();
if (card->rvalid)
release_region(card->port, ICN_PORTLEN);
card->port = (unsigned short) a;
card->rvalid = 0;
if (card->doubleS0) {
card->other->port = (unsigned short) a;
card->other->rvalid = 0;
}
restore_flags(flags);
printk(KERN_INFO
"icn: (%s) port set to 0x%03x\n",
CID, card->port);
}
} else
return -EINVAL;
break;
case ICN_IOCTL_GETPORT:
return (int) card->port;
case ICN_IOCTL_GETDOUBLE:
return (int) card->doubleS0;
case ICN_IOCTL_DEBUGVAR:
if ((i = copy_to_user((char *) a,
(char *) &card, sizeof(ulong))))
return i;
a += sizeof(ulong);
{
ulong l = (ulong) & dev;
if ((i = copy_to_user((char *) a,
(char *) &l, sizeof(ulong))))
return i;
}
return 0;
case ICN_IOCTL_LOADBOOT:
if (dev.firstload) {
icn_disable_cards();
dev.firstload = 0;
}
icn_stopcard(card);
return (icn_loadboot((u_char *) a, card));
case ICN_IOCTL_LOADPROTO:
icn_stopcard(card);
if ((i = (icn_loadproto((u_char *) a, card))))
return i;
if (card->doubleS0)
i = icn_loadproto((u_char *) (a + ICN_CODE_STAGE2), card->other);
return i;
break;
case ICN_IOCTL_ADDCARD:
if (!dev.firstload)
return -EBUSY;
if ((i = copy_from_user((char *) &cdef, (char *) a, sizeof(cdef))))
return i;
return (icn_addcard(cdef.port, cdef.id1, cdef.id2));
break;
case ICN_IOCTL_LEASEDCFG:
if (a) {
if (!card->leased) {
card->leased = 1;
while (card->ptype == ISDN_PTYPE_UNKNOWN) {
schedule_timeout(ICN_BOOT_TIMEOUT1);
}
schedule_timeout(ICN_BOOT_TIMEOUT1);
sprintf(cbuf, "00;FV2ON\n01;EAZ%c\n02;EAZ%c\n",
(a & 1)?'1':'C', (a & 2)?'2':'C');
i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
printk(KERN_INFO
"icn: (%s) Leased-line mode enabled\n",
CID);
cmd.command = ISDN_STAT_RUN;
cmd.driver = card->myid;
cmd.arg = 0;
card->interface.statcallb(&cmd);
}
} else {
if (card->leased) {
card->leased = 0;
sprintf(cbuf, "00;FV2OFF\n");
i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
printk(KERN_INFO
"icn: (%s) Leased-line mode disabled\n",
CID);
cmd.command = ISDN_STAT_RUN;
cmd.driver = card->myid;
cmd.arg = 0;
card->interface.statcallb(&cmd);
}
}
return 0;
default:
return -EINVAL;
}
break;
case ISDN_CMD_DIAL:
if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
if (card->leased)
break;
if ((c->arg & 255) < ICN_BCH) {
char *p;
char dial[50];
char dcode[4];
a = c->arg;
p = c->parm.setup.phone;
if (*p == 's' || *p == 'S') {
/* Dial for SPV */
p++;
strcpy(dcode, "SCA");
} else
/* Normal Dial */
strcpy(dcode, "CAL");
strcpy(dial, p);
sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
dcode, dial, c->parm.setup.si1,
c->parm.setup.si2, c->parm.setup.eazmsn);
i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
}
break;
case ISDN_CMD_ACCEPTD:
if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
if (c->arg < ICN_BCH) {
a = c->arg + 1;
if (card->fw_rev >= 300) {
switch (card->l2_proto[a - 1]) {
case ISDN_PROTO_L2_X75I:
sprintf(cbuf, "%02d;BX75\n", (int) a);
break;
case ISDN_PROTO_L2_HDLC:
sprintf(cbuf, "%02d;BTRA\n", (int) a);
break;
}
i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
}
sprintf(cbuf, "%02d;DCON_R\n", (int) a);
i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
}
break;
case ISDN_CMD_ACCEPTB:
if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
if (c->arg < ICN_BCH) {
a = c->arg + 1;
if (card->fw_rev >= 300)
switch (card->l2_proto[a - 1]) {
case ISDN_PROTO_L2_X75I:
sprintf(cbuf, "%02d;BCON_R,BX75\n", (int) a);
break;
case ISDN_PROTO_L2_HDLC:
sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int) a);
break;
} else
sprintf(cbuf, "%02d;BCON_R\n", (int) a);
i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
}
break;
case ISDN_CMD_HANGUP:
if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
if (c->arg < ICN_BCH) {
a = c->arg + 1;
sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a);
i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
}
break;
case ISDN_CMD_SETEAZ:
if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
if (card->leased)
break;
if (c->arg < ICN_BCH) {
a = c->arg + 1;
if (card->ptype == ISDN_PTYPE_EURO) {
sprintf(cbuf, "%02d;MS%s%s\n", (int) a,
c->parm.num[0] ? "N" : "ALL", c->parm.num);
} else
sprintf(cbuf, "%02d;EAZ%s\n", (int) a,
c->parm.num[0] ? (char *)(c->parm.num) : "0123456789");
i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
}
break;
case ISDN_CMD_CLREAZ:
if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
if (card->leased)
break;
if (c->arg < ICN_BCH) {
a = c->arg + 1;
if (card->ptype == ISDN_PTYPE_EURO)
sprintf(cbuf, "%02d;MSNC\n", (int) a);
else
sprintf(cbuf, "%02d;EAZC\n", (int) a);
i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
}
break;
case ISDN_CMD_SETL2:
if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
if ((c->arg & 255) < ICN_BCH) {
a = c->arg;
switch (a >> 8) {
case ISDN_PROTO_L2_X75I:
sprintf(cbuf, "%02d;BX75\n", (int) (a & 255) + 1);
break;
case ISDN_PROTO_L2_HDLC:
sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1);
break;
default:
return -EINVAL;
}
i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
card->l2_proto[a & 255] = (a >> 8);
}
break;
case ISDN_CMD_GETL2:
if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
if ((c->arg & 255) < ICN_BCH)
return card->l2_proto[c->arg & 255];
else
return -ENODEV;
case ISDN_CMD_SETL3:
if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
return 0;
case ISDN_CMD_GETL3:
if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
if ((c->arg & 255) < ICN_BCH)
return ISDN_PROTO_L3_TRANS;
else
return -ENODEV;
case ISDN_CMD_GETEAZ:
if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
break;
case ISDN_CMD_SETSIL:
if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
break;
case ISDN_CMD_GETSIL:
if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
break;
case ISDN_CMD_LOCK:
MOD_INC_USE_COUNT;
break;
case ISDN_CMD_UNLOCK:
MOD_DEC_USE_COUNT;
break;
default:
return -EINVAL;
}
return 0;
}
Generated by GNU enscript 1.6.4.