diff options
author | florian <florian@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2007-04-10 21:47:20 +0000 |
---|---|---|
committer | florian <florian@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2007-04-10 21:47:20 +0000 |
commit | 50d7e6ec294061923d350a7eb3b340b23b00d513 (patch) | |
tree | beb15749fccd659117cc80d76e4b896d48be4619 /target/linux/easygate-2.6/files/drivers | |
parent | 5a834359ace359edaac1ac3d73b3f61bfef78c00 (diff) |
Wrong svn repository
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@6927 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/easygate-2.6/files/drivers')
-rw-r--r-- | target/linux/easygate-2.6/files/drivers/mtd/maps/bcm963xx-flash.c | 467 | ||||
-rw-r--r-- | target/linux/easygate-2.6/files/drivers/serial/bcm63xx_cons.c | 1042 |
2 files changed, 0 insertions, 1509 deletions
diff --git a/target/linux/easygate-2.6/files/drivers/mtd/maps/bcm963xx-flash.c b/target/linux/easygate-2.6/files/drivers/mtd/maps/bcm963xx-flash.c deleted file mode 100644 index 3424749a5..000000000 --- a/target/linux/easygate-2.6/files/drivers/mtd/maps/bcm963xx-flash.c +++ /dev/null @@ -1,467 +0,0 @@ -/* - * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> - * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org> - * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org) - * - * original functions for finding root filesystem from Mike Baker - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Copyright 2001-2003, Broadcom Corporation - * All Rights Reserved. - * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. - * - * Flash mapping for BCM963XX boards - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/wait.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/map.h> -#ifdef CONFIG_MTD_PARTITIONS -#include <linux/mtd/partitions.h> -#endif -#include <linux/squashfs_fs.h> -#include <linux/jffs2.h> -#include <linux/crc32.h> -#include <asm/io.h> - -#include <asm/mach-bcm963xx/bootloaders.h> - -extern int boot_loader_type; -extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts, unsigned long fis_origin); -static struct mtd_partition *parsed_parts; - - -#define TRX_MAGIC 0x30524448 /* "HDR0" */ -#define TRX_VERSION 1 -#define TRX_MAX_LEN 0x3A0000 -#define TRX_NO_HEADER 1 /* Do not write TRX header */ -#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ -#define TRX_MAX_OFFSET 3 - -struct trx_header { - u32 magic; /* "HDR0" */ - u32 len; /* Length of file including header */ - u32 crc32; /* 32-bit CRC from flag_version to end of file */ - u32 flag_version; /* 0:15 flags, 16:31 version */ - u32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ -}; - -#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) -#define NVRAM_SPACE 0x8000 -#define WINDOW_ADDR 0x1f000000 -#define WINDOW_SIZE 0x800000 -#define BUSWIDTH 2 - -#define EXTENDED_SIZE 0xBFC00000 /* Extended flash address */ - -static struct mtd_info *bcm963xx_mtd; - -static struct map_info bcm963xx_map = { - .name = "Physically mapped flash", - .size = WINDOW_SIZE, - .bankwidth = BUSWIDTH, - .phys = WINDOW_ADDR, -}; - -#ifdef CONFIG_MTD_PARTITIONS - -static struct mtd_partition bcm963xx_parts[] = { - { name: "cfe", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, }, - { name: "linux", offset: 0, size: 0, }, - { name: "rootfs", offset: 0, size: 0, }, - { name: "nvram", offset: 0, size: 0, }, - { name: "OpenWrt", offset: 0, size: 0, }, - { name: NULL, }, -}; - -static int __init -find_cfe_size(struct mtd_info *mtd, size_t size) -{ - struct trx_header *trx; - unsigned char buf[512]; - int off; - size_t len; - int blocksize; - - trx = (struct trx_header *) buf; - - blocksize = mtd->erasesize; - if (blocksize < 0x10000) - blocksize = 0x10000; - - for (off = (128*1024); off < size; off += blocksize) { - memset(buf, 0xe5, sizeof(buf)); - - /* - * Read into buffer - */ - if (mtd->read(mtd, off, sizeof(buf), &len, buf) || - len != sizeof(buf)) - continue; - - /* found a TRX header */ - if (le32_to_cpu(trx->magic) == TRX_MAGIC) { - goto found; - } - } - - printk(KERN_NOTICE - "%s: Couldn't find bootloader size\n", - mtd->name); - return -1; - - found: - printk(KERN_NOTICE "bootloader size: %d\n", off); - return off; - -} - -/* - * Copied from mtdblock.c - * - * Cache stuff... - * - * Since typical flash erasable sectors are much larger than what Linux's - * buffer cache can handle, we must implement read-modify-write on flash - * sectors for each block write requests. To avoid over-erasing flash sectors - * and to speed things up, we locally cache a whole flash sector while it is - * being written to until a different sector is required. - */ - -static void erase_callback(struct erase_info *done) -{ - wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv; - wake_up(wait_q); -} - -static int erase_write (struct mtd_info *mtd, unsigned long pos, - int len, const char *buf) -{ - struct erase_info erase; - DECLARE_WAITQUEUE(wait, current); - wait_queue_head_t wait_q; - size_t retlen; - int ret; - - /* - * First, let's erase the flash block. - */ - - init_waitqueue_head(&wait_q); - erase.mtd = mtd; - erase.callback = erase_callback; - erase.addr = pos; - erase.len = len; - erase.priv = (u_long)&wait_q; - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&wait_q, &wait); - - ret = mtd->erase(mtd, &erase); - if (ret) { - set_current_state(TASK_RUNNING); - remove_wait_queue(&wait_q, &wait); - printk (KERN_WARNING "erase of region [0x%lx, 0x%x] " - "on \"%s\" failed\n", - pos, len, mtd->name); - return ret; - } - - schedule(); /* Wait for erase to finish. */ - remove_wait_queue(&wait_q, &wait); - - /* - * Next, writhe data to flash. - */ - - ret = mtd->write (mtd, pos, len, &retlen, buf); - if (ret) - return ret; - if (retlen != len) - return -EIO; - return 0; -} - - - - -static int __init -find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part) -{ - struct trx_header trx, *trx2; - unsigned char buf[512], *block; - int off, blocksize; - u32 i, crc = ~0; - size_t len; - struct squashfs_super_block *sb = (struct squashfs_super_block *) buf; - - blocksize = mtd->erasesize; - if (blocksize < 0x10000) - blocksize = 0x10000; - - for (off = (128*1024); off < size; off += blocksize) { - memset(&trx, 0xe5, sizeof(trx)); - - /* - * Read into buffer - */ - if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) || - len != sizeof(trx)) - continue; - - /* found a TRX header */ - if (le32_to_cpu(trx.magic) == TRX_MAGIC) { - part->offset = le32_to_cpu(trx.offsets[2]) ? : - le32_to_cpu(trx.offsets[1]); - part->size = le32_to_cpu(trx.len); - - part->size -= part->offset; - part->offset += off; - - goto found; - } - } - - printk(KERN_NOTICE - "%s: Couldn't find root filesystem\n", - mtd->name); - return -1; - - found: - if (part->size == 0) - return 0; - - if (mtd->read(mtd, part->offset, sizeof(buf), &len, buf) || len != sizeof(buf)) - return 0; - - if (*((__u32 *) buf) == SQUASHFS_MAGIC) { - printk(KERN_INFO "%s: Filesystem type: squashfs, size=0x%x\n", mtd->name, (u32) sb->bytes_used); - - /* Update the squashfs partition size based on the superblock info */ - part->size = sb->bytes_used; - len = part->offset + part->size; - len += (mtd->erasesize - 1); - len &= ~(mtd->erasesize - 1); - part->size = len - part->offset; - } else if (*((__u16 *) buf) == JFFS2_MAGIC_BITMASK) { - printk(KERN_INFO "%s: Filesystem type: jffs2\n", mtd->name); - - /* Move the squashfs outside of the trx */ - part->size = 0; - } else { - printk(KERN_INFO "%s: Filesystem type: unknown\n", mtd->name); - return 0; - } - - if (trx.len != part->offset + part->size - off) { - /* Update the trx offsets and length */ - trx.len = part->offset + part->size - off; - - /* Update the trx crc32 */ - for (i = (u32) &(((struct trx_header *)NULL)->flag_version); i <= trx.len; i += sizeof(buf)) { - if (mtd->read(mtd, off + i, sizeof(buf), &len, buf) || len != sizeof(buf)) - return 0; - crc = crc32_le(crc, buf, min(sizeof(buf), trx.len - i)); - } - trx.crc32 = crc; - - /* read first eraseblock from the trx */ - block = kmalloc(mtd->erasesize, GFP_KERNEL); - trx2 = (struct trx_header *) block; - if (mtd->read(mtd, off, mtd->erasesize, &len, block) || len != mtd->erasesize) { - printk("Error accessing the first trx eraseblock\n"); - return 0; - } - - printk("Updating TRX offsets and length:\n"); - printk("old trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx2->offsets[0], trx2->offsets[1], trx2->offsets[2], trx2->len, trx2->crc32); - printk("new trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx.offsets[0], trx.offsets[1], trx.offsets[2], trx.len, trx.crc32); - - /* Write updated trx header to the flash */ - memcpy(block, &trx, sizeof(trx)); - if (mtd->unlock) - mtd->unlock(mtd, off, mtd->erasesize); - erase_write(mtd, off, mtd->erasesize, block); - if (mtd->sync) - mtd->sync(mtd); - kfree(block); - printk("Done\n"); - } - - return part->size; -} - -struct mtd_partition * __init -init_mtd_partitions(struct mtd_info *mtd, size_t size) -{ - int cfe_size; - - if ((cfe_size = find_cfe_size(mtd,size)) < 0) - return NULL; - - /* boot loader */ - bcm963xx_parts[0].offset = 0; - bcm963xx_parts[0].size = cfe_size; - - /* nvram */ - if (cfe_size != 384 * 1024) { - bcm963xx_parts[3].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize); - bcm963xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize); - } else { - /* nvram (old 128kb config partition on netgear wgt634u) */ - bcm963xx_parts[3].offset = bcm963xx_parts[0].size; - bcm963xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize); - } - - /* linux (kernel and rootfs) */ - if (cfe_size != 384 * 1024) { - bcm963xx_parts[1].offset = bcm963xx_parts[0].size; - bcm963xx_parts[1].size = bcm963xx_parts[3].offset - - bcm963xx_parts[1].offset; - } else { - /* do not count the elf loader, which is on one block */ - bcm963xx_parts[1].offset = bcm963xx_parts[0].size + - bcm963xx_parts[3].size + mtd->erasesize; - bcm963xx_parts[1].size = size - - bcm963xx_parts[0].size - - (2*bcm963xx_parts[3].size) - - mtd->erasesize; - } - - /* find and size rootfs */ - if (find_root(mtd,size,&bcm963xx_parts[2])==0) { - /* entirely jffs2 */ - bcm963xx_parts[4].name = NULL; - bcm963xx_parts[2].size = size - bcm963xx_parts[2].offset - - bcm963xx_parts[3].size; - } else { - /* legacy setup */ - /* calculate leftover flash, and assign it to the jffs2 partition */ - if (cfe_size != 384 * 1024) { - bcm963xx_parts[4].offset = bcm963xx_parts[2].offset + - bcm963xx_parts[2].size; - if ((bcm963xx_parts[4].offset % mtd->erasesize) > 0) { - bcm963xx_parts[4].offset += mtd->erasesize - - (bcm963xx_parts[4].offset % mtd->erasesize); - } - bcm963xx_parts[4].size = bcm963xx_parts[3].offset - - bcm963xx_parts[4].offset; - } else { - bcm963xx_parts[4].offset = bcm963xx_parts[2].offset + - bcm963xx_parts[2].size; - if ((bcm963xx_parts[4].offset % mtd->erasesize) > 0) { - bcm963xx_parts[4].offset += mtd->erasesize - - (bcm963xx_parts[4].offset % mtd->erasesize); - } - bcm963xx_parts[4].size = size - bcm963xx_parts[3].size - - bcm963xx_parts[4].offset; - } - } - - return bcm963xx_parts; -} -#endif - -int __init init_bcm963xx_map(void) -{ - size_t size; - int ret = 0; - struct mtd_partition *parts; - int i; - - printk("BCM963xx flash init: 0x%08x 0x%08x\n", WINDOW_ADDR, WINDOW_SIZE); - bcm963xx_map.virt = ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE); - - if (!bcm963xx_map.virt) { - printk("Failed to ioremap\n"); - return -EIO; - } - - simple_map_init(&bcm963xx_map); - - if (!(bcm963xx_mtd = do_map_probe("jedec_probe", &bcm963xx_map))) { - printk("Failed to jedec_probe\n"); - iounmap((void *)bcm963xx_map.virt); - return -ENXIO; - } - - bcm963xx_mtd->owner = THIS_MODULE; - - size = bcm963xx_mtd->size; - - printk(KERN_NOTICE "Flash device: 0x%x at 0x%x\n", size, WINDOW_ADDR); - - if (boot_loader_type == BOOT_LOADER_REDBOOT) { - int parsed_nr_parts = 0; - char * part_type; - - if (bcm963xx_mtd->size > 0x00400000) { - printk("Support for extended flash memory size : 0x%08X ; ONLY 64MBIT SUPPORT\n", bcm963xx_mtd->size); - bcm963xx_map.virt = (unsigned long)EXTENDED_SIZE; - } - - if (parsed_nr_parts == 0) { - int ret = parse_redboot_partitions(bcm963xx_mtd, &parsed_parts, 0); - if (ret > 0) { - part_type = "RedBoot"; - parsed_nr_parts = ret; - } - } - add_mtd_partitions(bcm963xx_mtd, parsed_parts, parsed_nr_parts); - } - else { - parts = init_mtd_partitions(bcm963xx_mtd, size); - for (i = 0; parts[i].name; i++); - ret = add_mtd_partitions(bcm963xx_mtd, parts, i); - if (ret) { - printk(KERN_ERR "Flash: add_mtd_partitions failed\n"); - goto fail; - } - } - return 0; - - fail: - if (bcm963xx_mtd) - map_destroy(bcm963xx_mtd); - if (bcm963xx_map.virt) - iounmap((void *)bcm963xx_map.virt); - bcm963xx_map.virt = 0; - return ret; -} - -void __exit cleanup_bcm963xx_map(void) -{ - del_mtd_partitions(bcm963xx_mtd); - map_destroy(bcm963xx_mtd); - iounmap((void *)bcm963xx_map.virt); -} - -module_init(init_bcm963xx_map); -module_exit(cleanup_bcm963xx_map); diff --git a/target/linux/easygate-2.6/files/drivers/serial/bcm63xx_cons.c b/target/linux/easygate-2.6/files/drivers/serial/bcm63xx_cons.c deleted file mode 100644 index 469377977..000000000 --- a/target/linux/easygate-2.6/files/drivers/serial/bcm63xx_cons.c +++ /dev/null @@ -1,1042 +0,0 @@ -/* -<:copyright-gpl - Copyright 2002 Broadcom Corp. All Rights Reserved. - - This program is free software; you can distribute it and/or modify it - under the terms of the GNU General Public License (Version 2) as - published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -:> -*/ - -/* Description: Serial port driver for the BCM963XX. */ - -#define CARDNAME "bcm963xx_serial driver" -#define VERSION "2.0" -#define VER_STR CARDNAME " v" VERSION "\n" - - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/version.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> - -/* for definition of struct console */ -#include <linux/console.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/serial.h> -#include <linux/serialP.h> -#include <asm/uaccess.h> - -#include <bcmtypes.h> -#include <board.h> -#include <bcm_map_part.h> -#include <bcm_intr.h> -#include <6348_map_part.h> -#include <6348_intr.h> - -static DEFINE_SPINLOCK(bcm963xx_serial_lock); - -extern void _putc(char); -extern void _puts(const char *); - -typedef struct bcm_serial { - volatile Uart *port; - int type; - int flags; - int irq; - int baud_base; - int blocked_open; - unsigned short close_delay; - unsigned short closing_wait; - unsigned short line; /* port/line number */ - unsigned short cflags; /* line configuration flag */ - unsigned short x_char; /* xon/xoff character */ - unsigned short read_status_mask; /* mask for read condition */ - unsigned short ignore_status_mask; /* mask for ignore condition */ - unsigned long event; /* mask used in BH */ - int xmit_head; /* Position of the head */ - int xmit_tail; /* Position of the tail */ - int xmit_cnt; /* Count of the chars in the buffer */ - int count; /* indicates how many times it has been opened */ - int magic; - - struct async_icount icount; /* keep track of things ... */ - struct tty_struct *tty; /* tty associated */ - struct termios normal_termios; - - wait_queue_head_t open_wait; - wait_queue_head_t close_wait; - - long session; /* Session of opening process */ - long pgrp; /* pgrp of opening process */ - - unsigned char is_initialized; -} Context; - - -/*---------------------------------------------------------------------*/ -/* Define bits in the Interrupt Enable register */ -/*---------------------------------------------------------------------*/ -/* Enable receive interrupt */ -#define RXINT (RXFIFONE|RXOVFERR) - -/* Enable transmit interrupt */ -#define TXINT (TXFIFOEMT|TXUNDERR|TXOVFERR) - -/* Enable receiver line status interrupt */ -#define LSINT (RXBRK|RXPARERR|RXFRAMERR) - -#define BCM_NUM_UARTS 1 - -#define BD_BCM63XX_TIMER_CLOCK_INPUT (FPERIPH) - - -static struct bcm_serial multi[BCM_NUM_UARTS]; -static struct bcm_serial *lines[BCM_NUM_UARTS]; -static struct tty_driver *serial_driver; -static struct termios *serial_termios[BCM_NUM_UARTS]; -static struct termios *serial_termios_locked[BCM_NUM_UARTS]; - - -static void bcm_stop(struct tty_struct *tty); -static void bcm_start(struct tty_struct *tty); -static inline void receive_chars(struct bcm_serial *info); -static int startup(struct bcm_serial *info); -static void shutdown(struct bcm_serial *info); -static void change_speed(volatile Uart * pUart, tcflag_t cFlag); -static void bcm63xx_cons_flush_chars(struct tty_struct *tty); -static int bcm63xx_cons_write(struct tty_struct *tty, - const unsigned char *buf, int count); -static int bcm63xx_cons_write_room(struct tty_struct *tty); -static int bcm_chars_in_buffer(struct tty_struct *tty); -static void bcm_flush_buffer(struct tty_struct *tty); -static void bcm_throttle(struct tty_struct *tty); -static void bcm_unthrottle(struct tty_struct *tty); -static void bcm_send_xchar(struct tty_struct *tty, char ch); -static int get_serial_info(struct bcm_serial *info, - struct serial_struct *retinfo); -static int set_serial_info(struct bcm_serial *info, - struct serial_struct *new_info); -static int get_lsr_info(struct bcm_serial *info, unsigned int *value); -static void send_break(struct bcm_serial *info, int duration); -static int bcm_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg); -static void bcm_set_termios(struct tty_struct *tty, - struct termios *old_termios); -static void bcm63xx_cons_close(struct tty_struct *tty, struct file *filp); -static void bcm_hangup(struct tty_struct *tty); -static int block_til_ready(struct tty_struct *tty, struct file *filp, - struct bcm_serial *info); -static int bcm63xx_cons_open(struct tty_struct *tty, struct file *filp); -static int __init bcm63xx_serialinit(void); - - -/* - * ------------------------------------------------------------ - * rs_stop () and rs_start () - * - * These routines are called before setting or resetting - * tty->stopped. They enable or disable transmitter interrupts, - * as necessary. - * ------------------------------------------------------------ - */ -static void bcm_stop(struct tty_struct *tty) -{ -} - -static void bcm_start(struct tty_struct *tty) -{ - _puts(CARDNAME " Start\n"); -} - -/* - * ------------------------------------------------------------ - * receive_char () - * - * This routine deals with inputs from any lines. - * ------------------------------------------------------------ - */ -static inline void receive_chars(struct bcm_serial *info) -{ - struct tty_struct *tty = 0; - struct async_icount *icount; - int ignore = 0; - unsigned short status, tmp; - UCHAR ch = 0; - while ((status = info->port->intStatus) & RXINT) { - char flag_char = TTY_NORMAL; - - if (status & RXFIFONE) - ch = info->port->Data; // Read the character - tty = info->tty; /* now tty points to the proper dev */ - icount = &info->icount; - if (!tty) - break; - if (!tty_buffer_request_room(tty, 1)) - break; - icount->rx++; - if (status & RXBRK) { - flag_char = TTY_BREAK; - icount->brk++; - } - // keep track of the statistics - if (status & (RXFRAMERR | RXPARERR | RXOVFERR)) { - if (status & RXPARERR) /* parity error */ - icount->parity++; - else if (status & RXFRAMERR) /* frame error */ - icount->frame++; - if (status & RXOVFERR) { - // Overflow. Reset the RX FIFO - info->port->fifoctl |= RSTRXFIFOS; - icount->overrun++; - } - // check to see if we should ignore the character - // and mask off conditions that should be ignored - if (status & info->ignore_status_mask) { - if (++ignore > 100) - break; - goto ignore_char; - } - // Mask off the error conditions we want to ignore - tmp = status & info->read_status_mask; - if (tmp & RXPARERR) { - flag_char = TTY_PARITY; - } else if (tmp & RXFRAMERR) { - flag_char = TTY_FRAME; - } - if (tmp & RXOVFERR) { - tty_insert_flip_char(tty, ch, flag_char); - ch = 0; - flag_char = TTY_OVERRUN; - if (!tty_buffer_request_room(tty, 1)) - break; - } - } - tty_insert_flip_char(tty, ch, flag_char); - } - ignore_char:; - tty_flip_buffer_push(tty); - tty_schedule_flip(tty); - -} - - -/* - * ------------------------------------------------------------ - * bcm_interrupt () - * - * this is the main interrupt routine for the chip. - * It deals with the multiple ports. - * ------------------------------------------------------------ - */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static irqreturn_t bcm_interrupt(int irq, void *dev) -#else -static void bcm_interrupt(int irq, void *dev, struct pt_regs *regs) -#endif -{ - struct bcm_serial *info = lines[0]; - UINT16 intStat; - - /* get pending interrupt flags from UART */ - - /* Mask with only the serial interrupts that are enabled */ - intStat = info->port->intStatus & info->port->intMask; - while (intStat) { - if (intStat & RXINT) - receive_chars(info); - else if (intStat & TXINT) - info->port->intStatus = TXINT; - else /* don't know what it was, so let's mask it */ - info->port->intMask &= ~intStat; - - intStat = info->port->intStatus & info->port->intMask; - } - - // Clear the interrupt - enable_brcm_irq(INTERRUPT_ID_UART); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - return IRQ_HANDLED; -#endif -} - -/* - * ------------------------------------------------------------------- - * startup () - * - * various initialization tasks - * ------------------------------------------------------------------- - */ -static int startup(struct bcm_serial *info) -{ - // Port is already started... - return 0; -} - -/* - * ------------------------------------------------------------------- - * shutdown () - * - * This routine will shutdown a serial port; interrupts are disabled, and - * DTR is dropped if the hangup on close termio flag is on. - * ------------------------------------------------------------------- - */ -static void shutdown(struct bcm_serial *info) -{ - unsigned long flags; - if (!info->is_initialized) - return; - - spin_lock_irqsave(&bcm963xx_serial_lock, flags); - - info->port->control &= ~(BRGEN | TXEN | RXEN); - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - info->is_initialized = 0; - - spin_unlock_irqrestore(&bcm963xx_serial_lock, flags); -} - -/* - * ------------------------------------------------------------------- - * change_speed () - * - * Set the baud rate, character size, parity and stop bits. - * ------------------------------------------------------------------- - */ -static void change_speed(volatile Uart * pUart, tcflag_t cFlag) -{ - unsigned long ulFlags, ulBaud, ulClockFreqHz, ulTmp; - - spin_lock_irqsave(&bcm963xx_serial_lock, ulFlags); - switch (cFlag & (CBAUD | CBAUDEX)) { - case B115200: - ulBaud = 115200; - break; - case B57600: - ulBaud = 57600; - break; - case B38400: - ulBaud = 38400; - break; - case B19200: - ulBaud = 19200; - break; - case B9600: - ulBaud = 9600; - break; - case B4800: - ulBaud = 4800; - break; - case B2400: - ulBaud = 2400; - break; - case B1800: - ulBaud = 1800; - break; - case B1200: - ulBaud = 1200; - break; - case B600: - ulBaud = 600; - break; - case B300: - ulBaud = 300; - break; - case B200: - ulBaud = 200; - break; - case B150: - ulBaud = 150; - break; - case B134: - ulBaud = 134; - break; - case B110: - ulBaud = 110; - break; - case B75: - ulBaud = 75; - break; - case B50: - ulBaud = 50; - break; - default: - ulBaud = 115200; - break; - } - - /* Calculate buad rate. */ - ulClockFreqHz = BD_BCM63XX_TIMER_CLOCK_INPUT; - ulTmp = (ulClockFreqHz / ulBaud) / 16; - if (ulTmp & 0x01) - ulTmp /= 2; /* Rounding up, so sub is already accounted for */ - else - ulTmp = (ulTmp / 2) - 1; /* Rounding down so we must sub 1 */ - pUart->baudword = ulTmp; - - /* Set character size, stop bits and parity. */ - switch (cFlag & CSIZE) { - case CS5: - ulTmp = BITS5SYM; /* select transmit 5 bit data size */ - break; - case CS6: - ulTmp = BITS6SYM; /* select transmit 6 bit data size */ - break; - case CS7: - ulTmp = BITS7SYM; /* select transmit 7 bit data size */ - break; - default: - ulTmp = BITS8SYM; /* select transmit 8 bit data size */ - break; - } - if (cFlag & CSTOPB) - ulTmp |= TWOSTOP; /* select 2 stop bits */ - else - ulTmp |= ONESTOP; /* select one stop bit */ - - /* Write these values into the config reg. */ - pUart->config = ulTmp; - pUart->control &= - ~(RXPARITYEN | TXPARITYEN | RXPARITYEVEN | TXPARITYEVEN); - switch (cFlag & (PARENB | PARODD)) { - case PARENB | PARODD: - pUart->control |= RXPARITYEN | TXPARITYEN; - break; - case PARENB: - pUart->control |= - RXPARITYEN | TXPARITYEN | RXPARITYEVEN | TXPARITYEVEN; - break; - default: - pUart->control |= 0; - break; - } - - /* Reset and flush uart */ - pUart->fifoctl = RSTTXFIFOS | RSTRXFIFOS; - spin_unlock_irqrestore(&bcm963xx_serial_lock, ulFlags); -} - - -/* - * ------------------------------------------------------------------- - * bcm_flush_char () - * - * Nothing to flush. Polled I/O is used. - * ------------------------------------------------------------------- - */ -static void bcm63xx_cons_flush_chars(struct tty_struct *tty) -{ -} - - -/* - * ------------------------------------------------------------------- - * bcm63xx_cons_write () - * - * Main output routine using polled I/O. - * ------------------------------------------------------------------- - */ -static int bcm63xx_cons_write(struct tty_struct *tty, - const unsigned char *buf, int count) -{ - int c; - - for (c = 0; c < count; c++) - _putc(buf[c]); - return count; -} - -/* - * ------------------------------------------------------------------- - * bcm63xx_cons_write_room () - * - * Compute the amount of space available for writing. - * ------------------------------------------------------------------- - */ -static int bcm63xx_cons_write_room(struct tty_struct *tty) -{ - /* Pick a number. Any number. Polled I/O is used. */ - return 1024; -} - -/* - * ------------------------------------------------------------------- - * bcm_chars_in_buffer () - * - * compute the amount of char left to be transmitted - * ------------------------------------------------------------------- - */ -static int bcm_chars_in_buffer(struct tty_struct *tty) -{ - return 0; -} - -/* - * ------------------------------------------------------------------- - * bcm_flush_buffer () - * - * Empty the output buffer - * ------------------------------------------------------------------- - */ -static void bcm_flush_buffer(struct tty_struct *tty) -{ - tty_wakeup(tty); -} - -/* - * ------------------------------------------------------------ - * bcm_throttle () and bcm_unthrottle () - * - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled (or not). - * ------------------------------------------------------------ - */ -static void bcm_throttle(struct tty_struct *tty) -{ - struct bcm_serial *info = (struct bcm_serial *) tty->driver_data; - if (I_IXOFF(tty)) - info->x_char = STOP_CHAR(tty); -} - -static void bcm_unthrottle(struct tty_struct *tty) -{ - struct bcm_serial *info = (struct bcm_serial *) tty->driver_data; - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - info->x_char = START_CHAR(tty); - } -} - -static void bcm_send_xchar(struct tty_struct *tty, char ch) -{ - struct bcm_serial *info = (struct bcm_serial *) tty->driver_data; - info->x_char = ch; - if (ch) - bcm_start(info->tty); -} - -/* - * ------------------------------------------------------------ - * rs_ioctl () and friends - * ------------------------------------------------------------ - */ -static int get_serial_info(struct bcm_serial *info, - struct serial_struct *retinfo) -{ - struct serial_struct tmp; - - if (!retinfo) - return -EFAULT; - - memset(&tmp, 0, sizeof(tmp)); - tmp.type = info->type; - tmp.line = info->line; - tmp.port = (int) info->port; - tmp.irq = info->irq; - tmp.flags = 0; - tmp.baud_base = info->baud_base; - tmp.close_delay = info->close_delay; - tmp.closing_wait = info->closing_wait; - - return copy_to_user(retinfo, &tmp, sizeof(*retinfo)); -} - -static int set_serial_info(struct bcm_serial *info, - struct serial_struct *new_info) -{ - struct serial_struct new_serial; - struct bcm_serial old_info; - int retval = 0; - - if (!new_info) - return -EFAULT; - - copy_from_user(&new_serial, new_info, sizeof(new_serial)); - old_info = *info; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - - if (info->count > 1) - return -EBUSY; - - /* OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - info->baud_base = new_serial.baud_base; - info->type = new_serial.type; - info->close_delay = new_serial.close_delay; - info->closing_wait = new_serial.closing_wait; - retval = startup(info); - return retval; -} - -/* - * get_lsr_info - get line status register info - * - * Purpose: Let user call ioctl() to get info when the UART physically - * is emptied. On bus types like RS485, the transmitter must - * release the bus after transmitting. This must be done when - * the transmit shift register is empty, not be done when the - * transmit holding register is empty. This functionality - * allows an RS485 driver to be written in user space. - */ -static int get_lsr_info(struct bcm_serial *info, unsigned int *value) -{ - return (0); -} - -/* - * This routine sends a break character out the serial port. - */ -static void send_break(struct bcm_serial *info, int duration) -{ - unsigned long flags; - - if (!info->port) - return; - - current->state = TASK_INTERRUPTIBLE; - - /*save_flags (flags); - cli(); */ - spin_lock_irqsave(&bcm963xx_serial_lock, flags); - - info->port->control |= XMITBREAK; - schedule_timeout(duration); - info->port->control &= ~XMITBREAK; - - spin_unlock_irqrestore(&bcm963xx_serial_lock, flags); - //restore_flags (flags); -} - -static int bcm_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int error; - struct bcm_serial *info = (struct bcm_serial *) tty->driver_data; - int retval; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && - (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - switch (cmd) { - - case TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - if (!arg) - send_break(info, HZ / 4); /* 1/4 second */ - return 0; - - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - send_break(info, arg ? arg * (HZ / 10) : HZ / 4); - return 0; - - case TIOCGSOFTCAR: - error = - access_ok(VERIFY_WRITE, (void *) arg, sizeof(long)); - if (!error) - return -EFAULT; - else { - put_user(C_CLOCAL(tty) ? 1 : 0, - (unsigned long *) arg); - return 0; - } - - case TIOCSSOFTCAR: - error = get_user(arg, (unsigned long *) arg); - if (error) - return error; - tty->termios->c_cflag = - ((tty->termios-> - c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); - return 0; - - case TIOCGSERIAL: - error = - access_ok(VERIFY_WRITE, (void *) arg, - sizeof(struct serial_struct)); - if (!error) - return -EFAULT; - else - return get_serial_info(info, - (struct serial_struct *) - arg); - - case TIOCSSERIAL: - return set_serial_info(info, (struct serial_struct *) arg); - - case TIOCSERGETLSR: /* Get line status register */ - error = - access_ok(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int)); - if (!error) - return -EFAULT; - else - return get_lsr_info(info, (unsigned int *) arg); - - case TIOCSERGSTRUCT: - error = - access_ok(VERIFY_WRITE, (void *) arg, - sizeof(struct bcm_serial)); - if (!error) - return -EFAULT; - else { - copy_to_user((struct bcm_serial *) arg, info, - sizeof(struct bcm_serial)); - return 0; - } - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static void bcm_set_termios(struct tty_struct *tty, - struct termios *old_termios) -{ - struct bcm_serial *info = (struct bcm_serial *) tty->driver_data; - - if (tty->termios->c_cflag != old_termios->c_cflag) - change_speed(info->port, tty->termios->c_cflag); -} - -/* - * ------------------------------------------------------------ - * bcm63xx_cons_close() - * - * This routine is called when the serial port gets closed. First, we - * wait for the last remaining data to be sent. Then, we turn off - * the transmit enable and receive enable flags. - * ------------------------------------------------------------ - */ -static void bcm63xx_cons_close(struct tty_struct *tty, struct file *filp) -{ - struct bcm_serial *info = (struct bcm_serial *) tty->driver_data; - unsigned long flags; - - if (!info) - return; - - /*save_flags (flags); - cli(); */ - spin_lock_irqsave(&bcm963xx_serial_lock, flags); - - if (tty_hung_up_p(filp)) { - spin_unlock_irqrestore(&bcm963xx_serial_lock, flags); - //restore_flags (flags); - return; - } - - if ((tty->count == 1) && (info->count != 1)) { - - /* Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. Info->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk - ("bcm63xx_cons_close: bad serial port count; tty->count is 1, " - "info->count is %d\n", info->count); - info->count = 1; - } - - if (--info->count < 0) { - printk("ds_close: bad serial port count for ttys%d: %d\n", - info->line, info->count); - info->count = 0; - } - - if (info->count) { - //restore_flags (flags); - spin_unlock_irqrestore(&bcm963xx_serial_lock, flags); - return; - } - - /* Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - - /* At this point we stop accepting input. To do this, we - * disable the receive line status interrupts. - */ - shutdown(info); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - if (tty->driver->flush_buffer) - tty->driver->flush_buffer(tty); -#else - if (tty->driver.flush_buffer) - tty->driver.flush_buffer(tty); -#endif - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); - - tty->closing = 0; - info->event = 0; - info->tty = 0; - if (tty->ldisc.num != tty_ldisc_get(N_TTY)->num) { - if (tty->ldisc.close) - (tty->ldisc.close) (tty); - tty->ldisc = *tty_ldisc_get(N_TTY); - tty->termios->c_line = N_TTY; - if (tty->ldisc.open) - (tty->ldisc.open) (tty); - } - if (info->blocked_open) { - if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(info->close_delay); - } - wake_up_interruptible(&info->open_wait); - } - wake_up_interruptible(&info->close_wait); - - //restore_flags (flags); - spin_unlock_irqrestore(&bcm963xx_serial_lock, flags); -} - -/* - * bcm_hangup () --- called by tty_hangup() when a hangup is signaled. - */ -static void bcm_hangup(struct tty_struct *tty) -{ - - struct bcm_serial *info = (struct bcm_serial *) tty->driver_data; - - shutdown(info); - info->event = 0; - info->count = 0; - info->tty = 0; - wake_up_interruptible(&info->open_wait); -} - -/* - * ------------------------------------------------------------ - * rs_open() and friends - * ------------------------------------------------------------ - */ -static int block_til_ready(struct tty_struct *tty, struct file *filp, - struct bcm_serial *info) -{ - return 0; -} - -/* - * This routine is called whenever a serial port is opened. It - * enables interrupts for a serial port. It also performs the - * serial-specific initialization for the tty structure. - */ -static int bcm63xx_cons_open(struct tty_struct *tty, struct file *filp) -{ - struct bcm_serial *info; - int retval, line; - - // Make sure we're only opening on of the ports we support -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - line = MINOR(tty->driver->cdev.dev) - tty->driver->minor_start; -#else - line = MINOR(tty->device) - tty->driver.minor_start; -#endif - - if ((line < 0) || (line >= BCM_NUM_UARTS)) - return -ENODEV; - - info = lines[line]; - - tty->low_latency = 1; - info->port->intMask = 0; /* Clear any pending interrupts */ - info->port->intMask = RXINT; /* Enable RX */ - - info->count++; - tty->driver_data = info; - info->tty = tty; - enable_brcm_irq(INTERRUPT_ID_UART); - - // Start up serial port - retval = startup(info); - if (retval) - return retval; - - retval = block_til_ready(tty, filp, info); - if (retval) - return retval; - - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - info->pgrp = process_group(current); - info->session = current->signal->session; -#else - info->session = current->session; - info->pgrp = current->pgrp; -#endif - - return 0; -} - - -static struct tty_operations rs_ops = { - .open = bcm63xx_cons_open, - .close = bcm63xx_cons_close, - .write = bcm63xx_cons_write, - .flush_chars = bcm63xx_cons_flush_chars, - .write_room = bcm63xx_cons_write_room, - .chars_in_buffer = bcm_chars_in_buffer, - .flush_buffer = bcm_flush_buffer, - .ioctl = bcm_ioctl, - .throttle = bcm_throttle, - .unthrottle = bcm_unthrottle, - .send_xchar = bcm_send_xchar, - .set_termios = bcm_set_termios, - .stop = bcm_stop, - .start = bcm_start, - .hangup = bcm_hangup, -}; - -/* -------------------------------------------------------------------------- - Name: bcm63xx_serialinit - Purpose: Initialize our BCM63xx serial driver --------------------------------------------------------------------------- */ -static int __init bcm63xx_serialinit(void) -{ - int i, flags; - struct bcm_serial *info; - - // Print the driver version information - printk(VER_STR); - serial_driver = alloc_tty_driver(BCM_NUM_UARTS); - if (!serial_driver) - return -ENOMEM; - - serial_driver->owner = THIS_MODULE; - serial_driver->name = "ttyS"; - serial_driver->major = TTY_MAJOR; - serial_driver->minor_start = 64; - serial_driver->num = 1; - serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - serial_driver->subtype = SERIAL_TYPE_NORMAL; - serial_driver->init_termios = tty_std_termios; - serial_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver->flags = TTY_DRIVER_REAL_RAW; - - serial_driver->termios = serial_termios; - serial_driver->termios_locked = serial_termios_locked; - - tty_set_operations(serial_driver, &rs_ops); - - if (tty_register_driver(serial_driver)) - panic("Couldn't register serial driver\n"); - - //save_flags(flags); cli(); - spin_lock_irqsave(&bcm963xx_serial_lock, flags); - - for (i = 0; i < 1; i++) { - info = &multi[i]; - lines[i] = info; - info->magic = SERIAL_MAGIC; - info->port = (Uart *) ((char *) UART_BASE + (i * 0x20)); - info->tty = 0; - info->irq = (2 - i) + 8; - info->line = i; - info->close_delay = 50; - info->closing_wait = 3000; - info->x_char = 0; - info->event = 0; - info->count = 0; - info->blocked_open = 0; - info->normal_termios = serial_driver->init_termios; - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - - /* If we are pointing to address zero then punt - not correctly - * set up in setup.c to handle this. - */ - if (!info->port) - return 0; - BcmHalMapInterrupt(bcm_interrupt, 0, INTERRUPT_ID_UART); - } - - /* order matters here... the trick is that flags - * is updated... in request_irq - to immediatedly obliterate - * it is unwise. - */ - spin_unlock_irqrestore(&bcm963xx_serial_lock, flags); - return 0; -} - -module_init(bcm63xx_serialinit); - -/* -------------------------------------------------------------------------- - Name: bcm_console_print - Purpose: bcm_console_print is registered for printk. - The console_lock must be held when we get here. --------------------------------------------------------------------------- */ -static void bcm_console_print(struct console *cons, const char *str, - unsigned int count) -{ - unsigned int i; - //_puts(str); - for (i = 0; i < count; i++, str++) { - _putc(*str); - if (*str == 10) { - _putc(13); - } - } -} - -static struct tty_driver *bcm_console_device(struct console *c, int *index) -{ - *index = c->index; - return serial_driver; -} - -static int __init bcm_console_setup(struct console *co, char *options) -{ - return 0; -} - -static struct console bcm_sercons = { - .name = "ttyS", - .write = bcm_console_print, - .device = bcm_console_device, - .setup = bcm_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -static int __init bcm63xx_console_init(void) -{ - register_console(&bcm_sercons); - return 0; -} - -console_initcall(bcm63xx_console_init); |