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; }
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"); }
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; }
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; }