Enscript Output

extractedLnx/linux-2.5.49/drivers/isdn/eicon/eicon_mod.c_eicon_command.c

static int
eicon_command(eicon_card * card, isdn_ctrl * c)
{
        ulong a;
        eicon_chan *chan;
	eicon_cdef cdef;
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
	dia_start_t dstart;
        int idi_length = 0;
#endif
#endif
	isdn_ctrl cmd;
	int ret = 0;
	unsigned long flags;
 
	eicon_log(card, 16, "eicon_cmd 0x%x with arg 0x%lx (0x%lx)\n",
		c->command, c->arg, (ulong) *c->parm.num);

        switch (c->command) {
		case ISDN_CMD_IOCTL:
			memcpy(&a, c->parm.num, sizeof(ulong));
			switch (c->arg) {
				case EICON_IOCTL_GETVER:
					return(EICON_CTRL_VERSION);
				case EICON_IOCTL_GETTYPE:
					if (card->bus == EICON_BUS_PCI) {
						if (copy_to_user((char *)a,
							&card->hwif.pci.master,
								 sizeof(int)))
							return -EFAULT;
					}
					return(card->type);
				case EICON_IOCTL_GETMMIO:
					switch (card->bus) {
						case EICON_BUS_ISA:
						case EICON_BUS_MCA:
							return (int)card->hwif.isa.shmem;
						default:
							eicon_log(card, 1,
							       "eicon: Illegal BUS type %d\n",
							       card->bus);
							ret = -ENODEV;
					}
#ifdef CONFIG_ISDN_DRV_EICON_ISA
				case EICON_IOCTL_SETMMIO:
					if (card->flags & EICON_FLAGS_LOADED)
						return -EBUSY;
					switch (card->bus) {
						case EICON_BUS_ISA:
							if (eicon_isa_find_card(a,
								card->hwif.isa.irq,
								card->regname) < 0)
								return -EFAULT;
							card->hwif.isa.shmem = (eicon_isa_shmem *)a;
							return 0;
						case EICON_BUS_MCA:
#if CONFIG_MCA
							if (eicon_mca_find_card(
								0, a,
								card->hwif.isa.irq,
								card->regname) < 0)
								return -EFAULT;
							card->hwif.isa.shmem = (eicon_isa_shmem *)a;
							return 0;
#endif /* CONFIG_MCA */
						default:
							eicon_log(card, 1,
						      		"eicon: Illegal BUS type %d\n",
							       card->bus);
							ret = -ENODEV;
					}					
#endif
				case EICON_IOCTL_GETIRQ:
					switch (card->bus) {
						case EICON_BUS_ISA:
						case EICON_BUS_MCA:
							return card->hwif.isa.irq;
						default:
							eicon_log(card, 1,
							       "eicon: Illegal BUS type %d\n",
							       card->bus);
							ret = -ENODEV;
					}
				case EICON_IOCTL_SETIRQ:
					if (card->flags & EICON_FLAGS_LOADED)
						return -EBUSY;
					if ((a < 2) || (a > 15))
						return -EFAULT;
					switch (card->bus) {
						case EICON_BUS_ISA:
						case EICON_BUS_MCA:
							card->hwif.isa.irq = a;
							return 0;
						default:
							eicon_log(card, 1,
						      		"eicon: Illegal BUS type %d\n",
							       card->bus);
							ret = -ENODEV;
					}					
#ifdef CONFIG_ISDN_DRV_EICON_ISA
				case EICON_IOCTL_LOADBOOT:
					if (card->flags & EICON_FLAGS_RUNNING)
						return -EBUSY;  
					switch (card->bus) {
						case EICON_BUS_ISA:
						case EICON_BUS_MCA:
							ret = eicon_isa_bootload(
								&(card->hwif.isa),
								&(((eicon_codebuf *)a)->isa));
							break;
						default:
							eicon_log(card, 1,
							       "eicon: Illegal BUS type %d\n",
							       card->bus);
							ret = -ENODEV;
					}
					return ret;
#endif
#ifdef CONFIG_ISDN_DRV_EICON_ISA
				case EICON_IOCTL_LOADISA:
					if (card->flags & EICON_FLAGS_RUNNING)
						return -EBUSY;  
					switch (card->bus) {
						case EICON_BUS_ISA:
						case EICON_BUS_MCA:
							ret = eicon_isa_load(
								&(card->hwif.isa),
								&(((eicon_codebuf *)a)->isa));
							if (!ret) {
                                                                card->flags |= EICON_FLAGS_LOADED;
                                                                card->flags |= EICON_FLAGS_RUNNING;
								if (card->hwif.isa.channels > 1) {
									cmd.command = ISDN_STAT_ADDCH;
									cmd.driver = card->myid;
									cmd.arg = card->hwif.isa.channels - 1;
									card->interface.statcallb(&cmd);
								}
								cmd.command = ISDN_STAT_RUN;    
								cmd.driver = card->myid;        
								cmd.arg = 0;                    
								card->interface.statcallb(&cmd);
							}
							break;
						default:
							eicon_log(card, 1,
							       "eicon: Illegal BUS type %d\n",
							       card->bus);
							ret = -ENODEV;
					}
					return ret;
#endif
				case EICON_IOCTL_MANIF:
					if (!card->flags & EICON_FLAGS_RUNNING)
						return -ENODEV;
					if (!card->d)
						return -ENODEV;
					if (!card->d->features & DI_MANAGE)
						return -ENODEV;
					ret = eicon_idi_manage(
						card, 
						(eicon_manifbuf *)a);
					return ret;

				case EICON_IOCTL_GETXLOG:
					return -ENODEV;

				case EICON_IOCTL_ADDCARD:
					if (copy_from_user(&cdef, (char *)a,
							   sizeof(cdef)))
						return -EFAULT;
					if (!(eicon_addcard(0, cdef.membase, cdef.irq, cdef.id, 0)))
						return -EIO;
					return 0;
				case EICON_IOCTL_DEBUGVAR:
					DebugVar = a;
					eicon_log(card, 1, "Eicon: Debug Value set to %ld\n", DebugVar);
					return 0;
#ifdef MODULE
				case EICON_IOCTL_FREEIT:
					while (MOD_USE_COUNT > 0) MOD_DEC_USE_COUNT;
					MOD_INC_USE_COUNT;
					return 0;
#endif
				case EICON_IOCTL_LOADPCI:
					eicon_log(card, 1, "Eicon: Wrong version of load-utility,\n");
					eicon_log(card, 1, "Eicon: re-compile eiconctrl !\n");
					eicon_log(card, 1, "Eicon: Maybe update of utility is necessary !\n");
					return -EINVAL;
				default:	
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
					if (c->arg < EICON_IOCTL_DIA_OFFSET)
						return -EINVAL;
					if (copy_from_user(&dstart, (char *)a,
							   sizeof(dstart)))
						return -EFAULT;
					if (!(card = eicon_findnpcicard(dstart.card_id)))
						return -EINVAL;
					ret = do_ioctl(NULL, NULL,
						c->arg - EICON_IOCTL_DIA_OFFSET,
						(unsigned long) a);
					if (((c->arg - EICON_IOCTL_DIA_OFFSET)==DIA_IOCTL_START) && (!ret)) {
						if (card->type != EICON_CTYPE_MAESTRAQ) {
							DIVA_DIDD_Read(idi_d, sizeof(idi_d));
                                                        for(idi_length = 0; idi_length < 32; idi_length++) {
                                                          if (idi_d[idi_length].type == 0) break;
                                                        }
                                                        if ((idi_length < 1) || (idi_length >= 32)) {
					                  eicon_log(card, 1, "eicon: invalid idi table length.\n");
                                                          break;
                                                        }
							card->d = &idi_d[idi_length - 1];
							card->flags |= EICON_FLAGS_LOADED;
							card->flags |= EICON_FLAGS_RUNNING;
							eicon_pci_init_conf(card);
							if (card->d->channels > 1) {
								cmd.command = ISDN_STAT_ADDCH;
								cmd.driver = card->myid;
								cmd.arg = card->d->channels - 1;
								card->interface.statcallb(&cmd);
							}
							cmd.command = ISDN_STAT_RUN;    
							cmd.driver = card->myid;        
							cmd.arg = 0;                    
							card->interface.statcallb(&cmd);
							eicon_log(card, 1, "Eicon: %s started, %d channels (feat. 0x%x)\n",
								(card->type == EICON_CTYPE_MAESTRA) ? "BRI" : "PRI",
								card->d->channels, card->d->features);
						} else {
							int i;
							DIVA_DIDD_Read(idi_d, sizeof(idi_d));
                                                        for(idi_length = 0; idi_length < 32; idi_length++)
                                                          if (idi_d[idi_length].type == 0) break;
                                                        if ((idi_length < 1) || (idi_length >= 32)) {
					                  eicon_log(card, 1, "eicon: invalid idi table length.\n");
                                                          break;
                                                        }
        						for(i = 3; i >= 0; i--) {
								if (!(card = eicon_findnpcicard(dstart.card_id - i)))
									return -EINVAL;
	
								card->flags |= EICON_FLAGS_LOADED;
								card->flags |= EICON_FLAGS_RUNNING;
								card->d = &idi_d[idi_length - (i+1)];
								eicon_pci_init_conf(card);
								if (card->d->channels > 1) {
									cmd.command = ISDN_STAT_ADDCH;
									cmd.driver = card->myid;
									cmd.arg = card->d->channels - 1;
									card->interface.statcallb(&cmd);
								}
								cmd.command = ISDN_STAT_RUN;    
								cmd.driver = card->myid;        
								cmd.arg = 0;                    
								card->interface.statcallb(&cmd);
								eicon_log(card, 1, "Eicon: %d/4BRI started, %d channels (feat. 0x%x)\n",
									4-i, card->d->channels, card->d->features);
							}
						}
					}
					return ret;
#else
					return -EINVAL;
#endif
#endif /* CONFIG_PCI */
			}
			break;
		case ISDN_CMD_DIAL:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			spin_lock_irqsave(&eicon_lock, flags);
			if ((chan->fsm_state != EICON_STATE_NULL) && (chan->fsm_state != EICON_STATE_LISTEN)) {
				spin_unlock_irqrestore(&eicon_lock, flags);
				eicon_log(card, 1, "Dial on channel %d with state %d\n",
					chan->No, chan->fsm_state);
				return -EBUSY;
			}
			chan->fsm_state = EICON_STATE_OCALL;
			spin_unlock_irqrestore(&eicon_lock, flags);
			
			ret = idi_connect_req(card, chan, c->parm.setup.phone,
						     c->parm.setup.eazmsn,
						     c->parm.setup.si1,
						     c->parm.setup.si2);
			if (ret) {
				cmd.driver = card->myid;
				cmd.command = ISDN_STAT_DHUP;
				cmd.arg &= 0x1f;
				card->interface.statcallb(&cmd);
			}
			return ret;
		case ISDN_CMD_ACCEPTD:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			if (chan->fsm_state == EICON_STATE_ICALL) { 
				idi_connect_res(card, chan);
			}
			return 0;
		case ISDN_CMD_ACCEPTB:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			return 0;
		case ISDN_CMD_HANGUP:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			idi_hangup(card, chan);
			return 0;
		case ISDN_CMD_SETEAZ:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			chan->eazmask = 0x3ff;
			eicon_idi_listen_req(card, chan);
			return 0;
		case ISDN_CMD_CLREAZ:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			chan->eazmask = 0;
			eicon_idi_listen_req(card, chan);
			return 0;
		case ISDN_CMD_SETL2:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			chan->l2prot = (c->arg >> 8);
			return 0;
		case ISDN_CMD_GETL2:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			return chan->l2prot;
		case ISDN_CMD_SETL3:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			chan->l3prot = (c->arg >> 8);
#ifdef CONFIG_ISDN_TTY_FAX
			if (chan->l3prot == ISDN_PROTO_L3_FCLASS2) {
				chan->fax = c->parm.fax;
				eicon_log(card, 128, "idi_cmd: Ch%d: SETL3 struct fax=0x%x\n",chan->No, chan->fax);
			}
#endif
			return 0;
		case ISDN_CMD_GETL3:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			return chan->l3prot;
		case ISDN_CMD_GETEAZ:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			eicon_log(card, 1, "eicon CMD_GETEAZ not implemented\n");
			return 0;
		case ISDN_CMD_SETSIL:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			eicon_log(card, 1, "eicon CMD_SETSIL not implemented\n");
			return 0;
		case ISDN_CMD_GETSIL:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			eicon_log(card, 1, "eicon CMD_GETSIL not implemented\n");
			return 0;
		case ISDN_CMD_LOCK:
			MOD_INC_USE_COUNT;
			return 0;
		case ISDN_CMD_UNLOCK:
			MOD_DEC_USE_COUNT;
			return 0;
#ifdef CONFIG_ISDN_TTY_FAX
		case ISDN_CMD_FAXCMD:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			if (!chan->fax)
				break;
			idi_fax_cmd(card, chan);
			return 0;
#endif
		case ISDN_CMD_AUDIO:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			idi_audio_cmd(card, chan, c->arg >> 8, c->parm.num);
			return 0;
		case CAPI_PUT_MESSAGE:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			if (c->parm.cmsg.Length < 8)
				break;
			switch(c->parm.cmsg.Command) {
				case CAPI_FACILITY:
					if (c->parm.cmsg.Subcommand == CAPI_REQ)
						return(capipmsg(card, chan, &c->parm.cmsg));
					break;
				case CAPI_MANUFACTURER:
				default:
					break;
			}
			return 0;
        }
	
        return -EINVAL;
}

Generated by GNU enscript 1.6.4.