예제 #1
0
파일: ipoctal.c 프로젝트: 03199618/linux
static void ipoctal_free_channel(struct ipoctal_channel *channel)
{
	ipoctal_reset_stats(&channel->stats);
	channel->pointer_read = 0;
	channel->pointer_write = 0;
	channel->nb_bytes = 0;
}
예제 #2
0
파일: ipoctal_drvr.c 프로젝트: dcobas/coht
static void ipoctal_free_channel(struct tty_struct *tty)
{
	int index = *(int *)tty->driver_data;
	int channel = tty->index;
	struct ipoctal *ipoctal = &ipoctal_installed[index];

	if (ipoctal != NULL) {
		ipoctal_reset_stats(&ipoctal->chan_stats[channel]);
		ipoctal->chan_status[channel] = CHAN_CLOSE;
		ipoctal->minor[channel] = 0;

		ipoctal->pointer_read[channel] = 0;
		ipoctal->pointer_write[channel] = 0;
		ipoctal->nb_bytes[channel] = 0;
	}
	else
		printk(KERN_ERR PFX "ipoctal_free_channel : ipoctal == NULL, is it"
				"installed? \n");
}
예제 #3
0
파일: ipoctal.c 프로젝트: 03199618/linux
static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
			     unsigned int slot)
{
	int res;
	int i;
	struct tty_driver *tty;
	char name[20];
	struct ipoctal_channel *channel;
	struct ipack_region *region;
	void __iomem *addr;
	union scc2698_channel __iomem *chan_regs;
	union scc2698_block __iomem *block_regs;

	ipoctal->board_id = ipoctal->dev->id_device;

	region = &ipoctal->dev->region[IPACK_IO_SPACE];
	addr = devm_ioremap_nocache(&ipoctal->dev->dev,
				    region->start, region->size);
	if (!addr) {
		dev_err(&ipoctal->dev->dev,
			"Unable to map slot [%d:%d] IO space!\n",
			bus_nr, slot);
		return -EADDRNOTAVAIL;
	}
	/* Save the virtual address to access the registers easily */
	chan_regs =
		(union scc2698_channel __iomem *) addr;
	block_regs =
		(union scc2698_block __iomem *) addr;

	region = &ipoctal->dev->region[IPACK_INT_SPACE];
	ipoctal->int_space =
		devm_ioremap_nocache(&ipoctal->dev->dev,
				     region->start, region->size);
	if (!ipoctal->int_space) {
		dev_err(&ipoctal->dev->dev,
			"Unable to map slot [%d:%d] INT space!\n",
			bus_nr, slot);
		return -EADDRNOTAVAIL;
	}

	region = &ipoctal->dev->region[IPACK_MEM8_SPACE];
	ipoctal->mem8_space =
		devm_ioremap_nocache(&ipoctal->dev->dev,
				     region->start, 0x8000);
	if (!ipoctal->mem8_space) {
		dev_err(&ipoctal->dev->dev,
			"Unable to map slot [%d:%d] MEM8 space!\n",
			bus_nr, slot);
		return -EADDRNOTAVAIL;
	}


	/* Disable RX and TX before touching anything */
	for (i = 0; i < NR_CHANNELS ; i++) {
		struct ipoctal_channel *channel = &ipoctal->channel[i];
		channel->regs = chan_regs + i;
		channel->block_regs = block_regs + (i >> 1);
		channel->board_id = ipoctal->board_id;
		if (i & 1) {
			channel->isr_tx_rdy_mask = ISR_TxRDY_B;
			channel->isr_rx_rdy_mask = ISR_RxRDY_FFULL_B;
		} else {
			channel->isr_tx_rdy_mask = ISR_TxRDY_A;
			channel->isr_rx_rdy_mask = ISR_RxRDY_FFULL_A;
		}

		iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr);
		channel->rx_enable = 0;
		iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
		iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
		iowrite8(MR1_CHRL_8_BITS | MR1_ERROR_CHAR | MR1_RxINT_RxRDY,
			 &channel->regs->w.mr); /* mr1 */
		iowrite8(0, &channel->regs->w.mr); /* mr2 */
		iowrite8(TX_CLK_9600  | RX_CLK_9600, &channel->regs->w.csr);
	}

	for (i = 0; i < IP_OCTAL_NB_BLOCKS; i++) {
		iowrite8(ACR_BRG_SET2, &block_regs[i].w.acr);
		iowrite8(OPCR_MPP_OUTPUT | OPCR_MPOa_RTSN | OPCR_MPOb_RTSN,
			 &block_regs[i].w.opcr);
		iowrite8(IMR_TxRDY_A | IMR_RxRDY_FFULL_A | IMR_DELTA_BREAK_A |
			 IMR_TxRDY_B | IMR_RxRDY_FFULL_B | IMR_DELTA_BREAK_B,
			 &block_regs[i].w.imr);
	}

	/*
	 * IP-OCTAL has different addresses to copy its IRQ vector.
	 * Depending of the carrier these addresses are accesible or not.
	 * More info in the datasheet.
	 */
	ipoctal->dev->bus->ops->request_irq(ipoctal->dev,
				       ipoctal_irq_handler, ipoctal);
	/* Dummy write */
	iowrite8(1, ipoctal->mem8_space + 1);

	/* Register the TTY device */

	/* Each IP-OCTAL channel is a TTY port */
	tty = alloc_tty_driver(NR_CHANNELS);

	if (!tty)
		return -ENOMEM;

	/* Fill struct tty_driver with ipoctal data */
	tty->owner = THIS_MODULE;
	tty->driver_name = KBUILD_MODNAME;
	sprintf(name, KBUILD_MODNAME ".%d.%d.", bus_nr, slot);
	tty->name = name;
	tty->major = 0;

	tty->minor_start = 0;
	tty->type = TTY_DRIVER_TYPE_SERIAL;
	tty->subtype = SERIAL_TYPE_NORMAL;
	tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
	tty->init_termios = tty_std_termios;
	tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
	tty->init_termios.c_ispeed = 9600;
	tty->init_termios.c_ospeed = 9600;

	tty_set_operations(tty, &ipoctal_fops);
	res = tty_register_driver(tty);
	if (res) {
		dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n");
		put_tty_driver(tty);
		return res;
	}

	/* Save struct tty_driver for use it when uninstalling the device */
	ipoctal->tty_drv = tty;

	for (i = 0; i < NR_CHANNELS; i++) {
		struct device *tty_dev;

		channel = &ipoctal->channel[i];
		tty_port_init(&channel->tty_port);
		tty_port_alloc_xmit_buf(&channel->tty_port);
		channel->tty_port.ops = &ipoctal_tty_port_ops;

		ipoctal_reset_stats(&channel->stats);
		channel->nb_bytes = 0;
		spin_lock_init(&channel->lock);
		channel->pointer_read = 0;
		channel->pointer_write = 0;
		tty_dev = tty_port_register_device(&channel->tty_port, tty, i, NULL);
		if (IS_ERR(tty_dev)) {
			dev_err(&ipoctal->dev->dev, "Failed to register tty device.\n");
			tty_port_destroy(&channel->tty_port);
			continue;
		}
		dev_set_drvdata(tty_dev, channel);
	}

	return 0;
}
예제 #4
0
파일: ipoctal_drvr.c 프로젝트: dcobas/coht
static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int carrier_number, unsigned int slot_position, unsigned int vector, char *carrier)
{
	char name[NAME_MAX];
	unsigned char manufacturerID;
	int res = 0;
	int i;
	int model = 0;

	ipoctal->slot_id = NULL;
	ipoctal->block_regs = NULL;
	ipoctal->chan_regs = NULL;

	for(i=0; i<NR_CHANNELS ; i++){
		ipoctal_reset_stats(&ipoctal->chan_stats[i]);
		ipoctal->chan_status[i] = CHAN_CLOSE;
		ipoctal->read_write[i].buffer = 0;
		ipoctal->read_write[i].error_flag = UART_NOERROR;
		ipoctal->read_write[i].nb_bytes = 0;
		ipoctal->read_write[i].timeout = 0;
		ipoctal->buffer[i] = kzalloc(MAX_CHAR*sizeof(unsigned char), GFP_KERNEL);
		ipoctal->nb_bytes[i] = 0;
		init_waitqueue_head(&ipoctal->queue[i]);
		ipoctal->error_flag[i] = UART_NOERROR;
		ipoctal->minor[i] = 0;
	}

	/* Register the device */
	sprintf(name, "%s_%d_%d", MODULE_NAME, carrier_number, slot_position);
	ipoctal->slot_id = ip_slot_register(name, carrier_number, slot_position);

	if (ipoctal->slot_id == NULL){
		printk(KERN_ERR PFX "Unable to install slot [%d:%d]!\n", carrier_number, slot_position);
		res = -ENXIO;
		goto out_err;
	}

	/* Map the corresponding spaces */
	res = ip_slot_map_space(ipoctal->slot_id, 0, SLOT_ID_SPACE);
	if (res){
		printk(KERN_ERR PFX "Unable to map slot [%d:%d] ID space!\n", carrier_number, slot_position);
		goto out_unregisterSlot;
	}

	res = ip_slot_map_space(ipoctal->slot_id, 0, SLOT_IO_SPACE);
	if (res){
		printk(KERN_ERR PFX "Unable to map slot [%d:%d] IO space!\n", carrier_number, slot_position);
		goto out_unregisterSlot;
	}

	res = ip_slot_map_space(ipoctal->slot_id, 0x8000, SLOT_MEM_SPACE);
	if (res){
		printk(KERN_ERR PFX "Unable to map slot [%d:%d] MEM space!\n", carrier_number, slot_position);
		goto out_unregisterSlot;
	}
	ipoctal->chan_regs = (struct scc2698_channel *) ipoctal->slot_id->io_space.address;
	ipoctal->block_regs = (struct scc2698_block *) ipoctal->slot_id->io_space.address;

	/* Check if the HW is managed by this driver */
	ip_slot_read_uchar(&manufacturerID, ipoctal->slot_id, SLOT_ID_SPACE, 
					SLOT_IDPROM_OFFSET_MANUFACTURER_ID);

	if (manufacturerID != IP_OCTAL_MANUFACTURER_ID) {
		printk(KERN_ERR PFX "Manufacturer ID of slot [%d:%d] must be 0x%X and not 0x%X !\n",
				carrier_number, slot_position,
				IP_OCTAL_MANUFACTURER_ID, manufacturerID);
		res = -ENODEV;
		goto out_unregisterSlot;
	}

	ip_slot_read_uchar(&ipoctal->board_id, ipoctal->slot_id, SLOT_ID_SPACE, 
							SLOT_IDPROM_OFFSET_MODEL);
	switch(ipoctal->board_id) {
	case IP_OCTAL_232_ID :
		printk(KERN_INFO PFX "Slot [%d:%d] is a RS-232 %d channels.\n",
				carrier_number, slot_position, NR_CHANNELS);
		model = 232;
		break;
	case IP_OCTAL_422_ID :
		printk(KERN_INFO PFX "Slot [%d:%d] is a RS-422 %d channels.\n",
				carrier_number, slot_position, NR_CHANNELS);
		model = 422;
		break;
	case IP_OCTAL_485_ID :
		printk(KERN_INFO PFX "Slot [%d:%d] is a RS-485 %d channels.\n",
				carrier_number, slot_position, NR_CHANNELS);
		model = 485;
	break;
	default :
		printk(KERN_ERR PFX "Model ID (0x%X) of slot [%d:%d] is unknown !\n",
				ipoctal->board_id, carrier_number, slot_position);
		res = -ENODEV;
		goto out_unregisterSlot;
		break;
	}

	for(i=0; i<IP_OCTAL_NB_BLOCKS ; i++){
		ipoctal_write_io_reg(ipoctal, &ipoctal->block_regs[i].u.w.acr, ACR_BRG_SET2);
		ipoctal_write_io_reg(
				ipoctal, 
				&ipoctal->block_regs[i].u.w.opcr, 
				OPCR_MPP_OUTPUT | OPCR_MPOa_RTSN | OPCR_MPOb_RTSN);
		ipoctal_write_io_reg(
				ipoctal, 
				&ipoctal->block_regs[i].u.w.imr,
				IMR_TxRDY_A | IMR_RxRDY_FFULL_A | IMR_DELTA_BREAK_A |
				IMR_TxRDY_B | IMR_RxRDY_FFULL_B | IMR_DELTA_BREAK_B);
	}

	for(i=0; i<NR_CHANNELS ; i++){
		ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[i].u.w.cr, 
						CR_DISABLE_RX | CR_DISABLE_TX);
	}

	/* Install IRQ */

	/* IP-OCTAL has different addresses to copy its IRQ vector. Depending of the carrier
         * these addresses are accesible or not. More data in the datasheet.
	 */

	if (strcmp(carrier, "TVME200") == 0)
		ip_slot_write_vector(vector, ipoctal->slot_id, SLOT_ID_SPACE, IP_OCTAL_ID_SPACE_VECTOR);
	else
		ip_slot_write_vector(vector, ipoctal->slot_id, SLOT_MEM_SPACE, 0);

	res = ip_slot_request_irq(ipoctal->slot_id, vector, ipoctal_irq_handler, (void *) ipoctal, name);
	if (res){
		printk(KERN_ERR PFX "Unable to install IRQ of slot [%d:%d]!\n", carrier_number, slot_position);
		goto out_unregisterSlot;
	}

	return 0;

out_unregisterSlot :
	ip_slot_unregister(ipoctal->slot_id);
out_err :
	return res;
}