Пример #1
0
static int
process_line(struct conf_writedata *cnf)
{
	unsigned char *cp = cnf->conf_line;
	int i;

	if (cnf->card->debug_flags & LOG_CNF_LINE)
		hysdn_addlog(cnf->card, "conf line: %s", cp);

	if (*cp == '-') {	/* option */
		cp++;		/* point to option char */

		if (*cp++ != 'c')
			return (0);	/* option unknown or used */
		i = 0;		/* start value for channel */
		while ((*cp <= '9') && (*cp >= '0'))
			i = i * 10 + *cp++ - '0';	/* get decimal number */
		if (i > 65535) {
			if (cnf->card->debug_flags & LOG_CNF_MISC)
				hysdn_addlog(cnf->card, "conf channel invalid  %d", i);
			return (-ERR_INV_CHAN);		/* invalid channel */
		}
		cnf->channel = i & 0xFFFF;	/* set new channel number */
		return (0);	/* success */
	}			/* option */
	if (*cp == '*') {	/* line to send */
		if (cnf->card->debug_flags & LOG_CNF_DATA)
			hysdn_addlog(cnf->card, "conf chan=%d %s", cnf->channel, cp);
		return (hysdn_tx_cfgline(cnf->card, cnf->conf_line + 1,
					 cnf->channel));	/* send the line without * */
	}			/* line to send */
	return (0);
}				/* process_line */
static int
process_line(struct conf_writedata *cnf)
{
	unsigned char *cp = cnf->conf_line;
	int i;

	if (cnf->card->debug_flags & LOG_CNF_LINE)
		hysdn_addlog(cnf->card, "conf line: %s", cp);

	if (*cp == '-') {	/*        */
		cp++;		/*                      */

		if (*cp++ != 'c')
			return (0);	/*                        */
		i = 0;		/*                         */
		while ((*cp <= '9') && (*cp >= '0'))
			i = i * 10 + *cp++ - '0';	/*                    */
		if (i > 65535) {
			if (cnf->card->debug_flags & LOG_CNF_MISC)
				hysdn_addlog(cnf->card, "conf channel invalid  %d", i);
			return (-ERR_INV_CHAN);		/*                 */
		}
		cnf->channel = i & 0xFFFF;	/*                        */
		return (0);	/*         */
	}			/*        */
	if (*cp == '*') {	/*              */
		if (cnf->card->debug_flags & LOG_CNF_DATA)
			hysdn_addlog(cnf->card, "conf chan=%d %s", cnf->channel, cp);
		return (hysdn_tx_cfgline(cnf->card, cnf->conf_line + 1,
					 cnf->channel));	/*                         */
	}			/*              */
	return (0);
}				/*              */
Пример #3
0
static int
ergo_writebootseq(struct HYSDN_CARD *card, unsigned char *buf, int len)
{
	tDpramBootSpooler *sp = (tDpramBootSpooler *) card->dpram;
	unsigned char *dst;
	unsigned char buflen;
	int nr_write;
	unsigned char tmp_rdptr;
	unsigned char wr_mirror;
	int i;

	if (card->debug_flags & LOG_POF_CARD)
		hysdn_addlog(card, "ERGO: write boot seq len=%d ", len);

	dst = sp->Data;		/* point to data in spool structure */
	buflen = sp->Len;	/* maximum len of spooled data */
	wr_mirror = sp->WrPtr;	/* only once read */
	sti();

	/* try until all bytes written or error */
	i = 0x1000;		/* timeout value */
	while (len) {

		/* first determine the number of bytes that may be buffered */
		do {
			tmp_rdptr = sp->RdPtr;	/* first read the pointer */
			i--;	/* decrement timeout */
		} while (i && (tmp_rdptr != sp->RdPtr));	/* wait for stable pointer */

		if (!i) {
			if (card->debug_flags & LOG_POF_CARD)
				hysdn_addlog(card, "ERGO: write boot seq timeout");
			return (-ERR_BOOTSEQ_FAIL);	/* value not stable -> timeout */
		}
		if ((nr_write = tmp_rdptr - wr_mirror - 1) < 0)
			nr_write += buflen;	/* now we got number of free bytes - 1 in buffer */

		if (!nr_write)
			continue;	/* no free bytes in buffer */

		if (nr_write > len)
			nr_write = len;		/* limit if last few bytes */
		i = 0x1000;	/* reset timeout value */

		/* now we know how much bytes we may put in the puffer */
		len -= nr_write;	/* we savely could adjust len before output */
		while (nr_write--) {
			*(dst + wr_mirror) = *buf++;	/* output one byte */
			if (++wr_mirror >= buflen)
				wr_mirror = 0;
			sp->WrPtr = wr_mirror;	/* announce the next byte to E1 */
		}		/* while (nr_write) */

	}			/* while (len) */
	return (0);
}				/* ergo_writebootseq */
Пример #4
0
static int
ergo_writebootseq(struct HYSDN_CARD *card, unsigned char *buf, int len)
{
	tDpramBootSpooler *sp = (tDpramBootSpooler *) card->dpram;
	unsigned char *dst;
	unsigned char buflen;
	int nr_write;
	unsigned char tmp_rdptr;
	unsigned char wr_mirror;
	int i;

	if (card->debug_flags & LOG_POF_CARD)
		hysdn_addlog(card, "ERGO: write boot seq len=%d ", len);

	dst = sp->Data;		
	buflen = sp->Len;	
	wr_mirror = sp->WrPtr;	

	
	i = 0x1000;		
	while (len) {

		
		do {
			tmp_rdptr = sp->RdPtr;	
			i--;	
		} while (i && (tmp_rdptr != sp->RdPtr));	

		if (!i) {
			if (card->debug_flags & LOG_POF_CARD)
				hysdn_addlog(card, "ERGO: write boot seq timeout");
			return (-ERR_BOOTSEQ_FAIL);	
		}
		if ((nr_write = tmp_rdptr - wr_mirror - 1) < 0)
			nr_write += buflen;	

		if (!nr_write)
			continue;	

		if (nr_write > len)
			nr_write = len;		
		i = 0x1000;	

		
		len -= nr_write;	
		while (nr_write--) {
			*(dst + wr_mirror) = *buf++;	
			if (++wr_mirror >= buflen)
				wr_mirror = 0;
			sp->WrPtr = wr_mirror;	
		}		

	}			
	return (0);
}				
int
hysdn_tx_cfgline(hysdn_card *card, unsigned char *line, unsigned short chan)
{
	int cnt = 50;		/* timeout intervalls */
	unsigned long flags;

	if (card->debug_flags & LOG_SCHED_ASYN)
		hysdn_addlog(card, "async tx-cfg chan=%d len=%d", chan, strlen(line) + 1);

	while (card->async_busy) {

		if (card->debug_flags & LOG_SCHED_ASYN)
			hysdn_addlog(card, "async tx-cfg delayed");

		msleep_interruptible(20);		/* Timeout 20ms */
		if (!--cnt)
			return (-ERR_ASYNC_TIME);	/* timed out */
	}			/* wait for buffer to become free */

	spin_lock_irqsave(&card->hysdn_lock, flags);
	strcpy(card->async_data, line);
	card->async_len = strlen(line) + 1;
	card->async_channel = chan;
	card->async_busy = 1;	/* request transfer */

	/* now queue the task */
	schedule_work(&card->irq_queue);
	spin_unlock_irqrestore(&card->hysdn_lock, flags);

	if (card->debug_flags & LOG_SCHED_ASYN)
		hysdn_addlog(card, "async tx-cfg data queued");

	cnt++;			/* short delay */

	while (card->async_busy) {

		if (card->debug_flags & LOG_SCHED_ASYN)
			hysdn_addlog(card, "async tx-cfg waiting for tx-ready");

		msleep_interruptible(20);		/* Timeout 20ms */
		if (!--cnt)
			return (-ERR_ASYNC_TIME);	/* timed out */
	}			/* wait for buffer to become free again */

	if (card->debug_flags & LOG_SCHED_ASYN)
		hysdn_addlog(card, "async tx-cfg data send");

	return (0);		/* line send correctly */
}				/* hysdn_tx_cfgline */
Пример #6
0
static int
ergo_writebootimg(struct HYSDN_CARD *card, unsigned char *buf,
			unsigned long offs)
{
	unsigned char *dst;
	tErgDpram *dpram;
	int cnt = (BOOT_IMG_SIZE >> 2);		/* number of words to move and swap (byte order!) */
	
	if (card->debug_flags & LOG_POF_CARD)
		hysdn_addlog(card, "ERGO: write bootldr offs=0x%lx ", offs);

	dst = card->dpram;	/* pointer to start of DPRAM */
	dst += (offs + ERG_DPRAM_FILL_SIZE);	/* offset in the DPRAM */
	while (cnt--) {
		*dst++ = *(buf + 1);	/* high byte */
		*dst++ = *buf;	/* low byte */
		dst += 2;	/* point to next longword */
		buf += 2;	/* buffer only filled with words */
	}

	/* if low words (offs = 2) have been written, clear the rest of the DPRAM, */
	/* flush the PCI-write-buffer and take the E1 out of reset */
	if (offs) {
		memset(card->dpram, 0, ERG_DPRAM_FILL_SIZE);	/* fill the DPRAM still not cleared */
		dpram = card->dpram;	/* get pointer to dpram structure */
		dpram->ToHyNoDpramErrLog = 0xFF;	/* write a dpram register */
		while (!dpram->ToHyNoDpramErrLog);	/* reread volatile register to flush PCI */

		byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RUN);	/* start E1 processor */
		/* the interrupts are still masked */

		sti();
		msleep_interruptible(20);		/* Timeout 20ms */

		if (((tDpramBootSpooler *) card->dpram)->Len != DPRAM_SPOOLER_DATA_SIZE) {
			if (card->debug_flags & LOG_POF_CARD)
				hysdn_addlog(card, "ERGO: write bootldr no answer");
			return (-ERR_BOOTIMG_FAIL);
		}
	}			/* start_boot_img */
	return (0);		/* successful */
}				/* ergo_writebootimg */
Пример #7
0
static int
ergo_writebootimg(struct HYSDN_CARD *card, unsigned char *buf,
			unsigned long offs)
{
	unsigned char *dst;
	tErgDpram *dpram;
	int cnt = (BOOT_IMG_SIZE >> 2);		
	
	if (card->debug_flags & LOG_POF_CARD)
		hysdn_addlog(card, "ERGO: write bootldr offs=0x%lx ", offs);

	dst = card->dpram;	
	dst += (offs + ERG_DPRAM_FILL_SIZE);	
	while (cnt--) {
		*dst++ = *(buf + 1);	
		*dst++ = *buf;	
		dst += 2;	
		buf += 2;	
	}

	
	
	if (offs) {
		memset(card->dpram, 0, ERG_DPRAM_FILL_SIZE);	
		dpram = card->dpram;	
		dpram->ToHyNoDpramErrLog = 0xFF;	
		while (!dpram->ToHyNoDpramErrLog);	

		byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RUN);	
		

		msleep_interruptible(20);		

		if (((tDpramBootSpooler *) card->dpram)->Len != DPRAM_SPOOLER_DATA_SIZE) {
			if (card->debug_flags & LOG_POF_CARD)
				hysdn_addlog(card, "ERGO: write bootldr no answer");
			return (-ERR_BOOTIMG_FAIL);
		}
	}			
	return (0);		
}				
Пример #8
0
static int
hysdn_conf_close(struct inode *ino, struct file *filep)
{
	hysdn_card *card;
	struct conf_writedata *cnf;
	int retval = 0;
	struct proc_dir_entry *pd;

#ifndef COMPAT_USE_MODCOUNT_LOCK
	lock_kernel();
#endif
	/* search the addressed card */
	card = card_root;
	while (card) {
		pd = card->procconf;
		if (pd->low_ino == (ino->i_ino & 0xFFFF))
			break;
		card = card->next;	/* search next entry */
	}
	if (!card) {
#ifndef COMPAT_USE_MODCOUNT_LOCK
		unlock_kernel();
#endif
		return (-ENODEV);	/* device is unknown/invalid */
	}
	if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
		hysdn_addlog(card, "config close for uid=%d gid=%d mode=0x%x",
			     filep->f_uid, filep->f_gid, filep->f_mode);

	if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
		/* write only access -> write boot file or conf line */
		if (filep->private_data) {
			cnf = filep->private_data;

			if (cnf->state == CONF_STATE_POF)
				retval = pof_write_close(cnf->card);	/* close the pof write */
			kfree(filep->private_data);	/* free allocated memory for buffer */

		}		/* handle write private data */
	} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
		/* read access -> output card info data */

		if (filep->private_data)
			kfree(filep->private_data);	/* release memory */
	}
#ifdef COMPAT_USE_MODCOUNT_LOCK
	MOD_DEC_USE_COUNT;
#else
	unlock_kernel();
#endif
	return (retval);
}				/* hysdn_conf_close */
Пример #9
0
int
pof_write_open(hysdn_card * card, uchar ** bufp)
{
	struct boot_data *boot;	/* pointer to boot specific data */

	if (card->boot) {
		if (card->debug_flags & LOG_POF_OPEN)
			hysdn_addlog(card, "POF open: already opened for boot");
		return (-ERR_ALREADY_BOOT);	/* boot already active */
	}
	/* error no mem available */
	if (!(boot = kmalloc(sizeof(struct boot_data), GFP_KERNEL))) {
		if (card->debug_flags & LOG_MEM_ERR)
			hysdn_addlog(card, "POF open: unable to allocate mem");
		return (-EFAULT);
	}
	card->boot = boot;
	card->state = CARD_STATE_BOOTING;
	memset(boot, 0, sizeof(struct boot_data));

	card->stopcard(card);	/* first stop the card */
	if (card->testram(card)) {
		if (card->debug_flags & LOG_POF_OPEN)
			hysdn_addlog(card, "POF open: DPRAM test failure");
		boot->last_error = -ERR_BOARD_DPRAM;
		card->state = CARD_STATE_BOOTERR;	/* show boot error */
		return (boot->last_error);
	}
	boot->BufSize = 0;	/* Buffer is empty */
	boot->pof_state = POF_READ_FILE_HEAD;	/* read file header */
	StartDecryption(boot);	/* if POF File should be encrypted */

	if (card->debug_flags & LOG_POF_OPEN)
		hysdn_addlog(card, "POF open: success");

	*bufp = boot->buf.BootBuf;	/* point to buffer */
	return (sizeof(tPofFileHdr));
}				/* pof_write_open */
Пример #10
0
int
pof_write_open(hysdn_card * card, unsigned char **bufp)
{
	struct boot_data *boot;	

	if (card->boot) {
		if (card->debug_flags & LOG_POF_OPEN)
			hysdn_addlog(card, "POF open: already opened for boot");
		return (-ERR_ALREADY_BOOT);	
	}
	
	if (!(boot = kzalloc(sizeof(struct boot_data), GFP_KERNEL))) {
		if (card->debug_flags & LOG_MEM_ERR)
			hysdn_addlog(card, "POF open: unable to allocate mem");
		return (-EFAULT);
	}
	card->boot = boot;
	card->state = CARD_STATE_BOOTING;

	card->stopcard(card);	
	if (card->testram(card)) {
		if (card->debug_flags & LOG_POF_OPEN)
			hysdn_addlog(card, "POF open: DPRAM test failure");
		boot->last_error = -ERR_BOARD_DPRAM;
		card->state = CARD_STATE_BOOTERR;	
		return (boot->last_error);
	}
	boot->BufSize = 0;	
	boot->pof_state = POF_READ_FILE_HEAD;	
	StartDecryption(boot);	

	if (card->debug_flags & LOG_POF_OPEN)
		hysdn_addlog(card, "POF open: success");

	*bufp = boot->buf.BootBuf;	
	return (sizeof(tPofFileHdr));
}				
Пример #11
0
static ssize_t
hysdn_log_write(struct file *file, const char *buf, size_t count, loff_t * off)
{
	ulong u = 0;
	int found = 0;
	uchar *cp, valbuf[128];
	long base = 10;
	hysdn_card *card = (hysdn_card *) file->private_data;

	if (&file->f_pos != off)	/* fs error check */
		return (-ESPIPE);

	if (count > (sizeof(valbuf) - 1))
		count = sizeof(valbuf) - 1;	/* limit length */
	if (copy_from_user(valbuf, buf, count))
		return (-EFAULT);	/* copy failed */

	valbuf[count] = 0;	/* terminating 0 */
	cp = valbuf;
	if ((count > 2) && (valbuf[0] == '0') && (valbuf[1] == 'x')) {
		cp += 2;	/* pointer after hex modifier */
		base = 16;
	}
	/* scan the input for debug flags */
	while (*cp) {
		if ((*cp >= '0') && (*cp <= '9')) {
			found = 1;
			u *= base;	/* adjust to next digit */
			u += *cp++ - '0';
			continue;
		}
		if (base != 16)
			break;	/* end of number */

		if ((*cp >= 'a') && (*cp <= 'f')) {
			found = 1;
			u *= base;	/* adjust to next digit */
			u += *cp++ - 'a' + 10;
			continue;
		}
		break;		/* terminated */
	}

	if (found) {
		card->debug_flags = u;	/* remember debug flags */
		hysdn_addlog(card, "debug set to 0x%lx", card->debug_flags);
	}
	return (count);
}				/* hysdn_log_write */
Пример #12
0
static int
hysdn_conf_close(struct inode *ino, struct file *filep)
{
	hysdn_card *card;
	struct conf_writedata *cnf;
	int retval = 0;
	struct proc_dir_entry *pd;

	mutex_lock(&hysdn_conf_mutex);
	/* search the addressed card */
	card = card_root;
	while (card) {
		pd = card->procconf;
		if (pd == PDE(ino))
			break;
		card = card->next;	/* search next entry */
	}
	if (!card) {
		mutex_unlock(&hysdn_conf_mutex);
		return (-ENODEV);	/* device is unknown/invalid */
	}
	if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
		hysdn_addlog(card, "config close for uid=%d gid=%d mode=0x%x",
			     filep->f_cred->fsuid, filep->f_cred->fsgid,
			     filep->f_mode);

	if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
		/* write only access -> write boot file or conf line */
		if (filep->private_data) {
			cnf = filep->private_data;

			if (cnf->state == CONF_STATE_POF)
				retval = pof_write_close(cnf->card);	/* close the pof write */
			kfree(filep->private_data);	/* free allocated memory for buffer */

		}		/* handle write private data */
	} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
		/* read access -> output card info data */

		kfree(filep->private_data);	/* release memory */
	}
	mutex_unlock(&hysdn_conf_mutex);
	return (retval);
}				/* hysdn_conf_close */
static int
hysdn_conf_close(struct inode *ino, struct file *filep)
{
	hysdn_card *card;
	struct conf_writedata *cnf;
	int retval = 0;
	struct proc_dir_entry *pd;

	mutex_lock(&hysdn_conf_mutex);
	/*                           */
	card = card_root;
	while (card) {
		pd = card->procconf;
		if (pd == PDE(ino))
			break;
		card = card->next;	/*                   */
	}
	if (!card) {
		mutex_unlock(&hysdn_conf_mutex);
		return (-ENODEV);	/*                           */
	}
	if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
		hysdn_addlog(card, "config close for uid=%d gid=%d mode=0x%x",
			     filep->f_cred->fsuid, filep->f_cred->fsgid,
			     filep->f_mode);

	if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
		/*                                                   */
		if (filep->private_data) {
			cnf = filep->private_data;

			if (cnf->state == CONF_STATE_POF)
				retval = pof_write_close(cnf->card);	/*                     */
			kfree(filep->private_data);	/*                                  */

		}		/*                           */
	} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
		/*                                      */

		kfree(filep->private_data);	/*                */
	}
	mutex_unlock(&hysdn_conf_mutex);
	return (retval);
}				/*                  */
Пример #14
0
int
pof_write_close(hysdn_card * card)
{
	struct boot_data *boot = card->boot;	

	if (!boot)
		return (-EFAULT);	

	card->boot = NULL;	
	kfree(boot);

	if (card->state == CARD_STATE_RUN)
		card->set_errlog_state(card, 1);	

	if (card->debug_flags & LOG_POF_OPEN)
		hysdn_addlog(card, "POF close: success");

	return (0);
}				
Пример #15
0
int
pof_write_close(hysdn_card * card)
{
	struct boot_data *boot = card->boot;	/* pointer to boot specific data */

	if (!boot)
		return (-EFAULT);	/* invalid call */

	card->boot = NULL;	/* no boot active */
	kfree(boot);

	if (card->state == CARD_STATE_RUN)
		card->set_errlog_state(card, 1);	/* activate error log */

	if (card->debug_flags & LOG_POF_OPEN)
		hysdn_addlog(card, "POF close: success");

	return (0);
}				/* pof_write_close */
Пример #16
0
int
hysdn_net_create(hysdn_card * card)
{
	struct net_device *dev;
	int i;
	struct net_local *lp;

	if(!card) {
		printk(KERN_WARNING "No card-pt in hysdn_net_create!\n");
		return (-ENOMEM);
	}
	hysdn_net_release(card);	/* release an existing net device */

	dev = alloc_etherdev(sizeof(struct net_local));
	if (!dev) {
		printk(KERN_WARNING "HYSDN: unable to allocate mem\n");
		return (-ENOMEM);
	}

	lp = netdev_priv(dev);
	lp->dev = dev;

	dev->netdev_ops = &hysdn_netdev_ops;
	spin_lock_init(&((struct net_local *) dev)->lock);

	/* initialise necessary or informing fields */
	dev->base_addr = card->iobase;	/* IO address */
	dev->irq = card->irq;	/* irq */

	dev->netdev_ops = &hysdn_netdev_ops;
	if ((i = register_netdev(dev))) {
		printk(KERN_WARNING "HYSDN: unable to create network device\n");
		free_netdev(dev);
		return (i);
	}
	dev->ml_priv = card;	/* remember pointer to own data structure */
	card->netif = dev;	/* setup the local pointer */

	if (card->debug_flags & LOG_NET_INIT)
		hysdn_addlog(card, "network device created");
	return (0);		/* and return success */
}				/* hysdn_net_create */
Пример #17
0
int
hysdn_net_release(hysdn_card * card)
{
	struct net_device *dev = card->netif;

	if (!dev)
		return (0);	/* non existing */

	card->netif = NULL;	/* clear out pointer */
	net_close(dev);

	flush_tx_buffers((struct net_local *) dev);	/* empty buffers */

	unregister_netdev(dev);	/* release the device */
	free_netdev(dev);	/* release the memory allocated */
	if (card->debug_flags & LOG_NET_INIT)
		hysdn_addlog(card, "network device deleted");

	return (0);		/* always successful */
}				/* hysdn_net_release */
Пример #18
0
int
hysdn_net_create(hysdn_card * card)
{
	struct net_device *dev;
	int i;
	if(!card) {
		printk(KERN_WARNING "No card-pt in hysdn_net_create!\n");
		return (-ENOMEM);
	}
	hysdn_net_release(card);	/* release an existing net device */
	if ((dev = kmalloc(sizeof(struct net_local), GFP_KERNEL)) == NULL) {
		printk(KERN_WARNING "HYSDN: unable to allocate mem\n");
		return (-ENOMEM);
	}
	memset(dev, 0, sizeof(struct net_local));	/* clean the structure */

	spin_lock_init(&((struct net_local *) dev)->lock);

	/* initialise necessary or informing fields */
	dev->base_addr = card->iobase;	/* IO address */
	dev->irq = card->irq;	/* irq */
	dev->init = net_init;	/* the init function of the device */
	if(dev->name) {
		strcpy(dev->name, ((struct net_local *) dev)->dev_name);
	} 
	if ((i = register_netdev(dev))) {
		printk(KERN_WARNING "HYSDN: unable to create network device\n");
		kfree(dev);
		return (i);
	}
	dev->priv = card;	/* remember pointer to own data structure */
	card->netif = dev;	/* setup the local pointer */

	if (card->debug_flags & LOG_NET_INIT)
		hysdn_addlog(card, "network device created");
	return (0);		/* and return success */
}				/* hysdn_net_create */
Пример #19
0
static int
ergo_waitpofready(struct HYSDN_CARD *card)
{
	tErgDpram *dpr = card->dpram;	/* pointer to DPRAM structure */
	int timecnt = 10000 / 50;	/* timeout is 10 secs max. */
	unsigned long flags;
	int msg_size;
	int i;

	if (card->debug_flags & LOG_POF_CARD)
		hysdn_addlog(card, "ERGO: waiting for pof ready");
	while (timecnt--) {
		/* wait until timeout  */

		if (dpr->ToPcFlag) {
			/* data has arrived */

			if ((dpr->ToPcChannel != CHAN_SYSTEM) ||
			    (dpr->ToPcSize < MIN_RDY_MSG_SIZE) ||
			    (dpr->ToPcSize > MAX_RDY_MSG_SIZE) ||
			    ((*(unsigned long *) dpr->ToPcBuf) != RDY_MAGIC))
				break;	/* an error occurred */

			/* Check for additional data delivered during SysReady */
			msg_size = dpr->ToPcSize - RDY_MAGIC_SIZE;
			if (msg_size > 0)
				if (EvalSysrTokData(card, dpr->ToPcBuf + RDY_MAGIC_SIZE, msg_size))
					break;

			if (card->debug_flags & LOG_POF_RECORD)
				hysdn_addlog(card, "ERGO: pof boot success");
			spin_lock_irqsave(&card->hysdn_lock, flags);

			card->state = CARD_STATE_RUN;	/* now card is running */
			/* enable the cards interrupt */
			byteout(card->iobase + PCI9050_INTR_REG,
				bytein(card->iobase + PCI9050_INTR_REG) |
			(PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1));
			card->irq_enabled = 1;	/* we are ready to receive interrupts */

			dpr->ToPcFlag = 0;	/* reset data indicator */
			dpr->ToHyInt = 1;
			dpr->ToPcInt = 1;	/* interrupt to E1 for all cards */

			spin_unlock_irqrestore(&card->hysdn_lock, flags);
			if ((hynet_enable & (1 << card->myid)) 
			    && (i = hysdn_net_create(card))) 
			{
				ergo_stopcard(card);
				card->state = CARD_STATE_BOOTERR;
				return (i);
			}
#ifdef CONFIG_HYSDN_CAPI
			if((i = hycapi_capi_create(card))) {
				printk(KERN_WARNING "HYSDN: failed to create capi-interface.\n");
			}
#endif /* CONFIG_HYSDN_CAPI */
			return (0);	/* success */
		}		/* data has arrived */
		sti();
		msleep_interruptible(50);		/* Timeout 50ms */
	}			/* wait until timeout */

	if (card->debug_flags & LOG_POF_CARD)
		hysdn_addlog(card, "ERGO: pof boot ready timeout");
	return (-ERR_POF_TIMEOUT);
}				/* ergo_waitpofready */
Пример #20
0
static int
pof_handle_data(hysdn_card * card, int datlen)
{
	struct boot_data *boot = card->boot;	
	long l;
	unsigned char *imgp;
	int img_len;

	
	switch (boot->pof_recid) {

		case TAG_TIMESTMP:
			if (card->debug_flags & LOG_POF_RECORD)
				hysdn_addlog(card, "POF created %s", boot->buf.PofTime.DateTimeText);
			break;

		case TAG_CBOOTDTA:
			DecryptBuf(boot, datlen);	
		case TAG_BOOTDTA:
			if (card->debug_flags & LOG_POF_RECORD)
				hysdn_addlog(card, "POF got %s len=%d offs=0x%lx",
					     (boot->pof_recid == TAG_CBOOTDTA) ? "CBOOTDATA" : "BOOTDTA",
					     datlen, boot->pof_recoffset);

			if (boot->pof_reclen != POF_BOOT_LOADER_TOTAL_SIZE) {
				boot->last_error = EPOF_BAD_IMG_SIZE;	
				return (boot->last_error);
			}
			imgp = boot->buf.BootBuf;	
			img_len = datlen;	

			l = POF_BOOT_LOADER_OFF_IN_PAGE -
			    (boot->pof_recoffset & (POF_BOOT_LOADER_PAGE_SIZE - 1));
			if (l > 0) {
				
				imgp += l;	
				img_len -= l;	
			}
			
			
			
			
			
			

			if (img_len > 0) {
				
				if ((boot->last_error =
				     card->writebootimg(card, imgp,
							(boot->pof_recoffset > POF_BOOT_LOADER_PAGE_SIZE) ? 2 : 0)) < 0)
					return (boot->last_error);
			}
			break;	

		case TAG_CABSDATA:
			DecryptBuf(boot, datlen);	
		case TAG_ABSDATA:
			if (card->debug_flags & LOG_POF_RECORD)
				hysdn_addlog(card, "POF got %s len=%d offs=0x%lx",
					     (boot->pof_recid == TAG_CABSDATA) ? "CABSDATA" : "ABSDATA",
					     datlen, boot->pof_recoffset);

			if ((boot->last_error = card->writebootseq(card, boot->buf.BootBuf, datlen) < 0))
				return (boot->last_error);	

			if (boot->pof_recoffset + datlen >= boot->pof_reclen)
				return (card->waitpofready(card));	

			break;	

		default:
			if (card->debug_flags & LOG_POF_RECORD)
				hysdn_addlog(card, "POF got data(id=0x%lx) len=%d offs=0x%lx", boot->pof_recid,
					     datlen, boot->pof_recoffset);

			break;	
	}			

	return (0);
}				
Пример #21
0
int
pof_write_buffer(hysdn_card * card, int datlen)
{
	struct boot_data *boot = card->boot;	/* pointer to boot specific data */

	if (!boot)
		return (-EFAULT);	/* invalid call */
	if (boot->last_error < 0)
		return (boot->last_error);	/* repeated error */

	if (card->debug_flags & LOG_POF_WRITE)
		hysdn_addlog(card, "POF write: got %d bytes ", datlen);

	switch (boot->pof_state) {
		case POF_READ_FILE_HEAD:
			if (card->debug_flags & LOG_POF_WRITE)
				hysdn_addlog(card, "POF write: checking file header");

			if (datlen != sizeof(tPofFileHdr)) {
				boot->last_error = -EPOF_INTERNAL;
				break;
			}
			if (boot->buf.PofFileHdr.Magic != TAGFILEMAGIC) {
				boot->last_error = -EPOF_BAD_MAGIC;
				break;
			}
			/* Setup the new state and vars */
			boot->Nrecs = (word) (boot->buf.PofFileHdr.N_PofRecs);	/* limited to 65535 */
			boot->pof_state = POF_READ_TAG_HEAD;	/* now start with single tags */
			boot->last_error = sizeof(tPofRecHdr);	/* new length */
			break;

		case POF_READ_TAG_HEAD:
			if (card->debug_flags & LOG_POF_WRITE)
				hysdn_addlog(card, "POF write: checking tag header");

			if (datlen != sizeof(tPofRecHdr)) {
				boot->last_error = -EPOF_INTERNAL;
				break;
			}
			boot->pof_recid = boot->buf.PofRecHdr.PofRecId;		/* actual pof recid */
			boot->pof_reclen = boot->buf.PofRecHdr.PofRecDataLen;	/* total length */
			boot->pof_recoffset = 0;	/* no starting offset */

			if (card->debug_flags & LOG_POF_RECORD)
				hysdn_addlog(card, "POF: got record id=0x%lx length=%ld ",
				      boot->pof_recid, boot->pof_reclen);

			boot->pof_state = POF_READ_TAG_DATA;	/* now start with tag data */
			if (boot->pof_reclen < BOOT_BUF_SIZE)
				boot->last_error = boot->pof_reclen;	/* limit size */
			else
				boot->last_error = BOOT_BUF_SIZE;	/* maximum */

			if (!boot->last_error) {	/* no data inside record */
				boot->pof_state = POF_READ_TAG_HEAD;	/* now start with single tags */
				boot->last_error = sizeof(tPofRecHdr);	/* new length */
			}
			break;

		case POF_READ_TAG_DATA:
			if (card->debug_flags & LOG_POF_WRITE)
				hysdn_addlog(card, "POF write: getting tag data");

			if (datlen != boot->last_error) {
				boot->last_error = -EPOF_INTERNAL;
				break;
			}
			if ((boot->last_error = pof_handle_data(card, datlen)) < 0)
				return (boot->last_error);	/* an error occurred */
			boot->pof_recoffset += datlen;
			if (boot->pof_recoffset >= boot->pof_reclen) {
				boot->pof_state = POF_READ_TAG_HEAD;	/* now start with single tags */
				boot->last_error = sizeof(tPofRecHdr);	/* new length */
			} else {
				if (boot->pof_reclen - boot->pof_recoffset < BOOT_BUF_SIZE)
					boot->last_error = boot->pof_reclen - boot->pof_recoffset;	/* limit size */
				else
					boot->last_error = BOOT_BUF_SIZE;	/* maximum */
			}
			break;

		default:
			boot->last_error = -EPOF_INTERNAL;	/* unknown state */
			break;
	}			/* switch (boot->pof_state) */

	return (boot->last_error);
}				/* pof_write_buffer */
Пример #22
0
static int
hysdn_conf_open(struct inode *ino, struct file *filep)
{
	hysdn_card *card;
	struct proc_dir_entry *pd;
	struct conf_writedata *cnf;
	char *cp, *tmp;

	/* now search the addressed card */
	mutex_lock(&hysdn_conf_mutex);
	card = card_root;
	while (card) {
		pd = card->procconf;
		if (pd == PDE(ino))
			break;
		card = card->next;	/* search next entry */
	}
	if (!card) {
		mutex_unlock(&hysdn_conf_mutex);
		return (-ENODEV);	/* device is unknown/invalid */
	}
	if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
		hysdn_addlog(card, "config open for uid=%d gid=%d mode=0x%x",
			     filep->f_cred->fsuid, filep->f_cred->fsgid,
			     filep->f_mode);

	if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
		/* write only access -> write boot file or conf line */

		if (!(cnf = kmalloc(sizeof(struct conf_writedata), GFP_KERNEL))) {
			mutex_unlock(&hysdn_conf_mutex);
			return (-EFAULT);
		}
		cnf->card = card;
		cnf->buf_size = 0;	/* nothing buffered */
		cnf->state = CONF_STATE_DETECT;		/* start auto detect */
		filep->private_data = cnf;

	} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
		/* read access -> output card info data */

		if (!(tmp = kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) {
			mutex_unlock(&hysdn_conf_mutex);
			return (-EFAULT);	/* out of memory */
		}
		filep->private_data = tmp;	/* start of string */

		/* first output a headline */
		sprintf(tmp, "id bus slot type irq iobase dp-mem     b-chans fax-chans state device");
		cp = tmp;	/* start of string */
		while (*cp)
			cp++;
		while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN)
			*cp++ = ' ';
		*cp++ = '\n';

		/* and now the data */
		sprintf(cp, "%d  %3d %4d %4d %3d 0x%04x 0x%08lx %7d %9d %3d   %s",
			card->myid,
			card->bus,
			PCI_SLOT(card->devfn),
			card->brdtype,
			card->irq,
			card->iobase,
			card->membase,
			card->bchans,
			card->faxchans,
			card->state,
			hysdn_net_getname(card));
		while (*cp)
			cp++;
		while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN)
			*cp++ = ' ';
		*cp++ = '\n';
		*cp = 0;	/* end of string */
	} else {		/* simultaneous read/write access forbidden ! */
		mutex_unlock(&hysdn_conf_mutex);
		return (-EPERM);	/* no permission this time */
	}
	mutex_unlock(&hysdn_conf_mutex);
	return nonseekable_open(ino, filep);
}				/* hysdn_conf_open */
Пример #23
0
static int
ergo_waitpofready(struct HYSDN_CARD *card)
{
	tErgDpram *dpr = card->dpram;	
	int timecnt = 10000 / 50;	
	unsigned long flags;
	int msg_size;
	int i;

	if (card->debug_flags & LOG_POF_CARD)
		hysdn_addlog(card, "ERGO: waiting for pof ready");
	while (timecnt--) {
		

		if (dpr->ToPcFlag) {
			

			if ((dpr->ToPcChannel != CHAN_SYSTEM) ||
			    (dpr->ToPcSize < MIN_RDY_MSG_SIZE) ||
			    (dpr->ToPcSize > MAX_RDY_MSG_SIZE) ||
			    ((*(unsigned long *) dpr->ToPcBuf) != RDY_MAGIC))
				break;	

			
			msg_size = dpr->ToPcSize - RDY_MAGIC_SIZE;
			if (msg_size > 0)
				if (EvalSysrTokData(card, dpr->ToPcBuf + RDY_MAGIC_SIZE, msg_size))
					break;

			if (card->debug_flags & LOG_POF_RECORD)
				hysdn_addlog(card, "ERGO: pof boot success");
			spin_lock_irqsave(&card->hysdn_lock, flags);

			card->state = CARD_STATE_RUN;	
			
			byteout(card->iobase + PCI9050_INTR_REG,
				bytein(card->iobase + PCI9050_INTR_REG) |
			(PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1));
			card->irq_enabled = 1;	

			dpr->ToPcFlag = 0;	
			dpr->ToHyInt = 1;
			dpr->ToPcInt = 1;	

			spin_unlock_irqrestore(&card->hysdn_lock, flags);
			if ((hynet_enable & (1 << card->myid)) 
			    && (i = hysdn_net_create(card))) 
			{
				ergo_stopcard(card);
				card->state = CARD_STATE_BOOTERR;
				return (i);
			}
#ifdef CONFIG_HYSDN_CAPI
			if((i = hycapi_capi_create(card))) {
				printk(KERN_WARNING "HYSDN: failed to create capi-interface.\n");
			}
#endif 
			return (0);	
		}		
		msleep_interruptible(50);		
	}			

	if (card->debug_flags & LOG_POF_CARD)
		hysdn_addlog(card, "ERGO: pof boot ready timeout");
	return (-ERR_POF_TIMEOUT);
}				
Пример #24
0
static int
pof_handle_data(hysdn_card * card, int datlen)
{
	struct boot_data *boot = card->boot;	/* pointer to boot specific data */
	long l;
	uchar *imgp;
	int img_len;

	/* handle the different record types */
	switch (boot->pof_recid) {

		case TAG_TIMESTMP:
			if (card->debug_flags & LOG_POF_RECORD)
				hysdn_addlog(card, "POF created %s", boot->buf.PofTime.DateTimeText);
			break;

		case TAG_CBOOTDTA:
			DecryptBuf(boot, datlen);	/* we need to encrypt the buffer */
		case TAG_BOOTDTA:
			if (card->debug_flags & LOG_POF_RECORD)
				hysdn_addlog(card, "POF got %s len=%d offs=0x%lx",
					     (boot->pof_recid == TAG_CBOOTDTA) ? "CBOOTDATA" : "BOOTDTA",
					     datlen, boot->pof_recoffset);

			if (boot->pof_reclen != POF_BOOT_LOADER_TOTAL_SIZE) {
				boot->last_error = EPOF_BAD_IMG_SIZE;	/* invalid length */
				return (boot->last_error);
			}
			imgp = boot->buf.BootBuf;	/* start of buffer */
			img_len = datlen;	/* maximum length to transfer */

			l = POF_BOOT_LOADER_OFF_IN_PAGE -
			    (boot->pof_recoffset & (POF_BOOT_LOADER_PAGE_SIZE - 1));
			if (l > 0) {
				/* buffer needs to be truncated */
				imgp += l;	/* advance pointer */
				img_len -= l;	/* adjust len */
			}
			/* at this point no special handling for data wrapping over buffer */
			/* is necessary, because the boot image always will be adjusted to */
			/* match a page boundary inside the buffer.                        */
			/* The buffer for the boot image on the card is filled in 2 cycles */
			/* first the 1024 hi-words are put in the buffer, then the low 1024 */
			/* word are handled in the same way with different offset.         */

			if (img_len > 0) {
				/* data available for copy */
				if ((boot->last_error =
				     card->writebootimg(card, imgp,
							(boot->pof_recoffset > POF_BOOT_LOADER_PAGE_SIZE) ? 2 : 0)) < 0)
					return (boot->last_error);
			}
			break;	/* end of case boot image hi/lo */

		case TAG_CABSDATA:
			DecryptBuf(boot, datlen);	/* we need to encrypt the buffer */
		case TAG_ABSDATA:
			if (card->debug_flags & LOG_POF_RECORD)
				hysdn_addlog(card, "POF got %s len=%d offs=0x%lx",
					     (boot->pof_recid == TAG_CABSDATA) ? "CABSDATA" : "ABSDATA",
					     datlen, boot->pof_recoffset);

			if ((boot->last_error = card->writebootseq(card, boot->buf.BootBuf, datlen) < 0))
				return (boot->last_error);	/* error writing data */

			if (boot->pof_recoffset + datlen >= boot->pof_reclen)
				return (card->waitpofready(card));	/* data completely spooled, wait for ready */

			break;	/* end of case boot seq data */

		default:
			if (card->debug_flags & LOG_POF_RECORD)
				hysdn_addlog(card, "POF got data(id=0x%lx) len=%d offs=0x%lx", boot->pof_recid,
					     datlen, boot->pof_recoffset);

			break;	/* simply skip record */
	}			/* switch boot->pof_recid */

	return (0);
}				/* pof_handle_data */
Пример #25
0
int
EvalSysrTokData(hysdn_card * card, uchar * cp, int len)
{
	u_char *p;
	u_char crc;

	if (card->debug_flags & LOG_POF_RECORD)
		hysdn_addlog(card, "SysReady Token data length %d", len);

	if (len < 2) {
		hysdn_addlog(card, "SysReady Token Data to short");
		return (1);
	}
	for (p = cp, crc = 0; p < (cp + len - 2); p++)
		if ((crc & 0x80))
			crc = (((u_char) (crc << 1)) + 1) + *p;
		else
			crc = ((u_char) (crc << 1)) + *p;
	crc = ~crc;
	if (crc != *(cp + len - 1)) {
		hysdn_addlog(card, "SysReady Token Data invalid CRC");
		return (1);
	}
	len--;			/* don't check CRC byte */
	while (len > 0) {

		if (*cp == SYSR_TOK_END)
			return (0);	/* End of Token stream */

		if (len < (*(cp + 1) + 2)) {
			hysdn_addlog(card, "token 0x%x invalid length %d", *cp, *(cp + 1));
			return (1);
		}
		switch (*cp) {
			case SYSR_TOK_B_CHAN:	/* 1 */
				if (*(cp + 1) != 1)
					return (1);	/* length invalid */
				card->bchans = *(cp + 2);
				break;

			case SYSR_TOK_FAX_CHAN:	/* 2 */
				if (*(cp + 1) != 1)
					return (1);	/* length invalid */
				card->faxchans = *(cp + 2);
				break;

			case SYSR_TOK_MAC_ADDR:	/* 3 */
				if (*(cp + 1) != 6)
					return (1);	/* length invalid */
				memcpy(card->mac_addr, cp + 2, 6);
				break;

			default:
				hysdn_addlog(card, "unknown token 0x%02x length %d", *cp, *(cp + 1));
				break;
		}
		len -= (*(cp + 1) + 2);		/* adjust len */
		cp += (*(cp + 1) + 2);	/* and pointer */
	}

	hysdn_addlog(card, "no end token found");
	return (1);
}				/* EvalSysrTokData */
static int
hysdn_conf_open(struct inode *ino, struct file *filep)
{
	hysdn_card *card;
	struct proc_dir_entry *pd;
	struct conf_writedata *cnf;
	char *cp, *tmp;

	/*                               */
	mutex_lock(&hysdn_conf_mutex);
	card = card_root;
	while (card) {
		pd = card->procconf;
		if (pd == PDE(ino))
			break;
		card = card->next;	/*                   */
	}
	if (!card) {
		mutex_unlock(&hysdn_conf_mutex);
		return (-ENODEV);	/*                           */
	}
	if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
		hysdn_addlog(card, "config open for uid=%d gid=%d mode=0x%x",
			     filep->f_cred->fsuid, filep->f_cred->fsgid,
			     filep->f_mode);

	if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
		/*                                                   */

		if (!(cnf = kmalloc(sizeof(struct conf_writedata), GFP_KERNEL))) {
			mutex_unlock(&hysdn_conf_mutex);
			return (-EFAULT);
		}
		cnf->card = card;
		cnf->buf_size = 0;	/*                  */
		cnf->state = CONF_STATE_DETECT;		/*                   */
		filep->private_data = cnf;

	} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
		/*                                      */

		if (!(tmp = kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) {
			mutex_unlock(&hysdn_conf_mutex);
			return (-EFAULT);	/*               */
		}
		filep->private_data = tmp;	/*                 */

		/*                         */
		sprintf(tmp, "id bus slot type irq iobase dp-mem     b-chans fax-chans state device");
		cp = tmp;	/*                 */
		while (*cp)
			cp++;
		while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN)
			*cp++ = ' ';
		*cp++ = '\n';

		/*                  */
		sprintf(cp, "%d  %3d %4d %4d %3d 0x%04x 0x%08lx %7d %9d %3d   %s",
			card->myid,
			card->bus,
			PCI_SLOT(card->devfn),
			card->brdtype,
			card->irq,
			card->iobase,
			card->membase,
			card->bchans,
			card->faxchans,
			card->state,
			hysdn_net_getname(card));
		while (*cp)
			cp++;
		while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN)
			*cp++ = ' ';
		*cp++ = '\n';
		*cp = 0;	/*               */
	} else {		/*                                            */
		mutex_unlock(&hysdn_conf_mutex);
		return (-EPERM);	/*                         */
	}
	mutex_unlock(&hysdn_conf_mutex);
	return nonseekable_open(ino, filep);
}				/*                 */
static ssize_t
hysdn_conf_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
{
	struct conf_writedata *cnf;
	int i;
	unsigned char ch, *cp;

	if (!count)
		return (0);	/*                   */

	if (!(cnf = file->private_data))
		return (-EFAULT);	/*                     */

	if (cnf->state == CONF_STATE_DETECT) {	/*                             */
		if (copy_from_user(&ch, buf, 1))	/*                           */
			return (-EFAULT);

		if (ch == 0x1A) {
			/*                        */
			if ((cnf->needed_size = pof_write_open(cnf->card, &cnf->pof_buffer)) <= 0)
				return (cnf->needed_size);	/*                           */
			cnf->buf_size = 0;	/*                 */
			cnf->state = CONF_STATE_POF;	/*           */
		} else {
			/*                             */
			cnf->buf_size = 0;	/*                 */
			cnf->state = CONF_STATE_CONF;	/*                           */
			if (cnf->card->state != CARD_STATE_RUN)
				return (-ERR_NOT_BOOTED);
			cnf->conf_line[CONF_LINE_LEN - 1] = 0;	/*                     */
			cnf->channel = 4098;	/*                            */
		}
	}			/*                       */
	if (cnf->state == CONF_STATE_POF) {	/*                  */
		i = cnf->needed_size - cnf->buf_size;	/*                               */
		if (i <= 0)
			return (-EINVAL);	/*                         */

		if (i < count)
			count = i;	/*                                 */
		if (copy_from_user(cnf->pof_buffer + cnf->buf_size, buf, count))
			return (-EFAULT);	/*                     */
		cnf->buf_size += count;

		if (cnf->needed_size == cnf->buf_size) {
			cnf->needed_size = pof_write_buffer(cnf->card, cnf->buf_size);	/*            */
			if (cnf->needed_size <= 0) {
				cnf->card->state = CARD_STATE_BOOTERR;	/*                 */
				return (cnf->needed_size);	/*                   */
			}
			cnf->buf_size = 0;	/*                       */
		}
	}
	/*                  */
	else {			/*                   */

		if (cnf->card->state != CARD_STATE_RUN) {
			if (cnf->card->debug_flags & LOG_CNF_MISC)
				hysdn_addlog(cnf->card, "cnf write denied -> not booted");
			return (-ERR_NOT_BOOTED);
		}
		i = (CONF_LINE_LEN - 1) - cnf->buf_size;	/*                           */
		if (i > 0) {
			/*                                  */

			if (count > i)
				count = i;	/*                */
			if (copy_from_user(cnf->conf_line + cnf->buf_size, buf, count))
				return (-EFAULT);	/*                     */

			i = count;	/*                           */
			cp = cnf->conf_line + cnf->buf_size;
			while (i) {
				/*                        */
				if ((*cp < ' ') && (*cp != 9))
					break;	/*                   */
				cp++;
				i--;
			}	/*                        */

			if (i) {
				/*                 */
				*cp++ = 0;	/*                    */
				count -= (i - 1);	/*                                     */
				while ((i) && (*cp < ' ') && (*cp != 9)) {
					i--;	/*                   */
					count++;	/*              */
					cp++;	/*           */
				}
				cnf->buf_size = 0;	/*                                */
				if ((i = process_line(cnf)) < 0)	/*                 */
					count = i;	/*                  */
			}
			/*                 */
			else {
				cnf->buf_size += count;		/*                     */
				if (cnf->buf_size >= CONF_LINE_LEN - 1) {
					if (cnf->card->debug_flags & LOG_CNF_MISC)
						hysdn_addlog(cnf->card, "cnf line too long %d chars pos %d", cnf->buf_size, count);
					return (-ERR_CONF_LONG);
				}
			}	/*               */

		}
		/*                                  */
		else {
			if (cnf->card->debug_flags & LOG_CNF_MISC)
				hysdn_addlog(cnf->card, "cnf line too long");
			return (-ERR_CONF_LONG);
		}
	}			/*                   */

	return (count);
}				/*                  */
Пример #28
0
static ssize_t
hysdn_conf_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
{
	struct conf_writedata *cnf;
	int i;
	unsigned char ch, *cp;

	if (!count)
		return (0);	/* nothing to handle */

	if (!(cnf = file->private_data))
		return (-EFAULT);	/* should never happen */

	if (cnf->state == CONF_STATE_DETECT) {	/* auto detect cnf or pof data */
		if (copy_from_user(&ch, buf, 1))	/* get first char for detect */
			return (-EFAULT);

		if (ch == 0x1A) {
			/* we detected a pof file */
			if ((cnf->needed_size = pof_write_open(cnf->card, &cnf->pof_buffer)) <= 0)
				return (cnf->needed_size);	/* an error occurred -> exit */
			cnf->buf_size = 0;	/* buffer is empty */
			cnf->state = CONF_STATE_POF;	/* new state */
		} else {
			/* conf data has been detected */
			cnf->buf_size = 0;	/* buffer is empty */
			cnf->state = CONF_STATE_CONF;	/* requested conf data write */
			if (cnf->card->state != CARD_STATE_RUN)
				return (-ERR_NOT_BOOTED);
			cnf->conf_line[CONF_LINE_LEN - 1] = 0;	/* limit string length */
			cnf->channel = 4098;	/* default channel for output */
		}
	}			/* state was auto detect */
	if (cnf->state == CONF_STATE_POF) {	/* pof write active */
		i = cnf->needed_size - cnf->buf_size;	/* bytes still missing for write */
		if (i <= 0)
			return (-EINVAL);	/* size error handling pof */

		if (i < count)
			count = i;	/* limit requested number of bytes */
		if (copy_from_user(cnf->pof_buffer + cnf->buf_size, buf, count))
			return (-EFAULT);	/* error while copying */
		cnf->buf_size += count;

		if (cnf->needed_size == cnf->buf_size) {
			cnf->needed_size = pof_write_buffer(cnf->card, cnf->buf_size);	/* write data */
			if (cnf->needed_size <= 0) {
				cnf->card->state = CARD_STATE_BOOTERR;	/* show boot error */
				return (cnf->needed_size);	/* an error occurred */
			}
			cnf->buf_size = 0;	/* buffer is empty again */
		}
	}
	/* pof write active */
	else {			/* conf write active */

		if (cnf->card->state != CARD_STATE_RUN) {
			if (cnf->card->debug_flags & LOG_CNF_MISC)
				hysdn_addlog(cnf->card, "cnf write denied -> not booted");
			return (-ERR_NOT_BOOTED);
		}
		i = (CONF_LINE_LEN - 1) - cnf->buf_size;	/* bytes available in buffer */
		if (i > 0) {
			/* copy remaining bytes into buffer */

			if (count > i)
				count = i;	/* limit transfer */
			if (copy_from_user(cnf->conf_line + cnf->buf_size, buf, count))
				return (-EFAULT);	/* error while copying */

			i = count;	/* number of chars in buffer */
			cp = cnf->conf_line + cnf->buf_size;
			while (i) {
				/* search for end of line */
				if ((*cp < ' ') && (*cp != 9))
					break;	/* end of line found */
				cp++;
				i--;
			}	/* search for end of line */

			if (i) {
				/* delimiter found */
				*cp++ = 0;	/* string termination */
				count -= (i - 1);	/* subtract remaining bytes from count */
				while ((i) && (*cp < ' ') && (*cp != 9)) {
					i--;	/* discard next char */
					count++;	/* mark as read */
					cp++;	/* next char */
				}
				cnf->buf_size = 0;	/* buffer is empty after transfer */
				if ((i = process_line(cnf)) < 0)	/* handle the line */
					count = i;	/* return the error */
			}
			/* delimiter found */
			else {
				cnf->buf_size += count;		/* add chars to string */
				if (cnf->buf_size >= CONF_LINE_LEN - 1) {
					if (cnf->card->debug_flags & LOG_CNF_MISC)
						hysdn_addlog(cnf->card, "cnf line too long %d chars pos %d", cnf->buf_size, count);
					return (-ERR_CONF_LONG);
				}
			}	/* not delimited */

		}
		/* copy remaining bytes into buffer */
		else {
			if (cnf->card->debug_flags & LOG_CNF_MISC)
				hysdn_addlog(cnf->card, "cnf line too long");
			return (-ERR_CONF_LONG);
		}
	}			/* conf write active */

	return (count);
}				/* hysdn_conf_write */
Пример #29
0
int
pof_write_buffer(hysdn_card * card, int datlen)
{
	struct boot_data *boot = card->boot;	

	if (!boot)
		return (-EFAULT);	
	if (boot->last_error < 0)
		return (boot->last_error);	

	if (card->debug_flags & LOG_POF_WRITE)
		hysdn_addlog(card, "POF write: got %d bytes ", datlen);

	switch (boot->pof_state) {
		case POF_READ_FILE_HEAD:
			if (card->debug_flags & LOG_POF_WRITE)
				hysdn_addlog(card, "POF write: checking file header");

			if (datlen != sizeof(tPofFileHdr)) {
				boot->last_error = -EPOF_INTERNAL;
				break;
			}
			if (boot->buf.PofFileHdr.Magic != TAGFILEMAGIC) {
				boot->last_error = -EPOF_BAD_MAGIC;
				break;
			}
			
			boot->Nrecs = (unsigned short)(boot->buf.PofFileHdr.N_PofRecs);	
			boot->pof_state = POF_READ_TAG_HEAD;	
			boot->last_error = sizeof(tPofRecHdr);	
			break;

		case POF_READ_TAG_HEAD:
			if (card->debug_flags & LOG_POF_WRITE)
				hysdn_addlog(card, "POF write: checking tag header");

			if (datlen != sizeof(tPofRecHdr)) {
				boot->last_error = -EPOF_INTERNAL;
				break;
			}
			boot->pof_recid = boot->buf.PofRecHdr.PofRecId;		
			boot->pof_reclen = boot->buf.PofRecHdr.PofRecDataLen;	
			boot->pof_recoffset = 0;	

			if (card->debug_flags & LOG_POF_RECORD)
				hysdn_addlog(card, "POF: got record id=0x%lx length=%ld ",
				      boot->pof_recid, boot->pof_reclen);

			boot->pof_state = POF_READ_TAG_DATA;	
			if (boot->pof_reclen < BOOT_BUF_SIZE)
				boot->last_error = boot->pof_reclen;	
			else
				boot->last_error = BOOT_BUF_SIZE;	

			if (!boot->last_error) {	
				boot->pof_state = POF_READ_TAG_HEAD;	
				boot->last_error = sizeof(tPofRecHdr);	
			}
			break;

		case POF_READ_TAG_DATA:
			if (card->debug_flags & LOG_POF_WRITE)
				hysdn_addlog(card, "POF write: getting tag data");

			if (datlen != boot->last_error) {
				boot->last_error = -EPOF_INTERNAL;
				break;
			}
			if ((boot->last_error = pof_handle_data(card, datlen)) < 0)
				return (boot->last_error);	
			boot->pof_recoffset += datlen;
			if (boot->pof_recoffset >= boot->pof_reclen) {
				boot->pof_state = POF_READ_TAG_HEAD;	
				boot->last_error = sizeof(tPofRecHdr);	
			} else {
				if (boot->pof_reclen - boot->pof_recoffset < BOOT_BUF_SIZE)
					boot->last_error = boot->pof_reclen - boot->pof_recoffset;	
				else
					boot->last_error = BOOT_BUF_SIZE;	
			}
			break;

		default:
			boot->last_error = -EPOF_INTERNAL;	
			break;
	}			

	return (boot->last_error);
}