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; 1518410235fd4d20b8feaf8930a0575d23acc088aa87Jiri Slaby unsigned int i, line = tty->index; 151965f76a82ec7a0374fad85211535330e203740475Jiri Slaby int retval; 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby for (i = 0; i < NR_CARDS; i++) 1522dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby if (line < cy_card[i].first_line + cy_card[i].nports && 1523dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby line >= cy_card[i].first_line) 1524dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby break; 1525dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby if (i >= NR_CARDS) 1526dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby return -ENODEV; 1527dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby info = &cy_card[i].ports[line - cy_card[i].first_line]; 152815ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (info->line < 0) 152902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENODEV; 15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 153102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* If the card's firmware hasn't been loaded, 153202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby treat it as absent from the system. This 153302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby will make the user pay attention. 153402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 15352693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (cy_is_Z(info->card)) { 1536875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *cinfo = info->card; 153702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; 153802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 15392693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cyz_is_loaded(cinfo)) { 15402693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (cinfo->hw_ver == ZE_V1 && cyz_fpga_loaded(cinfo) && 1541101b81590d8df0a74c33cf739886247c0a13f4afJiri Slaby readl(&firm_id->signature) == 1542101b81590d8df0a74c33cf739886247c0a13f4afJiri Slaby ZFIRM_HLT) { 1543217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:Cyclades-Z Error: you " 1544217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "need an external power supply for " 1545217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "this number of ports.\nFirmware " 1546217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "halted.\n"); 154702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 1548217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:Cyclades-Z firmware not " 1549217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "yet loaded\n"); 155002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 155102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENODEV; 155202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 155302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#ifdef CONFIG_CYZ_INTR 155402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else { 155502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* In case this Z board is operating in interrupt mode, its 155602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby interrupts should be enabled as soon as the first open 155702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby happens to one of its ports. */ 155802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!cinfo->intr_enabled) { 155997e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby u16 intr; 156002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 156102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Enable interrupts on the PLX chip */ 156297e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby intr = readw(&cinfo->ctl_addr.p9060-> 156397e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby intr_ctrl_stat) | 0x0900; 156497e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby cy_writew(&cinfo->ctl_addr.p9060-> 156597e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby intr_ctrl_stat, intr); 156602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Enable interrupts on the FW */ 156702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby retval = cyz_issue_cmd(cinfo, 0, 156802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby C_CM_IRQ_ENBL, 0L); 156902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 1570217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:IRQ enable retval " 1571217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "was %x\n", retval); 157202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 157302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cinfo->intr_enabled = 1; 157402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 157602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_CYZ_INTR */ 157702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Make sure this Z port really exists in hardware */ 157802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->line > (cinfo->first_line + cinfo->nports - 1)) 157902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENODEV; 15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OTHER 1582217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_open ttyC%d\n", info->line); 15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 158402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tty->driver_data = info; 158515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (serial_paranoia_check(info, tty->name, "cy_open")) 158602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENODEV; 158715ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox 15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OPEN 1589217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d\n", info->line, 159077451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.count); 15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 159277451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.count++; 15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_COUNT 1594217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_open (%d): incrementing count to %d\n", 159577451e53e0a509a98eda272567869cfe96431ba9Alan Cox current->pid, info->port.count); 15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 159802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 159902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * If the port is the middle of closing, bail out now 160002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 160177451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { 1602be1bc2889a4db4961ef69f47fb471ecae9f23adeArnd Bergmann wait_event_interruptible_tty(info->port.close_wait, 160377451e53e0a509a98eda272567869cfe96431ba9Alan Cox !(info->port.flags & ASYNC_CLOSING)); 160477451e53e0a509a98eda272567869cfe96431ba9Alan Cox return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; 160502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 160702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 160802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * Start up serial port 160902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 1610d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby retval = cy_startup(info, tty); 161115ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (retval) 161202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return retval; 16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1614f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby retval = tty_port_block_til_ready(&info->port, tty, filp); 161502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval) { 16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OPEN 1617217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready " 1618217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "with %d\n", retval); 16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 162002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return retval; 162102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 162302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->throttle = 0; 1624d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty_port_tty_set(&info->port, tty); 16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 162602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#ifdef CY_DEBUG_OPEN 1627217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_open done\n"); 162802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif 162902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 163002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_open */ 16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cy_wait_until_sent() --- wait until the transmitter is empty 16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 163502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_wait_until_sent(struct tty_struct *tty, int timeout) 16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1637875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card; 1638cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 163902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long orig_jiffies; 164002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int char_time; 164102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 164202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent")) 164302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 164402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 164502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->xmit_fifo_size == 0) 164602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; /* Just in case.... */ 16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 164802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby orig_jiffies = jiffies; 164902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 165002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * Set the check interval to be 1/5 of the estimated time to 165102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * send a single character, and make it at least 1. The check 165202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * interval should also be less than the timeout. 165302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * 165402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * Note: we have to use pretty tight timings here to satisfy 165502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * the NIST-PCTS. 165602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 165702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size; 165802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_time = char_time / 5; 165902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (char_time <= 0) 166002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_time = 1; 166102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (timeout < 0) 166202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby timeout = 0; 166302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (timeout) 166402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_time = min(char_time, timeout); 166502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 166602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * If the transmitter hasn't cleared in twice the approximate 166702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * amount of time to send the entire FIFO, it probably won't 166802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * ever clear. This assumes the UART isn't doing flow 166902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * control, which is currently the case. Hence, if it ever 167002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * takes longer than info->timeout, this is probably due to a 167102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * UART bug of some kind. So, we clamp the timeout parameter at 167202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * 2*info->timeout. 167302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 167402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!timeout || timeout > 2 * info->timeout) 167502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby timeout = 2 * info->timeout; 16768bab534b508230f33be5f7ba8492923754274a8dJiri Slaby 167702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby card = info->card; 16782693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 16793aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby while (cyy_readb(info, CySRER) & CyTxRdy) { 168002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (msleep_interruptible(jiffies_to_msecs(char_time))) 168102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 168202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (timeout && time_after(jiffies, orig_jiffies + 168302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby timeout)) 168402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 168502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 168702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Run one more char cycle */ 168802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby msleep_interruptible(jiffies_to_msecs(char_time * 5)); 16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Coxstatic void cy_flush_buffer(struct tty_struct *tty) 1692978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox{ 1693978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox struct cyclades_port *info = tty->driver_data; 1694978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox struct cyclades_card *card; 1695978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox int channel, retval; 1696978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox unsigned long flags; 1697978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox 1698978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox#ifdef CY_DEBUG_IO 1699978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line); 1700978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox#endif 1701978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox 1702978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox if (serial_paranoia_check(info, tty->name, "cy_flush_buffer")) 1703978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox return; 1704978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox 1705978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox card = info->card; 1706978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox channel = info->line - card->first_line; 1707978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox 1708978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox spin_lock_irqsave(&card->card_lock, flags); 1709978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; 1710978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox spin_unlock_irqrestore(&card->card_lock, flags); 1711978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox 17122693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (cy_is_Z(card)) { /* If it is a Z card, flush the on-board 1713978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox buffers as well */ 1714978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox spin_lock_irqsave(&card->card_lock, flags); 1715978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L); 1716978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox if (retval != 0) { 1717978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d " 1718978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox "was %x\n", info->line, retval); 1719978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox } 1720978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox spin_unlock_irqrestore(&card->card_lock, flags); 1721978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox } 1722978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox tty_wakeup(tty); 1723978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox} /* cy_flush_buffer */ 1724978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox 1725978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox 1726e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Coxstatic void cy_do_close(struct tty_port *port) 17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1728e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox struct cyclades_port *info = container_of(port, struct cyclades_port, 1729e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox port); 17309fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby struct cyclades_card *card; 173102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 17323aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby int channel; 17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17349fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby card = info->card; 17353aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby channel = info->line - card->first_line; 17369fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 173702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 17382693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 173902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Stop accepting input */ 17403aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel & 0x03); 17413aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyRxData); 174277451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (info->port.flags & ASYNC_INITIALIZED) { 174315ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox /* Waiting for on-board buffers to be empty before 174415ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox closing the port */ 17459fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 1746e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox cy_wait_until_sent(port->tty, info->timeout); 17479fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 174802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 174902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 175002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#ifdef Z_WAKE 175115ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox /* Waiting for on-board buffers to be empty before closing 175215ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox the port */ 1753f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; 175402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int retval; 175502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 1756f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby if (readl(&ch_ctrl->flow_status) != C_FS_TXIDLE) { 17579fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L); 175802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 1759217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_close retval on " 1760217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "ttyC%d was %x\n", info->line, retval); 176102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 17629fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 17632c7fea992104b5ca2b510d585a27b3ba018b795fJiri Slaby wait_for_completion_interruptible(&info->shutdown_wait); 17649fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 176502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 176702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 17689fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 1769e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox cy_shutdown(info, port->tty); 1770e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox} 17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1772e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox/* 1773e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox * This routine is called when a particular tty device is closed. 1774e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox */ 1775e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Coxstatic void cy_close(struct tty_struct *tty, struct file *filp) 1776e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox{ 1777e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox struct cyclades_port *info = tty->driver_data; 1778e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox if (!info || serial_paranoia_check(info, tty->name, "cy_close")) 1779e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox return; 1780e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox tty_port_close(&info->port, tty, filp); 178102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_close */ 17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This routine gets called when tty_write has put something into 17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the write_queue. The characters may come from user space or 17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * kernel space. 17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine will return the number of characters actually 17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * accepted for writing. 17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the port is not already transmitting stuff, start it off by 17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * enabling interrupts. The interrupt service routine will then 17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ensure that the characters are sent. 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the port is already active, there is no need to kick it. 17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 179602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) 17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1798cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 179902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 180002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int c, ret = 0; 18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_IO 1803217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_write ttyC%d\n", info->line); 18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 180615ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (serial_paranoia_check(info, tty->name, "cy_write")) 180702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 180977451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (!info->port.xmit_buf) 181002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18129fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&info->card->card_lock, flags); 181302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby while (1) { 18141a4e2351e7fcf2d10bb5524b0ace7797ffad4d98Harvey Harrison c = min(count, (int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1)); 18151a4e2351e7fcf2d10bb5524b0ace7797ffad4d98Harvey Harrison c = min(c, (int)(SERIAL_XMIT_SIZE - info->xmit_head)); 181602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 181702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (c <= 0) 181802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 181902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 182077451e53e0a509a98eda272567869cfe96431ba9Alan Cox memcpy(info->port.xmit_buf + info->xmit_head, buf, c); 182102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->xmit_head = (info->xmit_head + c) & 182202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (SERIAL_XMIT_SIZE - 1); 182302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->xmit_cnt += c; 182402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby buf += c; 182502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby count -= c; 182602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret += c; 182702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 18289fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&info->card->card_lock, flags); 182902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 183002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->idle_stats.xmit_bytes += ret; 183102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->idle_stats.xmit_idle = jiffies; 183202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 183315ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) 183402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby start_xmit(info); 183515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox 183602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return ret; 183702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_write */ 18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine is called by the kernel to write a single 18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * character to the tty device. If the kernel uses this routine, 18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it must call the flush_chars() routine (if defined) when it is 18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * done stuffing characters into the driver. If there is no room 18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in the queue, the character is ignored. 18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 184676b25a5509bbafdbfc7d7d6b41a3c64947d59360Alan Coxstatic int cy_put_char(struct tty_struct *tty, unsigned char ch) 18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1848cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 184902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_IO 1852217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_put_char ttyC%d\n", info->line); 18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 185502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_put_char")) 185676b25a5509bbafdbfc7d7d6b41a3c64947d59360Alan Cox return 0; 18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 185877451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (!info->port.xmit_buf) 185976b25a5509bbafdbfc7d7d6b41a3c64947d59360Alan Cox return 0; 18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18619fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&info->card->card_lock, flags); 186290cc301859ea8840634324a7f5b9680312377667Jiri Slaby if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) { 18639fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&info->card->card_lock, flags); 186476b25a5509bbafdbfc7d7d6b41a3c64947d59360Alan Cox return 0; 186502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 186777451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.xmit_buf[info->xmit_head++] = ch; 186802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->xmit_head &= SERIAL_XMIT_SIZE - 1; 186902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->xmit_cnt++; 18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->idle_stats.xmit_bytes++; 18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->idle_stats.xmit_idle = jiffies; 18729fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&info->card->card_lock, flags); 187376b25a5509bbafdbfc7d7d6b41a3c64947d59360Alan Cox return 1; 187402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_put_char */ 18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine is called by the kernel after it has written a 187815ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox * series of characters to the tty device using put_char(). 18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 188002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_flush_chars(struct tty_struct *tty) 18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1882cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 188302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_IO 1885217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_flush_chars ttyC%d\n", info->line); 18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 188802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) 188902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 189102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || 189277451e53e0a509a98eda272567869cfe96431ba9Alan Cox !info->port.xmit_buf) 189302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 189502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby start_xmit(info); 189602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_flush_chars */ 18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine returns the numbers of characters the tty driver 19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * will accept for queuing to be written. This number is subject 19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to change as output buffers get emptied, or if the output flow 19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * control is activated. 19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 190402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int cy_write_room(struct tty_struct *tty) 19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1906cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 190702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int ret; 190802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_IO 1910217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_write_room ttyC%d\n", info->line); 19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 191302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_write_room")) 191402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 191502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; 191602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (ret < 0) 191702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret = 0; 191802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return ret; 191902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_write_room */ 19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 192102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int cy_chars_in_buffer(struct tty_struct *tty) 19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1923cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 192502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) 192602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 192702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef Z_EXT_CHARS_IN_BUFFER 1929f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby if (!cy_is_Z(info->card)) { 193002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* Z_EXT_CHARS_IN_BUFFER */ 19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_IO 1932217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", 1933217191910c0286e0b3c7e3011630273695253da3Jiri Slaby info->line, info->xmit_cnt); 19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 193502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return info->xmit_cnt; 19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef Z_EXT_CHARS_IN_BUFFER 193702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 1938f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl; 193902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int char_count; 1940ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby __u32 tx_put, tx_get, tx_bufsize; 194102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 1942db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby tx_get = readl(&buf_ctrl->tx_get); 1943db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby tx_put = readl(&buf_ctrl->tx_put); 1944db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby tx_bufsize = readl(&buf_ctrl->tx_bufsize); 194502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (tx_put >= tx_get) 194602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_count = tx_put - tx_get; 194702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else 194802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char_count = tx_put - tx_get + tx_bufsize; 19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_IO 1950217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", 1951217191910c0286e0b3c7e3011630273695253da3Jiri Slaby info->line, info->xmit_cnt + char_count); 19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1953096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return info->xmit_cnt + char_count; 195402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 195502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* Z_EXT_CHARS_IN_BUFFER */ 195602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_chars_in_buffer */ 19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 19591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ------------------------------------------------------------ 19601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cy_ioctl() and friends 19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ------------------------------------------------------------ 19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19641a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielkastatic void cyy_baud_calc(struct cyclades_port *info, __u32 baud) 19651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 196602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int co, co_val, bpr; 19671a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka __u32 cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : 196802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 25000000); 19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 197002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (baud == 0) { 197102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->tbpr = info->tco = info->rbpr = info->rco = 0; 197202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 197302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 19741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 197502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* determine which prescaler to use */ 197602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for (co = 4, co_val = 2048; co; co--, co_val >>= 2) { 197702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cy_clock / co_val / baud > 63) 197802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 197902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 198102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby bpr = (cy_clock / co_val * 2 / baud + 1) / 2; 198202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (bpr > 255) 198302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby bpr = 255; 19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 198502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->tbpr = info->rbpr = bpr; 198602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->tco = info->rco = co; 19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine finds or computes the various line characteristics. 19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * It used to be called config_setup 19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1993d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slabystatic void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty) 19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1995875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card; 199602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 19973aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby int channel; 199802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned cflag, iflag; 199902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int baud, baud_rate = 0; 200002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int i; 200102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 2002d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if (!tty->termios) /* XXX can this happen at all? */ 200302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 200415ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox 200515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (info->line == -1) 200602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 200715ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox 2008d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby cflag = tty->termios->c_cflag; 2009d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby iflag = tty->termios->c_iflag; 20101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 201202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * Set up the tty->alt_speed kludge 201302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 2014d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) 2015d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty->alt_speed = 57600; 2016d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) 2017d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty->alt_speed = 115200; 2018d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) 2019d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty->alt_speed = 230400; 2020d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) 2021d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty->alt_speed = 460800; 202202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 202302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby card = info->card; 2024875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby channel = info->line - card->first_line; 202502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 20262693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 202746fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby u32 cflags; 202846fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby 202902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* baud rate */ 2030d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby baud = tty_get_baud_rate(tty); 203177451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == 203202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ASYNC_SPD_CUST) { 203302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->custom_divisor) 203402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud_rate = info->baud / info->custom_divisor; 203502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else 203602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud_rate = info->baud; 203702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else if (baud > CD1400_MAX_SPEED) { 203802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud = CD1400_MAX_SPEED; 203902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 204002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* find the baud index */ 204102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for (i = 0; i < 20; i++) { 204215ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (baud == baud_table[i]) 204302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 204402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 204515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (i == 20) 204602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby i = 19; /* CD1400_MAX_SPEED */ 204702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 204877451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == 204902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ASYNC_SPD_CUST) { 205002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cyy_baud_calc(info, baud_rate); 205102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 205202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->chip_rev >= CD1400_REV_J) { 205302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* It is a CD1400 rev. J or later */ 205402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->tbpr = baud_bpr_60[i]; /* Tx BPR */ 205502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->tco = baud_co_60[i]; /* Tx CO */ 205602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->rbpr = baud_bpr_60[i]; /* Rx BPR */ 205702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->rco = baud_co_60[i]; /* Rx CO */ 205802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 205902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->tbpr = baud_bpr_25[i]; /* Tx BPR */ 206002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->tco = baud_co_25[i]; /* Tx CO */ 206102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->rbpr = baud_bpr_25[i]; /* Rx BPR */ 206202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->rco = baud_co_25[i]; /* Rx CO */ 206302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 206402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 206502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (baud_table[i] == 134) { 206602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* get it right for 134.5 baud */ 206702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) + 206802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 2; 206977451e53e0a509a98eda272567869cfe96431ba9Alan Cox } else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == 207002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ASYNC_SPD_CUST) { 207102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->timeout = (info->xmit_fifo_size * HZ * 15 / 207202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud_rate) + 2; 207302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else if (baud_table[i]) { 207402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->timeout = (info->xmit_fifo_size * HZ * 15 / 207502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud_table[i]) + 2; 207602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* this needs to be propagated into the card info */ 207702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 207802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->timeout = 0; 207902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 208002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* By tradition (is it a standard?) a baud rate of zero 208102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby implies the line should be/has been closed. A bit 208202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby later in this routine such a test is performed. */ 208302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 208402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* byte size and parity */ 208502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor5 = 0; 208602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor4 = 0; 208702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* receive threshold */ 208802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor3 = (info->default_threshold ? 208902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->default_threshold : baud_cor3[i]); 209002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor2 = CyETC; 209102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby switch (cflag & CSIZE) { 209202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CS5: 209302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor1 = Cy_5_BITS; 209402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 209502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CS6: 209602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor1 = Cy_6_BITS; 209702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 209802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CS7: 209902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor1 = Cy_7_BITS; 210002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 210102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CS8: 210202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor1 = Cy_8_BITS; 210302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 210402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 210515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (cflag & CSTOPB) 210602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor1 |= Cy_2_STOP; 210715ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox 210802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cflag & PARENB) { 210915ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (cflag & PARODD) 211002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor1 |= CyPARITY_O; 211115ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox else 211202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor1 |= CyPARITY_E; 211315ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox } else 211402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor1 |= CyPARITY_NONE; 211502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 211602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* CTS flow control flag */ 211702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cflag & CRTSCTS) { 211877451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags |= ASYNC_CTS_FLOW; 211902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor2 |= CyCtsAE; 212002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 212177451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags &= ~ASYNC_CTS_FLOW; 212202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor2 &= ~CyCtsAE; 212302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 212402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cflag & CLOCAL) 212577451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags &= ~ASYNC_CHECK_CD; 212602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else 212777451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags |= ASYNC_CHECK_CD; 21281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /*********************************************** 21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The hardware option, CyRtsAO, presents RTS when 21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the chip has characters to send. Since most modems 21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds use RTS as reverse (inbound) flow control, this 21331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds option is not used. If inbound flow control is 21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds necessary, DTR can be programmed to provide the 21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds appropriate signals for use with a non-standard 21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cable. Contact Marcio Saito for details. 21371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ***********************************************/ 21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 213902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby channel &= 0x03; 21401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21419fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 21423aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel); 214302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 214402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* tx and rx baud rate */ 214502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 21463aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyTCOR, info->tco); 21473aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyTBPR, info->tbpr); 21483aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyRCOR, info->rco); 21493aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyRBPR, info->rbpr); 215002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 215102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* set line characteristics according configuration */ 215202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 21533aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySCHR1, START_CHAR(tty)); 21543aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySCHR2, STOP_CHAR(tty)); 21553aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCOR1, info->cor1); 21563aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCOR2, info->cor2); 21573aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCOR3, info->cor3); 21583aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCOR4, info->cor4); 21593aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCOR5, info->cor5); 216002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 21613aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch | 21623aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby CyCOR3ch); 216302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 216415ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox /* !!! Is this needed? */ 21653aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel); 21663aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyRTPR, 216702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (info->default_timeout ? info->default_timeout : 0x02)); 216802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 10ms rx timeout */ 216902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 217046fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby cflags = CyCTS; 217146fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby if (!C_CLOCAL(tty)) 217246fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby cflags |= CyDSR | CyRI | CyDCD; 217346fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby /* without modem intr */ 217446fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyMdmCh); 217546fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby /* act on 1->0 modem transitions */ 217646fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby if ((cflag & CRTSCTS) && info->rflow) 217746fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby cyy_writeb(info, CyMCOR1, cflags | rflow_thr[i]); 217846fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby else 217946fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby cyy_writeb(info, CyMCOR1, cflags); 218046fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby /* act on 0->1 modem transitions */ 218146fb782522092f772c6ce2b129f201ca6e1e15a2Jiri Slaby cyy_writeb(info, CyMCOR2, cflags); 218202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 21834d7682005ca88a37667c4af03908798e188b5224Jiri Slaby if (i == 0) /* baud rate is zero, turn off line */ 21844d7682005ca88a37667c4af03908798e188b5224Jiri Slaby cyy_change_rts_dtr(info, 0, TIOCM_DTR); 21854d7682005ca88a37667c4af03908798e188b5224Jiri Slaby else 21864d7682005ca88a37667c4af03908798e188b5224Jiri Slaby cyy_change_rts_dtr(info, TIOCM_DTR, 0); 21871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2188d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby clear_bit(TTY_IO_ERROR, &tty->flags); 21899fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 21901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2192f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; 21931a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka __u32 sw_flow; 219402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int retval; 21951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21962693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cyz_is_loaded(card)) 219702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 21981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 219902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* baud rate */ 2200d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby baud = tty_get_baud_rate(tty); 220177451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == 220202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ASYNC_SPD_CUST) { 220302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->custom_divisor) 220402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud_rate = info->baud / info->custom_divisor; 220502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else 220602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud_rate = info->baud; 220702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else if (baud > CYZ_MAX_SPEED) { 220802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud = CYZ_MAX_SPEED; 220902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 221002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_baud, baud); 221102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 221202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (baud == 134) { 221302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* get it right for 134.5 baud */ 221402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) + 221502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 2; 221677451e53e0a509a98eda272567869cfe96431ba9Alan Cox } else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == 221702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ASYNC_SPD_CUST) { 221802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->timeout = (info->xmit_fifo_size * HZ * 15 / 221902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud_rate) + 2; 222002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else if (baud) { 222102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->timeout = (info->xmit_fifo_size * HZ * 15 / 222202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby baud) + 2; 222302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* this needs to be propagated into the card info */ 222402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 222502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->timeout = 0; 222602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 22271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 222802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* byte size and parity */ 222902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby switch (cflag & CSIZE) { 223002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CS5: 223102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_data_l, C_DL_CS5); 223202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 223302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CS6: 223402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_data_l, C_DL_CS6); 223502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 223602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CS7: 223702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_data_l, C_DL_CS7); 223802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 223902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CS8: 224002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_data_l, C_DL_CS8); 224102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 224202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 224302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cflag & CSTOPB) { 224402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_data_l, 2245db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby readl(&ch_ctrl->comm_data_l) | C_DL_2STOP); 224602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 224702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_data_l, 2248db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby readl(&ch_ctrl->comm_data_l) | C_DL_1STOP); 224902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 225002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cflag & PARENB) { 225115ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (cflag & PARODD) 225202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_parity, C_PR_ODD); 225315ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox else 225402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN); 225515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox } else 225602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->comm_parity, C_PR_NONE); 22571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 225802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* CTS flow control flag */ 225902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cflag & CRTSCTS) { 226002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->hw_flow, 2261db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS); 226202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 2263db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby cy_writel(&ch_ctrl->hw_flow, readl(&ch_ctrl->hw_flow) & 2264db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby ~(C_RS_CTS | C_RS_RTS)); 226502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 226602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* As the HW flow control is done in firmware, the driver 226702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby doesn't need to care about it */ 226877451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags &= ~ASYNC_CTS_FLOW; 226902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 227002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* XON/XOFF/XANY flow control flags */ 227102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby sw_flow = 0; 227202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (iflag & IXON) { 227302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby sw_flow |= C_FL_OXX; 227402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (iflag & IXANY) 227502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby sw_flow |= C_FL_OIXANY; 227602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 227702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->sw_flow, sw_flow); 227802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 2279875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L); 228002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 2281217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:set_line_char retval on ttyC%d " 2282217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "was %x\n", info->line, retval); 228302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 228402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 228502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* CD sensitivity */ 228615ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (cflag & CLOCAL) 228777451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags &= ~ASYNC_CHECK_CD; 228815ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox else 228977451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags |= ASYNC_CHECK_CD; 22901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 229102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (baud == 0) { /* baud rate is zero, turn off line */ 229202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->rs_control, 2293db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby readl(&ch_ctrl->rs_control) & ~C_RS_DTR); 22941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_DTR 2295217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:set_line_char dropping Z DTR\n"); 22961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 229702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 229802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writel(&ch_ctrl->rs_control, 2299db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby readl(&ch_ctrl->rs_control) | C_RS_DTR); 23001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_DTR 2301217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:set_line_char raising Z DTR\n"); 23021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 230302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 23041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 230515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); 230602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 2307217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:set_line_char(2) retval on ttyC%d " 2308217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "was %x\n", info->line, retval); 230902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 23101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2311d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby clear_bit(TTY_IO_ERROR, &tty->flags); 23121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 231302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* set_line_char */ 23141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23156c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slabystatic int cy_get_serial_info(struct cyclades_port *info, 231615ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox struct serial_struct __user *retinfo) 23171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2318875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *cinfo = info->card; 23196c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby struct serial_struct tmp = { 23206c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .type = info->type, 23216c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .line = info->line, 23226c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .port = (info->card - cy_card) * 0x100 + info->line - 23236c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby cinfo->first_line, 23246c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .irq = cinfo->irq, 23256c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .flags = info->port.flags, 23266c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .close_delay = info->port.close_delay, 23276c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .closing_wait = info->port.closing_wait, 23286c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .baud_base = info->baud, 23296c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .custom_divisor = info->custom_divisor, 23306c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby .hub6 = 0, /*!!! */ 23316c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby }; 233202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; 23336c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby} 23341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 2336d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slabycy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty, 233715ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox struct serial_struct __user *new_info) 23381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 233902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby struct serial_struct new_serial; 234025c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox int ret; 234102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 234202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) 234302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -EFAULT; 234402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 234525c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox mutex_lock(&info->port.mutex); 234602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!capable(CAP_SYS_ADMIN)) { 234744b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox if (new_serial.close_delay != info->port.close_delay || 234802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby new_serial.baud_base != info->baud || 234902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (new_serial.flags & ASYNC_FLAGS & 235002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ~ASYNC_USR_MASK) != 235177451e53e0a509a98eda272567869cfe96431ba9Alan Cox (info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)) 235225c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox { 235325c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox mutex_unlock(&info->port.mutex); 235402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -EPERM; 235525c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox } 235677451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) | 235702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (new_serial.flags & ASYNC_USR_MASK); 235802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->baud = new_serial.baud_base; 235902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->custom_divisor = new_serial.custom_divisor; 236002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby goto check_and_exit; 236102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 236202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 236302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 236402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * OK, past this point, all the error checking has been done. 236502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * At this point, we start making changes..... 236602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 236702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 236802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->baud = new_serial.baud_base; 236902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->custom_divisor = new_serial.custom_divisor; 237077451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags = (info->port.flags & ~ASYNC_FLAGS) | 237102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (new_serial.flags & ASYNC_FLAGS); 237244b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox info->port.close_delay = new_serial.close_delay * HZ / 100; 237344b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox info->port.closing_wait = new_serial.closing_wait * HZ / 100; 23741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscheck_and_exit: 237677451e53e0a509a98eda272567869cfe96431ba9Alan Cox if (info->port.flags & ASYNC_INITIALIZED) { 2377d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby cy_set_line_char(info, tty); 237825c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox ret = 0; 237902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 238025c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox ret = cy_startup(info, tty); 238102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 238225c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox mutex_unlock(&info->port.mutex); 238325c3cdf80c73156e910a322aba468ddaca0b91aeAlan Cox return ret; 238402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* set_serial_info */ 23851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 23871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get_lsr_info - get line status register info 23881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 23891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose: Let user call ioctl() to get info when the UART physically 23901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is emptied. On bus types like RS485, the transmitter must 23911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * release the bus after transmitting. This must be done when 23921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the transmit shift register is empty, not be done when the 23931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transmit holding register is empty. This functionality 23941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allows an RS485 driver to be written in user space. 23951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 239615ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Coxstatic int get_lsr_info(struct cyclades_port *info, unsigned int __user *value) 23971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 23983aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby struct cyclades_card *card = info->card; 239902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned int result; 240002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 24013aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby u8 status; 24021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24032693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 24049fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 24053aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby status = cyy_readb(info, CySRER) & (CyTxRdy | CyTxMpty); 24069fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 240702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby result = (status ? 0 : TIOCSER_TEMT); 240802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 240902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Not supported yet */ 241002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -EINVAL; 241102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 2412dbca36eab48ee48dfc60b8f41ffad54160ebdd09Dan Carpenter return put_user(result, value); 24131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241560b33c133ca0b7c0b6072c87234b63fee6e80558Alan Coxstatic int cy_tiocmget(struct tty_struct *tty) 24161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2417cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 2418875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card; 24193aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby int result; 242002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 2421bf9d89295233ae2ba7b312c78ee5657307b09f4cHarvey Harrison if (serial_paranoia_check(info, tty->name, __func__)) 242202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENODEV; 24231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 242402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby card = info->card; 24250d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby 24262693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 24270d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby unsigned long flags; 24283aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby int channel = info->line - card->first_line; 24293aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby u8 status; 24301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24319fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 24323aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel & 0x03); 24333aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby status = cyy_readb(info, CyMSVR1); 24343aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby status |= cyy_readb(info, CyMSVR2); 24359fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 243602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 243702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->rtsdtr_inv) { 243802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby result = ((status & CyRTS) ? TIOCM_DTR : 0) | 243902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ((status & CyDTR) ? TIOCM_RTS : 0); 244002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 244102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby result = ((status & CyRTS) ? TIOCM_RTS : 0) | 244202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ((status & CyDTR) ? TIOCM_DTR : 0); 244302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 244402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby result |= ((status & CyDCD) ? TIOCM_CAR : 0) | 244502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ((status & CyRI) ? TIOCM_RNG : 0) | 244602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ((status & CyDSR) ? TIOCM_DSR : 0) | 244702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ((status & CyCTS) ? TIOCM_CTS : 0); 24481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 24490d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby u32 lstatus; 24500d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby 24510d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby if (!cyz_is_loaded(card)) { 24520d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby result = -ENODEV; 24530d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby goto end; 245402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 24551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24560d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby lstatus = readl(&info->u.cyz.ch_ctrl->rs_status); 24570d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) | 24580d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) | 24590d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) | 24600d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby ((lstatus & C_RS_RI) ? TIOCM_RNG : 0) | 24610d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby ((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) | 24620d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); 246302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 24640d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slabyend: 246502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return result; 246602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_tiomget */ 24671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 246920b9d17715017ae4dd4ec87fabc36d33b9de708eAlan Coxcy_tiocmset(struct tty_struct *tty, 247002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned int set, unsigned int clear) 24711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2472cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 2473875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card; 247402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 247502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 2476bf9d89295233ae2ba7b312c78ee5657307b09f4cHarvey Harrison if (serial_paranoia_check(info, tty->name, __func__)) 247702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENODEV; 247802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 247902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby card = info->card; 24802693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 24814d7682005ca88a37667c4af03908798e188b5224Jiri Slaby spin_lock_irqsave(&card->card_lock, flags); 24824d7682005ca88a37667c4af03908798e188b5224Jiri Slaby cyy_change_rts_dtr(info, set, clear); 24834d7682005ca88a37667c4af03908798e188b5224Jiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 248402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 24850d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; 24860d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby int retval, channel = info->line - card->first_line; 24870d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby u32 rs; 24880d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby 24890d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby if (!cyz_is_loaded(card)) 24900d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby return -ENODEV; 24910d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby 24920d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby spin_lock_irqsave(&card->card_lock, flags); 24930d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby rs = readl(&ch_ctrl->rs_control); 24940d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby if (set & TIOCM_RTS) 24950d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby rs |= C_RS_RTS; 24960d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby if (clear & TIOCM_RTS) 24970d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby rs &= ~C_RS_RTS; 24980d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby if (set & TIOCM_DTR) { 24990d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby rs |= C_RS_DTR; 25001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_DTR 25010d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby printk(KERN_DEBUG "cyc:set_modem_info raising Z DTR\n"); 25021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 25030d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby } 25040d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby if (clear & TIOCM_DTR) { 25050d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby rs &= ~C_RS_DTR; 25061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_DTR 25070d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby printk(KERN_DEBUG "cyc:set_modem_info clearing " 25080d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby "Z DTR\n"); 25091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 251002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 25110d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby cy_writel(&ch_ctrl->rs_control, rs); 25129fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); 25130d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 251402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 2515217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d " 2516217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "was %x\n", info->line, retval); 251702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 25181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 251902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 25200d3487294e4e175eb6371c8df8ef44b45964e0f6Jiri Slaby} 25211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 25231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cy_break() --- routine which turns the break handling on or off 25241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 25259e98966c7bb94355689478bc84cc3e0c190f977eAlan Coxstatic int cy_break(struct tty_struct *tty, int break_state) 25261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2527cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 25289fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby struct cyclades_card *card; 252902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 25309e98966c7bb94355689478bc84cc3e0c190f977eAlan Cox int retval = 0; 25311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 253202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_break")) 25339e98966c7bb94355689478bc84cc3e0c190f977eAlan Cox return -EINVAL; 25341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25359fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby card = info->card; 25369fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby 25379fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 25382693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 253902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Let the transmit ISR take care of this (since it 254002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby requires stuffing characters into the output stream). 254102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 254202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (break_state == -1) { 254302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!info->breakon) { 254402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->breakon = 1; 254502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!info->xmit_cnt) { 25469fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 254702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby start_xmit(info); 25489fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 254902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 255002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 255102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 255202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!info->breakoff) { 255302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->breakoff = 1; 255402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!info->xmit_cnt) { 25559fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 255602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby start_xmit(info); 25579fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 255802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 255902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 25601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 256202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (break_state == -1) { 25639fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby retval = cyz_issue_cmd(card, 25649fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby info->line - card->first_line, 256502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby C_CM_SET_BREAK, 0L); 256602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 2567217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "cyc:cy_break (set) retval on " 2568217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "ttyC%d was %x\n", info->line, retval); 256902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 257002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 25719fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby retval = cyz_issue_cmd(card, 25729fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby info->line - card->first_line, 257302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby C_CM_CLR_BREAK, 0L); 257402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (retval != 0) { 2575217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_break (clr) retval " 2576217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "on ttyC%d was %x\n", info->line, 2577217191910c0286e0b3c7e3011630273695253da3Jiri Slaby retval); 257802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 25791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25819fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 25829e98966c7bb94355689478bc84cc3e0c190f977eAlan Cox return retval; 258302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_break */ 25841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 258502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int set_threshold(struct cyclades_port *info, unsigned long value) 25861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25873aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby struct cyclades_card *card = info->card; 258802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 25891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25902693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 259102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor3 &= ~CyREC_FIFO; 259202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->cor3 |= value & CyREC_FIFO; 25931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25949fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 25953aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCOR3, info->cor3); 25963aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR3ch); 25979fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 259802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 259902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 260002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* set_threshold */ 26011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 260215ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Coxstatic int get_threshold(struct cyclades_port *info, 260315ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox unsigned long __user *value) 26041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26053aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby struct cyclades_card *card = info->card; 26061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26072693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 26083aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby u8 tmp = cyy_readb(info, CyCOR3) & CyREC_FIFO; 260902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return put_user(tmp, value); 261002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 2611f742903424aae3fc7ea7079a3618d90634c0b301Jiri Slaby return 0; 261202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* get_threshold */ 26131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int set_timeout(struct cyclades_port *info, unsigned long value) 26151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26163aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby struct cyclades_card *card = info->card; 261702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 26181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26192693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 26209fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 26213aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyRTPR, value & 0xff); 26229fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 262302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 262402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return 0; 262502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* set_timeout */ 26261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 262715ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Coxstatic int get_timeout(struct cyclades_port *info, 262815ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox unsigned long __user *value) 26291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26303aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby struct cyclades_card *card = info->card; 26311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26322693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 26333aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby u8 tmp = cyy_readb(info, CyRTPR); 263402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return put_user(tmp, value); 263502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 2636f742903424aae3fc7ea7079a3618d90634c0b301Jiri Slaby return 0; 263702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* get_timeout */ 26381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26396c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slabystatic int cy_cflags_changed(struct cyclades_port *info, unsigned long arg, 26406c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby struct cyclades_icount *cprev) 26411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26426c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby struct cyclades_icount cnow; 26436c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby unsigned long flags; 26446c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby int ret; 26451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26466c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby spin_lock_irqsave(&info->card->card_lock, flags); 26476c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby cnow = info->icount; /* atomic copy */ 26486c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby spin_unlock_irqrestore(&info->card->card_lock, flags); 26496c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby 26506c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby ret = ((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) || 26516c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby ((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) || 26526c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby ((arg & TIOCM_CD) && (cnow.dcd != cprev->dcd)) || 26536c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby ((arg & TIOCM_CTS) && (cnow.cts != cprev->cts)); 26546c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby 26556c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby *cprev = cnow; 26566c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby 26576c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby return ret; 26586c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby} 26591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 26611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine allows the tty driver to implement device- 26621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * specific ioctl's. If the ioctl number passed in cmd is 26631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * not recognized by the driver, it should return ENOIOCTLCMD. 26641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 26651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 26666caa76b7786891b42b66a0e61e2c2fff2c884620Alan Coxcy_ioctl(struct tty_struct *tty, 266702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned int cmd, unsigned long arg) 26681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2669cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 26706c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby struct cyclades_icount cnow; /* kernel counter temps */ 267102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int ret_val = 0; 267202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 267302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby void __user *argp = (void __user *)arg; 267402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 267502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_ioctl")) 267602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return -ENODEV; 26771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OTHER 2679217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", 2680217191910c0286e0b3c7e3011630273695253da3Jiri Slaby info->line, cmd, arg); 26811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 26821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 268302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby switch (cmd) { 268402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYGETMON: 26856c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby if (copy_to_user(argp, &info->mon, sizeof(info->mon))) { 26866c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby ret_val = -EFAULT; 26876c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby break; 26886c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby } 26896c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby memset(&info->mon, 0, sizeof(info->mon)); 269002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 269102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYGETTHRESH: 269202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = get_threshold(info, argp); 269302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 269402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYSETTHRESH: 269502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = set_threshold(info, arg); 269602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 269702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYGETDEFTHRESH: 26986c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby ret_val = put_user(info->default_threshold, 26996c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby (unsigned long __user *)argp); 270002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 270102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYSETDEFTHRESH: 27026c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby info->default_threshold = arg & 0x0f; 270302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 270402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYGETTIMEOUT: 270502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = get_timeout(info, argp); 270602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 270702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYSETTIMEOUT: 270802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = set_timeout(info, arg); 270902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 271002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYGETDEFTIMEOUT: 27116c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby ret_val = put_user(info->default_timeout, 27126c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby (unsigned long __user *)argp); 271302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 271402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case CYSETDEFTIMEOUT: 27156c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby info->default_timeout = arg & 0xff; 271602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 27171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYSETRFLOW: 271802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->rflow = (int)arg; 271902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 27201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYGETRFLOW: 272102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = info->rflow; 272202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 27231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYSETRTSDTR_INV: 272402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->rtsdtr_inv = (int)arg; 272502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 27261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYGETRTSDTR_INV: 272702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = info->rtsdtr_inv; 272802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 27291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYGETCD1400VER: 273002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = info->chip_rev; 273102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 27321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_CYZ_INTR 27331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYZSETPOLLCYCLE: 273402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cyz_polling_cycle = (arg * HZ) / 1000; 273502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 27361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYZGETPOLLCYCLE: 273702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = (cyz_polling_cycle * 1000) / HZ; 273802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 273902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_CYZ_INTR */ 27401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYSETWAIT: 274144b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox info->port.closing_wait = (unsigned short)arg * HZ / 100; 274202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 27431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CYGETWAIT: 274444b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox ret_val = info->port.closing_wait / (HZ / 100); 274502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 274602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case TIOCGSERIAL: 27476c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby ret_val = cy_get_serial_info(info, argp); 274802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 274902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case TIOCSSERIAL: 2750d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby ret_val = cy_set_serial_info(info, tty, argp); 275102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 275202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby case TIOCSERGETLSR: /* Get line status register */ 275302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = get_lsr_info(info, argp); 275402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 275502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 275602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change 275702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * - mask passed in arg for lines of interest 275802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) 275902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * Caller should use TIOCGICOUNT to see which one it was 276002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 27611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TIOCMIWAIT: 27629fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&info->card->card_lock, flags); 276302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* note the counters on entry */ 27642c7fea992104b5ca2b510d585a27b3ba018b795fJiri Slaby cnow = info->icount; 27659fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&info->card->card_lock, flags); 2766bdc04e3174e18f475289fa8f4144f66686326b7eAlan Cox ret_val = wait_event_interruptible(info->port.delta_msr_wait, 27676c28181cf8b7d5af5f20a7bd102452033e14d946Jiri Slaby cy_cflags_changed(info, arg, &cnow)); 27682c7fea992104b5ca2b510d585a27b3ba018b795fJiri Slaby break; 27691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 277002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 277102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) 277202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * Return: write counters to the user passed counter struct 277302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * NB: both 1->0 and 0->1 transitions are counted except for 277402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * RI where only 0->1 is counted. 277502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 277602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby default: 277702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ret_val = -ENOIOCTLCMD; 277802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 27791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OTHER 2781217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_ioctl done\n"); 27821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 278302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return ret_val; 278402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_ioctl */ 27851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27860587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Coxstatic int cy_get_icount(struct tty_struct *tty, 27870587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox struct serial_icounter_struct *sic) 27880587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox{ 27890587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox struct cyclades_port *info = tty->driver_data; 27900587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox struct cyclades_icount cnow; /* Used to snapshot */ 27910587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox unsigned long flags; 27920587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox 27930587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox spin_lock_irqsave(&info->card->card_lock, flags); 27940587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox cnow = info->icount; 27950587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox spin_unlock_irqrestore(&info->card->card_lock, flags); 27960587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox 27970587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->cts = cnow.cts; 27980587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->dsr = cnow.dsr; 27990587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->rng = cnow.rng; 28000587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->dcd = cnow.dcd; 28010587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->rx = cnow.rx; 28020587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->tx = cnow.tx; 28030587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->frame = cnow.frame; 28040587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->overrun = cnow.overrun; 28050587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->parity = cnow.parity; 28060587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->brk = cnow.brk; 28070587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox sic->buf_overrun = cnow.buf_overrun; 28080587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox return 0; 28090587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox} 28100587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox 28111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 28121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine allows the tty driver to be notified when 28131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * device's termios settings have changed. Note that a 28141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * well-designed tty driver should be prepared to accept the case 28151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * where old == NULL, and try to do something rational. 28161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 281702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) 28181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2819cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 28201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OTHER 2822217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line); 28231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 28241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2825d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby cy_set_line_char(info, tty); 282602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 282702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if ((old_termios->c_cflag & CRTSCTS) && 282802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby !(tty->termios->c_cflag & CRTSCTS)) { 282902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tty->hw_stopped = 0; 283002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_start(tty); 283102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 28321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 283302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 283402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * No need to wake up processes in open wait, since they 283502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * sample the CLOCAL flag once, and don't recheck it. 283602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * XXX It's not clear whether the current behavior is correct 283702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * or not. Hence, this may change..... 283802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 283902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!(old_termios->c_cflag & CLOCAL) && 284002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (tty->termios->c_cflag & CLOCAL)) 284177451e53e0a509a98eda272567869cfe96431ba9Alan Cox wake_up_interruptible(&info->port.open_wait); 28421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 284302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_set_termios */ 28441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This function is used to send a high-priority XON/XOFF character to 28461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the device. 28471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 284802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_send_xchar(struct tty_struct *tty, char ch) 28491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2850cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 2851875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card; 2852875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby int channel; 28531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 285402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_send_xchar")) 28551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 28561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 285702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->x_char = ch; 28581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch) 286002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_start(tty); 28611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card = info->card; 2863875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby channel = info->line - card->first_line; 28641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28652693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (cy_is_Z(card)) { 286602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (ch == STOP_CHAR(tty)) 2867875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L); 286802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else if (ch == START_CHAR(tty)) 2869875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby cyz_issue_cmd(card, channel, C_CM_SENDXON, 0L); 28701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 28711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 28721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This routine is called by the upper-layer tty layer to signal 28741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds that incoming characters should be throttled because the input 28751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffers are close to full. 28761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 287702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_throttle(struct tty_struct *tty) 28781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2879cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 2880875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card; 288102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 28821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_THROTTLE 288402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char buf[64]; 28851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2886217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d\n", tty_name(tty, buf), 288702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tty->ldisc.chars_in_buffer(tty), info->line); 28881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 28891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 289015ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (serial_paranoia_check(info, tty->name, "cy_throttle")) 289102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 289202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 289302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby card = info->card; 289402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 289502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (I_IXOFF(tty)) { 28962693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) 289702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_send_xchar(tty, STOP_CHAR(tty)); 289802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else 289902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->throttle = 1; 290002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 29011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 290202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (tty->termios->c_cflag & CRTSCTS) { 29032693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 29049fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 29054d7682005ca88a37667c4af03908798e188b5224Jiri Slaby cyy_change_rts_dtr(info, 0, TIOCM_RTS); 29069fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 290702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 290802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->throttle = 1; 290902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 291002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 291102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_throttle */ 29121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 29141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine notifies the tty driver that it should signal 29151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that characters can now be sent to the tty without fear of 29161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * overrunning the input buffers of the line disciplines. 29171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 291802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_unthrottle(struct tty_struct *tty) 29191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2920cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 2921875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby struct cyclades_card *card; 292202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 29231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_THROTTLE 292502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby char buf[64]; 292602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 2927217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n", 292815ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox tty_name(tty, buf), tty_chars_in_buffer(tty), info->line); 29291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 29301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 293115ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) 293202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 29331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 293402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (I_IXOFF(tty)) { 293502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (info->x_char) 293602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->x_char = 0; 293702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby else 293802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_send_xchar(tty, START_CHAR(tty)); 29391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 294102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (tty->termios->c_cflag & CRTSCTS) { 294202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby card = info->card; 29432693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(card)) { 29449fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&card->card_lock, flags); 29454d7682005ca88a37667c4af03908798e188b5224Jiri Slaby cyy_change_rts_dtr(info, TIOCM_RTS, 0); 29469fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&card->card_lock, flags); 294702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 294802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby info->throttle = 0; 294902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 295002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 295102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_unthrottle */ 29521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* cy_start and cy_stop provide software output flow control as a 29541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds function of XON/XOFF, software CTS, and other such stuff. 29551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 295602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_stop(struct tty_struct *tty) 29571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 295802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby struct cyclades_card *cinfo; 2959cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 29603aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby int channel; 296102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 29621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OTHER 2964217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_stop ttyC%d\n", info->line); 29651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 29661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 296702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_stop")) 296802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 29691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2970875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby cinfo = info->card; 297102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby channel = info->line - cinfo->first_line; 29722693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(cinfo)) { 29739fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&cinfo->card_lock, flags); 29743aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel & 0x03); 29753aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy); 29769fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&cinfo->card_lock, flags); 297702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 297802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_stop */ 29791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 298002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_start(struct tty_struct *tty) 29811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 298202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby struct cyclades_card *cinfo; 2983cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 29843aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby int channel; 298502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned long flags; 29861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OTHER 2988217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_start ttyC%d\n", info->line); 29891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 29901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 299102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_start")) 299202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 29931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2994875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby cinfo = info->card; 299502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby channel = info->line - cinfo->first_line; 29962693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(cinfo)) { 29979fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_lock_irqsave(&cinfo->card_lock, flags); 29983aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel & 0x03); 29993aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy); 30009fa1b3b185a802fa0b3f764ad468efd64e1b582eJiri Slaby spin_unlock_irqrestore(&cinfo->card_lock, flags); 300102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 300202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_start */ 30031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 30051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cy_hangup() --- called by tty_hangup() when a hangup is signaled. 30061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 300702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void cy_hangup(struct tty_struct *tty) 30081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3009cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby struct cyclades_port *info = tty->driver_data; 301002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 30111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_DEBUG_OTHER 3012217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_DEBUG "cyc:cy_hangup ttyC%d\n", info->line); 30131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 30141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (serial_paranoia_check(info, tty->name, "cy_hangup")) 301602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return; 30171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_flush_buffer(tty); 3019d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby cy_shutdown(info, tty); 3020174e6fe01e7881caaa350b5e98e4c6189b6cb593Jiri Slaby tty_port_hangup(&info->port); 302102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_hangup */ 30221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3023f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slabystatic int cyy_carrier_raised(struct tty_port *port) 3024f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby{ 3025f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby struct cyclades_port *info = container_of(port, struct cyclades_port, 3026f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby port); 3027f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby struct cyclades_card *cinfo = info->card; 3028f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby unsigned long flags; 3029f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby int channel = info->line - cinfo->first_line; 3030f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby u32 cd; 3031f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3032f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby spin_lock_irqsave(&cinfo->card_lock, flags); 30333aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cyy_writeb(info, CyCAR, channel & 0x03); 30343aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby cd = cyy_readb(info, CyMSVR1) & CyDCD; 3035f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby spin_unlock_irqrestore(&cinfo->card_lock, flags); 3036f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3037f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby return cd; 3038f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby} 3039f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3040f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slabystatic void cyy_dtr_rts(struct tty_port *port, int raise) 3041f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby{ 3042f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby struct cyclades_port *info = container_of(port, struct cyclades_port, 3043f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby port); 3044f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby struct cyclades_card *cinfo = info->card; 3045f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby unsigned long flags; 3046f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3047f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby spin_lock_irqsave(&cinfo->card_lock, flags); 30484d7682005ca88a37667c4af03908798e188b5224Jiri Slaby cyy_change_rts_dtr(info, raise ? TIOCM_RTS | TIOCM_DTR : 0, 30494d7682005ca88a37667c4af03908798e188b5224Jiri Slaby raise ? 0 : TIOCM_RTS | TIOCM_DTR); 3050f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby spin_unlock_irqrestore(&cinfo->card_lock, flags); 3051f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby} 3052f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3053f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slabystatic int cyz_carrier_raised(struct tty_port *port) 3054f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby{ 3055f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby struct cyclades_port *info = container_of(port, struct cyclades_port, 3056f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby port); 3057f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3058f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby return readl(&info->u.cyz.ch_ctrl->rs_status) & C_RS_DCD; 3059f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby} 3060f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3061f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slabystatic void cyz_dtr_rts(struct tty_port *port, int raise) 3062f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby{ 3063f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby struct cyclades_port *info = container_of(port, struct cyclades_port, 3064f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby port); 3065f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby struct cyclades_card *cinfo = info->card; 3066f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; 3067f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby int ret, channel = info->line - cinfo->first_line; 3068f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby u32 rs; 3069f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3070f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby rs = readl(&ch_ctrl->rs_control); 3071f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby if (raise) 3072f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby rs |= C_RS_RTS | C_RS_DTR; 3073f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby else 3074f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby rs &= ~(C_RS_RTS | C_RS_DTR); 3075f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby cy_writel(&ch_ctrl->rs_control, rs); 3076f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby ret = cyz_issue_cmd(cinfo, channel, C_CM_IOCTLM, 0L); 3077f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby if (ret != 0) 3078f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby printk(KERN_ERR "%s: retval on ttyC%d was %x\n", 3079f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby __func__, info->line, ret); 3080f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby#ifdef CY_DEBUG_DTR 3081f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby printk(KERN_DEBUG "%s: raising Z DTR\n", __func__); 3082f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby#endif 3083f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby} 3084f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3085f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slabystatic const struct tty_port_operations cyy_port_ops = { 3086f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby .carrier_raised = cyy_carrier_raised, 3087f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby .dtr_rts = cyy_dtr_rts, 3088e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox .shutdown = cy_do_close, 3089f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby}; 3090f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 3091f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slabystatic const struct tty_port_operations cyz_port_ops = { 3092f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby .carrier_raised = cyz_carrier_raised, 3093f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby .dtr_rts = cyz_dtr_rts, 3094e936ffd5cb2b4c7ee04925c9b92b616c01f1e022Alan Cox .shutdown = cy_do_close, 3095f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby}; 3096f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby 30971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 30981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * --------------------------------------------------------------------- 30991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cy_init() and friends 31001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cy_init() is called at boot-time to initialize the serial driver. 31021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * --------------------------------------------------------------------- 31031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 31041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3105dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slabystatic int __devinit cy_init_card(struct cyclades_card *cinfo) 31060809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby{ 31070809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby struct cyclades_port *info; 3108f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby unsigned int channel, port; 31090809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby 31103046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby spin_lock_init(&cinfo->card_lock); 3111963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby cinfo->intr_enabled = 0; 31123046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby 3113963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby cinfo->ports = kcalloc(cinfo->nports, sizeof(*cinfo->ports), 3114963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby GFP_KERNEL); 3115dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby if (cinfo->ports == NULL) { 3116dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby printk(KERN_ERR "Cyclades: cannot allocate ports\n"); 3117dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby return -ENOMEM; 3118dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby } 3119dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby 3120f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby for (channel = 0, port = cinfo->first_line; channel < cinfo->nports; 3121f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby channel++, port++) { 3122f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby info = &cinfo->ports[channel]; 312344b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox tty_port_init(&info->port); 31243046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby info->magic = CYCLADES_MAGIC; 3125875b206b5f4971cc990a12e891f5519f0f6772a9Jiri Slaby info->card = cinfo; 31263046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby info->line = port; 31273046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby 312844b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox info->port.closing_wait = CLOSING_WAIT_DELAY; 312944b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox info->port.close_delay = 5 * HZ / 10; 313077451e53e0a509a98eda272567869cfe96431ba9Alan Cox info->port.flags = STD_COM_FLAGS; 31312c7fea992104b5ca2b510d585a27b3ba018b795fJiri Slaby init_completion(&info->shutdown_wait); 31323046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby 31332693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (cy_is_Z(cinfo)) { 3134f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct FIRM_ID *firm_id = cinfo->base_addr + ID_ADDRESS; 3135f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct ZFW_CTRL *zfw_ctrl; 3136f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby 3137f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby info->port.ops = &cyz_port_ops; 31380809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->type = PORT_STARTECH; 3139f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby 3140f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby zfw_ctrl = cinfo->base_addr + 3141f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby (readl(&firm_id->zfwctrl_addr) & 0xfffff); 3142f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby info->u.cyz.ch_ctrl = &zfw_ctrl->ch_ctrl[channel]; 3143f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby info->u.cyz.buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; 3144f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby 3145101b81590d8df0a74c33cf739886247c0a13f4afJiri Slaby if (cinfo->hw_ver == ZO_V1) 31460809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->xmit_fifo_size = CYZ_FIFO_SIZE; 31470809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby else 31483046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE; 31490809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby#ifdef CONFIG_CYZ_INTR 31503991428d9efc7185312196f82cc36e9df4a2ddb0Jiri Slaby setup_timer(&cyz_rx_full_timer[port], 31513991428d9efc7185312196f82cc36e9df4a2ddb0Jiri Slaby cyz_rx_restart, (unsigned long)info); 31520809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby#endif 31533046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby } else { 3154f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby unsigned short chip_number; 3155963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby int index = cinfo->bus_index; 3156f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby 3157f0737579424dd2c4e68bdd54c718455a3f42c7b5Jiri Slaby info->port.ops = &cyy_port_ops; 31580809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->type = PORT_CIRRUS; 31590809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->xmit_fifo_size = CyMAX_CHAR_FIFO; 31603046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; 31610809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->cor2 = CyETC; 31620809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->cor3 = 0x08; /* _very_ small rcv threshold */ 31633046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby 3164f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby chip_number = channel / CyPORTS_PER_CHIP; 31653aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby info->u.cyy.base_addr = cinfo->base_addr + 31663aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby (cy_chip_offset[chip_number] << index); 31673aeea5b92210083c7cffd4f08a0bb141d3f2d574Jiri Slaby info->chip_rev = cyy_readb(info, CyGFRCR); 316815ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox 316915ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (info->chip_rev >= CD1400_REV_J) { 31700809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby /* It is a CD1400 rev. J or later */ 31710809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->tbpr = baud_bpr_60[13]; /* Tx BPR */ 31720809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->tco = baud_co_60[13]; /* Tx CO */ 31730809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->rbpr = baud_bpr_60[13]; /* Rx BPR */ 31740809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->rco = baud_co_60[13]; /* Rx CO */ 31750809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->rtsdtr_inv = 1; 31760809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby } else { 31770809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->tbpr = baud_bpr_25[13]; /* Tx BPR */ 31780809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->tco = baud_co_25[13]; /* Tx CO */ 31790809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->rbpr = baud_bpr_25[13]; /* Rx BPR */ 31800809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->rco = baud_co_25[13]; /* Rx CO */ 31810809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby info->rtsdtr_inv = 0; 31820809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby } 31833046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby info->read_status_mask = CyTIMEOUT | CySPECHAR | 31843046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby CyBREAK | CyPARITY | CyFRAME | CyOVERRUN; 31850809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby } 31863046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby 31870809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby } 31883046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby 31893046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby#ifndef CONFIG_CYZ_INTR 31902693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (cy_is_Z(cinfo) && !timer_pending(&cyz_timerlist)) { 31913046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby mod_timer(&cyz_timerlist, jiffies + 1); 31923046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby#ifdef CY_PCI_DEBUG 31933046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby printk(KERN_DEBUG "Cyclades-Z polling initialized\n"); 31943046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby#endif 31953046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby } 31963046d50ea58676759453faeefccf57fbc9b72a90Jiri Slaby#endif 3197dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby return 0; 31980809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby} 31990809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby 32001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* initialize chips on Cyclom-Y card -- return number of valid 32011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chips (which is number of ports/4) */ 320231b4f0a118a7ade8444059ec898af8f07de206e9Jiri Slabystatic unsigned short __devinit cyy_init_card(void __iomem *true_base_addr, 320331b4f0a118a7ade8444059ec898af8f07de206e9Jiri Slaby int index) 32041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 320502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned int chip_number; 320602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby void __iomem *base_addr; 320702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 320802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(true_base_addr + (Cy_HwReset << index), 0); 320902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Cy_HwReset is 0x1400 */ 321002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(true_base_addr + (Cy_ClrIntr << index), 0); 321102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Cy_ClrIntr is 0x1800 */ 321202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby udelay(500L); 321302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 321415ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD; 321515ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox chip_number++) { 321602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby base_addr = 321702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby true_base_addr + (cy_chip_offset[chip_number] << index); 321802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby mdelay(1); 3219db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby if (readb(base_addr + (CyCCR << index)) != 0x00) { 322002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /************* 322102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby printk(" chip #%d at %#6lx is never idle (CCR != 0)\n", 322202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby chip_number, (unsigned long)base_addr); 322302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby *************/ 322402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return chip_number; 322502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 322602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 322702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(base_addr + (CyGFRCR << index), 0); 322802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby udelay(10L); 322902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 323002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* The Cyclom-16Y does not decode address bit 9 and therefore 323102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cannot distinguish between references to chip 0 and a non- 323202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby existent chip 4. If the preceding clearing of the supposed 323302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby chip 4 GFRCR register appears at chip 0, there is no chip 4 323402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby and this must be a Cyclom-16Y, not a Cyclom-32Ye. 323502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 3236db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby if (chip_number == 4 && readb(true_base_addr + 323702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (cy_chip_offset[0] << index) + 323802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (CyGFRCR << index)) == 0) { 323902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return chip_number; 324002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 324102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 324202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET); 324302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby mdelay(1); 324402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 3245db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby if (readb(base_addr + (CyGFRCR << index)) == 0x00) { 324602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 324702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby printk(" chip #%d at %#6lx is not responding ", 324802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby chip_number, (unsigned long)base_addr); 324902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby printk("(GFRCR stayed 0)\n", 325002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 325102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return chip_number; 325202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 3253db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby if ((0xf0 & (readb(base_addr + (CyGFRCR << index)))) != 325402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 0x40) { 325502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 325602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby printk(" chip #%d at %#6lx is not valid (GFRCR == " 325702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby "%#2x)\n", 325802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby chip_number, (unsigned long)base_addr, 325902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby base_addr[CyGFRCR<<index]); 326002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 326102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return chip_number; 326202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 326302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(base_addr + (CyGCR << index), CyCH0_SERIAL); 3264db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby if (readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) { 326502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* It is a CD1400 rev. J or later */ 326602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Impossible to reach 5ms with this chip. 326702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby Changed to 2ms instead (f = 500 Hz). */ 326802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(base_addr + (CyPPR << index), CyCLOCK_60_2MS); 326902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } else { 327002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* f = 200 Hz */ 327102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_writeb(base_addr + (CyPPR << index), CyCLOCK_25_5MS); 327202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 32731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 327402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* 327502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby printk(" chip #%d at %#6lx is rev 0x%2x\n", 327602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby chip_number, (unsigned long)base_addr, 3277db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby readb(base_addr+(CyGFRCR<<index))); 327802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */ 327902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 328002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby return chip_number; 328102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cyy_init_card */ 32821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 32841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * --------------------------------------------------------------------- 32851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cy_detect_isa() - Probe for Cyclom-Y/ISA boards. 32861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sets global variables and return the number of ISA boards found. 32871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * --------------------------------------------------------------------- 32881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 328902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int __init cy_detect_isa(void) 32901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 32911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_ISA 329202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned short cy_isa_irq, nboard; 329302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby void __iomem *cy_isa_address; 329402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned short i, j, cy_isa_nchan; 329502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby int isparam = 0; 32961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 329702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby nboard = 0; 32981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check for module parameters */ 330002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for (i = 0; i < NR_CARDS; i++) { 330102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (maddr[i] || i) { 330202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby isparam = 1; 330302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_isa_addresses[i] = maddr[i]; 330402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 330502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!maddr[i]) 330602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 33071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 33081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 330902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* scan the address table probing for Cyclom-Y/ISA boards */ 331002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for (i = 0; i < NR_ISA_ADDRS; i++) { 331102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby unsigned int isa_address = cy_isa_addresses[i]; 331215ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (isa_address == 0x0000) 3313096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return nboard; 33141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* probe for CD1400... */ 3316cd989b3a8c30148c872c7677c7a0415584f1658cAlan Cox cy_isa_address = ioremap_nocache(isa_address, CyISA_Ywin); 33173137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (cy_isa_address == NULL) { 33183137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby printk(KERN_ERR "Cyclom-Y/ISA: can't remap base " 33193137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "address\n"); 33203137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby continue; 33213137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 332202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_isa_nchan = CyPORTS_PER_CHIP * 332302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cyy_init_card(cy_isa_address, 0); 332402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cy_isa_nchan == 0) { 33253137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby iounmap(cy_isa_address); 332602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby continue; 332702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 33282090436357c20afad377a61c789f502c36d637deBartlomiej Zolnierkiewicz 3329196b3167efd13a02cdd34acc1a12316b9f45f41dRoel Kluin if (isparam && i < NR_CARDS && irq[i]) 333002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_isa_irq = irq[i]; 33311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 333202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* find out the board's irq by probing */ 333302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_isa_irq = detect_isa_irq(cy_isa_address); 333402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (cy_isa_irq == 0) { 3335217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but the " 3336217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "IRQ could not be detected.\n", 333702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (unsigned long)cy_isa_address); 33383137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby iounmap(cy_isa_address); 333902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby continue; 334002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 334102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 334202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) { 3343217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no " 3344217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "more channels are available. Change NR_PORTS " 3345217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "in cyclades.c and recompile kernel.\n", 334602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (unsigned long)cy_isa_address); 33473137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby iounmap(cy_isa_address); 3348096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return nboard; 334902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 335002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* fill the next cy_card structure available */ 335102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for (j = 0; j < NR_CARDS; j++) { 3352f742903424aae3fc7ea7079a3618d90634c0b301Jiri Slaby if (cy_card[j].base_addr == NULL) 335302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby break; 335402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 335502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (j == NR_CARDS) { /* no more cy_cards available */ 3356217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no " 3357217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "more cards can be used. Change NR_CARDS in " 3358217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "cyclades.c and recompile kernel.\n", 335902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (unsigned long)cy_isa_address); 33603137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby iounmap(cy_isa_address); 3361096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return nboard; 336202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 336302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 336402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* allocate IRQ */ 336502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (request_irq(cy_isa_irq, cyy_interrupt, 33669cfb5c05fee914cc65d4706801f6bc424082b5f5Yong Zhang 0, "Cyclom-Y", &cy_card[j])) { 3367217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but " 3368217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "could not allocate IRQ#%d.\n", 3369217191910c0286e0b3c7e3011630273695253da3Jiri Slaby (unsigned long)cy_isa_address, cy_isa_irq); 33703137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby iounmap(cy_isa_address); 3371096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return nboard; 337202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 337302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 337402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* set cy_card */ 337502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_card[j].base_addr = cy_isa_address; 337697e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby cy_card[j].ctl_addr.p9050 = NULL; 337702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_card[j].irq = (int)cy_isa_irq; 337802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_card[j].bus_index = 0; 337902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_card[j].first_line = cy_next_channel; 3380963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP; 3381963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby cy_card[j].nports = cy_isa_nchan; 33823137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (cy_init_card(&cy_card[j])) { 33833137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_card[j].base_addr = NULL; 33843137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby free_irq(cy_isa_irq, &cy_card[j]); 33853137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby iounmap(cy_isa_address); 33863137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby continue; 33873137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 338802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby nboard++; 338902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 3390217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_INFO "Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d found: " 3391217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "%d channels starting from port %d\n", 339202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby j + 1, (unsigned long)cy_isa_address, 339302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)), 3394217191910c0286e0b3c7e3011630273695253da3Jiri Slaby cy_isa_irq, cy_isa_nchan, cy_next_channel); 3395217191910c0286e0b3c7e3011630273695253da3Jiri Slaby 33966ad1ccc196f76833f41b187e01a28a024fe11f8bJiri Slaby for (j = cy_next_channel; 33976ad1ccc196f76833f41b187e01a28a024fe11f8bJiri Slaby j < cy_next_channel + cy_isa_nchan; j++) 33986ad1ccc196f76833f41b187e01a28a024fe11f8bJiri Slaby tty_register_device(cy_serial_driver, j, NULL); 339902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_next_channel += cy_isa_nchan; 340002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 3401096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return nboard; 34021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 3403096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby return 0; 340402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_ISA */ 340502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_detect_isa */ 34061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 340758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby#ifdef CONFIG_PCI 3408054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slabystatic inline int __devinit cyc_isfwstr(const char *str, unsigned int size) 3409054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby{ 3410054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby unsigned int a; 3411054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3412054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby for (a = 0; a < size && *str; a++, str++) 3413054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (*str & 0x80) 3414054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3415054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3416054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby for (; a < size; a++, str++) 3417054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (*str) 3418054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3419054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3420054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return 0; 3421054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby} 3422054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3423f61e761e2128c7ca0d044651b18928991ab03be2David Woodhousestatic inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data, 3424054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby unsigned int size) 3425054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby{ 3426054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby for (; size > 0; size--) { 3427054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(fpga, *data++); 3428054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby udelay(10); 3429054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3430054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby} 3431054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3432054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slabystatic void __devinit plx_init(struct pci_dev *pdev, int irq, 3433054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby struct RUNTIME_9060 __iomem *addr) 34341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 343502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Reset PLX */ 3436054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x40000000); 343702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby udelay(100L); 3438054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x40000000); 343902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 344002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Reload Config. Registers from EEPROM */ 3441054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x20000000); 344202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby udelay(100L); 3443054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x20000000); 3444054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3445054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* For some yet unknown reason, once the PLX9060 reloads the EEPROM, 3446054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby * the IRQ is lost and, thus, we have to re-write it to the PCI config. 3447054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby * registers. This will remain here until we find a permanent fix. 3448054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby */ 3449054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq); 3450054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby} 3451054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3452054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slabystatic int __devinit __cyz_load_fw(const struct firmware *fw, 3453054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby const char *name, const u32 mailbox, void __iomem *base, 3454054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby void __iomem *fpga) 3455054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby{ 3456f61e761e2128c7ca0d044651b18928991ab03be2David Woodhouse const void *ptr = fw->data; 3457f61e761e2128c7ca0d044651b18928991ab03be2David Woodhouse const struct zfile_header *h = ptr; 3458f61e761e2128c7ca0d044651b18928991ab03be2David Woodhouse const struct zfile_config *c, *cs; 3459f61e761e2128c7ca0d044651b18928991ab03be2David Woodhouse const struct zfile_block *b, *bs; 3460054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby unsigned int a, tmp, len = fw->size; 3461054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby#define BAD_FW KERN_ERR "Bad firmware: " 3462054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (len < sizeof(*h)) { 3463054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby printk(BAD_FW "too short: %u<%zu\n", len, sizeof(*h)); 3464054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3465054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3466054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3467054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cs = ptr + h->config_offset; 3468054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby bs = ptr + h->block_offset; 3469054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3470054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if ((void *)(cs + h->n_config) > ptr + len || 3471054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby (void *)(bs + h->n_blocks) > ptr + len) { 3472054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby printk(BAD_FW "too short"); 3473054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3474054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3475054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3476054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (cyc_isfwstr(h->name, sizeof(h->name)) || 3477054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cyc_isfwstr(h->date, sizeof(h->date))) { 3478054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby printk(BAD_FW "bad formatted header string\n"); 3479054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3480054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3481054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3482054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (strncmp(name, h->name, sizeof(h->name))) { 3483054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby printk(BAD_FW "bad name '%s' (expected '%s')\n", h->name, name); 3484054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3485054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3486054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3487054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby tmp = 0; 3488054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby for (c = cs; c < cs + h->n_config; c++) { 3489054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby for (a = 0; a < c->n_blocks; a++) 3490054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (c->block_list[a] > h->n_blocks) { 3491054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby printk(BAD_FW "bad block ref number in cfgs\n"); 3492054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3493054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3494054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (c->mailbox == mailbox && c->function == 0) /* 0 is normal */ 3495054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby tmp++; 3496054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3497054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (!tmp) { 3498054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby printk(BAD_FW "nothing appropriate\n"); 3499054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3500054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3501054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3502054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby for (b = bs; b < bs + h->n_blocks; b++) 3503054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (b->file_offset + b->size > len) { 3504054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby printk(BAD_FW "bad block data offset\n"); 3505054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return -EINVAL; 3506054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3507054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3508054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* everything is OK, let's seek'n'load it */ 3509054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby for (c = cs; c < cs + h->n_config; c++) 3510054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (c->mailbox == mailbox && c->function == 0) 3511054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby break; 3512054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3513054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby for (a = 0; a < c->n_blocks; a++) { 3514054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby b = &bs[c->block_list[a]]; 3515054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (b->type == ZBLOCK_FPGA) { 3516054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (fpga != NULL) 3517054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cyz_fpga_copy(fpga, ptr + b->file_offset, 3518054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby b->size); 3519054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } else { 3520054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (base != NULL) 3521054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby memcpy_toio(base + b->ram_offset, 3522054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby ptr + b->file_offset, b->size); 3523054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3524054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3525054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby#undef BAD_FW 3526054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return 0; 3527054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby} 3528054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3529054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slabystatic int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, 3530054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby struct RUNTIME_9060 __iomem *ctl_addr, int irq) 3531054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby{ 3532054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby const struct firmware *fw; 3533054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby struct FIRM_ID __iomem *fid = base_addr + ID_ADDRESS; 3534054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby struct CUSTOM_REG __iomem *cust = base_addr; 3535054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby struct ZFW_CTRL __iomem *pt_zfwctrl; 3536c4923b4f13156455a9e84f0b918866aef300cc57Jiri Slaby void __iomem *tmp; 3537963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby u32 mailbox, status, nchan; 3538054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby unsigned int i; 3539054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby int retval; 3540054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3541054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby retval = request_firmware(&fw, "cyzfirm.bin", &pdev->dev); 3542054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (retval) { 3543054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_err(&pdev->dev, "can't get firmware\n"); 3544054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby goto err; 3545054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3546054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3547054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* Check whether the firmware is already loaded and running. If 3548054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby positive, skip this board */ 35492693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (__cyz_fpga_loaded(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) { 3550054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby u32 cntval = readl(base_addr + 0x190); 3551054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3552054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby udelay(100); 3553054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (cntval != readl(base_addr + 0x190)) { 3554054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* FW counter is working, FW is running */ 3555054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_dbg(&pdev->dev, "Cyclades-Z FW already loaded. " 3556054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "Skipping board.\n"); 3557054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby retval = 0; 3558054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby goto err_rel; 3559054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3560054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3561054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3562054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* start boot */ 3563054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) & 3564054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby ~0x00030800UL); 3565054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3566054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby mailbox = readl(&ctl_addr->mail_box_0); 3567054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 35682693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (mailbox == 0 || __cyz_fpga_loaded(ctl_addr)) { 3569054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* stops CPU and set window to beginning of RAM */ 3570054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); 3571054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&cust->cpu_stop, 0); 3572054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); 3573054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby udelay(100); 3574054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3575054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3576054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby plx_init(pdev, irq, ctl_addr); 3577054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3578054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (mailbox != 0) { 3579054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* load FPGA */ 3580054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, NULL, 3581054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby base_addr); 3582054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (retval) 3583054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby goto err_rel; 35842693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!__cyz_fpga_loaded(ctl_addr)) { 3585054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_err(&pdev->dev, "fw upload successful, but fw is " 3586054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "not loaded\n"); 3587054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby goto err_rel; 3588054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3589054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3590054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3591054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* stops CPU and set window to beginning of RAM */ 3592054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); 3593054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&cust->cpu_stop, 0); 3594054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); 3595054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby udelay(100); 3596054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3597054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* clear memory */ 3598c4923b4f13156455a9e84f0b918866aef300cc57Jiri Slaby for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++) 3599054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writeb(tmp, 255); 3600054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (mailbox != 0) { 3601054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* set window to last 512K of RAM */ 3602054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_RAM + RAM_SIZE); 3603c4923b4f13156455a9e84f0b918866aef300cc57Jiri Slaby for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++) 3604054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writeb(tmp, 255); 3605054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* set window to beginning of RAM */ 3606054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); 3607054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3608054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3609054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, base_addr, NULL); 3610054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby release_firmware(fw); 3611054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (retval) 3612054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby goto err; 3613054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3614054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* finish boot and start boards */ 3615054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); 3616054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&cust->cpu_start, 0); 3617054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); 3618054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby i = 0; 3619054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby while ((status = readl(&fid->signature)) != ZFIRM_ID && i++ < 40) 3620054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby msleep(100); 3621054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (status != ZFIRM_ID) { 3622054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (status == ZFIRM_HLT) { 3623054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_err(&pdev->dev, "you need an external power supply " 3624054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "for this number of ports. Firmware halted and " 3625054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "board reset.\n"); 3626054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby retval = -EIO; 3627054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby goto err; 3628054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3629054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_warn(&pdev->dev, "fid->signature = 0x%x... Waiting " 3630054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "some more time\n", status); 3631054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby while ((status = readl(&fid->signature)) != ZFIRM_ID && 3632054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby i++ < 200) 3633054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby msleep(100); 3634054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby if (status != ZFIRM_ID) { 3635054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_err(&pdev->dev, "Board not started in 20 seconds! " 3636054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "Giving up. (fid->signature = 0x%x)\n", 3637054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby status); 3638054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_info(&pdev->dev, "*** Warning ***: if you are " 3639054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "upgrading the FW, please power cycle the " 3640054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "system before loading the new FW to the " 3641054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "Cyclades-Z.\n"); 3642054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 36432693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (__cyz_fpga_loaded(ctl_addr)) 3644054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby plx_init(pdev, irq, ctl_addr); 3645054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3646054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby retval = -EIO; 3647054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby goto err; 3648054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3649054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_dbg(&pdev->dev, "Firmware started after %d seconds.\n", 3650054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby i / 10); 3651054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3652054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby pt_zfwctrl = base_addr + readl(&fid->zfwctrl_addr); 3653054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3654054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_dbg(&pdev->dev, "fid=> %p, zfwctrl_addr=> %x, npt_zfwctrl=> %p\n", 3655054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr), 3656054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby base_addr + readl(&fid->zfwctrl_addr)); 3657054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3658963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby nchan = readl(&pt_zfwctrl->board_ctrl.n_channel); 3659054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n", 3660963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby readl(&pt_zfwctrl->board_ctrl.fw_version), nchan); 3661054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3662963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby if (nchan == 0) { 3663054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please " 3664054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "check the connection between the Z host card and the " 3665054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "serial expanders.\n"); 3666054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 36672693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (__cyz_fpga_loaded(ctl_addr)) 3668054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby plx_init(pdev, irq, ctl_addr); 3669054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3670054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby dev_info(&pdev->dev, "Null number of ports detected. Board " 3671054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby "reset.\n"); 3672054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby retval = 0; 3673054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby goto err; 3674054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby } 3675054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3676054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&pt_zfwctrl->board_ctrl.op_system, C_OS_LINUX); 3677054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&pt_zfwctrl->board_ctrl.dr_version, DRIVER_VERSION); 3678054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3679054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby /* 3680054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby Early firmware failed to start looking for commands. 3681054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby This enables firmware interrupts for those commands. 3682054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby */ 3683054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) | 3684054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby (1 << 17)); 3685054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) | 3686054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 0x00030800UL); 3687054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby 3688963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby return nchan; 3689054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slabyerr_rel: 3690054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby release_firmware(fw); 3691054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slabyerr: 3692054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby return retval; 36931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 36941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 369558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slabystatic int __devinit cy_pci_probe(struct pci_dev *pdev, 369658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby const struct pci_device_id *ent) 36971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 36983137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby void __iomem *addr0 = NULL, *addr2 = NULL; 36993137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby char *card_name = NULL; 3700101b81590d8df0a74c33cf739886247c0a13f4afJiri Slaby u32 uninitialized_var(mailbox); 37013137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby unsigned int device_id, nchan = 0, card_no, i; 37023137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby unsigned char plx_ver; 37033137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby int retval, irq; 370402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 370558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby retval = pci_enable_device(pdev); 370658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby if (retval) { 370758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby dev_err(&pdev->dev, "cannot enable device\n"); 37083137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err; 370958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 37101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby /* read PCI configuration area */ 37123137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby irq = pdev->irq; 371358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby device_id = pdev->device & ~PCI_DEVICE_ID_MASK; 37141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37153137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby#if defined(__alpha__) 37163137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ 37173137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "Cyclom-Y/PCI not supported for low " 37183137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "addresses on Alpha systems.\n"); 37193137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby retval = -EIO; 37203137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_dis; 37213137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 37223137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby#endif 37233137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) { 37243137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "Cyclades-Z/PCI not supported for low " 37253137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "addresses\n"); 37263137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby retval = -EIO; 37273137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_dis; 37283137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 37293137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby 37303137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { 37313137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_warn(&pdev->dev, "PCI I/O bit incorrectly set. Ignoring " 37323137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "it...\n"); 37333137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby pdev->resource[2].flags &= ~IORESOURCE_IO; 37343137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 37353137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby 37363137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby retval = pci_request_regions(pdev, "cyclades"); 37373137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (retval) { 37383137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "failed to reserve resources\n"); 37393137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_dis; 37403137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 37413137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby 37423137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby retval = -EIO; 374358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || 374458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { 37453137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby card_name = "Cyclom-Y"; 37461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 374724e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby addr0 = ioremap_nocache(pci_resource_start(pdev, 0), 374824e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby CyPCI_Yctl); 37493137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (addr0 == NULL) { 37503137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "can't remap ctl region\n"); 37513137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_reg; 375258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 375324e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby addr2 = ioremap_nocache(pci_resource_start(pdev, 2), 375424e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby CyPCI_Ywin); 37553137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (addr2 == NULL) { 37563137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "can't remap base region\n"); 37573137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_unmap; 375858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 37591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37603137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby nchan = CyPORTS_PER_CHIP * cyy_init_card(addr2, 1); 37613137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (nchan == 0) { 3762217191910c0286e0b3c7e3011630273695253da3Jiri Slaby dev_err(&pdev->dev, "Cyclom-Y PCI host card with no " 3763217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "Serial-Modules\n"); 3764c847d47cb7b2fa78b17c9e17ed3fbd010ee3d3caAndrew Morton goto err_unmap; 376558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 376658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { 37673137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby struct RUNTIME_9060 __iomem *ctl_addr; 3768217191910c0286e0b3c7e3011630273695253da3Jiri Slaby 376924e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby ctl_addr = addr0 = ioremap_nocache(pci_resource_start(pdev, 0), 377024e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby CyPCI_Zctl); 37713137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (addr0 == NULL) { 37723137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "can't remap ctl region\n"); 37733137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_reg; 37743137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 377558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby 377658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby /* Disable interrupts on the PLX before resetting it */ 377797e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby cy_writew(&ctl_addr->intr_ctrl_stat, 377897e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby readw(&ctl_addr->intr_ctrl_stat) & ~0x0900); 377958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby 3780054f5b0aaa58dfc841635e52b6c1cc2b14ec37fcJiri Slaby plx_init(pdev, irq, addr0); 378102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 3782101b81590d8df0a74c33cf739886247c0a13f4afJiri Slaby mailbox = readl(&ctl_addr->mail_box_0); 378358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby 378424e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby addr2 = ioremap_nocache(pci_resource_start(pdev, 2), 378524e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin); 37863137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (addr2 == NULL) { 37873137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "can't remap base region\n"); 37883137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_unmap; 378958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 379058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby 379158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby if (mailbox == ZE_V1) { 37923137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby card_name = "Cyclades-Ze"; 379358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } else { 37943137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby card_name = "Cyclades-8Zo"; 37951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CY_PCI_DEBUG 37963137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (mailbox == ZO_V1) { 37973137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); 37983137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_info(&pdev->dev, "Cyclades-8Zo/PCI: FPGA " 37993137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "id %lx, ver %lx\n", (ulong)(0xff & 38003137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby readl(&((struct CUSTOM_REG *)addr2)-> 38013137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby fpga_id)), (ulong)(0xff & 38023137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby readl(&((struct CUSTOM_REG *)addr2)-> 38033137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby fpga_version))); 38043137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); 38053137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } else { 38063137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_info(&pdev->dev, "Cyclades-Z/PCI: New " 38073137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "Cyclades-Z board. FPGA not loaded\n"); 38083137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 38091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 38103137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby /* The following clears the firmware id word. This 38113137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby ensures that the driver will not attempt to talk to 38123137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby the board until it has been properly initialized. 38133137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby */ 38143137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) 38153137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_writel(addr2 + ID_ADDRESS, 0L); 381658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 3817ace08c3c4403140e5ce82116c8f2acb38f58f61dJiri Slaby 3818ace08c3c4403140e5ce82116c8f2acb38f58f61dJiri Slaby retval = cyz_load_fw(pdev, addr2, addr0, irq); 3819963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby if (retval <= 0) 3820ace08c3c4403140e5ce82116c8f2acb38f58f61dJiri Slaby goto err_unmap; 3821963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby nchan = retval; 38223137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 38233137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby 38243137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if ((cy_next_channel + nchan) > NR_PORTS) { 38253137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no " 38263137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "channels are available. Change NR_PORTS in " 38273137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "cyclades.c and recompile kernel.\n"); 38283137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_unmap; 38293137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 38303137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby /* fill the next cy_card structure available */ 38313137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby for (card_no = 0; card_no < NR_CARDS; card_no++) { 38323137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (cy_card[card_no].base_addr == NULL) 38333137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby break; 38343137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 38353137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (card_no == NR_CARDS) { /* no more cy_cards available */ 38363137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no " 38373137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "more cards can be used. Change NR_CARDS in " 38383137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "cyclades.c and recompile kernel.\n"); 38393137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_unmap; 38403137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 38413137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby 38423137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || 38433137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { 38443137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby /* allocate IRQ */ 38453137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby retval = request_irq(irq, cyy_interrupt, 38463137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]); 38473137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (retval) { 38483137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_err(&pdev->dev, "could not allocate IRQ\n"); 38493137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_unmap; 385058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 3851963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP; 38523137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } else { 3853f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS; 3854f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby struct ZFW_CTRL __iomem *zfw_ctrl; 3855f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby 3856f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff); 3857f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby 3858101b81590d8df0a74c33cf739886247c0a13f4afJiri Slaby cy_card[card_no].hw_ver = mailbox; 3859101b81590d8df0a74c33cf739886247c0a13f4afJiri Slaby cy_card[card_no].num_chips = (unsigned int)-1; 3860f0eefdc30e55e761facf645bd1be1339b21c30e6Jiri Slaby cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl; 386102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#ifdef CONFIG_CYZ_INTR 386258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby /* allocate IRQ only if board has an IRQ */ 38633137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (irq != 0 && irq != 255) { 38643137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby retval = request_irq(irq, cyz_interrupt, 386558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby IRQF_SHARED, "Cyclades-Z", 38663137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby &cy_card[card_no]); 386758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby if (retval) { 3868217191910c0286e0b3c7e3011630273695253da3Jiri Slaby dev_err(&pdev->dev, "could not allocate IRQ\n"); 38693137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_unmap; 387002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 387158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 387202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#endif /* CONFIG_CYZ_INTR */ 38733137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 387402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 38753137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby /* set cy_card */ 38763137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_card[card_no].base_addr = addr2; 387797e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby cy_card[card_no].ctl_addr.p9050 = addr0; 38783137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_card[card_no].irq = irq; 38793137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_card[card_no].bus_index = 1; 38803137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_card[card_no].first_line = cy_next_channel; 3881963118eef9e6706e2b5356309fb0cdd9c9eba81dJiri Slaby cy_card[card_no].nports = nchan; 38823137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby retval = cy_init_card(&cy_card[card_no]); 38833137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (retval) 38843137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby goto err_null; 388558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby 38863137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby pci_set_drvdata(pdev, &cy_card[card_no]); 388758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby 38883137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || 38893137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { 38903137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby /* enable interrupts in the PCI interface */ 38913137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby plx_ver = readb(addr2 + CyPLX_VER) & 0x0f; 38923137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby switch (plx_ver) { 38933137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby case PLX_9050: 38943137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_writeb(addr0 + 0x4c, 0x43); 38953137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby break; 38963137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby 38973137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby case PLX_9060: 38983137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby case PLX_9080: 38993137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby default: /* Old boards, use PLX_9060 */ 390097e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby { 390197e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby struct RUNTIME_9060 __iomem *ctl_addr = addr0; 390297e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby plx_init(pdev, irq, ctl_addr); 390397e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby cy_writew(&ctl_addr->intr_ctrl_stat, 390497e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby readw(&ctl_addr->intr_ctrl_stat) | 0x0900); 39053137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby break; 39063137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby } 390797e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby } 390858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby } 390958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby 39103137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from " 39113137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby "port %d.\n", card_name, card_no + 1, nchan, cy_next_channel); 39123137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby for (i = cy_next_channel; i < cy_next_channel + nchan; i++) 39133137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby tty_register_device(cy_serial_driver, i, &pdev->dev); 39143137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_next_channel += nchan; 39153137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby 391658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby return 0; 39173137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slabyerr_null: 39183137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby cy_card[card_no].base_addr = NULL; 39193137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby free_irq(irq, &cy_card[card_no]); 39203137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slabyerr_unmap: 392124e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby iounmap(addr0); 39223137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby if (addr2) 392324e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby iounmap(addr2); 39243137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slabyerr_reg: 39253137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby pci_release_regions(pdev); 39263137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slabyerr_dis: 39273137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby pci_disable_device(pdev); 39283137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slabyerr: 39293137553d3f78f12a077459ee59e4b17f8db9f0cfJiri Slaby return retval; 393058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby} 393158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby 39326747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slabystatic void __devexit cy_pci_remove(struct pci_dev *pdev) 393358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby{ 393438d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby struct cyclades_card *cinfo = pci_get_drvdata(pdev); 3935f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slaby unsigned int i; 393638d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby 393785c93fa95b8fa8dabc6d14c77eb9a9c2e9753eccJiri Slaby /* non-Z with old PLX */ 39382693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) == 3939c2ad4c75154d98c07d30493e4906e1cd0a9162a5Jiri Slaby PLX_9050) 394097e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby cy_writeb(cinfo->ctl_addr.p9050 + 0x4c, 0); 394185c93fa95b8fa8dabc6d14c77eb9a9c2e9753eccJiri Slaby else 394285c93fa95b8fa8dabc6d14c77eb9a9c2e9753eccJiri Slaby#ifndef CONFIG_CYZ_INTR 39432693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby if (!cy_is_Z(cinfo)) 394485c93fa95b8fa8dabc6d14c77eb9a9c2e9753eccJiri Slaby#endif 394597e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby cy_writew(&cinfo->ctl_addr.p9060->intr_ctrl_stat, 394697e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby readw(&cinfo->ctl_addr.p9060->intr_ctrl_stat) & 394797e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby ~0x0900); 394885c93fa95b8fa8dabc6d14c77eb9a9c2e9753eccJiri Slaby 394924e6fd4cdc841176ca3713fddc9a02bd128b1191Jiri Slaby iounmap(cinfo->base_addr); 395097e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby if (cinfo->ctl_addr.p9050) 395197e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby iounmap(cinfo->ctl_addr.p9050); 395238d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby if (cinfo->irq 395338d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby#ifndef CONFIG_CYZ_INTR 39542693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby && !cy_is_Z(cinfo) 395538d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby#endif /* CONFIG_CYZ_INTR */ 395638d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby ) 395738d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby free_irq(cinfo->irq, cinfo); 395838d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby pci_release_regions(pdev); 395938d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby 396038d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby cinfo->base_addr = NULL; 39616ad1ccc196f76833f41b187e01a28a024fe11f8bJiri Slaby for (i = cinfo->first_line; i < cinfo->first_line + 39626ad1ccc196f76833f41b187e01a28a024fe11f8bJiri Slaby cinfo->nports; i++) 39636ad1ccc196f76833f41b187e01a28a024fe11f8bJiri Slaby tty_unregister_device(cy_serial_driver, i); 3964dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby cinfo->nports = 0; 3965dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby kfree(cinfo->ports); 396638d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby} 396738d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby 39686747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slabystatic struct pci_driver cy_pci_driver = { 39696747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby .name = "cyclades", 39706747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby .id_table = cy_pci_dev_id, 39716747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby .probe = cy_pci_probe, 39726747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby .remove = __devexit_p(cy_pci_remove) 39736747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby}; 39746747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby#endif 39756747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby 3976444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyanstatic int cyclades_proc_show(struct seq_file *m, void *v) 39771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 397802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby struct cyclades_port *info; 3979dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby unsigned int i, j; 398002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby __u32 cur_jifs = jiffies; 398102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 3982444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan seq_puts(m, "Dev TimeOpen BytesOut IdleOut BytesIn " 398302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby "IdleIn Overruns Ldisc\n"); 398402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 398502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Output one line for each known port */ 3986dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby for (i = 0; i < NR_CARDS; i++) 3987dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby for (j = 0; j < cy_card[i].nports; j++) { 3988dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby info = &cy_card[i].ports[j]; 3989dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby 3990d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if (info->port.count) { 3991d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby /* XXX is the ldisc num worth this? */ 3992d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby struct tty_struct *tty; 3993d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby struct tty_ldisc *ld; 3994d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby int num = 0; 3995d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty = tty_port_tty_get(&info->port); 3996d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if (tty) { 3997d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby ld = tty_ldisc_ref(tty); 3998d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby if (ld) { 3999d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby num = ld->ops->num; 4000d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty_ldisc_deref(ld); 4001d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby } 4002d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby tty_kref_put(tty); 4003d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby } 4004444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan seq_printf(m, "%3d %8lu %10lu %8lu " 4005d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby "%10lu %8lu %9lu %6d\n", info->line, 4006dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby (cur_jifs - info->idle_stats.in_use) / 4007dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby HZ, info->idle_stats.xmit_bytes, 4008dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby (cur_jifs - info->idle_stats.xmit_idle)/ 4009dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby HZ, info->idle_stats.recv_bytes, 4010dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby (cur_jifs - info->idle_stats.recv_idle)/ 4011dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby HZ, info->idle_stats.overruns, 4012d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby num); 4013d13549f804d2965a9f279a8ff867f35d949572c8Jiri Slaby } else 4014444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan seq_printf(m, "%3d %8lu %10lu %8lu " 4015dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby "%10lu %8lu %9lu %6ld\n", 4016dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); 401702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 4018444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan return 0; 4019444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan} 4020444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan 4021444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyanstatic int cyclades_proc_open(struct inode *inode, struct file *file) 4022444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan{ 4023444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan return single_open(file, cyclades_proc_show, NULL); 40241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 40251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4026444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyanstatic const struct file_operations cyclades_proc_fops = { 4027444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan .owner = THIS_MODULE, 4028444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan .open = cyclades_proc_open, 4029444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan .read = seq_read, 4030444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan .llseek = seq_lseek, 4031444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan .release = single_release, 4032444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan}; 4033444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan 40341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The serial driver boot-time initialization code! 40351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Hardware I/O ports are mapped to character special devices on a 40361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds first found, first allocated manner. That is, this code searches 40371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for Cyclom cards in the system. As each is found, it is probed 40381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to discover how many chips (and thus how many ports) are present. 40391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds These ports are mapped to the tty ports 32 and upward in monotonic 40401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fashion. If an 8-port card is replaced with a 16-port card, the 40411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port mapping on a following card will shift. 40421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This approach is different from what is used in the other serial 40441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device driver because the Cyclom is more properly a multiplexer, 40451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds not just an aggregation of serial ports on one card. 40461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds If there are more cards with more ports than have been 40481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds statically allocated above, a warning is printed and the 40491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds extra ports are ignored. 40501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 40511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4052b68e31d0ebbcc909d1941f9f230c9d062a3a13d3Jeff Dikestatic const struct tty_operations cy_ops = { 405302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .open = cy_open, 405402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .close = cy_close, 405502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .write = cy_write, 405602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .put_char = cy_put_char, 405702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .flush_chars = cy_flush_chars, 405802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .write_room = cy_write_room, 405902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .chars_in_buffer = cy_chars_in_buffer, 406002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .flush_buffer = cy_flush_buffer, 406102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .ioctl = cy_ioctl, 406202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .throttle = cy_throttle, 406302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .unthrottle = cy_unthrottle, 406402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .set_termios = cy_set_termios, 406502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .stop = cy_stop, 406602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .start = cy_start, 406702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .hangup = cy_hangup, 406802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .break_ctl = cy_break, 406902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .wait_until_sent = cy_wait_until_sent, 407002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .tiocmget = cy_tiocmget, 407102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby .tiocmset = cy_tiocmset, 40720587102cf9f427c185bfdeb2cef41e13ee0264b1Alan Cox .get_icount = cy_get_icount, 4073444697d61b6d5ae43b317d259db7c362c9d3756aAlexey Dobriyan .proc_fops = &cyclades_proc_fops, 40741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 40751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 407602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int __init cy_init(void) 40771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4078dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby unsigned int nboards; 40799dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby int retval = -ENOMEM; 408002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 408102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver = alloc_tty_driver(NR_PORTS); 408202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby if (!cy_serial_driver) 40839dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby goto err; 4084217191910c0286e0b3c7e3011630273695253da3Jiri Slaby 408564a14b51bed6427a2e6d68ed687027f065f5a156Michal Marek printk(KERN_INFO "Cyclades driver " CY_VERSION "\n"); 408602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 408702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* Initialize the tty_driver structure */ 408802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 408902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->driver_name = "cyclades"; 409002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->name = "ttyC"; 409102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->major = CYCLADES_MAJOR; 409202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->minor_start = 0; 409302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; 409402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->subtype = SERIAL_TYPE_NORMAL; 409502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->init_termios = tty_std_termios; 409602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby cy_serial_driver->init_termios.c_cflag = 409702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby B9600 | CS8 | CREAD | HUPCL | CLOCAL; 40986ad1ccc196f76833f41b187e01a28a024fe11f8bJiri Slaby cy_serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; 409902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby tty_set_operations(cy_serial_driver, &cy_ops); 410002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 41019dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby retval = tty_register_driver(cy_serial_driver); 41029dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby if (retval) { 41039dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby printk(KERN_ERR "Couldn't register Cyclades serial driver\n"); 41049dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby goto err_frtty; 41059dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby } 410602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 410702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* the code below is responsible to find the boards. Each different 410802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby type of board has its own detection routine. If a board is found, 410902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby the next cy_card structure available is set by the detection 411002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby routine. These functions are responsible for checking the 411102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby availability of cy_card and cy_port data structures and updating 411202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby the cy_next_channel. */ 411302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 411402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* look for isa boards */ 411514a55a6789d8409e58329310f9a18fc141deb4c2Jiri Slaby nboards = cy_detect_isa(); 411602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby 41176747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby#ifdef CONFIG_PCI 411802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby /* look for pci boards */ 41196747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby retval = pci_register_driver(&cy_pci_driver); 4120d941ea7d496db914205c3872942fd1ff0e7dccefJesper Juhl if (retval && !nboards) { 4121d941ea7d496db914205c3872942fd1ff0e7dccefJesper Juhl tty_unregister_driver(cy_serial_driver); 4122d941ea7d496db914205c3872942fd1ff0e7dccefJesper Juhl goto err_frtty; 4123d941ea7d496db914205c3872942fd1ff0e7dccefJesper Juhl } 41246747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby#endif 41259dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby 41269dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby return 0; 41279dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slabyerr_frtty: 41289dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby put_tty_driver(cy_serial_driver); 41299dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slabyerr: 41309dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby return retval; 413102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby} /* cy_init */ 41321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 413302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void __exit cy_cleanup_module(void) 41341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4135dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby struct cyclades_card *card; 413665f76a82ec7a0374fad85211535330e203740475Jiri Slaby unsigned int i, e1; 41371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_CYZ_INTR 4139b70509066cba24067757f1422c899c43e433429dJiri Slaby del_timer_sync(&cyz_timerlist); 41401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_CYZ_INTR */ 41411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 414215ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox e1 = tty_unregister_driver(cy_serial_driver); 414315ed6cc0ba6b7beaf31c6756b0c838188800051bAlan Cox if (e1) 4144217191910c0286e0b3c7e3011630273695253da3Jiri Slaby printk(KERN_ERR "failed to unregister Cyclades serial " 4145217191910c0286e0b3c7e3011630273695253da3Jiri Slaby "driver(%d)\n", e1); 41461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41476747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby#ifdef CONFIG_PCI 41486747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby pci_unregister_driver(&cy_pci_driver); 41496747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby#endif 41506747cd93f3ed6e60b4e851b5985d038ac0b88742Jiri Slaby 415102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby for (i = 0; i < NR_CARDS; i++) { 4152dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby card = &cy_card[i]; 4153dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby if (card->base_addr) { 415485c93fa95b8fa8dabc6d14c77eb9a9c2e9753eccJiri Slaby /* clear interrupt */ 4155dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby cy_writeb(card->base_addr + Cy_ClrIntr, 0); 4156dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby iounmap(card->base_addr); 415797e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby if (card->ctl_addr.p9050) 415897e87f8ebe978e881c7325ba490574bd5500b133Jiri Slaby iounmap(card->ctl_addr.p9050); 4159dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby if (card->irq 41601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_CYZ_INTR 41612693f485c22d18474c077f12fd0f797ee8679b33Jiri Slaby && !cy_is_Z(card) 41621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_CYZ_INTR */ 416302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby ) 4164dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby free_irq(card->irq, card); 416565f76a82ec7a0374fad85211535330e203740475Jiri Slaby for (e1 = card->first_line; e1 < card->first_line + 4166dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby card->nports; e1++) 41676ad1ccc196f76833f41b187e01a28a024fe11f8bJiri Slaby tty_unregister_device(cy_serial_driver, e1); 4168dd025c0c7a047b1be7dfaa4061368b4783d89ebbJiri Slaby kfree(card->ports); 416902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 417002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby } 4171f2462bfe558559c9fbc4ef60812d5df30ccb01f6Jiri Slaby 4172f2462bfe558559c9fbc4ef60812d5df30ccb01f6Jiri Slaby put_tty_driver(cy_serial_driver); 41731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* cy_cleanup_module */ 41741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(cy_init); 41761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(cy_cleanup_module); 41771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 4179c8e1693a4f63e317966f3dfe8f815eda95e26610Jiri SlabyMODULE_VERSION(CY_VERSION); 41809f56fad741163fe2111cbbcfb7ff795ebdabdab1Scott James RemnantMODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR); 4181e6c4ef984ebbd1a0458503417da91f3de47cbbe0Ben HutchingsMODULE_FIRMWARE("cyzfirm.bin"); 4182