cyclades.c revision 8bab534b508230f33be5f7ba8492923754274a8d
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef BLOCKMOVE 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Z_WAKE 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef Z_EXT_CHARS_IN_BUFFER 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file contains the driver for the Cyclades async multiport 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * serial boards. 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initially written by Randolph Bentson <bentson@grieg.seaslug.org>. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified and maintained by Marcio Saito <marcio@cyclades.com>. 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 12ebdb513596c0eb1dcb3bad8f53865964a2207ca9Jiri Slaby * Copyright (C) 2007-2009 Jiri Slaby <jirislaby@gmail.com> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Much of the design and some of the code came from serial.c 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * which was copyright (C) 1991, 1992 Linus Torvalds. It was 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92, 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and then fixed as suggested by Michael K. Johnson 12/12/92. 18c8e1693a4f63e317966f3dfe8f815eda95e26610Jiri Slaby * Converted to pci probing and cleaned up by Jiri Slaby. 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22ebdb513596c0eb1dcb3bad8f53865964a2207ca9Jiri Slaby#define CY_VERSION "2.6" 23096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* If you need to install more boards than NR_CARDS, change the constant 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in the definition below. No other change is necessary to support up to 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eight boards. Beyond that you'll have to extend cy_isa_addresses. */ 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#define NR_CARDS 4 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds If the total number of ports is larger than NR_PORTS, change this 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds constant in the definition below. No other change is necessary to 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds support more boards/ports. */ 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#define NR_PORTS 256 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ZO_V1 0 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ZO_V2 1 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ZE_V1 2 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SERIAL_PARANOIA_CHECK 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef CY_DEBUG_OPEN 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef CY_DEBUG_THROTTLE 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef CY_DEBUG_OTHER 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef CY_DEBUG_IO 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef CY_DEBUG_COUNT 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef CY_DEBUG_DTR 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef CY_DEBUG_INTERRUPTS 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef CY_16Y_HACK 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef CY_ENABLE_MONITORING 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef CY_PCI_DEBUG 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5415ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox * Include section 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/signal.h> 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h> 6333f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox#include <linux/tty_flip.h> 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/serial.h> 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/major.h> 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fcntl.h> 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ptrace.h> 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/cyclades.h> 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h> 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h> 76054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby#include <linux/firmware.h> 779f56fad741163fe2111cbbcfb7ff795ebdabdab1Scott James Remnant#include <linux/device.h> 785a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8015ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox#include <linux/io.h> 8115ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox#include <linux/uaccess.h> 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/stat.h> 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h> 88444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan#include <linux/seq_file.h> 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_send_xchar(struct tty_struct *tty, char ch); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef SERIAL_XMIT_SIZE 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SERIAL_XMIT_SIZE (min(PAGE_SIZE, 4096)) 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define STD_COM_FLAGS (0) 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 98054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby/* firmware stuff */ 99054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby#define ZL_MAX_BLOCKS 16 100054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby#define DRIVER_VERSION 0x02010203 101054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby#define RAM_SIZE 0x80000 102054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 103054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slabyenum zblock_type { 104054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby ZBLOCK_PRG = 0, 105054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby ZBLOCK_FPGA = 1 106054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby}; 107054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 108054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slabystruct zfile_header { 109054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby char name[64]; 110054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby char date[32]; 111054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby char aux[32]; 112054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby u32 n_config; 113054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby u32 config_offset; 114054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby u32 n_blocks; 115054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby u32 block_offset; 116054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby u32 reserved[9]; 117054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby} __attribute__ ((packed)); 118054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 119054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slabystruct zfile_config { 120054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby char name[64]; 121054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby u32 mailbox; 122054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby u32 function; 123054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby u32 n_blocks; 124054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby u32 block_list[ZL_MAX_BLOCKS]; 125054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby} __attribute__ ((packed)); 126054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 127054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slabystruct zfile_block { 128054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby u32 type; 129054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby u32 file_offset; 130054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby u32 ram_offset; 131054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby u32 size; 132054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby} __attribute__ ((packed)); 133054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct tty_driver *cy_serial_driver; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_ISA 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This is the address lookup table. The driver will probe for 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Cyclom-Y/ISA boards at all addresses in here. If you want the 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver to probe addresses at a different address, add it to 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds this table. If the driver is probing some other board and 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds causing problems, remove the offending address from this table. 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int cy_isa_addresses[] = { 14502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0xD0000, 14602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0xD2000, 14702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0xD4000, 14802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0xD6000, 14902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0xD8000, 15002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0xDA000, 15102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0xDC000, 15202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0xDE000, 15302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0, 0, 0, 0, 0, 0, 0, 0 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 15502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 156fe971071a89c5c5184fc9f3482c7a8e997cf0520Tobias Klauser#define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses) 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1583046d50ea58676759453faeefccf57fbc9b72a90Jiri Slabystatic long maddr[NR_CARDS]; 1593046d50ea58676759453faeefccf57fbc9b72a90Jiri Slabystatic int irq[NR_CARDS]; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(maddr, long, NULL, 0); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(irq, int, NULL, 0); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_ISA */ 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This is the per-card data structure containing address, irq, number of 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds channels, etc. This driver supports a maximum of NR_CARDS cards. 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct cyclades_card cy_card[NR_CARDS]; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int cy_next_channel; /* next minor available */ 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is used to look up the divisor speeds and the timeouts 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We're normally limited to 15 distinct baud rates. The extra 17677451e53e0a509a98eda272567869cfe96431ba9Alan Cox * are accessed via settings in info->port.flags. 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * HI VHI 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 182ebdb513596c0eb1dcb3bad8f53865964a2207ca9Jiri Slabystatic const int baud_table[] = { 18302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 18402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000, 18502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 230400, 0 18602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}; 18702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 188ebdb513596c0eb1dcb3bad8f53865964a2207ca9Jiri Slabystatic const char baud_co_25[] = { /* 25 MHz clock option table */ 18902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* value => 00 01 02 03 04 */ 19002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* divide by 8 32 128 512 2048 */ 19102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, 19202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 19302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}; 19402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 195ebdb513596c0eb1dcb3bad8f53865964a2207ca9Jiri Slabystatic const char baud_bpr_25[] = { /* 25 MHz baud rate period table */ 19602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3, 19702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15 19802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}; 19902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 200ebdb513596c0eb1dcb3bad8f53865964a2207ca9Jiri Slabystatic const char baud_co_60[] = { /* 60 MHz clock option table (CD1400 J) */ 20102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* value => 00 01 02 03 04 */ 20202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* divide by 8 32 128 512 2048 */ 20302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 20402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 20502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x00 20602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}; 20702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 208ebdb513596c0eb1dcb3bad8f53865964a2207ca9Jiri Slabystatic const char baud_bpr_60[] = { /* 60 MHz baud rate period table (CD1400 J) */ 20902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62, 21002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32, 21102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x21 21202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}; 21302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 214ebdb513596c0eb1dcb3bad8f53865964a2207ca9Jiri Slabystatic const char baud_cor3[] = { /* receive threshold */ 21502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 21602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07, 21702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x07 21802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The Cyclades driver implements HW flow control as any serial driver. 22215ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox * The cyclades_port structure member rflow and the vector rflow_thr 22315ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox * allows us to take advantage of a special feature in the CD1400 to avoid 22415ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox * data loss even when the system interrupt latency is too high. These flags 22515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox * are to be used only with very special applications. Setting these flags 22615ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox * requires the use of a special cable (DTR and RTS reversed). In the new 22715ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox * CD1400-based boards (rev. 6.00 or later), there is no need for special 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cables. 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231ebdb513596c0eb1dcb3bad8f53865964a2207ca9Jiri Slabystatic const char rflow_thr[] = { /* rflow threshold */ 23202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 23302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 23402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x0a 23502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}; 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The Cyclom-Ye has placed the sequential chips in non-sequential 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * address order. This look-up table overcomes that problem. 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 240f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slabystatic const unsigned int cy_chip_offset[] = { 0x0000, 24102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x0400, 24202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x0800, 24302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x0C00, 24402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x0200, 24502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x0600, 24602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x0A00, 24702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x0E00 24802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* PCI related definitions */ 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI 253ebdb513596c0eb1dcb3bad8f53865964a2207ca9Jiri Slabystatic const struct pci_device_id cy_pci_dev_id[] = { 25415ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox /* PCI < 1Mb */ 25515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) }, 25615ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox /* PCI > 1Mb */ 25715ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Hi) }, 25815ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox /* 4Y PCI < 1Mb */ 25915ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Lo) }, 26015ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox /* 4Y PCI > 1Mb */ 26115ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Hi) }, 26215ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox /* 8Y PCI < 1Mb */ 26315ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Lo) }, 26415ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox /* 8Y PCI > 1Mb */ 26515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Hi) }, 26615ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox /* Z PCI < 1Mb */ 26715ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Lo) }, 26815ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox /* Z PCI > 1Mb */ 26915ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Hi) }, 270893de2dffb0923d9bdba4abd66afcec3cf9103baJiri Slaby { } /* end of table */ 27102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}; 272893de2dffb0923d9bdba4abd66afcec3cf9103baJiri SlabyMODULE_DEVICE_TABLE(pci, cy_pci_dev_id); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void cy_start(struct tty_struct *); 276d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slabystatic void cy_set_line_char(struct cyclades_port *, struct tty_struct *); 2771a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielkastatic int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_ISA 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned detect_isa_irq(void __iomem *); 28002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_ISA */ 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_CYZ_INTR 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void cyz_poll(unsigned long); 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The Cyclades-Z polling cycle is defined by this variable */ 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic long cyz_polling_cycle = CZ_DEF_POLL; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2888d06afab73a75f40ae2864e6c296356bab1ab473Ingo Molnarstatic DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0); 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#else /* CONFIG_CYZ_INTR */ 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void cyz_rx_restart(unsigned long); 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct timer_list cyz_rx_full_timer[NR_PORTS]; 29302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_CYZ_INTR */ 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2953aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slabystatic inline void cyy_writeb(struct cyclades_port *port, u32 reg, u8 val) 2963aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby{ 2973aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby struct cyclades_card *card = port->card; 2983aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby 2993aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cy_writeb(port->u.cyy.base_addr + (reg << card->bus_index), val); 3003aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby} 3013aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby 3023aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slabystatic inline u8 cyy_readb(struct cyclades_port *port, u32 reg) 3033aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby{ 3043aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby struct cyclades_card *card = port->card; 3053aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby 3063aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby return readb(port->u.cyy.base_addr + (reg << card->bus_index)); 3073aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby} 3083aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby 3092693f485c22d18474c077f12fd0f797ee8679b33Jiri Slabystatic inline bool cy_is_Z(struct cyclades_card *card) 3102693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby{ 3112693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby return card->num_chips == (unsigned int)-1; 3122693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby} 3132693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby 3142693f485c22d18474c077f12fd0f797ee8679b33Jiri Slabystatic inline bool __cyz_fpga_loaded(struct RUNTIME_9060 __iomem *ctl_addr) 3152693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby{ 3162693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby return readl(&ctl_addr->init_ctrl) & (1 << 17); 3172693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby} 3182693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby 3192693f485c22d18474c077f12fd0f797ee8679b33Jiri Slabystatic inline bool cyz_fpga_loaded(struct cyclades_card *card) 3202693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby{ 3212693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby return __cyz_fpga_loaded(card->ctl_addr.p9060); 3222693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby} 3232693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby 3242693f485c22d18474c077f12fd0f797ee8679b33Jiri Slabystatic inline bool cyz_is_loaded(struct cyclades_card *card) 3252693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby{ 3262693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby struct FIRM_ID __iomem *fw_id = card->base_addr + ID_ADDRESS; 3272693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby 3282693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby return (card->hw_ver == ZO_V1 || cyz_fpga_loaded(card)) && 3292693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby readl(&fw_id->signature) == ZFIRM_ID; 3302693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby} 3312693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby 33202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic inline int serial_paranoia_check(struct cyclades_port *info, 333ebdb513596c0eb1dcb3bad8f53865964a2207ca9Jiri Slaby const char *name, const char *routine) 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SERIAL_PARANOIA_CHECK 33602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!info) { 337217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_WARNING "cyc Warning: null cyclades_port for (%s) " 338217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "in %s\n", name, routine); 33902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 1; 34002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 34102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 34202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->magic != CYCLADES_MAGIC) { 343217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_WARNING "cyc Warning: bad magic number for serial " 344217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "struct (%s) in %s\n", name, routine); 34502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 1; 34602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 34802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 349ebdb513596c0eb1dcb3bad8f53865964a2207ca9Jiri Slaby} 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************************************/ 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********* Start of block of Cyclom-Y specific code ********/ 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This routine waits up to 1000 micro-seconds for the previous 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds command to the Cirrus chip to complete and then issues the 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new command. An error is returned if the previous command 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds didn't finish within the time limit. 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This function is only called from inside spinlock-protected code. 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3613aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slabystatic int __cyy_issue_cmd(void __iomem *base_addr, u8 cmd, int index) 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3633aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby void __iomem *ccr = base_addr + (CyCCR << index); 364ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby unsigned int i; 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Check to see that the previous command has completed */ 36702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for (i = 0; i < 100; i++) { 3683aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby if (readb(ccr) == 0) 36902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 37002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby udelay(10L); 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 37202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* if the CCR never cleared, the previous command 37302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby didn't finish within the "reasonable time" */ 37402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (i == 100) 375096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return -1; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Issue the new command */ 3783aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cy_writeb(ccr, cmd); 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 380096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return 0; 3813aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby} 3823aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby 3833aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slabystatic inline int cyy_issue_cmd(struct cyclades_port *port, u8 cmd) 3843aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby{ 3853aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby return __cyy_issue_cmd(port->u.cyy.base_addr, cmd, 3863aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby port->card->bus_index); 3873aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby} 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_ISA 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ISA interrupt detection code */ 39115ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Coxstatic unsigned detect_isa_irq(void __iomem *address) 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 39302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int irq; 39402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long irqs, flags; 39502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int save_xir, save_car; 39602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int index = 0; /* IRQ probing is only for ISA */ 39702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 39802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* forget possible initially masked and pending IRQ */ 39902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby irq = probe_irq_off(probe_irq_on()); 40002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 40102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Clear interrupts on the board first */ 40202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(address + (Cy_ClrIntr << index), 0); 40302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Cy_ClrIntr is 0x1800 */ 40402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 40502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby irqs = probe_irq_on(); 40602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Wait ... */ 407f6e208c1119206e2382ef7df6e47aaee18eb7f10Jiri Slaby msleep(5); 40802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 40902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Enable the Tx interrupts on the CD1400 */ 41002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby local_irq_save(flags); 41102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(address + (CyCAR << index), 0); 4123aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby __cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index); 41302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 41402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(address + (CyCAR << index), 0); 41502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(address + (CySRER << index), 416db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby readb(address + (CySRER << index)) | CyTxRdy); 41702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby local_irq_restore(flags); 41802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 41902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Wait ... */ 420f6e208c1119206e2382ef7df6e47aaee18eb7f10Jiri Slaby msleep(5); 42102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 42202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Check which interrupt is in use */ 42302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby irq = probe_irq_off(irqs); 42402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 42502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Clean up */ 426db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby save_xir = (u_char) readb(address + (CyTIR << index)); 427db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby save_car = readb(address + (CyCAR << index)); 42802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(address + (CyCAR << index), (save_xir & 0x3)); 42902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(address + (CySRER << index), 430db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby readb(address + (CySRER << index)) & ~CyTxRdy); 43102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(address + (CyTIR << index), (save_xir & 0x3f)); 43202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(address + (CyCAR << index), (save_car)); 43302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(address + (Cy_ClrIntr << index), 0); 43402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Cy_ClrIntr is 0x1800 */ 43502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 43602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return (irq > 0) ? irq : 0; 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 43802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_ISA */ 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 440ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slabystatic void cyy_chip_rx(struct cyclades_card *cinfo, int chip, 441ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby void __iomem *base_addr) 442e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby{ 443e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby struct cyclades_port *info; 444e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby struct tty_struct *tty; 44565f76a82ec7a0374fad85211535330e203740475Jiri Slaby int len, index = cinfo->bus_index; 4463aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby u8 ivr, save_xir, channel, save_car, data, char_count; 447e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby 448e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby#ifdef CY_DEBUG_INTERRUPTS 449ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip); 450e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby#endif 451ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* determine the channel & change to that context */ 45265f76a82ec7a0374fad85211535330e203740475Jiri Slaby save_xir = readb(base_addr + (CyRIR << index)); 45365f76a82ec7a0374fad85211535330e203740475Jiri Slaby channel = save_xir & CyIRChannel; 454ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info = &cinfo->ports[channel + chip * 4]; 4553aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby save_car = cyy_readb(info, CyCAR); 4563aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, save_xir); 4573aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby ivr = cyy_readb(info, CyRIVR) & CyIVRMask; 458ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby 459d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty = tty_port_tty_get(&info->port); 460ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* if there is nowhere to put the data, discard it */ 461d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if (tty == NULL) { 4623aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby if (ivr == CyIVRRxEx) { /* exception */ 4633aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby data = cyy_readb(info, CyRDSR); 464ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } else { /* normal character reception */ 4653aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby char_count = cyy_readb(info, CyRDCR); 466ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby while (char_count--) 4673aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby data = cyy_readb(info, CyRDSR); 468ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } 469ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby goto end; 470ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } 471ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* there is an open port for this data */ 4723aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby if (ivr == CyIVRRxEx) { /* exception */ 4733aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby data = cyy_readb(info, CyRDSR); 474ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby 475ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* For statistics only */ 476ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (data & CyBREAK) 477ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.brk++; 478ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby else if (data & CyFRAME) 479ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.frame++; 480ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby else if (data & CyPARITY) 481ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.parity++; 482ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby else if (data & CyOVERRUN) 483ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.overrun++; 484ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby 485ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (data & info->ignore_status_mask) { 486ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.rx++; 487d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty_kref_put(tty); 488ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby return; 489ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } 490ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (tty_buffer_request_room(tty, 1)) { 491ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (data & info->read_status_mask) { 492ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (data & CyBREAK) { 493ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby tty_insert_flip_char(tty, 4943aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_readb(info, CyRDSR), 4953aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby TTY_BREAK); 496ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.rx++; 49777451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (info->port.flags & ASYNC_SAK) 498ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby do_SAK(tty); 499ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } else if (data & CyFRAME) { 50015ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox tty_insert_flip_char(tty, 5013aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_readb(info, CyRDSR), 5023aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby TTY_FRAME); 503ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.rx++; 504ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->idle_stats.frame_errs++; 505ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } else if (data & CyPARITY) { 506ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* Pieces of seven... */ 507ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby tty_insert_flip_char(tty, 5083aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_readb(info, CyRDSR), 5093aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby TTY_PARITY); 510ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.rx++; 511ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->idle_stats.parity_errs++; 512ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } else if (data & CyOVERRUN) { 513ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby tty_insert_flip_char(tty, 0, 514ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby TTY_OVERRUN); 515ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.rx++; 516ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* If the flip buffer itself is 517ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby overflowing, we still lose 518ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby the next incoming character. 519ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby */ 520ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby tty_insert_flip_char(tty, 5213aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_readb(info, CyRDSR), 5223aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby TTY_FRAME); 52302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->icount.rx++; 52402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->idle_stats.overruns++; 525ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* These two conditions may imply */ 526ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* a normal read should be done. */ 527ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* } else if(data & CyTIMEOUT) { */ 528ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* } else if(data & CySPECHAR) { */ 529ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } else { 530ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby tty_insert_flip_char(tty, 0, 531ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby TTY_NORMAL); 532ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.rx++; 53302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 534ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } else { 535ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby tty_insert_flip_char(tty, 0, TTY_NORMAL); 536ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.rx++; 537ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } 538ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } else { 539ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* there was a software buffer overrun and nothing 540ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby * could be done about it!!! */ 541ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.buf_overrun++; 542ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->idle_stats.overruns++; 543ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } 544ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } else { /* normal character reception */ 545ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* load # chars available from the chip */ 5463aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby char_count = cyy_readb(info, CyRDCR); 547e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby 548e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby#ifdef CY_ENABLE_MONITORING 549ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby ++info->mon.int_count; 550ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->mon.char_count += char_count; 551ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (char_count > info->mon.char_max) 552ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->mon.char_max = char_count; 553ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->mon.char_last = char_count; 554e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby#endif 555ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby len = tty_buffer_request_room(tty, char_count); 556ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby while (len--) { 5573aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby data = cyy_readb(info, CyRDSR); 558ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby tty_insert_flip_char(tty, data, TTY_NORMAL); 559ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->idle_stats.recv_bytes++; 560ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.rx++; 561e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby#ifdef CY_16Y_HACK 562ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby udelay(10L); 563e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby#endif 564e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby } 565ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->idle_stats.recv_idle = jiffies; 566e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby } 567ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby tty_schedule_flip(tty); 568d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty_kref_put(tty); 569ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slabyend: 570ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* end of service */ 5713aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyRIR, save_xir & 0x3f); 5723aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, save_car); 573ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby} 574e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby 57565f76a82ec7a0374fad85211535330e203740475Jiri Slabystatic void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip, 576ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby void __iomem *base_addr) 577ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby{ 578ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby struct cyclades_port *info; 579d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby struct tty_struct *tty; 58065f76a82ec7a0374fad85211535330e203740475Jiri Slaby int char_count, index = cinfo->bus_index; 58165f76a82ec7a0374fad85211535330e203740475Jiri Slaby u8 save_xir, channel, save_car, outch; 582ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby 583ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* Since we only get here when the transmit buffer 584ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby is empty, we know we can always stuff a dozen 585ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby characters. */ 586e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby#ifdef CY_DEBUG_INTERRUPTS 587ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d\n", chip); 588e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby#endif 589e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby 590ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* determine the channel & change to that context */ 59165f76a82ec7a0374fad85211535330e203740475Jiri Slaby save_xir = readb(base_addr + (CyTIR << index)); 59265f76a82ec7a0374fad85211535330e203740475Jiri Slaby channel = save_xir & CyIRChannel; 593ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby save_car = readb(base_addr + (CyCAR << index)); 594ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby cy_writeb(base_addr + (CyCAR << index), save_xir); 595ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby 596ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info = &cinfo->ports[channel + chip * 4]; 597d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty = tty_port_tty_get(&info->port); 598d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if (tty == NULL) { 5993aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy); 600ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby goto end; 601ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } 60202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 603ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* load the on-chip space for outbound data */ 604ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby char_count = info->xmit_fifo_size; 60502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 606ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (info->x_char) { /* send special char */ 607ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby outch = info->x_char; 6083aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyTDR, outch); 609ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby char_count--; 610ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.tx++; 611ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->x_char = 0; 612ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } 61302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 614ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (info->breakon || info->breakoff) { 615ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (info->breakon) { 6163aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyTDR, 0); 6173aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyTDR, 0x81); 618ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->breakon = 0; 619ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby char_count -= 2; 620e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby } 621ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (info->breakoff) { 6223aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyTDR, 0); 6233aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyTDR, 0x83); 624ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->breakoff = 0; 625ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby char_count -= 2; 626e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby } 627ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } 62802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 629ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby while (char_count-- > 0) { 630ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (!info->xmit_cnt) { 6313aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby if (cyy_readb(info, CySRER) & CyTxMpty) { 6323aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySRER, 6333aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_readb(info, CySRER) & ~CyTxMpty); 634ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } else { 6353aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySRER, CyTxMpty | 6363aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby (cyy_readb(info, CySRER) & ~CyTxRdy)); 63702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 638ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby goto done; 639ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } 64077451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (info->port.xmit_buf == NULL) { 6413aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySRER, 6423aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_readb(info, CySRER) & ~CyTxRdy); 643ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby goto done; 644ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } 645d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if (tty->stopped || tty->hw_stopped) { 6463aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySRER, 6473aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_readb(info, CySRER) & ~CyTxRdy); 648ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby goto done; 649ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } 650ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* Because the Embedded Transmit Commands have been enabled, 651ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby * we must check to see if the escape character, NULL, is being 652ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby * sent. If it is, we must ensure that there is room for it to 653ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby * be doubled in the output stream. Therefore we no longer 654ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby * advance the pointer when the character is fetched, but 655ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby * rather wait until after the check for a NULL output 656ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby * character. This is necessary because there may not be room 657ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby * for the two chars needed to send a NULL.) 658ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby */ 65977451e53e0a509a98eda272567869cfe96431ba9Alan Cox outch = info->port.xmit_buf[info->xmit_tail]; 660ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (outch) { 661ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->xmit_cnt--; 662ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->xmit_tail = (info->xmit_tail + 1) & 663ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby (SERIAL_XMIT_SIZE - 1); 6643aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyTDR, outch); 665ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.tx++; 666ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } else { 667ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (char_count > 1) { 66802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->xmit_cnt--; 66902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->xmit_tail = (info->xmit_tail + 1) & 670ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby (SERIAL_XMIT_SIZE - 1); 6713aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyTDR, outch); 6723aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyTDR, 0); 67302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->icount.tx++; 674ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby char_count--; 67502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 676e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby } 677e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby } 678e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby 679ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slabydone: 680d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty_wakeup(tty); 681d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty_kref_put(tty); 682ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slabyend: 683ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* end of service */ 6843aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyTIR, save_xir & 0x3f); 6853aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, save_car); 686ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby} 68702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 688ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slabystatic void cyy_chip_modem(struct cyclades_card *cinfo, int chip, 689ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby void __iomem *base_addr) 690ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby{ 691ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby struct cyclades_port *info; 692d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby struct tty_struct *tty; 69365f76a82ec7a0374fad85211535330e203740475Jiri Slaby int index = cinfo->bus_index; 69465f76a82ec7a0374fad85211535330e203740475Jiri Slaby u8 save_xir, channel, save_car, mdm_change, mdm_status; 695ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby 696ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* determine the channel & change to that context */ 69765f76a82ec7a0374fad85211535330e203740475Jiri Slaby save_xir = readb(base_addr + (CyMIR << index)); 69865f76a82ec7a0374fad85211535330e203740475Jiri Slaby channel = save_xir & CyIRChannel; 699ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info = &cinfo->ports[channel + chip * 4]; 7003aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby save_car = cyy_readb(info, CyCAR); 7013aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, save_xir); 702ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby 7033aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby mdm_change = cyy_readb(info, CyMISR); 7043aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby mdm_status = cyy_readb(info, CyMSVR1); 705ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby 706d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty = tty_port_tty_get(&info->port); 707d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if (!tty) 708ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby goto end; 709ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby 710ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (mdm_change & CyANY_DELTA) { 711ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* For statistics only */ 712ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (mdm_change & CyDCD) 713ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.dcd++; 714ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (mdm_change & CyCTS) 715ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.cts++; 716ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (mdm_change & CyDSR) 717ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.dsr++; 718ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (mdm_change & CyRI) 719ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby info->icount.rng++; 720ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby 721bdc04e3174e18f475289fa8f4144f66686326b7eAlan Cox wake_up_interruptible(&info->port.delta_msr_wait); 722ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } 723ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby 72477451e53e0a509a98eda272567869cfe96431ba9Alan Cox if ((mdm_change & CyDCD) && (info->port.flags & ASYNC_CHECK_CD)) { 725174e6fe01e7881caaa350b5e98e4c6189b6cb593Jiri Slaby if (mdm_status & CyDCD) 726174e6fe01e7881caaa350b5e98e4c6189b6cb593Jiri Slaby wake_up_interruptible(&info->port.open_wait); 727174e6fe01e7881caaa350b5e98e4c6189b6cb593Jiri Slaby else 728d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty_hangup(tty); 729ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } 73077451e53e0a509a98eda272567869cfe96431ba9Alan Cox if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) { 731d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if (tty->hw_stopped) { 732ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (mdm_status & CyCTS) { 733ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* cy_start isn't used 734ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby because... !!! */ 735d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty->hw_stopped = 0; 7363aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySRER, 7373aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_readb(info, CySRER) | CyTxRdy); 738d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty_wakeup(tty); 73902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 740ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } else { 741ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (!(mdm_status & CyCTS)) { 742ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* cy_stop isn't used 743ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby because ... !!! */ 744d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty->hw_stopped = 1; 7453aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySRER, 7463aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_readb(info, CySRER) & ~CyTxRdy); 74702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 748e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby } 749e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby } 750ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby/* if (mdm_change & CyDSR) { 751ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby } 752ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (mdm_change & CyRI) { 753ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby }*/ 754d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty_kref_put(tty); 755ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slabyend: 756ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby /* end of service */ 7573aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyMIR, save_xir & 0x3f); 7583aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, save_car); 759e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby} 760e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The real interrupt service routine is called 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds whenever the card wants its hand held--chars 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds received, out buffer empty, modem change, etc. 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 76502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic irqreturn_t cyy_interrupt(int irq, void *dev_id) 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 76702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int status; 768f742903424aae3fc7ea7079a3618d90634c0b301Jiri Slaby struct cyclades_card *cinfo = dev_id; 76902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby void __iomem *base_addr, *card_base_addr; 77065f76a82ec7a0374fad85211535330e203740475Jiri Slaby unsigned int chip, too_many, had_work; 77102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int index; 77202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 773f742903424aae3fc7ea7079a3618d90634c0b301Jiri Slaby if (unlikely(cinfo == NULL)) { 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_INTERRUPTS 77515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d\n", 77615ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox irq); 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 77802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return IRQ_NONE; /* spurious interrupt */ 77902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 78002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 78102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby card_base_addr = cinfo->base_addr; 78202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby index = cinfo->bus_index; 78302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 784f1e83c6c1e7b97ac11d88502c3e5b80cdac9a683Jiri Slaby /* card was not initialized yet (e.g. DEBUG_SHIRQ) */ 785f1e83c6c1e7b97ac11d88502c3e5b80cdac9a683Jiri Slaby if (unlikely(card_base_addr == NULL)) 786f1e83c6c1e7b97ac11d88502c3e5b80cdac9a683Jiri Slaby return IRQ_HANDLED; 787f1e83c6c1e7b97ac11d88502c3e5b80cdac9a683Jiri Slaby 78802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* This loop checks all chips in the card. Make a note whenever 78902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby _any_ chip had some work to do, as this is considered an 79002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby indication that there will be more to do. Only when no chip 79102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby has any work does this outermost loop exit. 79202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 79302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby do { 79402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby had_work = 0; 79502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for (chip = 0; chip < cinfo->num_chips; chip++) { 79602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby base_addr = cinfo->base_addr + 79702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (cy_chip_offset[chip] << index); 79802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby too_many = 0; 799db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby while ((status = readb(base_addr + 80002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (CySVRR << index))) != 0x00) { 80102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby had_work++; 80202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* The purpose of the following test is to ensure that 80302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby no chip can monopolize the driver. This forces the 80402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby chips to be checked in a round-robin fashion (after 80502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby draining each of a bunch (1000) of characters). 80602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 807ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (1000 < too_many++) 80802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 8091c0a387c1f9e48e480579d3b4e0f9c1a36c77751Jiri Slaby spin_lock(&cinfo->card_lock); 810ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (status & CySRReceive) /* rx intr */ 811ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby cyy_chip_rx(cinfo, chip, base_addr); 812ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (status & CySRTransmit) /* tx intr */ 813ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby cyy_chip_tx(cinfo, chip, base_addr); 814ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby if (status & CySRModem) /* modem intr */ 815ce97a09767b59dcde3715ba4a9eebc71b0ce71b2Jiri Slaby cyy_chip_modem(cinfo, chip, base_addr); 8161c0a387c1f9e48e480579d3b4e0f9c1a36c77751Jiri Slaby spin_unlock(&cinfo->card_lock); 81702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 81802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 81902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } while (had_work); 82002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 82102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* clear interrupts */ 82202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby spin_lock(&cinfo->card_lock); 82302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(card_base_addr + (Cy_ClrIntr << index), 0); 82402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Cy_ClrIntr is 0x1800 */ 82502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby spin_unlock(&cinfo->card_lock); 82602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return IRQ_HANDLED; 82702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cyy_interrupt */ 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8294d7682005ca88a37667c4af03908798e188b5224Jiri Slabystatic void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set, 8304d7682005ca88a37667c4af03908798e188b5224Jiri Slaby unsigned int clear) 8314d7682005ca88a37667c4af03908798e188b5224Jiri Slaby{ 8324d7682005ca88a37667c4af03908798e188b5224Jiri Slaby struct cyclades_card *card = info->card; 8333aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby int channel = info->line - card->first_line; 8340d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby u32 rts, dtr, msvrr, msvrd; 8354d7682005ca88a37667c4af03908798e188b5224Jiri Slaby 8364d7682005ca88a37667c4af03908798e188b5224Jiri Slaby channel &= 0x03; 8374d7682005ca88a37667c4af03908798e188b5224Jiri Slaby 8380d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby if (info->rtsdtr_inv) { 8390d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby msvrr = CyMSVR2; 8400d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby msvrd = CyMSVR1; 8410d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby rts = CyDTR; 8420d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby dtr = CyRTS; 8430d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby } else { 8440d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby msvrr = CyMSVR1; 8450d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby msvrd = CyMSVR2; 8460d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby rts = CyRTS; 8470d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby dtr = CyDTR; 8480d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby } 8494d7682005ca88a37667c4af03908798e188b5224Jiri Slaby if (set & TIOCM_RTS) { 8503aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel); 8513aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, msvrr, rts); 8524d7682005ca88a37667c4af03908798e188b5224Jiri Slaby } 8534d7682005ca88a37667c4af03908798e188b5224Jiri Slaby if (clear & TIOCM_RTS) { 8543aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel); 8553aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, msvrr, ~rts); 8564d7682005ca88a37667c4af03908798e188b5224Jiri Slaby } 8574d7682005ca88a37667c4af03908798e188b5224Jiri Slaby if (set & TIOCM_DTR) { 8583aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel); 8593aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, msvrd, dtr); 8604d7682005ca88a37667c4af03908798e188b5224Jiri Slaby#ifdef CY_DEBUG_DTR 8614d7682005ca88a37667c4af03908798e188b5224Jiri Slaby printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n"); 8624d7682005ca88a37667c4af03908798e188b5224Jiri Slaby printk(KERN_DEBUG " status: 0x%x, 0x%x\n", 8633aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_readb(info, CyMSVR1), 8643aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_readb(info, CyMSVR2)); 8654d7682005ca88a37667c4af03908798e188b5224Jiri Slaby#endif 8664d7682005ca88a37667c4af03908798e188b5224Jiri Slaby } 8674d7682005ca88a37667c4af03908798e188b5224Jiri Slaby if (clear & TIOCM_DTR) { 8683aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel); 8693aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, msvrd, ~dtr); 8704d7682005ca88a37667c4af03908798e188b5224Jiri Slaby#ifdef CY_DEBUG_DTR 8714d7682005ca88a37667c4af03908798e188b5224Jiri Slaby printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n"); 8724d7682005ca88a37667c4af03908798e188b5224Jiri Slaby printk(KERN_DEBUG " status: 0x%x, 0x%x\n", 8733aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_readb(info, CyMSVR1), 8743aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_readb(info, CyMSVR2)); 8754d7682005ca88a37667c4af03908798e188b5224Jiri Slaby#endif 8764d7682005ca88a37667c4af03908798e188b5224Jiri Slaby } 8774d7682005ca88a37667c4af03908798e188b5224Jiri Slaby} 8784d7682005ca88a37667c4af03908798e188b5224Jiri Slaby 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************************************/ 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********* End of block of Cyclom-Y specific code **********/ 88115ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox/******** Start of block of Cyclades-Z specific code *******/ 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************************************/ 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 88502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabycyz_fetch_msg(struct cyclades_card *cinfo, 88615ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox __u32 *channel, __u8 *cmd, __u32 *param) 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 888f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl; 88902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long loc_doorbell; 89002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 89197e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby loc_doorbell = readl(&cinfo->ctl_addr.p9060->loc_doorbell); 89202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (loc_doorbell) { 89302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby *cmd = (char)(0xff & loc_doorbell); 894db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby *channel = readl(&board_ctrl->fwcmd_channel); 895db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby *param = (__u32) readl(&board_ctrl->fwcmd_param); 89697e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby cy_writel(&cinfo->ctl_addr.p9060->loc_doorbell, 0xffffffff); 89702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 1; 89802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 89902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 90002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cyz_fetch_msg */ 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 90302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabycyz_issue_cmd(struct cyclades_card *cinfo, 9041a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka __u32 channel, __u8 cmd, __u32 param) 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 906f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl; 9071a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka __u32 __iomem *pci_doorbell; 90865f76a82ec7a0374fad85211535330e203740475Jiri Slaby unsigned int index; 90902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 9102693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cyz_is_loaded(cinfo)) 911096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return -1; 91215ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox 91302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby index = 0; 91497e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby pci_doorbell = &cinfo->ctl_addr.p9060->pci_doorbell; 915db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby while ((readl(pci_doorbell) & 0xff) != 0) { 91615ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (index++ == 1000) 917db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby return (int)(readl(pci_doorbell) & 0xff); 91802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby udelay(50L); 91902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 92002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&board_ctrl->hcmd_channel, channel); 92102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&board_ctrl->hcmd_param, param); 92202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(pci_doorbell, (long)cmd); 92302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 924096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return 0; 92502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cyz_issue_cmd */ 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 927f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slabystatic void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty) 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 929f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl; 930875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *cinfo = info->card; 93165f76a82ec7a0374fad85211535330e203740475Jiri Slaby unsigned int char_count; 93202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int len; 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef BLOCKMOVE 934ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby unsigned char *buf; 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 93602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char data; 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 938ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby __u32 rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr; 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 940db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby rx_get = new_rx_get = readl(&buf_ctrl->rx_get); 941db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby rx_put = readl(&buf_ctrl->rx_put); 942db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby rx_bufsize = readl(&buf_ctrl->rx_bufsize); 943db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby rx_bufaddr = readl(&buf_ctrl->rx_bufaddr); 94402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (rx_put >= rx_get) 94502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_count = rx_put - rx_get; 94602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else 94702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_count = rx_put - rx_get + rx_bufsize; 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 94902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (char_count) { 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_ENABLE_MONITORING 95102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->mon.int_count++; 95202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->mon.char_count += char_count; 95302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (char_count > info->mon.char_max) 95402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->mon.char_max = char_count; 95502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->mon.char_last = char_count; 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 957f742903424aae3fc7ea7079a3618d90634c0b301Jiri Slaby if (tty == NULL) { 95802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* flush received characters */ 95902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby new_rx_get = (new_rx_get + char_count) & 96002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (rx_bufsize - 1); 96102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->rflush_count++; 96202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef BLOCKMOVE 96402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* we'd like to use memcpy(t, f, n) and memset(s, c, count) 96502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for performance, but because of buffer boundaries, there 96602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby may be several steps to the operation */ 967ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby while (1) { 968ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby len = tty_prepare_flip_string(tty, &buf, 969ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby char_count); 970ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby if (!len) 971ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby break; 972ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby 973ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby len = min_t(unsigned int, min(len, char_count), 974ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby rx_bufsize - new_rx_get); 975ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby 976ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby memcpy_fromio(buf, cinfo->base_addr + 977ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby rx_bufaddr + new_rx_get, len); 978ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby 979ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby new_rx_get = (new_rx_get + len) & 98002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (rx_bufsize - 1); 981ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby char_count -= len; 982ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby info->icount.rx += len; 983ce71b0ffd01b0917a74c03562aaa110a71a0ee29Jiri Slaby info->idle_stats.recv_bytes += len; 98402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 98602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby len = tty_buffer_request_room(tty, char_count); 98702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby while (len--) { 988db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby data = readb(cinfo->base_addr + rx_bufaddr + 98902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby new_rx_get); 99015ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox new_rx_get = (new_rx_get + 1) & 99115ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox (rx_bufsize - 1); 99202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tty_insert_flip_char(tty, data, TTY_NORMAL); 99302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->idle_stats.recv_bytes++; 99402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->icount.rx++; 99502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_CYZ_INTR 99802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Recalculate the number of chars in the RX buffer and issue 99902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby a cmd in case it's higher than the RX high water mark */ 1000db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby rx_put = readl(&buf_ctrl->rx_put); 100102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (rx_put >= rx_get) 100202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_count = rx_put - rx_get; 100302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else 100402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_count = rx_put - rx_get + rx_bufsize; 100565f76a82ec7a0374fad85211535330e203740475Jiri Slaby if (char_count >= readl(&buf_ctrl->rx_threshold) && 1006ebafeeff0fea029099e9952f233e0794106897a6Jiri Slaby !timer_pending(&cyz_rx_full_timer[ 1007ebafeeff0fea029099e9952f233e0794106897a6Jiri Slaby info->line])) 1008ebafeeff0fea029099e9952f233e0794106897a6Jiri Slaby mod_timer(&cyz_rx_full_timer[info->line], 1009ebafeeff0fea029099e9952f233e0794106897a6Jiri Slaby jiffies + 1); 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 101102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->idle_stats.recv_idle = jiffies; 101202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tty_schedule_flip(tty); 101302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 101402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Update rx_get */ 101502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&buf_ctrl->rx_get, new_rx_get); 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1019f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slabystatic void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty) 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1021f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl; 1022875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *cinfo = info->card; 102365f76a82ec7a0374fad85211535330e203740475Jiri Slaby u8 data; 102465f76a82ec7a0374fad85211535330e203740475Jiri Slaby unsigned int char_count; 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef BLOCKMOVE 102602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int small_count; 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1028ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby __u32 tx_put, tx_get, tx_bufsize, tx_bufaddr; 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 103002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->xmit_cnt <= 0) /* Nothing to transmit */ 103102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1033db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby tx_get = readl(&buf_ctrl->tx_get); 1034db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby tx_put = readl(&buf_ctrl->tx_put); 1035db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby tx_bufsize = readl(&buf_ctrl->tx_bufsize); 1036db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby tx_bufaddr = readl(&buf_ctrl->tx_bufaddr); 103702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (tx_put >= tx_get) 103802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_count = tx_get - tx_put - 1 + tx_bufsize; 103902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else 104002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_count = tx_get - tx_put - 1; 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 104202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (char_count) { 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1044f742903424aae3fc7ea7079a3618d90634c0b301Jiri Slaby if (tty == NULL) 104502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby goto ztxdone; 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 104702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->x_char) { /* send special char */ 104802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby data = info->x_char; 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 105002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data); 105102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tx_put = (tx_put + 1) & (tx_bufsize - 1); 105202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->x_char = 0; 105302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_count--; 105402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->icount.tx++; 105502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef BLOCKMOVE 105702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby while (0 < (small_count = min_t(unsigned int, 105802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tx_bufsize - tx_put, min_t(unsigned int, 105902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (SERIAL_XMIT_SIZE - info->xmit_tail), 106002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby min_t(unsigned int, info->xmit_cnt, 106102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_count))))) { 106202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 106302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr + 106402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tx_put), 106577451e53e0a509a98eda272567869cfe96431ba9Alan Cox &info->port.xmit_buf[info->xmit_tail], 106602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby small_count); 106702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 106802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tx_put = (tx_put + small_count) & (tx_bufsize - 1); 106902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_count -= small_count; 107002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->icount.tx += small_count; 107102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->xmit_cnt -= small_count; 107202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->xmit_tail = (info->xmit_tail + small_count) & 107302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (SERIAL_XMIT_SIZE - 1); 107402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 107602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby while (info->xmit_cnt && char_count) { 107777451e53e0a509a98eda272567869cfe96431ba9Alan Cox data = info->port.xmit_buf[info->xmit_tail]; 107802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->xmit_cnt--; 107902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->xmit_tail = (info->xmit_tail + 1) & 108002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (SERIAL_XMIT_SIZE - 1); 108102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 108202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data); 108302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tx_put = (tx_put + 1) & (tx_bufsize - 1); 108402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_count--; 108502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->icount.tx++; 108602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1088ebafeeff0fea029099e9952f233e0794106897a6Jiri Slaby tty_wakeup(tty); 10897fa57a0cd98bdd163eeb5f15cbe234c3a0cf68a1Jiri Slabyztxdone: 109002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Update tx_put */ 109102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&buf_ctrl->tx_put, tx_put); 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 109502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cyz_handle_cmd(struct cyclades_card *cinfo) 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1097f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl; 109802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby struct tty_struct *tty; 109902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby struct cyclades_port *info; 1100101b81590d8df0a74c33cf739886247c0a13f4afJiri Slaby __u32 channel, param, fw_ver; 11011a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka __u8 cmd; 110202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int special_count; 110302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int delta_count; 110402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 1105db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby fw_ver = readl(&board_ctrl->fw_version); 110602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 110702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { 110802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby special_count = 0; 110902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby delta_count = 0; 1110dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby info = &cinfo->ports[channel]; 1111d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty = tty_port_tty_get(&info->port); 111215ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (tty == NULL) 111302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby continue; 1114f742903424aae3fc7ea7079a3618d90634c0b301Jiri Slaby 111502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby switch (cmd) { 111602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case C_CM_PR_ERROR: 111702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tty_insert_flip_char(tty, 0, TTY_PARITY); 111802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->icount.rx++; 111902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby special_count++; 112002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 112102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case C_CM_FR_ERROR: 112202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tty_insert_flip_char(tty, 0, TTY_FRAME); 112302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->icount.rx++; 112402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby special_count++; 112502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 112602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case C_CM_RXBRK: 112702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tty_insert_flip_char(tty, 0, TTY_BREAK); 112802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->icount.rx++; 112902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby special_count++; 113002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 113102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case C_CM_MDCD: 113202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->icount.dcd++; 113302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby delta_count++; 113477451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (info->port.flags & ASYNC_CHECK_CD) { 1135f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby u32 dcd = fw_ver > 241 ? param : 1136f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby readl(&info->u.cyz.ch_ctrl->rs_status); 1137174e6fe01e7881caaa350b5e98e4c6189b6cb593Jiri Slaby if (dcd & C_RS_DCD) 113877451e53e0a509a98eda272567869cfe96431ba9Alan Cox wake_up_interruptible(&info->port.open_wait); 1139174e6fe01e7881caaa350b5e98e4c6189b6cb593Jiri Slaby else 1140d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty_hangup(tty); 114102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 114202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 114302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case C_CM_MCTS: 114402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->icount.cts++; 114502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby delta_count++; 114602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 114702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case C_CM_MRI: 114802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->icount.rng++; 114902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby delta_count++; 115002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 115102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case C_CM_MDSR: 115202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->icount.dsr++; 115302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby delta_count++; 115402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef Z_WAKE 115602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case C_CM_IOCTLW: 1157ebafeeff0fea029099e9952f233e0794106897a6Jiri Slaby complete(&info->shutdown_wait); 115802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_CYZ_INTR 116102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case C_CM_RXHIWM: 116202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case C_CM_RXNNDT: 116302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case C_CM_INTBACK2: 116402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Reception Interrupt */ 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_INTERRUPTS 1166217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, " 1167217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "port %ld\n", info->card, channel); 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1169f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby cyz_handle_rx(info, tty); 117002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 117102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case C_CM_TXBEMPTY: 117202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case C_CM_TXLOWWM: 117302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case C_CM_INTBACK: 117402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Transmission Interrupt */ 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_INTERRUPTS 1176217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, " 1177217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "port %ld\n", info->card, channel); 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1179f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby cyz_handle_tx(info, tty); 118002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 118102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_CYZ_INTR */ 118202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case C_CM_FATAL: 118302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* should do something with this !!! */ 118402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 118502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby default: 118602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 118702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 118802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (delta_count) 1189bdc04e3174e18f475289fa8f4144f66686326b7eAlan Cox wake_up_interruptible(&info->port.delta_msr_wait); 119002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (special_count) 119102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tty_schedule_flip(tty); 1192d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty_kref_put(tty); 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_CYZ_INTR 119702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic irqreturn_t cyz_interrupt(int irq, void *dev_id) 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1199f742903424aae3fc7ea7079a3618d90634c0b301Jiri Slaby struct cyclades_card *cinfo = dev_id; 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12012693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (unlikely(!cyz_is_loaded(cinfo))) { 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_INTERRUPTS 1203217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyz_interrupt: board not yet loaded " 1204217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "(IRQ%d).\n", irq); 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 120602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return IRQ_NONE; 120702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 120902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Handle the interrupts */ 121002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cyz_handle_cmd(cinfo); 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return IRQ_HANDLED; 121302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cyz_interrupt */ 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cyz_rx_restart(unsigned long arg) 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 121702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby struct cyclades_port *info = (struct cyclades_port *)arg; 1218875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card = info->card; 121902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int retval; 1220875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby __u32 channel = info->line - card->first_line; 122102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 122202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 12239fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 1224875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby retval = cyz_issue_cmd(card, channel, C_CM_INTBACK2, 0L); 122502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 1226217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:cyz_rx_restart retval on ttyC%d was %x\n", 122702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->line, retval); 122802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 12299fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 123202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#else /* CONFIG_CYZ_INTR */ 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 123402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cyz_poll(unsigned long arg) 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 123602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby struct cyclades_card *cinfo; 123702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby struct cyclades_port *info; 1238b70509066cba24067757f1422c899c43e433429dJiri Slaby unsigned long expires = jiffies + HZ; 123965f76a82ec7a0374fad85211535330e203740475Jiri Slaby unsigned int port, card; 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 124102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for (card = 0; card < NR_CARDS; card++) { 124202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cinfo = &cy_card[card]; 124302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 12442693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(cinfo)) 124502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby continue; 12462693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cyz_is_loaded(cinfo)) 124702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby continue; 124802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Skip first polling cycle to avoid racing conditions with the FW */ 125002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!cinfo->intr_enabled) { 125102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cinfo->intr_enabled = 1; 125202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby continue; 125302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 125502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cyz_handle_cmd(cinfo); 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 125702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for (port = 0; port < cinfo->nports; port++) { 1258d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby struct tty_struct *tty; 1259d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby 1260dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby info = &cinfo->ports[port]; 1261d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty = tty_port_tty_get(&info->port); 1262d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby /* OK to pass NULL to the handle functions below. 1263d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby They need to drop the data in that case. */ 1264d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby 126502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!info->throttle) 1266f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby cyz_handle_rx(info, tty); 1267f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby cyz_handle_tx(info, tty); 1268d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty_kref_put(tty); 126902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 127002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* poll every 'cyz_polling_cycle' period */ 1271b70509066cba24067757f1422c899c43e433429dJiri Slaby expires = jiffies + cyz_polling_cycle; 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1273b70509066cba24067757f1422c899c43e433429dJiri Slaby mod_timer(&cyz_timerlist, expires); 127402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cyz_poll */ 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 127602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_CYZ_INTR */ 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********** End of block of Cyclades-Z specific code *********/ 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************************************/ 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This is called whenever a port becomes active; 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds interrupts are enabled and DTR & RTS are turned on. 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1284d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slabystatic int cy_startup(struct cyclades_port *info, struct tty_struct *tty) 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1286875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card; 128702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 128802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int retval = 0; 1289cc7fdf49d6f06efdf0cb7da8d7abe7eff663aa9bJiri Slaby int channel; 129002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long page; 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 129202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby card = info->card; 1293875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby channel = info->line - card->first_line; 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 129502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby page = get_zeroed_page(GFP_KERNEL); 129602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!page) 129702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENOMEM; 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12999fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301cc7fdf49d6f06efdf0cb7da8d7abe7eff663aa9bJiri Slaby if (info->port.flags & ASYNC_INITIALIZED) 130202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby goto errout; 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 130402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!info->type) { 1305d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby set_bit(TTY_IO_ERROR, &tty->flags); 130602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby goto errout; 130702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 130977451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (info->port.xmit_buf) 131002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby free_page(page); 131102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else 131277451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.xmit_buf = (unsigned char *)page; 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13149fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1316d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby cy_set_line_char(info, tty); 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13182693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 131902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby channel &= 0x03; 13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13219fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13233aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel); 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13253aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyRTPR, 132602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (info->default_timeout ? info->default_timeout : 0x02)); 132702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 10ms rx timeout */ 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13293aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_issue_cmd(info, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR); 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13314d7682005ca88a37667c4af03908798e188b5224Jiri Slaby cyy_change_rts_dtr(info, TIOCM_RTS | TIOCM_DTR, 0); 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13333aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyRxData); 133402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 1335f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13372693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cyz_is_loaded(card)) 133802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENODEV; 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OPEN 1341217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc startup Z card %d, channel %d, " 1342f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby "base_addr %p\n", card, channel, card->base_addr); 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 13449fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1346f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby cy_writel(&ch_ctrl->op_mode, C_CH_ENABLE); 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef Z_WAKE 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_CYZ_INTR 1349f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby cy_writel(&ch_ctrl->intr_enable, 135002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM | 135102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby C_IN_RXNNDT | C_IN_IOCTLW | C_IN_MDCD); 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 1353f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby cy_writel(&ch_ctrl->intr_enable, 135402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby C_IN_IOCTLW | C_IN_MDCD); 135502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_CYZ_INTR */ 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_CYZ_INTR 1358f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby cy_writel(&ch_ctrl->intr_enable, 135902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM | 136002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby C_IN_RXNNDT | C_IN_MDCD); 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 1362f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby cy_writel(&ch_ctrl->intr_enable, C_IN_MDCD); 136302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_CYZ_INTR */ 136402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* Z_WAKE */ 136502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 1366875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L); 136702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 1368217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:startup(1) retval on ttyC%d was " 1369217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "%x\n", info->line, retval); 137002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 137202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Flush RX buffers before raising DTR and RTS */ 1373875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_RX, 0L); 137402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 1375217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:startup(2) retval on ttyC%d was " 1376217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "%x\n", info->line, retval); 137702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 137902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* set timeout !!! */ 138002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* set RTS and DTR !!! */ 13814d7682005ca88a37667c4af03908798e188b5224Jiri Slaby tty_port_raise_dtr_rts(&info->port); 13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 138302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* enable send, recv, modem !!! */ 1384cc7fdf49d6f06efdf0cb7da8d7abe7eff663aa9bJiri Slaby } 138502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 1386cc7fdf49d6f06efdf0cb7da8d7abe7eff663aa9bJiri Slaby info->port.flags |= ASYNC_INITIALIZED; 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1388cc7fdf49d6f06efdf0cb7da8d7abe7eff663aa9bJiri Slaby clear_bit(TTY_IO_ERROR, &tty->flags); 1389cc7fdf49d6f06efdf0cb7da8d7abe7eff663aa9bJiri Slaby info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; 1390cc7fdf49d6f06efdf0cb7da8d7abe7eff663aa9bJiri Slaby info->breakon = info->breakoff = 0; 1391cc7fdf49d6f06efdf0cb7da8d7abe7eff663aa9bJiri Slaby memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats)); 1392cc7fdf49d6f06efdf0cb7da8d7abe7eff663aa9bJiri Slaby info->idle_stats.in_use = 1393cc7fdf49d6f06efdf0cb7da8d7abe7eff663aa9bJiri Slaby info->idle_stats.recv_idle = 1394cc7fdf49d6f06efdf0cb7da8d7abe7eff663aa9bJiri Slaby info->idle_stats.xmit_idle = jiffies; 1395cc7fdf49d6f06efdf0cb7da8d7abe7eff663aa9bJiri Slaby 1396cc7fdf49d6f06efdf0cb7da8d7abe7eff663aa9bJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OPEN 1399217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc startup done\n"); 14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserrout: 14049fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 1405cc7fdf49d6f06efdf0cb7da8d7abe7eff663aa9bJiri Slaby free_page(page); 14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 140702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* startup */ 14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 140902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void start_xmit(struct cyclades_port *info) 14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14113aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby struct cyclades_card *card = info->card; 141202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 14133aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby int channel = info->line - card->first_line; 14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14152693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 14169fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 14173aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel & 0x03); 14183aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy); 14199fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 142002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_CYZ_INTR 142202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int retval; 14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14249fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 1425875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby retval = cyz_issue_cmd(card, channel, C_CM_INTBACK, 0L); 142602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 1427217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:start_xmit retval on ttyC%d was " 1428217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "%x\n", info->line, retval); 142902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 14309fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 143102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#else /* CONFIG_CYZ_INTR */ 143202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Don't have to do anything at this time */ 143302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_CYZ_INTR */ 143402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 143502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* start_xmit */ 14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine shuts down a serial port; interrupts are disabled, 14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and DTR is dropped if the hangup on close termio flag is on. 14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1441d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slabystatic void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) 14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1443875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card; 144402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 144502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 144677451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (!(info->port.flags & ASYNC_INITIALIZED)) 144702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 144802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 144902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby card = info->card; 14502693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 14519fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 145202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 145302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Clear delta_msr_wait queue to avoid mem leaks. */ 1454bdc04e3174e18f475289fa8f4144f66686326b7eAlan Cox wake_up_interruptible(&info->port.delta_msr_wait); 14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 145677451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (info->port.xmit_buf) { 145702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned char *temp; 145877451e53e0a509a98eda272567869cfe96431ba9Alan Cox temp = info->port.xmit_buf; 145977451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.xmit_buf = NULL; 146002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby free_page((unsigned long)temp); 146102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 14624d7682005ca88a37667c4af03908798e188b5224Jiri Slaby if (tty->termios->c_cflag & HUPCL) 14634d7682005ca88a37667c4af03908798e188b5224Jiri Slaby cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR); 14644d7682005ca88a37667c4af03908798e188b5224Jiri Slaby 14653aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR); 146602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* it may be appropriate to clear _XMIT at 146702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby some later date (after testing)!!! */ 146802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 1469d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby set_bit(TTY_IO_ERROR, &tty->flags); 147077451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags &= ~ASYNC_INITIALIZED; 14719fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 147202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OPEN 14740e7f4194a0ef70c1d0d40152fa480a63719f35d5Jiri Slaby int channel = info->line - card->first_line; 1475217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, " 1476f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby "base_addr %p\n", card, channel, card->base_addr); 14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14792693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cyz_is_loaded(card)) 148002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14829fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 148477451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (info->port.xmit_buf) { 148502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned char *temp; 148677451e53e0a509a98eda272567869cfe96431ba9Alan Cox temp = info->port.xmit_buf; 148777451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.xmit_buf = NULL; 148802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby free_page((unsigned long)temp); 14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 149002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 14914d7682005ca88a37667c4af03908798e188b5224Jiri Slaby if (tty->termios->c_cflag & HUPCL) 14924d7682005ca88a37667c4af03908798e188b5224Jiri Slaby tty_port_lower_dtr_rts(&info->port); 14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1494d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby set_bit(TTY_IO_ERROR, &tty->flags); 149577451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags &= ~ASYNC_INITIALIZED; 149602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 14979fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 149802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OPEN 1501217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc shutdown done\n"); 15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 150302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* shutdown */ 15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ------------------------------------------------------------ 15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cy_open() and friends 15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ------------------------------------------------------------ 15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine is called whenever a serial port is opened. It 15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * performs the serial-specific initialization for the tty structure. 15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 151502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int cy_open(struct tty_struct *tty, struct file *filp) 15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 151702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby struct cyclades_port *info; 151865f76a82ec7a0374fad85211535330e203740475Jiri Slaby unsigned int i, line; 151965f76a82ec7a0374fad85211535330e203740475Jiri Slaby int retval; 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 152102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby line = tty->index; 152215ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (tty->index < 0 || NR_PORTS <= line) 152302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENODEV; 152415ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox 1525dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby for (i = 0; i < NR_CARDS; i++) 1526dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby if (line < cy_card[i].first_line + cy_card[i].nports && 1527dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby line >= cy_card[i].first_line) 1528dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby break; 1529dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby if (i >= NR_CARDS) 1530dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby return -ENODEV; 1531dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby info = &cy_card[i].ports[line - cy_card[i].first_line]; 153215ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (info->line < 0) 153302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENODEV; 15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 153502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* If the card's firmware hasn't been loaded, 153602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby treat it as absent from the system. This 153702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby will make the user pay attention. 153802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 15392693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (cy_is_Z(info->card)) { 1540875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *cinfo = info->card; 154102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; 154202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 15432693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cyz_is_loaded(cinfo)) { 15442693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (cinfo->hw_ver == ZE_V1 && cyz_fpga_loaded(cinfo) && 1545101b81590d8df0a74c33cf739886247c0a13f4afJiri Slaby readl(&firm_id->signature) == 1546101b81590d8df0a74c33cf739886247c0a13f4afJiri Slaby ZFIRM_HLT) { 1547217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:Cyclades-Z Error: you " 1548217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "need an external power supply for " 1549217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "this number of ports.\nFirmware " 1550217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "halted.\n"); 155102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 1552217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:Cyclades-Z firmware not " 1553217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "yet loaded\n"); 155402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 155502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENODEV; 155602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 155702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#ifdef CONFIG_CYZ_INTR 155802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else { 155902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* In case this Z board is operating in interrupt mode, its 156002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby interrupts should be enabled as soon as the first open 156102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby happens to one of its ports. */ 156202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!cinfo->intr_enabled) { 156397e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby u16 intr; 156402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 156502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Enable interrupts on the PLX chip */ 156697e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby intr = readw(&cinfo->ctl_addr.p9060-> 156797e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby intr_ctrl_stat) | 0x0900; 156897e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby cy_writew(&cinfo->ctl_addr.p9060-> 156997e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby intr_ctrl_stat, intr); 157002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Enable interrupts on the FW */ 157102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby retval = cyz_issue_cmd(cinfo, 0, 157202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby C_CM_IRQ_ENBL, 0L); 157302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 1574217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:IRQ enable retval " 1575217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "was %x\n", retval); 157602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 157702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cinfo->intr_enabled = 1; 157802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 158002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_CYZ_INTR */ 158102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Make sure this Z port really exists in hardware */ 158202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->line > (cinfo->first_line + cinfo->nports - 1)) 158302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENODEV; 15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OTHER 1586217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_open ttyC%d\n", info->line); 15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 158802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tty->driver_data = info; 158915ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (serial_paranoia_check(info, tty->name, "cy_open")) 159002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENODEV; 159115ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox 15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OPEN 1593217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d\n", info->line, 159477451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.count); 15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 159677451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.count++; 15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_COUNT 1598217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_open (%d): incrementing count to %d\n", 159977451e53e0a509a98eda272567869cfe96431ba9Alan Cox current->pid, info->port.count); 16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 160202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 160302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * If the port is the middle of closing, bail out now 160402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 160577451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { 1606be1bc2889a4db4961ef69f47fb471ecae9f23adeArnd Bergmann wait_event_interruptible_tty(info->port.close_wait, 160777451e53e0a509a98eda272567869cfe96431ba9Alan Cox !(info->port.flags & ASYNC_CLOSING)); 160877451e53e0a509a98eda272567869cfe96431ba9Alan Cox return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; 160902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 161102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 161202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * Start up serial port 161302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 1614d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby retval = cy_startup(info, tty); 161515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (retval) 161602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return retval; 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1618f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby retval = tty_port_block_til_ready(&info->port, tty, filp); 161902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval) { 16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OPEN 1621217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready " 1622217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "with %d\n", retval); 16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 162402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return retval; 162502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 162702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->throttle = 0; 1628d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty_port_tty_set(&info->port, tty); 16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 163002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#ifdef CY_DEBUG_OPEN 1631217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_open done\n"); 163202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif 163302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 163402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_open */ 16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cy_wait_until_sent() --- wait until the transmitter is empty 16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 163902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_wait_until_sent(struct tty_struct *tty, int timeout) 16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1641875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card; 1642cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 164302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long orig_jiffies; 164402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int char_time; 164502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 164602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent")) 164702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 164802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 164902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->xmit_fifo_size == 0) 165002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; /* Just in case.... */ 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 165202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby orig_jiffies = jiffies; 165302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 165402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * Set the check interval to be 1/5 of the estimated time to 165502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * send a single character, and make it at least 1. The check 165602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * interval should also be less than the timeout. 165702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * 165802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * Note: we have to use pretty tight timings here to satisfy 165902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * the NIST-PCTS. 166002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 166102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size; 166202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_time = char_time / 5; 166302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (char_time <= 0) 166402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_time = 1; 166502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (timeout < 0) 166602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby timeout = 0; 166702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (timeout) 166802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_time = min(char_time, timeout); 166902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 167002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * If the transmitter hasn't cleared in twice the approximate 167102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * amount of time to send the entire FIFO, it probably won't 167202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * ever clear. This assumes the UART isn't doing flow 167302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * control, which is currently the case. Hence, if it ever 167402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * takes longer than info->timeout, this is probably due to a 167502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * UART bug of some kind. So, we clamp the timeout parameter at 167602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * 2*info->timeout. 167702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 167802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!timeout || timeout > 2 * info->timeout) 167902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby timeout = 2 * info->timeout; 16808bab534b508230f33be5f7ba8492923754274a8dJiri Slaby 168102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby card = info->card; 16822693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 16833aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby while (cyy_readb(info, CySRER) & CyTxRdy) { 168402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (msleep_interruptible(jiffies_to_msecs(char_time))) 168502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 168602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (timeout && time_after(jiffies, orig_jiffies + 168702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby timeout)) 168802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 168902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 169102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Run one more char cycle */ 169202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby msleep_interruptible(jiffies_to_msecs(char_time * 5)); 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1695978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Coxstatic void cy_flush_buffer(struct tty_struct *tty) 1696978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox{ 1697978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox struct cyclades_port *info = tty->driver_data; 1698978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox struct cyclades_card *card; 1699978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox int channel, retval; 1700978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox unsigned long flags; 1701978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox 1702978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox#ifdef CY_DEBUG_IO 1703978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line); 1704978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox#endif 1705978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox 1706978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox if (serial_paranoia_check(info, tty->name, "cy_flush_buffer")) 1707978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox return; 1708978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox 1709978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox card = info->card; 1710978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox channel = info->line - card->first_line; 1711978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox 1712978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox spin_lock_irqsave(&card->card_lock, flags); 1713978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; 1714978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox spin_unlock_irqrestore(&card->card_lock, flags); 1715978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox 17162693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (cy_is_Z(card)) { /* If it is a Z card, flush the on-board 1717978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox buffers as well */ 1718978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox spin_lock_irqsave(&card->card_lock, flags); 1719978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L); 1720978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox if (retval != 0) { 1721978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d " 1722978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox "was %x\n", info->line, retval); 1723978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox } 1724978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox spin_unlock_irqrestore(&card->card_lock, flags); 1725978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox } 1726978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox tty_wakeup(tty); 1727978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox} /* cy_flush_buffer */ 1728978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox 1729978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox 1730e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Coxstatic void cy_do_close(struct tty_port *port) 17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1732e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox struct cyclades_port *info = container_of(port, struct cyclades_port, 1733e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox port); 17349fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby struct cyclades_card *card; 173502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 17363aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby int channel; 17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17389fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby card = info->card; 17393aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby channel = info->line - card->first_line; 17409fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 174102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 17422693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 174302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Stop accepting input */ 17443aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel & 0x03); 17453aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyRxData); 174677451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (info->port.flags & ASYNC_INITIALIZED) { 174715ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox /* Waiting for on-board buffers to be empty before 174815ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox closing the port */ 17499fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 1750e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox cy_wait_until_sent(port->tty, info->timeout); 17519fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 175202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 175302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 175402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#ifdef Z_WAKE 175515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox /* Waiting for on-board buffers to be empty before closing 175615ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox the port */ 1757f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; 175802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int retval; 175902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 1760f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby if (readl(&ch_ctrl->flow_status) != C_FS_TXIDLE) { 17619fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L); 176202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 1763217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_close retval on " 1764217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "ttyC%d was %x\n", info->line, retval); 176502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 17669fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 17672c7fea992104b5ca2b510d585a27b3ba018b795fJiri Slaby wait_for_completion_interruptible(&info->shutdown_wait); 17689fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 176902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 177102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 17729fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 1773e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox cy_shutdown(info, port->tty); 1774e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox} 17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1776e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox/* 1777e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox * This routine is called when a particular tty device is closed. 1778e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox */ 1779e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Coxstatic void cy_close(struct tty_struct *tty, struct file *filp) 1780e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox{ 1781e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox struct cyclades_port *info = tty->driver_data; 1782e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox if (!info || serial_paranoia_check(info, tty->name, "cy_close")) 1783e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox return; 1784e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox tty_port_close(&info->port, tty, filp); 178502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_close */ 17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This routine gets called when tty_write has put something into 17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the write_queue. The characters may come from user space or 17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * kernel space. 17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine will return the number of characters actually 17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * accepted for writing. 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the port is not already transmitting stuff, start it off by 17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * enabling interrupts. The interrupt service routine will then 17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ensure that the characters are sent. 17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the port is already active, there is no need to kick it. 17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 180002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) 18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1802cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 180302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 180402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int c, ret = 0; 18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_IO 1807217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_write ttyC%d\n", info->line); 18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181015ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (serial_paranoia_check(info, tty->name, "cy_write")) 181102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181377451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (!info->port.xmit_buf) 181402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18169fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&info->card->card_lock, flags); 181702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby while (1) { 18181a4e2351e7fcf2d10bb5524b0ace7797ffad4d98Harvey Harrison c = min(count, (int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1)); 18191a4e2351e7fcf2d10bb5524b0ace7797ffad4d98Harvey Harrison c = min(c, (int)(SERIAL_XMIT_SIZE - info->xmit_head)); 182002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 182102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (c <= 0) 182202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 182302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 182477451e53e0a509a98eda272567869cfe96431ba9Alan Cox memcpy(info->port.xmit_buf + info->xmit_head, buf, c); 182502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->xmit_head = (info->xmit_head + c) & 182602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (SERIAL_XMIT_SIZE - 1); 182702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->xmit_cnt += c; 182802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby buf += c; 182902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby count -= c; 183002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret += c; 183102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 18329fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&info->card->card_lock, flags); 183302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 183402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->idle_stats.xmit_bytes += ret; 183502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->idle_stats.xmit_idle = jiffies; 183602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 183715ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) 183802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby start_xmit(info); 183915ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox 184002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return ret; 184102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_write */ 18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine is called by the kernel to write a single 18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * character to the tty device. If the kernel uses this routine, 18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it must call the flush_chars() routine (if defined) when it is 18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * done stuffing characters into the driver. If there is no room 18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in the queue, the character is ignored. 18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 185076b25a5509bbafdbfc7d7d6b41a3c64947d59360Alan Coxstatic int cy_put_char(struct tty_struct *tty, unsigned char ch) 18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1852cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 185302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_IO 1856217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_put_char ttyC%d\n", info->line); 18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 185902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_put_char")) 186076b25a5509bbafdbfc7d7d6b41a3c64947d59360Alan Cox return 0; 18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 186277451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (!info->port.xmit_buf) 186376b25a5509bbafdbfc7d7d6b41a3c64947d59360Alan Cox return 0; 18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18659fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&info->card->card_lock, flags); 186690cc301859ea8840634324a7f5b9680312377667Jiri Slaby if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) { 18679fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&info->card->card_lock, flags); 186876b25a5509bbafdbfc7d7d6b41a3c64947d59360Alan Cox return 0; 186902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 187177451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.xmit_buf[info->xmit_head++] = ch; 187202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->xmit_head &= SERIAL_XMIT_SIZE - 1; 187302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->xmit_cnt++; 18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->idle_stats.xmit_bytes++; 18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->idle_stats.xmit_idle = jiffies; 18769fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&info->card->card_lock, flags); 187776b25a5509bbafdbfc7d7d6b41a3c64947d59360Alan Cox return 1; 187802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_put_char */ 18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine is called by the kernel after it has written a 188215ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox * series of characters to the tty device using put_char(). 18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 188402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_flush_chars(struct tty_struct *tty) 18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1886cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 188702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_IO 1889217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_flush_chars ttyC%d\n", info->line); 18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 189202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) 189302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 189502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || 189677451e53e0a509a98eda272567869cfe96431ba9Alan Cox !info->port.xmit_buf) 189702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 189902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby start_xmit(info); 190002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_flush_chars */ 19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine returns the numbers of characters the tty driver 19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * will accept for queuing to be written. This number is subject 19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to change as output buffers get emptied, or if the output flow 19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * control is activated. 19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 190802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int cy_write_room(struct tty_struct *tty) 19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1910cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 191102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int ret; 191202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_IO 1914217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_write_room ttyC%d\n", info->line); 19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 191702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_write_room")) 191802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 191902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; 192002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (ret < 0) 192102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret = 0; 192202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return ret; 192302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_write_room */ 19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 192502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int cy_chars_in_buffer(struct tty_struct *tty) 19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1927cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 192902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) 193002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 193102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef Z_EXT_CHARS_IN_BUFFER 1933f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby if (!cy_is_Z(info->card)) { 193402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* Z_EXT_CHARS_IN_BUFFER */ 19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_IO 1936217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", 1937217191910c0286e0b3c7e3011630273695253da3Jiri Slaby info->line, info->xmit_cnt); 19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 193902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return info->xmit_cnt; 19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef Z_EXT_CHARS_IN_BUFFER 194102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 1942f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl; 194302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int char_count; 1944ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby __u32 tx_put, tx_get, tx_bufsize; 194502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 1946db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby tx_get = readl(&buf_ctrl->tx_get); 1947db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby tx_put = readl(&buf_ctrl->tx_put); 1948db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby tx_bufsize = readl(&buf_ctrl->tx_bufsize); 194902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (tx_put >= tx_get) 195002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_count = tx_put - tx_get; 195102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else 195202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_count = tx_put - tx_get + tx_bufsize; 19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_IO 1954217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", 1955217191910c0286e0b3c7e3011630273695253da3Jiri Slaby info->line, info->xmit_cnt + char_count); 19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1957096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return info->xmit_cnt + char_count; 195802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 195902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* Z_EXT_CHARS_IN_BUFFER */ 196002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_chars_in_buffer */ 19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ------------------------------------------------------------ 19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cy_ioctl() and friends 19651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ------------------------------------------------------------ 19661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19681a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielkastatic void cyy_baud_calc(struct cyclades_port *info, __u32 baud) 19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 197002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int co, co_val, bpr; 19711a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka __u32 cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : 197202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 25000000); 19731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 197402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (baud == 0) { 197502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->tbpr = info->tco = info->rbpr = info->rco = 0; 197602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 197702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 197902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* determine which prescaler to use */ 198002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for (co = 4, co_val = 2048; co; co--, co_val >>= 2) { 198102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cy_clock / co_val / baud > 63) 198202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 198302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 198502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby bpr = (cy_clock / co_val * 2 / baud + 1) / 2; 198602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (bpr > 255) 198702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby bpr = 255; 19881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 198902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->tbpr = info->rbpr = bpr; 199002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->tco = info->rco = co; 19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine finds or computes the various line characteristics. 19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * It used to be called config_setup 19961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1997d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slabystatic void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty) 19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1999875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card; 200002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 20013aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby int channel; 200202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned cflag, iflag; 200302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int baud, baud_rate = 0; 200402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int i; 200502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 2006d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if (!tty->termios) /* XXX can this happen at all? */ 200702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 200815ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox 200915ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (info->line == -1) 201002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 201115ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox 2012d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby cflag = tty->termios->c_cflag; 2013d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby iflag = tty->termios->c_iflag; 20141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 201602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * Set up the tty->alt_speed kludge 201702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 2018d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) 2019d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty->alt_speed = 57600; 2020d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) 2021d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty->alt_speed = 115200; 2022d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) 2023d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty->alt_speed = 230400; 2024d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) 2025d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty->alt_speed = 460800; 202602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 202702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby card = info->card; 2028875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby channel = info->line - card->first_line; 202902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 20302693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 203146fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby u32 cflags; 203246fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby 203302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* baud rate */ 2034d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby baud = tty_get_baud_rate(tty); 203577451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == 203602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ASYNC_SPD_CUST) { 203702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->custom_divisor) 203802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud_rate = info->baud / info->custom_divisor; 203902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else 204002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud_rate = info->baud; 204102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else if (baud > CD1400_MAX_SPEED) { 204202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud = CD1400_MAX_SPEED; 204302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 204402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* find the baud index */ 204502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for (i = 0; i < 20; i++) { 204615ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (baud == baud_table[i]) 204702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 204802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 204915ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (i == 20) 205002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby i = 19; /* CD1400_MAX_SPEED */ 205102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 205277451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == 205302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ASYNC_SPD_CUST) { 205402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cyy_baud_calc(info, baud_rate); 205502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 205602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->chip_rev >= CD1400_REV_J) { 205702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* It is a CD1400 rev. J or later */ 205802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->tbpr = baud_bpr_60[i]; /* Tx BPR */ 205902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->tco = baud_co_60[i]; /* Tx CO */ 206002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->rbpr = baud_bpr_60[i]; /* Rx BPR */ 206102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->rco = baud_co_60[i]; /* Rx CO */ 206202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 206302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->tbpr = baud_bpr_25[i]; /* Tx BPR */ 206402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->tco = baud_co_25[i]; /* Tx CO */ 206502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->rbpr = baud_bpr_25[i]; /* Rx BPR */ 206602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->rco = baud_co_25[i]; /* Rx CO */ 206702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 206802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 206902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (baud_table[i] == 134) { 207002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* get it right for 134.5 baud */ 207102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) + 207202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 2; 207377451e53e0a509a98eda272567869cfe96431ba9Alan Cox } else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == 207402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ASYNC_SPD_CUST) { 207502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->timeout = (info->xmit_fifo_size * HZ * 15 / 207602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud_rate) + 2; 207702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else if (baud_table[i]) { 207802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->timeout = (info->xmit_fifo_size * HZ * 15 / 207902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud_table[i]) + 2; 208002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* this needs to be propagated into the card info */ 208102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 208202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->timeout = 0; 208302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 208402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* By tradition (is it a standard?) a baud rate of zero 208502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby implies the line should be/has been closed. A bit 208602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby later in this routine such a test is performed. */ 208702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 208802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* byte size and parity */ 208902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor5 = 0; 209002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor4 = 0; 209102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* receive threshold */ 209202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor3 = (info->default_threshold ? 209302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->default_threshold : baud_cor3[i]); 209402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor2 = CyETC; 209502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby switch (cflag & CSIZE) { 209602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CS5: 209702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor1 = Cy_5_BITS; 209802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 209902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CS6: 210002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor1 = Cy_6_BITS; 210102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 210202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CS7: 210302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor1 = Cy_7_BITS; 210402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 210502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CS8: 210602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor1 = Cy_8_BITS; 210702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 210802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 210915ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (cflag & CSTOPB) 211002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor1 |= Cy_2_STOP; 211115ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox 211202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cflag & PARENB) { 211315ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (cflag & PARODD) 211402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor1 |= CyPARITY_O; 211515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox else 211602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor1 |= CyPARITY_E; 211715ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox } else 211802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor1 |= CyPARITY_NONE; 211902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 212002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* CTS flow control flag */ 212102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cflag & CRTSCTS) { 212277451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags |= ASYNC_CTS_FLOW; 212302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor2 |= CyCtsAE; 212402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 212577451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags &= ~ASYNC_CTS_FLOW; 212602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor2 &= ~CyCtsAE; 212702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 212802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cflag & CLOCAL) 212977451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags &= ~ASYNC_CHECK_CD; 213002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else 213177451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags |= ASYNC_CHECK_CD; 21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /*********************************************** 21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The hardware option, CyRtsAO, presents RTS when 21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the chip has characters to send. Since most modems 21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds use RTS as reverse (inbound) flow control, this 21371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds option is not used. If inbound flow control is 21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds necessary, DTR can be programmed to provide the 21391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds appropriate signals for use with a non-standard 21401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cable. Contact Marcio Saito for details. 21411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ***********************************************/ 21421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 214302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby channel &= 0x03; 21441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21459fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 21463aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel); 214702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 214802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* tx and rx baud rate */ 214902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 21503aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyTCOR, info->tco); 21513aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyTBPR, info->tbpr); 21523aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyRCOR, info->rco); 21533aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyRBPR, info->rbpr); 215402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 215502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* set line characteristics according configuration */ 215602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 21573aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySCHR1, START_CHAR(tty)); 21583aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySCHR2, STOP_CHAR(tty)); 21593aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCOR1, info->cor1); 21603aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCOR2, info->cor2); 21613aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCOR3, info->cor3); 21623aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCOR4, info->cor4); 21633aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCOR5, info->cor5); 216402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 21653aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch | 21663aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby CyCOR3ch); 216702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 216815ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox /* !!! Is this needed? */ 21693aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel); 21703aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyRTPR, 217102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (info->default_timeout ? info->default_timeout : 0x02)); 217202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 10ms rx timeout */ 217302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 217446fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby cflags = CyCTS; 217546fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby if (!C_CLOCAL(tty)) 217646fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby cflags |= CyDSR | CyRI | CyDCD; 217746fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby /* without modem intr */ 217846fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyMdmCh); 217946fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby /* act on 1->0 modem transitions */ 218046fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby if ((cflag & CRTSCTS) && info->rflow) 218146fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby cyy_writeb(info, CyMCOR1, cflags | rflow_thr[i]); 218246fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby else 218346fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby cyy_writeb(info, CyMCOR1, cflags); 218446fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby /* act on 0->1 modem transitions */ 218546fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby cyy_writeb(info, CyMCOR2, cflags); 218602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 21874d7682005ca88a37667c4af03908798e188b5224Jiri Slaby if (i == 0) /* baud rate is zero, turn off line */ 21884d7682005ca88a37667c4af03908798e188b5224Jiri Slaby cyy_change_rts_dtr(info, 0, TIOCM_DTR); 21894d7682005ca88a37667c4af03908798e188b5224Jiri Slaby else 21904d7682005ca88a37667c4af03908798e188b5224Jiri Slaby cyy_change_rts_dtr(info, TIOCM_DTR, 0); 21911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2192d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby clear_bit(TTY_IO_ERROR, &tty->flags); 21939fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 21941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2196f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; 21971a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka __u32 sw_flow; 219802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int retval; 21991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22002693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cyz_is_loaded(card)) 220102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 22021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 220302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* baud rate */ 2204d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby baud = tty_get_baud_rate(tty); 220577451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == 220602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ASYNC_SPD_CUST) { 220702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->custom_divisor) 220802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud_rate = info->baud / info->custom_divisor; 220902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else 221002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud_rate = info->baud; 221102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else if (baud > CYZ_MAX_SPEED) { 221202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud = CYZ_MAX_SPEED; 221302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 221402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_baud, baud); 221502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 221602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (baud == 134) { 221702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* get it right for 134.5 baud */ 221802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) + 221902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 2; 222077451e53e0a509a98eda272567869cfe96431ba9Alan Cox } else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == 222102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ASYNC_SPD_CUST) { 222202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->timeout = (info->xmit_fifo_size * HZ * 15 / 222302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud_rate) + 2; 222402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else if (baud) { 222502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->timeout = (info->xmit_fifo_size * HZ * 15 / 222602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud) + 2; 222702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* this needs to be propagated into the card info */ 222802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 222902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->timeout = 0; 223002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 22311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 223202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* byte size and parity */ 223302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby switch (cflag & CSIZE) { 223402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CS5: 223502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_data_l, C_DL_CS5); 223602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 223702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CS6: 223802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_data_l, C_DL_CS6); 223902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 224002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CS7: 224102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_data_l, C_DL_CS7); 224202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 224302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CS8: 224402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_data_l, C_DL_CS8); 224502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 224602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 224702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cflag & CSTOPB) { 224802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_data_l, 2249db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby readl(&ch_ctrl->comm_data_l) | C_DL_2STOP); 225002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 225102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_data_l, 2252db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby readl(&ch_ctrl->comm_data_l) | C_DL_1STOP); 225302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 225402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cflag & PARENB) { 225515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (cflag & PARODD) 225602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_parity, C_PR_ODD); 225715ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox else 225802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN); 225915ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox } else 226002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_parity, C_PR_NONE); 22611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 226202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* CTS flow control flag */ 226302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cflag & CRTSCTS) { 226402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->hw_flow, 2265db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS); 226602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 2267db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby cy_writel(&ch_ctrl->hw_flow, readl(&ch_ctrl->hw_flow) & 2268db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby ~(C_RS_CTS | C_RS_RTS)); 226902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 227002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* As the HW flow control is done in firmware, the driver 227102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby doesn't need to care about it */ 227277451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags &= ~ASYNC_CTS_FLOW; 227302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 227402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* XON/XOFF/XANY flow control flags */ 227502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby sw_flow = 0; 227602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (iflag & IXON) { 227702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby sw_flow |= C_FL_OXX; 227802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (iflag & IXANY) 227902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby sw_flow |= C_FL_OIXANY; 228002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 228102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->sw_flow, sw_flow); 228202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 2283875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L); 228402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 2285217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:set_line_char retval on ttyC%d " 2286217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "was %x\n", info->line, retval); 228702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 228802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 228902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* CD sensitivity */ 229015ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (cflag & CLOCAL) 229177451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags &= ~ASYNC_CHECK_CD; 229215ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox else 229377451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags |= ASYNC_CHECK_CD; 22941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 229502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (baud == 0) { /* baud rate is zero, turn off line */ 229602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->rs_control, 2297db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby readl(&ch_ctrl->rs_control) & ~C_RS_DTR); 22981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_DTR 2299217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:set_line_char dropping Z DTR\n"); 23001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 230102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 230202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->rs_control, 2303db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby readl(&ch_ctrl->rs_control) | C_RS_DTR); 23041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_DTR 2305217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:set_line_char raising Z DTR\n"); 23061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 230702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 23081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 230915ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); 231002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 2311217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:set_line_char(2) retval on ttyC%d " 2312217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "was %x\n", info->line, retval); 231302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 23141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2315d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby clear_bit(TTY_IO_ERROR, &tty->flags); 23161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 231702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* set_line_char */ 23181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23196c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slabystatic int cy_get_serial_info(struct cyclades_port *info, 232015ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox struct serial_struct __user *retinfo) 23211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2322875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *cinfo = info->card; 23236c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby struct serial_struct tmp = { 23246c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .type = info->type, 23256c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .line = info->line, 23266c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .port = (info->card - cy_card) * 0x100 + info->line - 23276c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby cinfo->first_line, 23286c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .irq = cinfo->irq, 23296c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .flags = info->port.flags, 23306c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .close_delay = info->port.close_delay, 23316c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .closing_wait = info->port.closing_wait, 23326c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .baud_base = info->baud, 23336c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .custom_divisor = info->custom_divisor, 23346c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .hub6 = 0, /*!!! */ 23356c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby }; 233602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; 23376c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby} 23381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 2340d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slabycy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty, 234115ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox struct serial_struct __user *new_info) 23421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 234302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby struct serial_struct new_serial; 234425c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox int ret; 234502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 234602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) 234702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -EFAULT; 234802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 234925c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox mutex_lock(&info->port.mutex); 235002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!capable(CAP_SYS_ADMIN)) { 235144b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox if (new_serial.close_delay != info->port.close_delay || 235202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby new_serial.baud_base != info->baud || 235302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (new_serial.flags & ASYNC_FLAGS & 235402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ~ASYNC_USR_MASK) != 235577451e53e0a509a98eda272567869cfe96431ba9Alan Cox (info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)) 235625c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox { 235725c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox mutex_unlock(&info->port.mutex); 235802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -EPERM; 235925c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox } 236077451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) | 236102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (new_serial.flags & ASYNC_USR_MASK); 236202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->baud = new_serial.baud_base; 236302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->custom_divisor = new_serial.custom_divisor; 236402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby goto check_and_exit; 236502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 236602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 236702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 236802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * OK, past this point, all the error checking has been done. 236902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * At this point, we start making changes..... 237002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 237102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 237202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->baud = new_serial.baud_base; 237302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->custom_divisor = new_serial.custom_divisor; 237477451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags = (info->port.flags & ~ASYNC_FLAGS) | 237502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (new_serial.flags & ASYNC_FLAGS); 237644b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox info->port.close_delay = new_serial.close_delay * HZ / 100; 237744b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox info->port.closing_wait = new_serial.closing_wait * HZ / 100; 23781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscheck_and_exit: 238077451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (info->port.flags & ASYNC_INITIALIZED) { 2381d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby cy_set_line_char(info, tty); 238225c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox ret = 0; 238302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 238425c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox ret = cy_startup(info, tty); 238502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 238625c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox mutex_unlock(&info->port.mutex); 238725c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox return ret; 238802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* set_serial_info */ 23891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 23911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get_lsr_info - get line status register info 23921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 23931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose: Let user call ioctl() to get info when the UART physically 23941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is emptied. On bus types like RS485, the transmitter must 23951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * release the bus after transmitting. This must be done when 23961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the transmit shift register is empty, not be done when the 23971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transmit holding register is empty. This functionality 23981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allows an RS485 driver to be written in user space. 23991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 240015ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Coxstatic int get_lsr_info(struct cyclades_port *info, unsigned int __user *value) 24011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24023aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby struct cyclades_card *card = info->card; 240302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned int result; 240402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 24053aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby u8 status; 24061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24072693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 24089fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 24093aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby status = cyy_readb(info, CySRER) & (CyTxRdy | CyTxMpty); 24109fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 241102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby result = (status ? 0 : TIOCSER_TEMT); 241202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 241302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Not supported yet */ 241402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -EINVAL; 241502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 241602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return put_user(result, (unsigned long __user *)value); 24171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241960b33c133ca0b7c0b6072c87234b63fee6e80558Alan Coxstatic int cy_tiocmget(struct tty_struct *tty) 24201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2421cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 2422875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card; 24233aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby int result; 242402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 2425bf9d89295233ae2ba7b312c78ee5657307b09f4cHarvey Harrison if (serial_paranoia_check(info, tty->name, __func__)) 242602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENODEV; 24271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 242802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby card = info->card; 24290d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby 24302693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 24310d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby unsigned long flags; 24323aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby int channel = info->line - card->first_line; 24333aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby u8 status; 24341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24359fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 24363aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel & 0x03); 24373aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby status = cyy_readb(info, CyMSVR1); 24383aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby status |= cyy_readb(info, CyMSVR2); 24399fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 244002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 244102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->rtsdtr_inv) { 244202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby result = ((status & CyRTS) ? TIOCM_DTR : 0) | 244302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ((status & CyDTR) ? TIOCM_RTS : 0); 244402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 244502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby result = ((status & CyRTS) ? TIOCM_RTS : 0) | 244602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ((status & CyDTR) ? TIOCM_DTR : 0); 244702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 244802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby result |= ((status & CyDCD) ? TIOCM_CAR : 0) | 244902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ((status & CyRI) ? TIOCM_RNG : 0) | 245002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ((status & CyDSR) ? TIOCM_DSR : 0) | 245102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ((status & CyCTS) ? TIOCM_CTS : 0); 24521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 24530d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby u32 lstatus; 24540d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby 24550d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby if (!cyz_is_loaded(card)) { 24560d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby result = -ENODEV; 24570d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby goto end; 245802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 24591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24600d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby lstatus = readl(&info->u.cyz.ch_ctrl->rs_status); 24610d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) | 24620d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) | 24630d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) | 24640d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby ((lstatus & C_RS_RI) ? TIOCM_RNG : 0) | 24650d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby ((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) | 24660d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); 246702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 24680d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slabyend: 246902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return result; 247002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_tiomget */ 24711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 247320b9d17715017ae4dd4ec87fabc36d33b9de708eAlan Coxcy_tiocmset(struct tty_struct *tty, 247402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned int set, unsigned int clear) 24751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2476cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 2477875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card; 247802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 247902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 2480bf9d89295233ae2ba7b312c78ee5657307b09f4cHarvey Harrison if (serial_paranoia_check(info, tty->name, __func__)) 248102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENODEV; 248202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 248302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby card = info->card; 24842693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 24854d7682005ca88a37667c4af03908798e188b5224Jiri Slaby spin_lock_irqsave(&card->card_lock, flags); 24864d7682005ca88a37667c4af03908798e188b5224Jiri Slaby cyy_change_rts_dtr(info, set, clear); 24874d7682005ca88a37667c4af03908798e188b5224Jiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 248802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 24890d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; 24900d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby int retval, channel = info->line - card->first_line; 24910d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby u32 rs; 24920d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby 24930d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby if (!cyz_is_loaded(card)) 24940d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby return -ENODEV; 24950d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby 24960d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby spin_lock_irqsave(&card->card_lock, flags); 24970d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby rs = readl(&ch_ctrl->rs_control); 24980d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby if (set & TIOCM_RTS) 24990d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby rs |= C_RS_RTS; 25000d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby if (clear & TIOCM_RTS) 25010d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby rs &= ~C_RS_RTS; 25020d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby if (set & TIOCM_DTR) { 25030d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby rs |= C_RS_DTR; 25041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_DTR 25050d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby printk(KERN_DEBUG "cyc:set_modem_info raising Z DTR\n"); 25061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 25070d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby } 25080d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby if (clear & TIOCM_DTR) { 25090d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby rs &= ~C_RS_DTR; 25101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_DTR 25110d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby printk(KERN_DEBUG "cyc:set_modem_info clearing " 25120d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby "Z DTR\n"); 25131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 251402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 25150d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby cy_writel(&ch_ctrl->rs_control, rs); 25169fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); 25170d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 251802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 2519217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d " 2520217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "was %x\n", info->line, retval); 252102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 252302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 25240d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby} 25251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 25271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cy_break() --- routine which turns the break handling on or off 25281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 25299e98966c7bb94355689478bc84cc3e0c190f977eAlan Coxstatic int cy_break(struct tty_struct *tty, int break_state) 25301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2531cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 25329fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby struct cyclades_card *card; 253302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 25349e98966c7bb94355689478bc84cc3e0c190f977eAlan Cox int retval = 0; 25351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 253602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_break")) 25379e98966c7bb94355689478bc84cc3e0c190f977eAlan Cox return -EINVAL; 25381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25399fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby card = info->card; 25409fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby 25419fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 25422693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 254302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Let the transmit ISR take care of this (since it 254402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby requires stuffing characters into the output stream). 254502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 254602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (break_state == -1) { 254702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!info->breakon) { 254802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->breakon = 1; 254902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!info->xmit_cnt) { 25509fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 255102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby start_xmit(info); 25529fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 255302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 255402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 255502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 255602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!info->breakoff) { 255702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->breakoff = 1; 255802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!info->xmit_cnt) { 25599fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 256002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby start_xmit(info); 25619fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 256202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 256302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 25641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 256602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (break_state == -1) { 25679fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby retval = cyz_issue_cmd(card, 25689fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby info->line - card->first_line, 256902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby C_CM_SET_BREAK, 0L); 257002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 2571217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:cy_break (set) retval on " 2572217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "ttyC%d was %x\n", info->line, retval); 257302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 257402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 25759fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby retval = cyz_issue_cmd(card, 25769fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby info->line - card->first_line, 257702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby C_CM_CLR_BREAK, 0L); 257802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 2579217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_break (clr) retval " 2580217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "on ttyC%d was %x\n", info->line, 2581217191910c0286e0b3c7e3011630273695253da3Jiri Slaby retval); 258202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 25831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25859fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 25869e98966c7bb94355689478bc84cc3e0c190f977eAlan Cox return retval; 258702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_break */ 25881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 258902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int set_threshold(struct cyclades_port *info, unsigned long value) 25901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25913aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby struct cyclades_card *card = info->card; 259202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 25931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25942693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 259502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor3 &= ~CyREC_FIFO; 259602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor3 |= value & CyREC_FIFO; 25971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25989fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 25993aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCOR3, info->cor3); 26003aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR3ch); 26019fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 260202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 260302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 260402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* set_threshold */ 26051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 260615ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Coxstatic int get_threshold(struct cyclades_port *info, 260715ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox unsigned long __user *value) 26081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26093aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby struct cyclades_card *card = info->card; 26101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26112693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 26123aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby u8 tmp = cyy_readb(info, CyCOR3) & CyREC_FIFO; 261302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return put_user(tmp, value); 261402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 2615f742903424aae3fc7ea7079a3618d90634c0b301Jiri Slaby return 0; 261602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* get_threshold */ 26171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int set_timeout(struct cyclades_port *info, unsigned long value) 26191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26203aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby struct cyclades_card *card = info->card; 262102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 26221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26232693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 26249fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 26253aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyRTPR, value & 0xff); 26269fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 262702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 262802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 262902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* set_timeout */ 26301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 263115ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Coxstatic int get_timeout(struct cyclades_port *info, 263215ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox unsigned long __user *value) 26331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26343aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby struct cyclades_card *card = info->card; 26351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26362693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 26373aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby u8 tmp = cyy_readb(info, CyRTPR); 263802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return put_user(tmp, value); 263902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 2640f742903424aae3fc7ea7079a3618d90634c0b301Jiri Slaby return 0; 264102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* get_timeout */ 26421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26436c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slabystatic int cy_cflags_changed(struct cyclades_port *info, unsigned long arg, 26446c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby struct cyclades_icount *cprev) 26451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26466c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby struct cyclades_icount cnow; 26476c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby unsigned long flags; 26486c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby int ret; 26491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26506c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby spin_lock_irqsave(&info->card->card_lock, flags); 26516c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby cnow = info->icount; /* atomic copy */ 26526c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby spin_unlock_irqrestore(&info->card->card_lock, flags); 26536c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby 26546c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby ret = ((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) || 26556c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby ((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) || 26566c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby ((arg & TIOCM_CD) && (cnow.dcd != cprev->dcd)) || 26576c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby ((arg & TIOCM_CTS) && (cnow.cts != cprev->cts)); 26586c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby 26596c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby *cprev = cnow; 26606c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby 26616c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby return ret; 26626c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby} 26631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 26651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine allows the tty driver to implement device- 26661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * specific ioctl's. If the ioctl number passed in cmd is 26671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * not recognized by the driver, it should return ENOIOCTLCMD. 26681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 26691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 26706caa76b7786891b42b66a0e61e2c2fff2c884620Alan Coxcy_ioctl(struct tty_struct *tty, 267102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned int cmd, unsigned long arg) 26721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2673cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 26746c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby struct cyclades_icount cnow; /* kernel counter temps */ 267502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int ret_val = 0; 267602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 267702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby void __user *argp = (void __user *)arg; 267802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 267902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_ioctl")) 268002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENODEV; 26811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OTHER 2683217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", 2684217191910c0286e0b3c7e3011630273695253da3Jiri Slaby info->line, cmd, arg); 26851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 26861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 268702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby switch (cmd) { 268802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYGETMON: 26896c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby if (copy_to_user(argp, &info->mon, sizeof(info->mon))) { 26906c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby ret_val = -EFAULT; 26916c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby break; 26926c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby } 26936c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby memset(&info->mon, 0, sizeof(info->mon)); 269402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 269502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYGETTHRESH: 269602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = get_threshold(info, argp); 269702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 269802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYSETTHRESH: 269902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = set_threshold(info, arg); 270002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 270102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYGETDEFTHRESH: 27026c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby ret_val = put_user(info->default_threshold, 27036c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby (unsigned long __user *)argp); 270402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 270502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYSETDEFTHRESH: 27066c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby info->default_threshold = arg & 0x0f; 270702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 270802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYGETTIMEOUT: 270902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = get_timeout(info, argp); 271002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 271102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYSETTIMEOUT: 271202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = set_timeout(info, arg); 271302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 271402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYGETDEFTIMEOUT: 27156c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby ret_val = put_user(info->default_timeout, 27166c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby (unsigned long __user *)argp); 271702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 271802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYSETDEFTIMEOUT: 27196c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby info->default_timeout = arg & 0xff; 272002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 27211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYSETRFLOW: 272202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->rflow = (int)arg; 272302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 27241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYGETRFLOW: 272502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = info->rflow; 272602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 27271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYSETRTSDTR_INV: 272802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->rtsdtr_inv = (int)arg; 272902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 27301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYGETRTSDTR_INV: 273102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = info->rtsdtr_inv; 273202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 27331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYGETCD1400VER: 273402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = info->chip_rev; 273502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 27361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_CYZ_INTR 27371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYZSETPOLLCYCLE: 273802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cyz_polling_cycle = (arg * HZ) / 1000; 273902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 27401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYZGETPOLLCYCLE: 274102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = (cyz_polling_cycle * 1000) / HZ; 274202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 274302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_CYZ_INTR */ 27441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYSETWAIT: 274544b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox info->port.closing_wait = (unsigned short)arg * HZ / 100; 274602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 27471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYGETWAIT: 274844b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox ret_val = info->port.closing_wait / (HZ / 100); 274902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 275002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case TIOCGSERIAL: 27516c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby ret_val = cy_get_serial_info(info, argp); 275202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 275302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case TIOCSSERIAL: 2754d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby ret_val = cy_set_serial_info(info, tty, argp); 275502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 275602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case TIOCSERGETLSR: /* Get line status register */ 275702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = get_lsr_info(info, argp); 275802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 275902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 276002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change 276102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * - mask passed in arg for lines of interest 276202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) 276302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * Caller should use TIOCGICOUNT to see which one it was 276402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 27651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TIOCMIWAIT: 27669fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&info->card->card_lock, flags); 276702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* note the counters on entry */ 27682c7fea992104b5ca2b510d585a27b3ba018b795fJiri Slaby cnow = info->icount; 27699fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&info->card->card_lock, flags); 2770bdc04e3174e18f475289fa8f4144f66686326b7eAlan Cox ret_val = wait_event_interruptible(info->port.delta_msr_wait, 27716c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby cy_cflags_changed(info, arg, &cnow)); 27722c7fea992104b5ca2b510d585a27b3ba018b795fJiri Slaby break; 27731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 277402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 277502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) 277602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * Return: write counters to the user passed counter struct 277702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * NB: both 1->0 and 0->1 transitions are counted except for 277802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * RI where only 0->1 is counted. 277902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 278002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby default: 278102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = -ENOIOCTLCMD; 278202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 27831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OTHER 2785217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_ioctl done\n"); 27861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 278702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return ret_val; 278802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_ioctl */ 27891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27900587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Coxstatic int cy_get_icount(struct tty_struct *tty, 27910587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox struct serial_icounter_struct *sic) 27920587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox{ 27930587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox struct cyclades_port *info = tty->driver_data; 27940587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox struct cyclades_icount cnow; /* Used to snapshot */ 27950587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox unsigned long flags; 27960587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox 27970587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox spin_lock_irqsave(&info->card->card_lock, flags); 27980587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox cnow = info->icount; 27990587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox spin_unlock_irqrestore(&info->card->card_lock, flags); 28000587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox 28010587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->cts = cnow.cts; 28020587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->dsr = cnow.dsr; 28030587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->rng = cnow.rng; 28040587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->dcd = cnow.dcd; 28050587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->rx = cnow.rx; 28060587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->tx = cnow.tx; 28070587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->frame = cnow.frame; 28080587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->overrun = cnow.overrun; 28090587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->parity = cnow.parity; 28100587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->brk = cnow.brk; 28110587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->buf_overrun = cnow.buf_overrun; 28120587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox return 0; 28130587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox} 28140587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox 28151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 28161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine allows the tty driver to be notified when 28171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * device's termios settings have changed. Note that a 28181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * well-designed tty driver should be prepared to accept the case 28191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * where old == NULL, and try to do something rational. 28201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 282102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) 28221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2823cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 28241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OTHER 2826217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line); 28271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 28281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2829d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby cy_set_line_char(info, tty); 283002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 283102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if ((old_termios->c_cflag & CRTSCTS) && 283202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby !(tty->termios->c_cflag & CRTSCTS)) { 283302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tty->hw_stopped = 0; 283402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_start(tty); 283502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 28361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 283702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 283802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * No need to wake up processes in open wait, since they 283902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * sample the CLOCAL flag once, and don't recheck it. 284002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * XXX It's not clear whether the current behavior is correct 284102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * or not. Hence, this may change..... 284202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 284302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!(old_termios->c_cflag & CLOCAL) && 284402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (tty->termios->c_cflag & CLOCAL)) 284577451e53e0a509a98eda272567869cfe96431ba9Alan Cox wake_up_interruptible(&info->port.open_wait); 28461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 284702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_set_termios */ 28481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This function is used to send a high-priority XON/XOFF character to 28501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the device. 28511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 285202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_send_xchar(struct tty_struct *tty, char ch) 28531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2854cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 2855875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card; 2856875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby int channel; 28571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 285802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_send_xchar")) 28591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 28601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 286102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->x_char = ch; 28621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch) 286402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_start(tty); 28651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card = info->card; 2867875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby channel = info->line - card->first_line; 28681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28692693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (cy_is_Z(card)) { 287002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (ch == STOP_CHAR(tty)) 2871875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L); 287202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else if (ch == START_CHAR(tty)) 2873875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby cyz_issue_cmd(card, channel, C_CM_SENDXON, 0L); 28741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 28751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 28761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This routine is called by the upper-layer tty layer to signal 28781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds that incoming characters should be throttled because the input 28791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffers are close to full. 28801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 288102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_throttle(struct tty_struct *tty) 28821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2883cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 2884875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card; 288502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 28861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_THROTTLE 288802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char buf[64]; 28891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2890217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d\n", tty_name(tty, buf), 289102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tty->ldisc.chars_in_buffer(tty), info->line); 28921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 28931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 289415ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (serial_paranoia_check(info, tty->name, "cy_throttle")) 289502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 289602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 289702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby card = info->card; 289802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 289902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (I_IXOFF(tty)) { 29002693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) 290102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_send_xchar(tty, STOP_CHAR(tty)); 290202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else 290302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->throttle = 1; 290402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 29051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 290602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (tty->termios->c_cflag & CRTSCTS) { 29072693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 29089fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 29094d7682005ca88a37667c4af03908798e188b5224Jiri Slaby cyy_change_rts_dtr(info, 0, TIOCM_RTS); 29109fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 291102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 291202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->throttle = 1; 291302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 291402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 291502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_throttle */ 29161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 29181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine notifies the tty driver that it should signal 29191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that characters can now be sent to the tty without fear of 29201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * overrunning the input buffers of the line disciplines. 29211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 292202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_unthrottle(struct tty_struct *tty) 29231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2924cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 2925875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card; 292602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 29271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_THROTTLE 292902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char buf[64]; 293002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 2931217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n", 293215ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox tty_name(tty, buf), tty_chars_in_buffer(tty), info->line); 29331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 29341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 293515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) 293602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 29371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 293802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (I_IXOFF(tty)) { 293902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->x_char) 294002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->x_char = 0; 294102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else 294202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_send_xchar(tty, START_CHAR(tty)); 29431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 294502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (tty->termios->c_cflag & CRTSCTS) { 294602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby card = info->card; 29472693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 29489fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 29494d7682005ca88a37667c4af03908798e188b5224Jiri Slaby cyy_change_rts_dtr(info, TIOCM_RTS, 0); 29509fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 295102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 295202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->throttle = 0; 295302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 295402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 295502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_unthrottle */ 29561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* cy_start and cy_stop provide software output flow control as a 29581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds function of XON/XOFF, software CTS, and other such stuff. 29591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 296002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_stop(struct tty_struct *tty) 29611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 296202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby struct cyclades_card *cinfo; 2963cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 29643aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby int channel; 296502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 29661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OTHER 2968217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_stop ttyC%d\n", info->line); 29691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 29701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 297102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_stop")) 297202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 29731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2974875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby cinfo = info->card; 297502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby channel = info->line - cinfo->first_line; 29762693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(cinfo)) { 29779fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&cinfo->card_lock, flags); 29783aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel & 0x03); 29793aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy); 29809fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&cinfo->card_lock, flags); 298102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 298202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_stop */ 29831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 298402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_start(struct tty_struct *tty) 29851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 298602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby struct cyclades_card *cinfo; 2987cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 29883aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby int channel; 298902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 29901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OTHER 2992217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_start ttyC%d\n", info->line); 29931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 29941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 299502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_start")) 299602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 29971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2998875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby cinfo = info->card; 299902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby channel = info->line - cinfo->first_line; 30002693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(cinfo)) { 30019fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&cinfo->card_lock, flags); 30023aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel & 0x03); 30033aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy); 30049fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&cinfo->card_lock, flags); 300502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 300602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_start */ 30071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 30091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cy_hangup() --- called by tty_hangup() when a hangup is signaled. 30101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 301102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_hangup(struct tty_struct *tty) 30121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3013cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 301402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 30151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OTHER 3016217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_hangup ttyC%d\n", info->line); 30171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 30181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_hangup")) 302002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 30211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 302202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_flush_buffer(tty); 3023d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby cy_shutdown(info, tty); 3024174e6fe01e7881caaa350b5e98e4c6189b6cb593Jiri Slaby tty_port_hangup(&info->port); 302502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_hangup */ 30261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3027f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slabystatic int cyy_carrier_raised(struct tty_port *port) 3028f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby{ 3029f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby struct cyclades_port *info = container_of(port, struct cyclades_port, 3030f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby port); 3031f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby struct cyclades_card *cinfo = info->card; 3032f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby unsigned long flags; 3033f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby int channel = info->line - cinfo->first_line; 3034f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby u32 cd; 3035f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3036f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby spin_lock_irqsave(&cinfo->card_lock, flags); 30373aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel & 0x03); 30383aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cd = cyy_readb(info, CyMSVR1) & CyDCD; 3039f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby spin_unlock_irqrestore(&cinfo->card_lock, flags); 3040f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3041f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby return cd; 3042f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby} 3043f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3044f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slabystatic void cyy_dtr_rts(struct tty_port *port, int raise) 3045f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby{ 3046f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby struct cyclades_port *info = container_of(port, struct cyclades_port, 3047f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby port); 3048f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby struct cyclades_card *cinfo = info->card; 3049f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby unsigned long flags; 3050f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3051f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby spin_lock_irqsave(&cinfo->card_lock, flags); 30524d7682005ca88a37667c4af03908798e188b5224Jiri Slaby cyy_change_rts_dtr(info, raise ? TIOCM_RTS | TIOCM_DTR : 0, 30534d7682005ca88a37667c4af03908798e188b5224Jiri Slaby raise ? 0 : TIOCM_RTS | TIOCM_DTR); 3054f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby spin_unlock_irqrestore(&cinfo->card_lock, flags); 3055f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby} 3056f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3057f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slabystatic int cyz_carrier_raised(struct tty_port *port) 3058f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby{ 3059f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby struct cyclades_port *info = container_of(port, struct cyclades_port, 3060f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby port); 3061f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3062f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby return readl(&info->u.cyz.ch_ctrl->rs_status) & C_RS_DCD; 3063f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby} 3064f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3065f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slabystatic void cyz_dtr_rts(struct tty_port *port, int raise) 3066f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby{ 3067f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby struct cyclades_port *info = container_of(port, struct cyclades_port, 3068f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby port); 3069f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby struct cyclades_card *cinfo = info->card; 3070f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; 3071f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby int ret, channel = info->line - cinfo->first_line; 3072f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby u32 rs; 3073f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3074f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby rs = readl(&ch_ctrl->rs_control); 3075f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby if (raise) 3076f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby rs |= C_RS_RTS | C_RS_DTR; 3077f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby else 3078f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby rs &= ~(C_RS_RTS | C_RS_DTR); 3079f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby cy_writel(&ch_ctrl->rs_control, rs); 3080f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby ret = cyz_issue_cmd(cinfo, channel, C_CM_IOCTLM, 0L); 3081f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby if (ret != 0) 3082f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby printk(KERN_ERR "%s: retval on ttyC%d was %x\n", 3083f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby __func__, info->line, ret); 3084f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby#ifdef CY_DEBUG_DTR 3085f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby printk(KERN_DEBUG "%s: raising Z DTR\n", __func__); 3086f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby#endif 3087f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby} 3088f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3089f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slabystatic const struct tty_port_operations cyy_port_ops = { 3090f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby .carrier_raised = cyy_carrier_raised, 3091f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby .dtr_rts = cyy_dtr_rts, 3092e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox .shutdown = cy_do_close, 3093f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby}; 3094f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3095f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slabystatic const struct tty_port_operations cyz_port_ops = { 3096f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby .carrier_raised = cyz_carrier_raised, 3097f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby .dtr_rts = cyz_dtr_rts, 3098e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox .shutdown = cy_do_close, 3099f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby}; 3100f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 31011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 31021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * --------------------------------------------------------------------- 31031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cy_init() and friends 31041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cy_init() is called at boot-time to initialize the serial driver. 31061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * --------------------------------------------------------------------- 31071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 31081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3109dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slabystatic int __devinit cy_init_card(struct cyclades_card *cinfo) 31100809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby{ 31110809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby struct cyclades_port *info; 3112f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby unsigned int channel, port; 31130809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby 31143046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby spin_lock_init(&cinfo->card_lock); 3115963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby cinfo->intr_enabled = 0; 31163046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby 3117963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby cinfo->ports = kcalloc(cinfo->nports, sizeof(*cinfo->ports), 3118963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby GFP_KERNEL); 3119dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby if (cinfo->ports == NULL) { 3120dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby printk(KERN_ERR "Cyclades: cannot allocate ports\n"); 3121dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby return -ENOMEM; 3122dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby } 3123dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby 3124f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby for (channel = 0, port = cinfo->first_line; channel < cinfo->nports; 3125f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby channel++, port++) { 3126f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby info = &cinfo->ports[channel]; 312744b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox tty_port_init(&info->port); 31283046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby info->magic = CYCLADES_MAGIC; 3129875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby info->card = cinfo; 31303046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby info->line = port; 31313046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby 313244b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox info->port.closing_wait = CLOSING_WAIT_DELAY; 313344b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox info->port.close_delay = 5 * HZ / 10; 313477451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags = STD_COM_FLAGS; 31352c7fea992104b5ca2b510d585a27b3ba018b795fJiri Slaby init_completion(&info->shutdown_wait); 31363046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby 31372693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (cy_is_Z(cinfo)) { 3138f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct FIRM_ID *firm_id = cinfo->base_addr + ID_ADDRESS; 3139f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct ZFW_CTRL *zfw_ctrl; 3140f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby 3141f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby info->port.ops = &cyz_port_ops; 31420809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->type = PORT_STARTECH; 3143f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby 3144f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby zfw_ctrl = cinfo->base_addr + 3145f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby (readl(&firm_id->zfwctrl_addr) & 0xfffff); 3146f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby info->u.cyz.ch_ctrl = &zfw_ctrl->ch_ctrl[channel]; 3147f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby info->u.cyz.buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; 3148f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby 3149101b81590d8df0a74c33cf739886247c0a13f4afJiri Slaby if (cinfo->hw_ver == ZO_V1) 31500809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->xmit_fifo_size = CYZ_FIFO_SIZE; 31510809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby else 31523046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE; 31530809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby#ifdef CONFIG_CYZ_INTR 31543991428d9efc7185312196f82cc36e9df4a2ddb0Jiri Slaby setup_timer(&cyz_rx_full_timer[port], 31553991428d9efc7185312196f82cc36e9df4a2ddb0Jiri Slaby cyz_rx_restart, (unsigned long)info); 31560809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby#endif 31573046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby } else { 3158f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby unsigned short chip_number; 3159963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby int index = cinfo->bus_index; 3160f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby 3161f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby info->port.ops = &cyy_port_ops; 31620809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->type = PORT_CIRRUS; 31630809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->xmit_fifo_size = CyMAX_CHAR_FIFO; 31643046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; 31650809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->cor2 = CyETC; 31660809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->cor3 = 0x08; /* _very_ small rcv threshold */ 31673046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby 3168f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby chip_number = channel / CyPORTS_PER_CHIP; 31693aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby info->u.cyy.base_addr = cinfo->base_addr + 31703aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby (cy_chip_offset[chip_number] << index); 31713aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby info->chip_rev = cyy_readb(info, CyGFRCR); 317215ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox 317315ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (info->chip_rev >= CD1400_REV_J) { 31740809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby /* It is a CD1400 rev. J or later */ 31750809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->tbpr = baud_bpr_60[13]; /* Tx BPR */ 31760809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->tco = baud_co_60[13]; /* Tx CO */ 31770809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->rbpr = baud_bpr_60[13]; /* Rx BPR */ 31780809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->rco = baud_co_60[13]; /* Rx CO */ 31790809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->rtsdtr_inv = 1; 31800809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby } else { 31810809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->tbpr = baud_bpr_25[13]; /* Tx BPR */ 31820809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->tco = baud_co_25[13]; /* Tx CO */ 31830809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->rbpr = baud_bpr_25[13]; /* Rx BPR */ 31840809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->rco = baud_co_25[13]; /* Rx CO */ 31850809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->rtsdtr_inv = 0; 31860809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby } 31873046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby info->read_status_mask = CyTIMEOUT | CySPECHAR | 31883046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby CyBREAK | CyPARITY | CyFRAME | CyOVERRUN; 31890809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby } 31903046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby 31910809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby } 31923046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby 31933046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby#ifndef CONFIG_CYZ_INTR 31942693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (cy_is_Z(cinfo) && !timer_pending(&cyz_timerlist)) { 31953046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby mod_timer(&cyz_timerlist, jiffies + 1); 31963046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby#ifdef CY_PCI_DEBUG 31973046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby printk(KERN_DEBUG "Cyclades-Z polling initialized\n"); 31983046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby#endif 31993046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby } 32003046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby#endif 3201dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby return 0; 32020809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby} 32030809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby 32041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* initialize chips on Cyclom-Y card -- return number of valid 32051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chips (which is number of ports/4) */ 320631b4f0a118a7ade8444059ec898af8f07de206e9Jiri Slabystatic unsigned short __devinit cyy_init_card(void __iomem *true_base_addr, 320731b4f0a118a7ade8444059ec898af8f07de206e9Jiri Slaby int index) 32081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 320902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned int chip_number; 321002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby void __iomem *base_addr; 321102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 321202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(true_base_addr + (Cy_HwReset << index), 0); 321302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Cy_HwReset is 0x1400 */ 321402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(true_base_addr + (Cy_ClrIntr << index), 0); 321502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Cy_ClrIntr is 0x1800 */ 321602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby udelay(500L); 321702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 321815ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD; 321915ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox chip_number++) { 322002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby base_addr = 322102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby true_base_addr + (cy_chip_offset[chip_number] << index); 322202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby mdelay(1); 3223db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby if (readb(base_addr + (CyCCR << index)) != 0x00) { 322402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /************* 322502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby printk(" chip #%d at %#6lx is never idle (CCR != 0)\n", 322602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby chip_number, (unsigned long)base_addr); 322702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby *************/ 322802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return chip_number; 322902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 323002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 323102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(base_addr + (CyGFRCR << index), 0); 323202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby udelay(10L); 323302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 323402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* The Cyclom-16Y does not decode address bit 9 and therefore 323502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cannot distinguish between references to chip 0 and a non- 323602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby existent chip 4. If the preceding clearing of the supposed 323702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby chip 4 GFRCR register appears at chip 0, there is no chip 4 323802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby and this must be a Cyclom-16Y, not a Cyclom-32Ye. 323902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 3240db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby if (chip_number == 4 && readb(true_base_addr + 324102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (cy_chip_offset[0] << index) + 324202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (CyGFRCR << index)) == 0) { 324302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return chip_number; 324402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 324502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 324602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET); 324702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby mdelay(1); 324802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 3249db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby if (readb(base_addr + (CyGFRCR << index)) == 0x00) { 325002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 325102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby printk(" chip #%d at %#6lx is not responding ", 325202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby chip_number, (unsigned long)base_addr); 325302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby printk("(GFRCR stayed 0)\n", 325402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 325502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return chip_number; 325602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 3257db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby if ((0xf0 & (readb(base_addr + (CyGFRCR << index)))) != 325802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x40) { 325902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 326002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby printk(" chip #%d at %#6lx is not valid (GFRCR == " 326102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby "%#2x)\n", 326202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby chip_number, (unsigned long)base_addr, 326302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby base_addr[CyGFRCR<<index]); 326402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 326502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return chip_number; 326602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 326702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(base_addr + (CyGCR << index), CyCH0_SERIAL); 3268db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby if (readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) { 326902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* It is a CD1400 rev. J or later */ 327002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Impossible to reach 5ms with this chip. 327102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby Changed to 2ms instead (f = 500 Hz). */ 327202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(base_addr + (CyPPR << index), CyCLOCK_60_2MS); 327302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 327402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* f = 200 Hz */ 327502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(base_addr + (CyPPR << index), CyCLOCK_25_5MS); 327602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 32771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 327802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 327902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby printk(" chip #%d at %#6lx is rev 0x%2x\n", 328002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby chip_number, (unsigned long)base_addr, 3281db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby readb(base_addr+(CyGFRCR<<index))); 328202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 328302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 328402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return chip_number; 328502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cyy_init_card */ 32861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 32881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * --------------------------------------------------------------------- 32891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cy_detect_isa() - Probe for Cyclom-Y/ISA boards. 32901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sets global variables and return the number of ISA boards found. 32911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * --------------------------------------------------------------------- 32921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 329302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int __init cy_detect_isa(void) 32941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 32951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_ISA 329602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned short cy_isa_irq, nboard; 329702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby void __iomem *cy_isa_address; 329802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned short i, j, cy_isa_nchan; 329902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int isparam = 0; 33001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 330102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby nboard = 0; 33021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check for module parameters */ 330402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for (i = 0; i < NR_CARDS; i++) { 330502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (maddr[i] || i) { 330602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby isparam = 1; 330702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_isa_addresses[i] = maddr[i]; 330802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 330902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!maddr[i]) 331002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 33111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 33121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* scan the address table probing for Cyclom-Y/ISA boards */ 331402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for (i = 0; i < NR_ISA_ADDRS; i++) { 331502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned int isa_address = cy_isa_addresses[i]; 331615ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (isa_address == 0x0000) 3317096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return nboard; 33181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* probe for CD1400... */ 3320cd989b3a8c30148c872c7677c7a0415584f1658cAlan Cox cy_isa_address = ioremap_nocache(isa_address, CyISA_Ywin); 33213137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (cy_isa_address == NULL) { 33223137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby printk(KERN_ERR "Cyclom-Y/ISA: can't remap base " 33233137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "address\n"); 33243137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby continue; 33253137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 332602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_isa_nchan = CyPORTS_PER_CHIP * 332702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cyy_init_card(cy_isa_address, 0); 332802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cy_isa_nchan == 0) { 33293137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby iounmap(cy_isa_address); 333002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby continue; 333102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 33322090436357c20afad377a61c789f502c36d637deBartlomiej Zolnierkiewicz 3333196b3167efd13a02cdd34acc1a12316b9f45f41dRoel Kluin if (isparam && i < NR_CARDS && irq[i]) 333402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_isa_irq = irq[i]; 33351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 333602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* find out the board's irq by probing */ 333702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_isa_irq = detect_isa_irq(cy_isa_address); 333802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cy_isa_irq == 0) { 3339217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but the " 3340217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "IRQ could not be detected.\n", 334102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (unsigned long)cy_isa_address); 33423137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby iounmap(cy_isa_address); 334302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby continue; 334402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 334502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 334602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) { 3347217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no " 3348217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "more channels are available. Change NR_PORTS " 3349217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "in cyclades.c and recompile kernel.\n", 335002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (unsigned long)cy_isa_address); 33513137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby iounmap(cy_isa_address); 3352096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return nboard; 335302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 335402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* fill the next cy_card structure available */ 335502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for (j = 0; j < NR_CARDS; j++) { 3356f742903424aae3fc7ea7079a3618d90634c0b301Jiri Slaby if (cy_card[j].base_addr == NULL) 335702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 335802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 335902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (j == NR_CARDS) { /* no more cy_cards available */ 3360217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no " 3361217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "more cards can be used. Change NR_CARDS in " 3362217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "cyclades.c and recompile kernel.\n", 336302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (unsigned long)cy_isa_address); 33643137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby iounmap(cy_isa_address); 3365096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return nboard; 336602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 336702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 336802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* allocate IRQ */ 336902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (request_irq(cy_isa_irq, cyy_interrupt, 337002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) { 3371217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but " 3372217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "could not allocate IRQ#%d.\n", 3373217191910c0286e0b3c7e3011630273695253da3Jiri Slaby (unsigned long)cy_isa_address, cy_isa_irq); 33743137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby iounmap(cy_isa_address); 3375096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return nboard; 337602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 337702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 337802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* set cy_card */ 337902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_card[j].base_addr = cy_isa_address; 338097e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby cy_card[j].ctl_addr.p9050 = NULL; 338102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_card[j].irq = (int)cy_isa_irq; 338202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_card[j].bus_index = 0; 338302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_card[j].first_line = cy_next_channel; 3384963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP; 3385963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby cy_card[j].nports = cy_isa_nchan; 33863137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (cy_init_card(&cy_card[j])) { 33873137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_card[j].base_addr = NULL; 33883137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby free_irq(cy_isa_irq, &cy_card[j]); 33893137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby iounmap(cy_isa_address); 33903137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby continue; 33913137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 339202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby nboard++; 339302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 3394217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_INFO "Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d found: " 3395217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "%d channels starting from port %d\n", 339602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby j + 1, (unsigned long)cy_isa_address, 339702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)), 3398217191910c0286e0b3c7e3011630273695253da3Jiri Slaby cy_isa_irq, cy_isa_nchan, cy_next_channel); 3399217191910c0286e0b3c7e3011630273695253da3Jiri Slaby 34006ad1ccc196f76833f41b187e01a28a024fe11f8bJiri Slaby for (j = cy_next_channel; 34016ad1ccc196f76833f41b187e01a28a024fe11f8bJiri Slaby j < cy_next_channel + cy_isa_nchan; j++) 34026ad1ccc196f76833f41b187e01a28a024fe11f8bJiri Slaby tty_register_device(cy_serial_driver, j, NULL); 340302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_next_channel += cy_isa_nchan; 340402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 3405096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return nboard; 34061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 3407096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return 0; 340802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_ISA */ 340902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_detect_isa */ 34101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby#ifdef CONFIG_PCI 3412054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slabystatic inline int __devinit cyc_isfwstr(const char *str, unsigned int size) 3413054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby{ 3414054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby unsigned int a; 3415054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3416054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby for (a = 0; a < size && *str; a++, str++) 3417054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (*str & 0x80) 3418054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3419054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3420054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby for (; a < size; a++, str++) 3421054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (*str) 3422054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3423054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3424054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return 0; 3425054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby} 3426054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3427f61e761e2128c7ca0d044651b18928991ab03be2David Woodhousestatic inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data, 3428054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby unsigned int size) 3429054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby{ 3430054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby for (; size > 0; size--) { 3431054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(fpga, *data++); 3432054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby udelay(10); 3433054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3434054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby} 3435054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3436054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slabystatic void __devinit plx_init(struct pci_dev *pdev, int irq, 3437054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby struct RUNTIME_9060 __iomem *addr) 34381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 343902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Reset PLX */ 3440054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x40000000); 344102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby udelay(100L); 3442054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x40000000); 344302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 344402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Reload Config. Registers from EEPROM */ 3445054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x20000000); 344602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby udelay(100L); 3447054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x20000000); 3448054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3449054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* For some yet unknown reason, once the PLX9060 reloads the EEPROM, 3450054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby * the IRQ is lost and, thus, we have to re-write it to the PCI config. 3451054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby * registers. This will remain here until we find a permanent fix. 3452054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby */ 3453054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq); 3454054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby} 3455054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3456054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slabystatic int __devinit __cyz_load_fw(const struct firmware *fw, 3457054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby const char *name, const u32 mailbox, void __iomem *base, 3458054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby void __iomem *fpga) 3459054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby{ 3460f61e761e2128c7ca0d044651b18928991ab03be2David Woodhouse const void *ptr = fw->data; 3461f61e761e2128c7ca0d044651b18928991ab03be2David Woodhouse const struct zfile_header *h = ptr; 3462f61e761e2128c7ca0d044651b18928991ab03be2David Woodhouse const struct zfile_config *c, *cs; 3463f61e761e2128c7ca0d044651b18928991ab03be2David Woodhouse const struct zfile_block *b, *bs; 3464054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby unsigned int a, tmp, len = fw->size; 3465054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby#define BAD_FW KERN_ERR "Bad firmware: " 3466054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (len < sizeof(*h)) { 3467054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby printk(BAD_FW "too short: %u<%zu\n", len, sizeof(*h)); 3468054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3469054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3470054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3471054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cs = ptr + h->config_offset; 3472054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby bs = ptr + h->block_offset; 3473054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3474054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if ((void *)(cs + h->n_config) > ptr + len || 3475054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby (void *)(bs + h->n_blocks) > ptr + len) { 3476054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby printk(BAD_FW "too short"); 3477054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3478054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3479054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3480054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (cyc_isfwstr(h->name, sizeof(h->name)) || 3481054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cyc_isfwstr(h->date, sizeof(h->date))) { 3482054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby printk(BAD_FW "bad formatted header string\n"); 3483054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3484054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3485054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3486054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (strncmp(name, h->name, sizeof(h->name))) { 3487054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby printk(BAD_FW "bad name '%s' (expected '%s')\n", h->name, name); 3488054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3489054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3490054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3491054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby tmp = 0; 3492054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby for (c = cs; c < cs + h->n_config; c++) { 3493054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby for (a = 0; a < c->n_blocks; a++) 3494054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (c->block_list[a] > h->n_blocks) { 3495054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby printk(BAD_FW "bad block ref number in cfgs\n"); 3496054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3497054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3498054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (c->mailbox == mailbox && c->function == 0) /* 0 is normal */ 3499054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby tmp++; 3500054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3501054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (!tmp) { 3502054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby printk(BAD_FW "nothing appropriate\n"); 3503054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3504054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3505054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3506054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby for (b = bs; b < bs + h->n_blocks; b++) 3507054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (b->file_offset + b->size > len) { 3508054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby printk(BAD_FW "bad block data offset\n"); 3509054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3510054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3511054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3512054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* everything is OK, let's seek'n'load it */ 3513054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby for (c = cs; c < cs + h->n_config; c++) 3514054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (c->mailbox == mailbox && c->function == 0) 3515054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby break; 3516054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3517054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby for (a = 0; a < c->n_blocks; a++) { 3518054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby b = &bs[c->block_list[a]]; 3519054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (b->type == ZBLOCK_FPGA) { 3520054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (fpga != NULL) 3521054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cyz_fpga_copy(fpga, ptr + b->file_offset, 3522054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby b->size); 3523054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } else { 3524054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (base != NULL) 3525054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby memcpy_toio(base + b->ram_offset, 3526054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby ptr + b->file_offset, b->size); 3527054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3528054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3529054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby#undef BAD_FW 3530054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return 0; 3531054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby} 3532054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3533054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slabystatic int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, 3534054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby struct RUNTIME_9060 __iomem *ctl_addr, int irq) 3535054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby{ 3536054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby const struct firmware *fw; 3537054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby struct FIRM_ID __iomem *fid = base_addr + ID_ADDRESS; 3538054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby struct CUSTOM_REG __iomem *cust = base_addr; 3539054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby struct ZFW_CTRL __iomem *pt_zfwctrl; 3540c4923b4f13156455a9e84f0b918866aef300cc57Jiri Slaby void __iomem *tmp; 3541963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby u32 mailbox, status, nchan; 3542054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby unsigned int i; 3543054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby int retval; 3544054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3545054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby retval = request_firmware(&fw, "cyzfirm.bin", &pdev->dev); 3546054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (retval) { 3547054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_err(&pdev->dev, "can't get firmware\n"); 3548054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby goto err; 3549054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3550054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3551054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* Check whether the firmware is already loaded and running. If 3552054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby positive, skip this board */ 35532693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (__cyz_fpga_loaded(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) { 3554054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby u32 cntval = readl(base_addr + 0x190); 3555054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3556054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby udelay(100); 3557054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (cntval != readl(base_addr + 0x190)) { 3558054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* FW counter is working, FW is running */ 3559054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_dbg(&pdev->dev, "Cyclades-Z FW already loaded. " 3560054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "Skipping board.\n"); 3561054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby retval = 0; 3562054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby goto err_rel; 3563054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3564054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3565054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3566054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* start boot */ 3567054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) & 3568054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby ~0x00030800UL); 3569054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3570054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby mailbox = readl(&ctl_addr->mail_box_0); 3571054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 35722693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (mailbox == 0 || __cyz_fpga_loaded(ctl_addr)) { 3573054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* stops CPU and set window to beginning of RAM */ 3574054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); 3575054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&cust->cpu_stop, 0); 3576054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); 3577054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby udelay(100); 3578054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3579054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3580054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby plx_init(pdev, irq, ctl_addr); 3581054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3582054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (mailbox != 0) { 3583054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* load FPGA */ 3584054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, NULL, 3585054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby base_addr); 3586054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (retval) 3587054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby goto err_rel; 35882693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!__cyz_fpga_loaded(ctl_addr)) { 3589054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_err(&pdev->dev, "fw upload successful, but fw is " 3590054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "not loaded\n"); 3591054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby goto err_rel; 3592054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3593054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3594054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3595054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* stops CPU and set window to beginning of RAM */ 3596054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); 3597054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&cust->cpu_stop, 0); 3598054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); 3599054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby udelay(100); 3600054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3601054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* clear memory */ 3602c4923b4f13156455a9e84f0b918866aef300cc57Jiri Slaby for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++) 3603054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writeb(tmp, 255); 3604054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (mailbox != 0) { 3605054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* set window to last 512K of RAM */ 3606054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_RAM + RAM_SIZE); 3607c4923b4f13156455a9e84f0b918866aef300cc57Jiri Slaby for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++) 3608054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writeb(tmp, 255); 3609054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* set window to beginning of RAM */ 3610054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); 3611054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3612054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3613054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, base_addr, NULL); 3614054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby release_firmware(fw); 3615054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (retval) 3616054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby goto err; 3617054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3618054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* finish boot and start boards */ 3619054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); 3620054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&cust->cpu_start, 0); 3621054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); 3622054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby i = 0; 3623054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby while ((status = readl(&fid->signature)) != ZFIRM_ID && i++ < 40) 3624054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby msleep(100); 3625054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (status != ZFIRM_ID) { 3626054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (status == ZFIRM_HLT) { 3627054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_err(&pdev->dev, "you need an external power supply " 3628054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "for this number of ports. Firmware halted and " 3629054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "board reset.\n"); 3630054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby retval = -EIO; 3631054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby goto err; 3632054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3633054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_warn(&pdev->dev, "fid->signature = 0x%x... Waiting " 3634054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "some more time\n", status); 3635054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby while ((status = readl(&fid->signature)) != ZFIRM_ID && 3636054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby i++ < 200) 3637054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby msleep(100); 3638054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (status != ZFIRM_ID) { 3639054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_err(&pdev->dev, "Board not started in 20 seconds! " 3640054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "Giving up. (fid->signature = 0x%x)\n", 3641054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby status); 3642054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_info(&pdev->dev, "*** Warning ***: if you are " 3643054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "upgrading the FW, please power cycle the " 3644054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "system before loading the new FW to the " 3645054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "Cyclades-Z.\n"); 3646054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 36472693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (__cyz_fpga_loaded(ctl_addr)) 3648054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby plx_init(pdev, irq, ctl_addr); 3649054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3650054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby retval = -EIO; 3651054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby goto err; 3652054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3653054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_dbg(&pdev->dev, "Firmware started after %d seconds.\n", 3654054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby i / 10); 3655054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3656054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby pt_zfwctrl = base_addr + readl(&fid->zfwctrl_addr); 3657054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3658054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_dbg(&pdev->dev, "fid=> %p, zfwctrl_addr=> %x, npt_zfwctrl=> %p\n", 3659054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr), 3660054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby base_addr + readl(&fid->zfwctrl_addr)); 3661054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3662963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby nchan = readl(&pt_zfwctrl->board_ctrl.n_channel); 3663054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n", 3664963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby readl(&pt_zfwctrl->board_ctrl.fw_version), nchan); 3665054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3666963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby if (nchan == 0) { 3667054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please " 3668054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "check the connection between the Z host card and the " 3669054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "serial expanders.\n"); 3670054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 36712693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (__cyz_fpga_loaded(ctl_addr)) 3672054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby plx_init(pdev, irq, ctl_addr); 3673054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3674054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_info(&pdev->dev, "Null number of ports detected. Board " 3675054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "reset.\n"); 3676054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby retval = 0; 3677054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby goto err; 3678054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3679054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3680054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&pt_zfwctrl->board_ctrl.op_system, C_OS_LINUX); 3681054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&pt_zfwctrl->board_ctrl.dr_version, DRIVER_VERSION); 3682054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3683054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* 3684054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby Early firmware failed to start looking for commands. 3685054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby This enables firmware interrupts for those commands. 3686054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby */ 3687054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) | 3688054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby (1 << 17)); 3689054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) | 3690054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 0x00030800UL); 3691054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3692963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby return nchan; 3693054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slabyerr_rel: 3694054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby release_firmware(fw); 3695054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slabyerr: 3696054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return retval; 36971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 36981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 369958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slabystatic int __devinit cy_pci_probe(struct pci_dev *pdev, 370058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby const struct pci_device_id *ent) 37011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 37023137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby void __iomem *addr0 = NULL, *addr2 = NULL; 37033137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby char *card_name = NULL; 3704101b81590d8df0a74c33cf739886247c0a13f4afJiri Slaby u32 uninitialized_var(mailbox); 37053137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby unsigned int device_id, nchan = 0, card_no, i; 37063137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby unsigned char plx_ver; 37073137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby int retval, irq; 370802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 370958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby retval = pci_enable_device(pdev); 371058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby if (retval) { 371158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby dev_err(&pdev->dev, "cannot enable device\n"); 37123137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err; 371358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 37141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby /* read PCI configuration area */ 37163137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby irq = pdev->irq; 371758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby device_id = pdev->device & ~PCI_DEVICE_ID_MASK; 37181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37193137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby#if defined(__alpha__) 37203137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ 37213137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "Cyclom-Y/PCI not supported for low " 37223137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "addresses on Alpha systems.\n"); 37233137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby retval = -EIO; 37243137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_dis; 37253137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 37263137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby#endif 37273137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) { 37283137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "Cyclades-Z/PCI not supported for low " 37293137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "addresses\n"); 37303137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby retval = -EIO; 37313137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_dis; 37323137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 37333137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby 37343137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { 37353137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_warn(&pdev->dev, "PCI I/O bit incorrectly set. Ignoring " 37363137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "it...\n"); 37373137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby pdev->resource[2].flags &= ~IORESOURCE_IO; 37383137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 37393137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby 37403137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby retval = pci_request_regions(pdev, "cyclades"); 37413137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (retval) { 37423137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "failed to reserve resources\n"); 37433137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_dis; 37443137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 37453137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby 37463137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby retval = -EIO; 374758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || 374858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { 37493137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby card_name = "Cyclom-Y"; 37501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 375124e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby addr0 = ioremap_nocache(pci_resource_start(pdev, 0), 375224e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby CyPCI_Yctl); 37533137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (addr0 == NULL) { 37543137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "can't remap ctl region\n"); 37553137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_reg; 375658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 375724e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby addr2 = ioremap_nocache(pci_resource_start(pdev, 2), 375824e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby CyPCI_Ywin); 37593137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (addr2 == NULL) { 37603137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "can't remap base region\n"); 37613137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_unmap; 376258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 37631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37643137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby nchan = CyPORTS_PER_CHIP * cyy_init_card(addr2, 1); 37653137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (nchan == 0) { 3766217191910c0286e0b3c7e3011630273695253da3Jiri Slaby dev_err(&pdev->dev, "Cyclom-Y PCI host card with no " 3767217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "Serial-Modules\n"); 3768c847d47cb7b2fa78b17c9e17ed3fbd010ee3d3caAndrew Morton goto err_unmap; 376958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 377058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { 37713137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby struct RUNTIME_9060 __iomem *ctl_addr; 3772217191910c0286e0b3c7e3011630273695253da3Jiri Slaby 377324e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby ctl_addr = addr0 = ioremap_nocache(pci_resource_start(pdev, 0), 377424e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby CyPCI_Zctl); 37753137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (addr0 == NULL) { 37763137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "can't remap ctl region\n"); 37773137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_reg; 37783137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 377958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby 378058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby /* Disable interrupts on the PLX before resetting it */ 378197e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby cy_writew(&ctl_addr->intr_ctrl_stat, 378297e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby readw(&ctl_addr->intr_ctrl_stat) & ~0x0900); 378358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby 3784054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby plx_init(pdev, irq, addr0); 378502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 3786101b81590d8df0a74c33cf739886247c0a13f4afJiri Slaby mailbox = readl(&ctl_addr->mail_box_0); 378758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby 378824e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby addr2 = ioremap_nocache(pci_resource_start(pdev, 2), 378924e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin); 37903137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (addr2 == NULL) { 37913137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "can't remap base region\n"); 37923137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_unmap; 379358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 379458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby 379558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby if (mailbox == ZE_V1) { 37963137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby card_name = "Cyclades-Ze"; 379758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } else { 37983137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby card_name = "Cyclades-8Zo"; 37991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_PCI_DEBUG 38003137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (mailbox == ZO_V1) { 38013137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); 38023137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_info(&pdev->dev, "Cyclades-8Zo/PCI: FPGA " 38033137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "id %lx, ver %lx\n", (ulong)(0xff & 38043137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby readl(&((struct CUSTOM_REG *)addr2)-> 38053137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby fpga_id)), (ulong)(0xff & 38063137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby readl(&((struct CUSTOM_REG *)addr2)-> 38073137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby fpga_version))); 38083137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); 38093137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } else { 38103137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_info(&pdev->dev, "Cyclades-Z/PCI: New " 38113137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "Cyclades-Z board. FPGA not loaded\n"); 38123137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 38131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 38143137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby /* The following clears the firmware id word. This 38153137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby ensures that the driver will not attempt to talk to 38163137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby the board until it has been properly initialized. 38173137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby */ 38183137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) 38193137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_writel(addr2 + ID_ADDRESS, 0L); 382058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 3821ace08c3c4403140e5ce82116c8f2acb38f58f61dJiri Slaby 3822ace08c3c4403140e5ce82116c8f2acb38f58f61dJiri Slaby retval = cyz_load_fw(pdev, addr2, addr0, irq); 3823963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby if (retval <= 0) 3824ace08c3c4403140e5ce82116c8f2acb38f58f61dJiri Slaby goto err_unmap; 3825963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby nchan = retval; 38263137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 38273137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby 38283137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if ((cy_next_channel + nchan) > NR_PORTS) { 38293137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no " 38303137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "channels are available. Change NR_PORTS in " 38313137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "cyclades.c and recompile kernel.\n"); 38323137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_unmap; 38333137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 38343137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby /* fill the next cy_card structure available */ 38353137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby for (card_no = 0; card_no < NR_CARDS; card_no++) { 38363137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (cy_card[card_no].base_addr == NULL) 38373137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby break; 38383137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 38393137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (card_no == NR_CARDS) { /* no more cy_cards available */ 38403137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no " 38413137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "more cards can be used. Change NR_CARDS in " 38423137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "cyclades.c and recompile kernel.\n"); 38433137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_unmap; 38443137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 38453137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby 38463137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || 38473137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { 38483137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby /* allocate IRQ */ 38493137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby retval = request_irq(irq, cyy_interrupt, 38503137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]); 38513137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (retval) { 38523137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "could not allocate IRQ\n"); 38533137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_unmap; 385458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 3855963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP; 38563137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } else { 3857f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS; 3858f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct ZFW_CTRL __iomem *zfw_ctrl; 3859f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby 3860f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff); 3861f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby 3862101b81590d8df0a74c33cf739886247c0a13f4afJiri Slaby cy_card[card_no].hw_ver = mailbox; 3863101b81590d8df0a74c33cf739886247c0a13f4afJiri Slaby cy_card[card_no].num_chips = (unsigned int)-1; 3864f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl; 386502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#ifdef CONFIG_CYZ_INTR 386658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby /* allocate IRQ only if board has an IRQ */ 38673137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (irq != 0 && irq != 255) { 38683137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby retval = request_irq(irq, cyz_interrupt, 386958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby IRQF_SHARED, "Cyclades-Z", 38703137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby &cy_card[card_no]); 387158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby if (retval) { 3872217191910c0286e0b3c7e3011630273695253da3Jiri Slaby dev_err(&pdev->dev, "could not allocate IRQ\n"); 38733137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_unmap; 387402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 387558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 387602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_CYZ_INTR */ 38773137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 387802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 38793137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby /* set cy_card */ 38803137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_card[card_no].base_addr = addr2; 388197e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby cy_card[card_no].ctl_addr.p9050 = addr0; 38823137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_card[card_no].irq = irq; 38833137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_card[card_no].bus_index = 1; 38843137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_card[card_no].first_line = cy_next_channel; 3885963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby cy_card[card_no].nports = nchan; 38863137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby retval = cy_init_card(&cy_card[card_no]); 38873137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (retval) 38883137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_null; 388958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby 38903137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby pci_set_drvdata(pdev, &cy_card[card_no]); 389158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby 38923137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || 38933137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { 38943137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby /* enable interrupts in the PCI interface */ 38953137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby plx_ver = readb(addr2 + CyPLX_VER) & 0x0f; 38963137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby switch (plx_ver) { 38973137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby case PLX_9050: 38983137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_writeb(addr0 + 0x4c, 0x43); 38993137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby break; 39003137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby 39013137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby case PLX_9060: 39023137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby case PLX_9080: 39033137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby default: /* Old boards, use PLX_9060 */ 390497e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby { 390597e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby struct RUNTIME_9060 __iomem *ctl_addr = addr0; 390697e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby plx_init(pdev, irq, ctl_addr); 390797e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby cy_writew(&ctl_addr->intr_ctrl_stat, 390897e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby readw(&ctl_addr->intr_ctrl_stat) | 0x0900); 39093137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby break; 39103137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 391197e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby } 391258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 391358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby 39143137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from " 39153137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "port %d.\n", card_name, card_no + 1, nchan, cy_next_channel); 39163137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby for (i = cy_next_channel; i < cy_next_channel + nchan; i++) 39173137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby tty_register_device(cy_serial_driver, i, &pdev->dev); 39183137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_next_channel += nchan; 39193137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby 392058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby return 0; 39213137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slabyerr_null: 39223137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_card[card_no].base_addr = NULL; 39233137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby free_irq(irq, &cy_card[card_no]); 39243137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slabyerr_unmap: 392524e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby iounmap(addr0); 39263137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (addr2) 392724e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby iounmap(addr2); 39283137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slabyerr_reg: 39293137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby pci_release_regions(pdev); 39303137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slabyerr_dis: 39313137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby pci_disable_device(pdev); 39323137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slabyerr: 39333137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby return retval; 393458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby} 393558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby 39366747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slabystatic void __devexit cy_pci_remove(struct pci_dev *pdev) 393758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby{ 393838d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby struct cyclades_card *cinfo = pci_get_drvdata(pdev); 3939f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slaby unsigned int i; 394038d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby 394185c93fa95b8fa8dabc6d14c77eb9a9c2e9753eccJiri Slaby /* non-Z with old PLX */ 39422693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) == 3943c2ad4c75154d98c07d30493e4906e1cd0a9162a5Jiri Slaby PLX_9050) 394497e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby cy_writeb(cinfo->ctl_addr.p9050 + 0x4c, 0); 394585c93fa95b8fa8dabc6d14c77eb9a9c2e9753eccJiri Slaby else 394685c93fa95b8fa8dabc6d14c77eb9a9c2e9753eccJiri Slaby#ifndef CONFIG_CYZ_INTR 39472693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(cinfo)) 394885c93fa95b8fa8dabc6d14c77eb9a9c2e9753eccJiri Slaby#endif 394997e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby cy_writew(&cinfo->ctl_addr.p9060->intr_ctrl_stat, 395097e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby readw(&cinfo->ctl_addr.p9060->intr_ctrl_stat) & 395197e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby ~0x0900); 395285c93fa95b8fa8dabc6d14c77eb9a9c2e9753eccJiri Slaby 395324e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby iounmap(cinfo->base_addr); 395497e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby if (cinfo->ctl_addr.p9050) 395597e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby iounmap(cinfo->ctl_addr.p9050); 395638d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby if (cinfo->irq 395738d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby#ifndef CONFIG_CYZ_INTR 39582693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby && !cy_is_Z(cinfo) 395938d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby#endif /* CONFIG_CYZ_INTR */ 396038d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby ) 396138d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby free_irq(cinfo->irq, cinfo); 396238d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby pci_release_regions(pdev); 396338d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby 396438d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby cinfo->base_addr = NULL; 39656ad1ccc196f76833f41b187e01a28a024fe11f8bJiri Slaby for (i = cinfo->first_line; i < cinfo->first_line + 39666ad1ccc196f76833f41b187e01a28a024fe11f8bJiri Slaby cinfo->nports; i++) 39676ad1ccc196f76833f41b187e01a28a024fe11f8bJiri Slaby tty_unregister_device(cy_serial_driver, i); 3968dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby cinfo->nports = 0; 3969dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby kfree(cinfo->ports); 397038d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby} 397138d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby 39726747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slabystatic struct pci_driver cy_pci_driver = { 39736747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby .name = "cyclades", 39746747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby .id_table = cy_pci_dev_id, 39756747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby .probe = cy_pci_probe, 39766747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby .remove = __devexit_p(cy_pci_remove) 39776747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby}; 39786747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby#endif 39796747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby 3980444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyanstatic int cyclades_proc_show(struct seq_file *m, void *v) 39811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 398202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby struct cyclades_port *info; 3983dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby unsigned int i, j; 398402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby __u32 cur_jifs = jiffies; 398502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 3986444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan seq_puts(m, "Dev TimeOpen BytesOut IdleOut BytesIn " 398702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby "IdleIn Overruns Ldisc\n"); 398802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 398902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Output one line for each known port */ 3990dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby for (i = 0; i < NR_CARDS; i++) 3991dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby for (j = 0; j < cy_card[i].nports; j++) { 3992dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby info = &cy_card[i].ports[j]; 3993dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby 3994d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if (info->port.count) { 3995d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby /* XXX is the ldisc num worth this? */ 3996d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby struct tty_struct *tty; 3997d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby struct tty_ldisc *ld; 3998d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby int num = 0; 3999d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty = tty_port_tty_get(&info->port); 4000d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if (tty) { 4001d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby ld = tty_ldisc_ref(tty); 4002d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if (ld) { 4003d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby num = ld->ops->num; 4004d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty_ldisc_deref(ld); 4005d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby } 4006d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty_kref_put(tty); 4007d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby } 4008444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan seq_printf(m, "%3d %8lu %10lu %8lu " 4009d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby "%10lu %8lu %9lu %6d\n", info->line, 4010dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby (cur_jifs - info->idle_stats.in_use) / 4011dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby HZ, info->idle_stats.xmit_bytes, 4012dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby (cur_jifs - info->idle_stats.xmit_idle)/ 4013dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby HZ, info->idle_stats.recv_bytes, 4014dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby (cur_jifs - info->idle_stats.recv_idle)/ 4015dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby HZ, info->idle_stats.overruns, 4016d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby num); 4017d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby } else 4018444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan seq_printf(m, "%3d %8lu %10lu %8lu " 4019dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby "%10lu %8lu %9lu %6ld\n", 4020dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); 402102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 4022444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan return 0; 4023444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan} 4024444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan 4025444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyanstatic int cyclades_proc_open(struct inode *inode, struct file *file) 4026444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan{ 4027444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan return single_open(file, cyclades_proc_show, NULL); 40281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 40291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4030444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyanstatic const struct file_operations cyclades_proc_fops = { 4031444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan .owner = THIS_MODULE, 4032444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan .open = cyclades_proc_open, 4033444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan .read = seq_read, 4034444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan .llseek = seq_lseek, 4035444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan .release = single_release, 4036444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan}; 4037444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan 40381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The serial driver boot-time initialization code! 40391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Hardware I/O ports are mapped to character special devices on a 40401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds first found, first allocated manner. That is, this code searches 40411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for Cyclom cards in the system. As each is found, it is probed 40421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to discover how many chips (and thus how many ports) are present. 40431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds These ports are mapped to the tty ports 32 and upward in monotonic 40441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fashion. If an 8-port card is replaced with a 16-port card, the 40451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port mapping on a following card will shift. 40461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This approach is different from what is used in the other serial 40481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device driver because the Cyclom is more properly a multiplexer, 40491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds not just an aggregation of serial ports on one card. 40501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds If there are more cards with more ports than have been 40521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds statically allocated above, a warning is printed and the 40531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds extra ports are ignored. 40541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 40551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4056b68e31d0ebbcc909d1941f9f230c9d062a3a13d3Jeff Dikestatic const struct tty_operations cy_ops = { 405702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .open = cy_open, 405802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .close = cy_close, 405902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .write = cy_write, 406002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .put_char = cy_put_char, 406102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .flush_chars = cy_flush_chars, 406202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .write_room = cy_write_room, 406302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .chars_in_buffer = cy_chars_in_buffer, 406402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .flush_buffer = cy_flush_buffer, 406502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .ioctl = cy_ioctl, 406602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .throttle = cy_throttle, 406702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .unthrottle = cy_unthrottle, 406802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .set_termios = cy_set_termios, 406902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .stop = cy_stop, 407002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .start = cy_start, 407102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .hangup = cy_hangup, 407202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .break_ctl = cy_break, 407302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .wait_until_sent = cy_wait_until_sent, 407402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .tiocmget = cy_tiocmget, 407502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .tiocmset = cy_tiocmset, 40760587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox .get_icount = cy_get_icount, 4077444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan .proc_fops = &cyclades_proc_fops, 40781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 40791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 408002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int __init cy_init(void) 40811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4082dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby unsigned int nboards; 40839dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby int retval = -ENOMEM; 408402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 408502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver = alloc_tty_driver(NR_PORTS); 408602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!cy_serial_driver) 40879dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby goto err; 4088217191910c0286e0b3c7e3011630273695253da3Jiri Slaby 408964a14b51bed6427a2e6d68ed687027f065f5a156Michal Marek printk(KERN_INFO "Cyclades driver " CY_VERSION "\n"); 409002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 409102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Initialize the tty_driver structure */ 409202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 409302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->owner = THIS_MODULE; 409402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->driver_name = "cyclades"; 409502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->name = "ttyC"; 409602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->major = CYCLADES_MAJOR; 409702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->minor_start = 0; 409802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; 409902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->subtype = SERIAL_TYPE_NORMAL; 410002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->init_termios = tty_std_termios; 410102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->init_termios.c_cflag = 410202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby B9600 | CS8 | CREAD | HUPCL | CLOCAL; 41036ad1ccc196f76833f41b187e01a28a024fe11f8bJiri Slaby cy_serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; 410402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tty_set_operations(cy_serial_driver, &cy_ops); 410502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 41069dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby retval = tty_register_driver(cy_serial_driver); 41079dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby if (retval) { 41089dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby printk(KERN_ERR "Couldn't register Cyclades serial driver\n"); 41099dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby goto err_frtty; 41109dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby } 411102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 411202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* the code below is responsible to find the boards. Each different 411302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby type of board has its own detection routine. If a board is found, 411402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby the next cy_card structure available is set by the detection 411502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby routine. These functions are responsible for checking the 411602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby availability of cy_card and cy_port data structures and updating 411702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby the cy_next_channel. */ 411802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 411902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* look for isa boards */ 412014a55a6789d8409e58329310f9a18fc141deb4c2Jiri Slaby nboards = cy_detect_isa(); 412102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 41226747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby#ifdef CONFIG_PCI 412302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* look for pci boards */ 41246747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby retval = pci_register_driver(&cy_pci_driver); 4125d941ea7d496db914205c3872942fd1ff0e7dccefJesper Juhl if (retval && !nboards) { 4126d941ea7d496db914205c3872942fd1ff0e7dccefJesper Juhl tty_unregister_driver(cy_serial_driver); 4127d941ea7d496db914205c3872942fd1ff0e7dccefJesper Juhl goto err_frtty; 4128d941ea7d496db914205c3872942fd1ff0e7dccefJesper Juhl } 41296747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby#endif 41309dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby 41319dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby return 0; 41329dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slabyerr_frtty: 41339dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby put_tty_driver(cy_serial_driver); 41349dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slabyerr: 41359dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby return retval; 413602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_init */ 41371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 413802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void __exit cy_cleanup_module(void) 41391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4140dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby struct cyclades_card *card; 414165f76a82ec7a0374fad85211535330e203740475Jiri Slaby unsigned int i, e1; 41421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_CYZ_INTR 4144b70509066cba24067757f1422c899c43e433429dJiri Slaby del_timer_sync(&cyz_timerlist); 41451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_CYZ_INTR */ 41461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 414715ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox e1 = tty_unregister_driver(cy_serial_driver); 414815ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (e1) 4149217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "failed to unregister Cyclades serial " 4150217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "driver(%d)\n", e1); 41511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41526747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby#ifdef CONFIG_PCI 41536747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby pci_unregister_driver(&cy_pci_driver); 41546747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby#endif 41556747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby 415602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for (i = 0; i < NR_CARDS; i++) { 4157dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby card = &cy_card[i]; 4158dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby if (card->base_addr) { 415985c93fa95b8fa8dabc6d14c77eb9a9c2e9753eccJiri Slaby /* clear interrupt */ 4160dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby cy_writeb(card->base_addr + Cy_ClrIntr, 0); 4161dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby iounmap(card->base_addr); 416297e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby if (card->ctl_addr.p9050) 416397e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby iounmap(card->ctl_addr.p9050); 4164dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby if (card->irq 41651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_CYZ_INTR 41662693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby && !cy_is_Z(card) 41671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_CYZ_INTR */ 416802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ) 4169dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby free_irq(card->irq, card); 417065f76a82ec7a0374fad85211535330e203740475Jiri Slaby for (e1 = card->first_line; e1 < card->first_line + 4171dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby card->nports; e1++) 41726ad1ccc196f76833f41b187e01a28a024fe11f8bJiri Slaby tty_unregister_device(cy_serial_driver, e1); 4173dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby kfree(card->ports); 417402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 417502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 4176f2462bfe558559c9fbc4ef60812d5df30ccb01f6Jiri Slaby 4177f2462bfe558559c9fbc4ef60812d5df30ccb01f6Jiri Slaby put_tty_driver(cy_serial_driver); 41781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* cy_cleanup_module */ 41791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(cy_init); 41811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(cy_cleanup_module); 41821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 4184c8e1693a4f63e317966f3dfe8f815eda95e26610Jiri SlabyMODULE_VERSION(CY_VERSION); 41859f56fad741163fe2111cbbcfb7ff795ebdabdab1Scott James RemnantMODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR); 4186e6c4ef984ebbd1a0458503417da91f3de47cbbe0Ben HutchingsMODULE_FIRMWARE("cyzfirm.bin"); 4187