Commit 7282bee78798294bb1f0211a842cdb9f4872db3d

Authored by Chris Zankel
Committed by Linus Torvalds
1 parent e344b63eee

[PATCH] xtensa: Architecture support for Tensilica Xtensa Part 8

The attached patches provides part 8 of an architecture implementation
for the Tensilica Xtensa CPU series.

Signed-off-by: Chris Zankel <chris@zankel.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 8 changed files with 1967 additions and 0 deletions Side-by-side Diff

arch/xtensa/configs/iss_defconfig
  1 +#
  2 +# Automatically generated make config: don't edit
  3 +# Linux kernel version: 2.6.11-rc2
  4 +# Fri Feb 25 19:21:24 2005
  5 +#
  6 +CONFIG_FRAME_POINTER=y
  7 +CONFIG_XTENSA=y
  8 +# CONFIG_UID16 is not set
  9 +CONFIG_RWSEM_XCHGADD_ALGORITHM=y
  10 +CONFIG_HAVE_DEC_LOCK=y
  11 +CONFIG_GENERIC_HARDIRQS=y
  12 +
  13 +#
  14 +# Code maturity level options
  15 +#
  16 +CONFIG_EXPERIMENTAL=y
  17 +CONFIG_CLEAN_COMPILE=y
  18 +CONFIG_BROKEN_ON_SMP=y
  19 +
  20 +#
  21 +# General setup
  22 +#
  23 +CONFIG_LOCALVERSION=""
  24 +CONFIG_SWAP=y
  25 +CONFIG_SYSVIPC=y
  26 +# CONFIG_POSIX_MQUEUE is not set
  27 +# CONFIG_BSD_PROCESS_ACCT is not set
  28 +CONFIG_SYSCTL=y
  29 +# CONFIG_AUDIT is not set
  30 +CONFIG_LOG_BUF_SHIFT=14
  31 +# CONFIG_HOTPLUG is not set
  32 +# CONFIG_KOBJECT_UEVENT is not set
  33 +# CONFIG_IKCONFIG is not set
  34 +CONFIG_EMBEDDED=y
  35 +CONFIG_KALLSYMS=y
  36 +# CONFIG_KALLSYMS_ALL is not set
  37 +# CONFIG_KALLSYMS_EXTRA_PASS is not set
  38 +CONFIG_FUTEX=y
  39 +CONFIG_EPOLL=y
  40 +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
  41 +CONFIG_SHMEM=y
  42 +CONFIG_CC_ALIGN_FUNCTIONS=0
  43 +CONFIG_CC_ALIGN_LABELS=0
  44 +CONFIG_CC_ALIGN_LOOPS=0
  45 +CONFIG_CC_ALIGN_JUMPS=0
  46 +# CONFIG_TINY_SHMEM is not set
  47 +
  48 +#
  49 +# Loadable module support
  50 +#
  51 +# CONFIG_MODULES is not set
  52 +
  53 +#
  54 +# Processor type and features
  55 +#
  56 +CONFIG_XTENSA_ARCH_LINUX_BE=y
  57 +# CONFIG_XTENSA_ARCH_LINUX_LE is not set
  58 +# CONFIG_XTENSA_ARCH_LINUX_TEST is not set
  59 +# CONFIG_XTENSA_ARCH_S5 is not set
  60 +# CONFIG_XTENSA_CUSTOM is not set
  61 +CONFIG_MMU=y
  62 +# CONFIG_XTENSA_UNALIGNED_USER is not set
  63 +# CONFIG_PREEMPT is not set
  64 +# CONFIG_MATH_EMULATION is not set
  65 +# CONFIG_HIGHMEM is not set
  66 +
  67 +#
  68 +# Platform options
  69 +#
  70 +CONFIG_XTENSA_PLATFORM_ISS=y
  71 +# CONFIG_XTENSA_PLATFORM_XT2000 is not set
  72 +# CONFIG_XTENSA_PLATFORM_ARUBA is not set
  73 +# CONFIG_XTENSA_CALIBRATE_CCOUNT is not set
  74 +CONFIG_XTENSA_CPU_CLOCK=10
  75 +# CONFIG_GENERIC_CALIBRATE_DELAY is not set
  76 +CONFIG_CMDLINE_BOOL=y
  77 +CONFIG_CMDLINE="console=ttyS0,38400 eth0=tuntap,,tap0 ip=192.168.168.5:192.168.168.1 root=nfs nfsroot=192.168.168.1:/opt/montavista/pro/devkit/xtensa/linux_be/target"
  78 +CONFIG_SERIAL_CONSOLE=y
  79 +CONFIG_XTENSA_ISS_NETWORK=y
  80 +
  81 +#
  82 +# Bus options
  83 +#
  84 +
  85 +#
  86 +# PCCARD (PCMCIA/CardBus) support
  87 +#
  88 +# CONFIG_PCCARD is not set
  89 +
  90 +#
  91 +# PC-card bridges
  92 +#
  93 +
  94 +#
  95 +# PCI Hotplug Support
  96 +#
  97 +
  98 +#
  99 +# Exectuable file formats
  100 +#
  101 +CONFIG_KCORE_ELF=y
  102 +CONFIG_BINFMT_ELF=y
  103 +# CONFIG_BINFMT_MISC is not set
  104 +
  105 +#
  106 +# Device Drivers
  107 +#
  108 +
  109 +#
  110 +# Generic Driver Options
  111 +#
  112 +# CONFIG_STANDALONE is not set
  113 +CONFIG_PREVENT_FIRMWARE_BUILD=y
  114 +# CONFIG_FW_LOADER is not set
  115 +# CONFIG_DEBUG_DRIVER is not set
  116 +
  117 +#
  118 +# Memory Technology Devices (MTD)
  119 +#
  120 +# CONFIG_MTD is not set
  121 +
  122 +#
  123 +# Parallel port support
  124 +#
  125 +# CONFIG_PARPORT is not set
  126 +
  127 +#
  128 +# Plug and Play support
  129 +#
  130 +
  131 +#
  132 +# Block devices
  133 +#
  134 +# CONFIG_BLK_DEV_FD is not set
  135 +# CONFIG_BLK_DEV_COW_COMMON is not set
  136 +# CONFIG_BLK_DEV_LOOP is not set
  137 +# CONFIG_BLK_DEV_NBD is not set
  138 +# CONFIG_BLK_DEV_RAM is not set
  139 +CONFIG_BLK_DEV_RAM_COUNT=16
  140 +CONFIG_INITRAMFS_SOURCE=""
  141 +# CONFIG_CDROM_PKTCDVD is not set
  142 +
  143 +#
  144 +# IO Schedulers
  145 +#
  146 +CONFIG_IOSCHED_NOOP=y
  147 +# CONFIG_IOSCHED_AS is not set
  148 +# CONFIG_IOSCHED_DEADLINE is not set
  149 +# CONFIG_IOSCHED_CFQ is not set
  150 +# CONFIG_ATA_OVER_ETH is not set
  151 +
  152 +#
  153 +# ATA/ATAPI/MFM/RLL support
  154 +#
  155 +# CONFIG_IDE is not set
  156 +
  157 +#
  158 +# SCSI device support
  159 +#
  160 +# CONFIG_SCSI is not set
  161 +
  162 +#
  163 +# Multi-device support (RAID and LVM)
  164 +#
  165 +# CONFIG_MD is not set
  166 +
  167 +#
  168 +# Fusion MPT device support
  169 +#
  170 +
  171 +#
  172 +# IEEE 1394 (FireWire) support
  173 +#
  174 +
  175 +#
  176 +# I2O device support
  177 +#
  178 +
  179 +#
  180 +# Networking support
  181 +#
  182 +CONFIG_NET=y
  183 +
  184 +#
  185 +# Networking options
  186 +#
  187 +CONFIG_PACKET=y
  188 +# CONFIG_PACKET_MMAP is not set
  189 +# CONFIG_NETLINK_DEV is not set
  190 +CONFIG_UNIX=y
  191 +# CONFIG_NET_KEY is not set
  192 +CONFIG_INET=y
  193 +# CONFIG_IP_MULTICAST is not set
  194 +# CONFIG_IP_ADVANCED_ROUTER is not set
  195 +CONFIG_IP_PNP=y
  196 +CONFIG_IP_PNP_DHCP=y
  197 +CONFIG_IP_PNP_BOOTP=y
  198 +CONFIG_IP_PNP_RARP=y
  199 +# CONFIG_NET_IPIP is not set
  200 +# CONFIG_NET_IPGRE is not set
  201 +# CONFIG_ARPD is not set
  202 +# CONFIG_SYN_COOKIES is not set
  203 +# CONFIG_INET_AH is not set
  204 +# CONFIG_INET_ESP is not set
  205 +# CONFIG_INET_IPCOMP is not set
  206 +# CONFIG_INET_TUNNEL is not set
  207 +# CONFIG_IP_TCPDIAG is not set
  208 +# CONFIG_IP_TCPDIAG_IPV6 is not set
  209 +# CONFIG_IPV6 is not set
  210 +# CONFIG_NETFILTER is not set
  211 +
  212 +#
  213 +# SCTP Configuration (EXPERIMENTAL)
  214 +#
  215 +# CONFIG_IP_SCTP is not set
  216 +# CONFIG_SCTP_HMAC_NONE is not set
  217 +# CONFIG_SCTP_HMAC_SHA1 is not set
  218 +# CONFIG_SCTP_HMAC_MD5 is not set
  219 +# CONFIG_ATM is not set
  220 +# CONFIG_BRIDGE is not set
  221 +# CONFIG_VLAN_8021Q is not set
  222 +# CONFIG_DECNET is not set
  223 +# CONFIG_LLC2 is not set
  224 +# CONFIG_IPX is not set
  225 +# CONFIG_ATALK is not set
  226 +# CONFIG_X25 is not set
  227 +# CONFIG_LAPB is not set
  228 +# CONFIG_NET_DIVERT is not set
  229 +# CONFIG_ECONET is not set
  230 +# CONFIG_WAN_ROUTER is not set
  231 +
  232 +#
  233 +# QoS and/or fair queueing
  234 +#
  235 +# CONFIG_NET_SCHED is not set
  236 +# CONFIG_NET_SCH_CLK_JIFFIES is not set
  237 +# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
  238 +# CONFIG_NET_SCH_CLK_CPU is not set
  239 +# CONFIG_NET_CLS_ROUTE is not set
  240 +
  241 +#
  242 +# Network testing
  243 +#
  244 +# CONFIG_NET_PKTGEN is not set
  245 +# CONFIG_NETPOLL is not set
  246 +# CONFIG_NET_POLL_CONTROLLER is not set
  247 +# CONFIG_HAMRADIO is not set
  248 +# CONFIG_IRDA is not set
  249 +# CONFIG_BT is not set
  250 +# CONFIG_NETDEVICES is not set
  251 +
  252 +#
  253 +# ISDN subsystem
  254 +#
  255 +# CONFIG_ISDN is not set
  256 +
  257 +#
  258 +# Telephony Support
  259 +#
  260 +# CONFIG_PHONE is not set
  261 +
  262 +#
  263 +# Input device support
  264 +#
  265 +CONFIG_INPUT=y
  266 +
  267 +#
  268 +# Userland interfaces
  269 +#
  270 +# CONFIG_INPUT_MOUSEDEV is not set
  271 +# CONFIG_INPUT_JOYDEV is not set
  272 +# CONFIG_INPUT_TSDEV is not set
  273 +# CONFIG_INPUT_EVDEV is not set
  274 +# CONFIG_INPUT_EVBUG is not set
  275 +
  276 +#
  277 +# Input I/O drivers
  278 +#
  279 +# CONFIG_GAMEPORT is not set
  280 +CONFIG_SOUND_GAMEPORT=y
  281 +# CONFIG_SERIO is not set
  282 +# CONFIG_SERIO_I8042 is not set
  283 +
  284 +#
  285 +# Input Device Drivers
  286 +#
  287 +# CONFIG_INPUT_KEYBOARD is not set
  288 +# CONFIG_INPUT_MOUSE is not set
  289 +# CONFIG_INPUT_JOYSTICK is not set
  290 +# CONFIG_INPUT_TOUCHSCREEN is not set
  291 +# CONFIG_INPUT_MISC is not set
  292 +
  293 +#
  294 +# Character devices
  295 +#
  296 +CONFIG_VT=y
  297 +CONFIG_VT_CONSOLE=y
  298 +CONFIG_HW_CONSOLE=y
  299 +# CONFIG_SERIAL_NONSTANDARD is not set
  300 +
  301 +#
  302 +# Serial drivers
  303 +#
  304 +# CONFIG_SERIAL_8250 is not set
  305 +
  306 +#
  307 +# Non-8250 serial port support
  308 +#
  309 +CONFIG_UNIX98_PTYS=y
  310 +CONFIG_LEGACY_PTYS=y
  311 +CONFIG_LEGACY_PTY_COUNT=256
  312 +
  313 +#
  314 +# IPMI
  315 +#
  316 +# CONFIG_IPMI_HANDLER is not set
  317 +
  318 +#
  319 +# Watchdog Cards
  320 +#
  321 +CONFIG_WATCHDOG=y
  322 +CONFIG_WATCHDOG_NOWAYOUT=y
  323 +
  324 +#
  325 +# Watchdog Device Drivers
  326 +#
  327 +CONFIG_SOFT_WATCHDOG=y
  328 +# CONFIG_RTC is not set
  329 +# CONFIG_GEN_RTC is not set
  330 +# CONFIG_DTLK is not set
  331 +# CONFIG_R3964 is not set
  332 +
  333 +#
  334 +# Ftape, the floppy tape device driver
  335 +#
  336 +# CONFIG_DRM is not set
  337 +# CONFIG_RAW_DRIVER is not set
  338 +
  339 +#
  340 +# I2C support
  341 +#
  342 +# CONFIG_I2C is not set
  343 +
  344 +#
  345 +# Dallas's 1-wire bus
  346 +#
  347 +# CONFIG_W1 is not set
  348 +
  349 +#
  350 +# Misc devices
  351 +#
  352 +
  353 +#
  354 +# Multimedia devices
  355 +#
  356 +# CONFIG_VIDEO_DEV is not set
  357 +
  358 +#
  359 +# Digital Video Broadcasting Devices
  360 +#
  361 +# CONFIG_DVB is not set
  362 +
  363 +#
  364 +# Graphics support
  365 +#
  366 +# CONFIG_FB is not set
  367 +
  368 +#
  369 +# Console display driver support
  370 +#
  371 +# CONFIG_VGA_CONSOLE is not set
  372 +CONFIG_DUMMY_CONSOLE=y
  373 +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
  374 +
  375 +#
  376 +# Sound
  377 +#
  378 +# CONFIG_SOUND is not set
  379 +
  380 +#
  381 +# USB support
  382 +#
  383 +# CONFIG_USB_ARCH_HAS_HCD is not set
  384 +# CONFIG_USB_ARCH_HAS_OHCI is not set
  385 +
  386 +#
  387 +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
  388 +#
  389 +
  390 +#
  391 +# USB Gadget Support
  392 +#
  393 +# CONFIG_USB_GADGET is not set
  394 +
  395 +#
  396 +# MMC/SD Card support
  397 +#
  398 +# CONFIG_MMC is not set
  399 +
  400 +#
  401 +# InfiniBand support
  402 +#
  403 +# CONFIG_INFINIBAND is not set
  404 +
  405 +#
  406 +# File systems
  407 +#
  408 +# CONFIG_EXT2_FS is not set
  409 +# CONFIG_EXT3_FS is not set
  410 +# CONFIG_JBD is not set
  411 +# CONFIG_REISERFS_FS is not set
  412 +# CONFIG_JFS_FS is not set
  413 +# CONFIG_XFS_FS is not set
  414 +# CONFIG_MINIX_FS is not set
  415 +# CONFIG_ROMFS_FS is not set
  416 +# CONFIG_QUOTA is not set
  417 +# CONFIG_DNOTIFY is not set
  418 +# CONFIG_AUTOFS_FS is not set
  419 +# CONFIG_AUTOFS4_FS is not set
  420 +
  421 +#
  422 +# CD-ROM/DVD Filesystems
  423 +#
  424 +# CONFIG_ISO9660_FS is not set
  425 +# CONFIG_UDF_FS is not set
  426 +
  427 +#
  428 +# DOS/FAT/NT Filesystems
  429 +#
  430 +# CONFIG_MSDOS_FS is not set
  431 +# CONFIG_VFAT_FS is not set
  432 +# CONFIG_NTFS_FS is not set
  433 +
  434 +#
  435 +# Pseudo filesystems
  436 +#
  437 +CONFIG_PROC_FS=y
  438 +CONFIG_PROC_KCORE=y
  439 +CONFIG_SYSFS=y
  440 +CONFIG_DEVFS_FS=y
  441 +CONFIG_DEVFS_MOUNT=y
  442 +# CONFIG_DEVFS_DEBUG is not set
  443 +# CONFIG_DEVPTS_FS_XATTR is not set
  444 +CONFIG_TMPFS=y
  445 +# CONFIG_TMPFS_XATTR is not set
  446 +# CONFIG_HUGETLB_PAGE is not set
  447 +CONFIG_RAMFS=y
  448 +
  449 +#
  450 +# Miscellaneous filesystems
  451 +#
  452 +# CONFIG_ADFS_FS is not set
  453 +# CONFIG_AFFS_FS is not set
  454 +# CONFIG_HFS_FS is not set
  455 +# CONFIG_HFSPLUS_FS is not set
  456 +# CONFIG_BEFS_FS is not set
  457 +# CONFIG_BFS_FS is not set
  458 +# CONFIG_EFS_FS is not set
  459 +# CONFIG_CRAMFS is not set
  460 +# CONFIG_VXFS_FS is not set
  461 +# CONFIG_HPFS_FS is not set
  462 +# CONFIG_QNX4FS_FS is not set
  463 +# CONFIG_SYSV_FS is not set
  464 +# CONFIG_UFS_FS is not set
  465 +
  466 +#
  467 +# Network File Systems
  468 +#
  469 +CONFIG_NFS_FS=y
  470 +CONFIG_NFS_V3=y
  471 +# CONFIG_NFS_V4 is not set
  472 +CONFIG_NFS_DIRECTIO=y
  473 +# CONFIG_NFSD is not set
  474 +CONFIG_ROOT_NFS=y
  475 +CONFIG_LOCKD=y
  476 +CONFIG_LOCKD_V4=y
  477 +# CONFIG_EXPORTFS is not set
  478 +CONFIG_SUNRPC=y
  479 +# CONFIG_RPCSEC_GSS_KRB5 is not set
  480 +# CONFIG_RPCSEC_GSS_SPKM3 is not set
  481 +# CONFIG_SMB_FS is not set
  482 +# CONFIG_CIFS is not set
  483 +# CONFIG_NCP_FS is not set
  484 +# CONFIG_CODA_FS is not set
  485 +# CONFIG_AFS_FS is not set
  486 +
  487 +#
  488 +# Partition Types
  489 +#
  490 +# CONFIG_PARTITION_ADVANCED is not set
  491 +CONFIG_MSDOS_PARTITION=y
  492 +
  493 +#
  494 +# Native Language Support
  495 +#
  496 +# CONFIG_NLS is not set
  497 +
  498 +#
  499 +# Kernel hacking
  500 +#
  501 +CONFIG_DEBUG_KERNEL=y
  502 +# CONFIG_DEBUG_STACKOVERFLOW is not set
  503 +# CONFIG_DEBUG_SLAB is not set
  504 +# CONFIG_MAGIC_SYSRQ is not set
  505 +# CONFIG_DEBUG_SPINLOCK is not set
  506 +# CONFIG_DEBUG_PAGEALLOC is not set
  507 +# CONFIG_DEBUG_INFO is not set
  508 +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
  509 +# CONFIG_KGDB is not set
  510 +
  511 +#
  512 +# Security options
  513 +#
  514 +# CONFIG_KEYS is not set
  515 +# CONFIG_SECURITY is not set
  516 +
  517 +#
  518 +# Cryptographic options
  519 +#
  520 +# CONFIG_CRYPTO is not set
  521 +
  522 +#
  523 +# Hardware crypto devices
  524 +#
  525 +
  526 +#
  527 +# Library routines
  528 +#
  529 +# CONFIG_CRC_CCITT is not set
  530 +# CONFIG_CRC32 is not set
  531 +# CONFIG_LIBCRC32C is not set
arch/xtensa/platform-iss/Makefile
  1 +# $Id: Makefile,v 1.1.1.1 2002/08/28 16:10:14 aroll Exp $
  2 +#
  3 +# Makefile for the Xtensa Instruction Set Simulator (ISS)
  4 +# "prom monitor" library routines under Linux.
  5 +#
  6 +# Note! Dependencies are done automagically by 'make dep', which also
  7 +# removes any old dependencies. DON'T put your own dependencies here
  8 +# unless it's something special (ie not a .c file).
  9 +#
  10 +# Note 2! The CFLAGS definitions are in the main makefile...
  11 +
  12 +obj-y = io.o console.o setup.o network.o
arch/xtensa/platform-iss/console.c
  1 +/*
  2 + * arch/xtensa/platform-iss/console.c
  3 + *
  4 + * This file is subject to the terms and conditions of the GNU General Public
  5 + * License. See the file "COPYING" in the main directory of this archive
  6 + * for more details.
  7 + *
  8 + * Copyright (C) 2001-2005 Tensilica Inc.
  9 + * Authors Christian Zankel, Joe Taylor
  10 + */
  11 +
  12 +#include <linux/module.h>
  13 +#include <linux/config.h>
  14 +#include <linux/kernel.h>
  15 +#include <linux/sched.h>
  16 +#include <linux/console.h>
  17 +#include <linux/init.h>
  18 +#include <linux/slab.h>
  19 +#include <linux/mm.h>
  20 +#include <linux/major.h>
  21 +#include <linux/param.h>
  22 +#include <linux/serial.h>
  23 +#include <linux/serialP.h>
  24 +#include <linux/console.h>
  25 +
  26 +#include <asm/uaccess.h>
  27 +#include <asm/irq.h>
  28 +
  29 +#include <xtensa/simcall.h>
  30 +
  31 +#include <linux/tty.h>
  32 +#include <linux/tty_flip.h>
  33 +
  34 +#ifdef SERIAL_INLINE
  35 +#define _INLINE_ inline
  36 +#endif
  37 +
  38 +#define SERIAL_MAX_NUM_LINES 1
  39 +#define SERIAL_TIMER_VALUE (20 * HZ)
  40 +
  41 +static struct tty_driver *serial_driver;
  42 +static struct timer_list serial_timer;
  43 +
  44 +static DEFINE_SPINLOCK(timer_lock);
  45 +
  46 +int errno;
  47 +
  48 +static int __simc (int a, int b, int c, int d, int e, int f)
  49 +{
  50 + int ret;
  51 + __asm__ __volatile__ ("simcall\n"
  52 + "mov %0, a2\n"
  53 + "mov %1, a3\n" : "=a" (ret), "=a" (errno)
  54 + : : "a2", "a3");
  55 + return ret;
  56 +}
  57 +
  58 +static char *serial_version = "0.1";
  59 +static char *serial_name = "ISS serial driver";
  60 +
  61 +/*
  62 + * This routine is called whenever a serial port is opened. It
  63 + * enables interrupts for a serial port, linking in its async structure into
  64 + * the IRQ chain. It also performs the serial-specific
  65 + * initialization for the tty structure.
  66 + */
  67 +
  68 +static void rs_poll(unsigned long);
  69 +
  70 +static int rs_open(struct tty_struct *tty, struct file * filp)
  71 +{
  72 + int line = tty->index;
  73 +
  74 + if ((line < 0) || (line >= SERIAL_MAX_NUM_LINES))
  75 + return -ENODEV;
  76 +
  77 + spin_lock(&timer_lock);
  78 +
  79 + if (tty->count == 1) {
  80 + init_timer(&serial_timer);
  81 + serial_timer.data = (unsigned long) tty;
  82 + serial_timer.function = rs_poll;
  83 + mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
  84 + }
  85 + spin_unlock(&timer_lock);
  86 +
  87 + return 0;
  88 +}
  89 +
  90 +
  91 +/*
  92 + * ------------------------------------------------------------
  93 + * iss_serial_close()
  94 + *
  95 + * This routine is called when the serial port gets closed. First, we
  96 + * wait for the last remaining data to be sent. Then, we unlink its
  97 + * async structure from the interrupt chain if necessary, and we free
  98 + * that IRQ if nothing is left in the chain.
  99 + * ------------------------------------------------------------
  100 + */
  101 +static void rs_close(struct tty_struct *tty, struct file * filp)
  102 +{
  103 + spin_lock(&timer_lock);
  104 + if (tty->count == 1)
  105 + del_timer_sync(&serial_timer);
  106 + spin_unlock(&timer_lock);
  107 +}
  108 +
  109 +
  110 +static int rs_write(struct tty_struct * tty,
  111 + const unsigned char *buf, int count)
  112 +{
  113 + /* see drivers/char/serialX.c to reference original version */
  114 +
  115 + __simc (SYS_write, 1, (unsigned long)buf, count, 0, 0);
  116 + return count;
  117 +}
  118 +
  119 +static void rs_poll(unsigned long priv)
  120 +{
  121 + struct tty_struct* tty = (struct tty_struct*) priv;
  122 +
  123 + struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
  124 + int i = 0;
  125 + unsigned char c;
  126 +
  127 + spin_lock(&timer_lock);
  128 +
  129 + while (__simc(SYS_select_one, 0, XTISS_SELECT_ONE_READ, (int)&tv,0,0)){
  130 + __simc (SYS_read, 0, (unsigned long)&c, 1, 0, 0);
  131 + tty->flip.count++;
  132 + *tty->flip.char_buf_ptr++ = c;
  133 + *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
  134 + i++;
  135 + }
  136 +
  137 + if (i)
  138 + tty_flip_buffer_push(tty);
  139 +
  140 +
  141 + mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
  142 + spin_unlock(&timer_lock);
  143 +}
  144 +
  145 +
  146 +static void rs_put_char(struct tty_struct *tty, unsigned char ch)
  147 +{
  148 + char buf[2];
  149 +
  150 + if (!tty)
  151 + return;
  152 +
  153 + buf[0] = ch;
  154 + buf[1] = '\0'; /* Is this NULL necessary? */
  155 + __simc (SYS_write, 1, (unsigned long) buf, 1, 0, 0);
  156 +}
  157 +
  158 +static void rs_flush_chars(struct tty_struct *tty)
  159 +{
  160 +}
  161 +
  162 +static int rs_write_room(struct tty_struct *tty)
  163 +{
  164 + /* Let's say iss can always accept 2K characters.. */
  165 + return 2 * 1024;
  166 +}
  167 +
  168 +static int rs_chars_in_buffer(struct tty_struct *tty)
  169 +{
  170 + /* the iss doesn't buffer characters */
  171 + return 0;
  172 +}
  173 +
  174 +static void rs_hangup(struct tty_struct *tty)
  175 +{
  176 + /* Stub, once again.. */
  177 +}
  178 +
  179 +static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
  180 +{
  181 + /* Stub, once again.. */
  182 +}
  183 +
  184 +static int rs_read_proc(char *page, char **start, off_t off, int count,
  185 + int *eof, void *data)
  186 +{
  187 + int len = 0;
  188 + off_t begin = 0;
  189 +
  190 + len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
  191 + *eof = 1;
  192 +
  193 + if (off >= len + begin)
  194 + return 0;
  195 +
  196 + *start = page + (off - begin);
  197 + return ((count < begin + len - off) ? count : begin + len - off);
  198 +}
  199 +
  200 +
  201 +int register_serial(struct serial_struct*);
  202 +void unregister_serial(int);
  203 +
  204 +static struct tty_operations serial_ops = {
  205 + .open = rs_open,
  206 + .close = rs_close,
  207 + .write = rs_write,
  208 + .put_char = rs_put_char,
  209 + .flush_chars = rs_flush_chars,
  210 + .write_room = rs_write_room,
  211 + .chars_in_buffer = rs_chars_in_buffer,
  212 + .hangup = rs_hangup,
  213 + .wait_until_sent = rs_wait_until_sent,
  214 + .read_proc = rs_read_proc
  215 +};
  216 +
  217 +int __init rs_init(void)
  218 +{
  219 + serial_driver = alloc_tty_driver(1);
  220 +
  221 + printk ("%s %s\n", serial_name, serial_version);
  222 +
  223 + /* Initialize the tty_driver structure */
  224 +
  225 + serial_driver->owner = THIS_MODULE;
  226 + serial_driver->driver_name = "iss_serial";
  227 + serial_driver->name = "ttyS";
  228 + serial_driver->major = TTY_MAJOR;
  229 + serial_driver->minor_start = 64;
  230 + serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
  231 + serial_driver->subtype = SERIAL_TYPE_NORMAL;
  232 + serial_driver->init_termios = tty_std_termios;
  233 + serial_driver->init_termios.c_cflag =
  234 + B9600 | CS8 | CREAD | HUPCL | CLOCAL;
  235 + serial_driver->flags = TTY_DRIVER_REAL_RAW;
  236 +
  237 + tty_set_operations(serial_driver, &serial_ops);
  238 +
  239 + if (tty_register_driver(serial_driver))
  240 + panic("Couldn't register serial driver\n");
  241 + return 0;
  242 +}
  243 +
  244 +
  245 +static __exit void rs_exit(void)
  246 +{
  247 + int error;
  248 +
  249 + if ((error = tty_unregister_driver(serial_driver)))
  250 + printk("ISS_SERIAL: failed to unregister serial driver (%d)\n",
  251 + error);
  252 + put_tty_driver(serial_driver);
  253 +}
  254 +
  255 +
  256 +/* We use `late_initcall' instead of just `__initcall' as a workaround for
  257 + * the fact that (1) simcons_tty_init can't be called before tty_init,
  258 + * (2) tty_init is called via `module_init', (3) if statically linked,
  259 + * module_init == device_init, and (4) there's no ordering of init lists.
  260 + * We can do this easily because simcons is always statically linked, but
  261 + * other tty drivers that depend on tty_init and which must use
  262 + * `module_init' to declare their init routines are likely to be broken.
  263 + */
  264 +
  265 +late_initcall(rs_init);
  266 +
  267 +
  268 +#ifdef CONFIG_SERIAL_CONSOLE
  269 +
  270 +static void iss_console_write(struct console *co, const char *s, unsigned count)
  271 +{
  272 + int len = strlen(s);
  273 +
  274 + if (s != 0 && *s != 0)
  275 + __simc (SYS_write, 1, (unsigned long)s,
  276 + count < len ? count : len,0,0);
  277 +}
  278 +
  279 +static struct tty_driver* iss_console_device(struct console *c, int *index)
  280 +{
  281 + *index = c->index;
  282 + return serial_driver;
  283 +}
  284 +
  285 +
  286 +static struct console sercons = {
  287 + .name = "ttyS",
  288 + .write = iss_console_write,
  289 + .device = iss_console_device,
  290 + .flags = CON_PRINTBUFFER,
  291 + .index = -1
  292 +};
  293 +
  294 +static int __init iss_console_init(void)
  295 +{
  296 + register_console(&sercons);
  297 + return 0;
  298 +}
  299 +
  300 +console_initcall(iss_console_init);
  301 +
  302 +#endif /* CONFIG_SERIAL_CONSOLE */
arch/xtensa/platform-iss/io.c
  1 +/* This file isn't really needed right now. */
  2 +
  3 +#if 0
  4 +
  5 +#include <asm/io.h>
  6 +#include <xtensa/simcall.h>
  7 +
  8 +extern int __simc ();
  9 +
  10 +
  11 +char iss_serial_getc()
  12 +{
  13 + char c;
  14 + __simc( SYS_read, 0, &c, 1 );
  15 + return c;
  16 +}
  17 +
  18 +void iss_serial_putc( char c )
  19 +{
  20 + __simc( SYS_write, 1, &c, 1 );
  21 +}
  22 +
  23 +void iss_serial_puts( char *s )
  24 +{
  25 + if( s != 0 && *s != 0 )
  26 + __simc( SYS_write, 1, s, strlen(s) );
  27 +}
  28 +
  29 +/*#error Need I/O ports to specific hardware!*/
  30 +
  31 +#endif
arch/xtensa/platform-iss/network.c
  1 +/*
  2 + *
  3 + * arch/xtensa/platform-iss/network.c
  4 + *
  5 + * Platform specific initialization.
  6 + *
  7 + * Authors: Chris Zankel <chris@zankel.net>
  8 + * Based on work form the UML team.
  9 + *
  10 + * Copyright 2005 Tensilica Inc.
  11 + *
  12 + * This program is free software; you can redistribute it and/or modify it
  13 + * under the terms of the GNU General Public License as published by the
  14 + * Free Software Foundation; either version 2 of the License, or (at your
  15 + * option) any later version.
  16 + *
  17 + */
  18 +
  19 +#include <linux/config.h>
  20 +#include <linux/list.h>
  21 +#include <linux/irq.h>
  22 +#include <linux/spinlock.h>
  23 +#include <linux/slab.h>
  24 +#include <linux/timer.h>
  25 +#include <linux/if_ether.h>
  26 +#include <linux/inetdevice.h>
  27 +#include <linux/init.h>
  28 +#include <linux/if_tun.h>
  29 +#include <linux/etherdevice.h>
  30 +#include <linux/interrupt.h>
  31 +#include <linux/ioctl.h>
  32 +#include <linux/bootmem.h>
  33 +#include <linux/ethtool.h>
  34 +#include <linux/rtnetlink.h>
  35 +#include <linux/timer.h>
  36 +
  37 +#include <xtensa/simcall.h>
  38 +
  39 +#define DRIVER_NAME "iss-netdev"
  40 +#define ETH_MAX_PACKET 1500
  41 +#define ETH_HEADER_OTHER 14
  42 +#define ISS_NET_TIMER_VALUE (2 * HZ)
  43 +
  44 +
  45 +static DEFINE_SPINLOCK(opened_lock);
  46 +static LIST_HEAD(opened);
  47 +
  48 +static DEFINE_SPINLOCK(devices_lock);
  49 +static LIST_HEAD(devices);
  50 +
  51 +/* ------------------------------------------------------------------------- */
  52 +
  53 +/* We currently only support the TUNTAP transport protocol. */
  54 +
  55 +#define TRANSPORT_TUNTAP_NAME "tuntap"
  56 +#define TRANSPORT_TUNTAP_MTU ETH_MAX_PACKET
  57 +
  58 +struct tuntap_info {
  59 + char dev_name[IFNAMSIZ];
  60 + int fixed_config;
  61 + unsigned char gw[ETH_ALEN];
  62 + int fd;
  63 +};
  64 +
  65 +/* ------------------------------------------------------------------------- */
  66 +
  67 +
  68 +/* This structure contains out private information for the driver. */
  69 +
  70 +struct iss_net_private {
  71 +
  72 + struct list_head device_list;
  73 + struct list_head opened_list;
  74 +
  75 + spinlock_t lock;
  76 + struct net_device *dev;
  77 + struct platform_device pdev;
  78 + struct timer_list tl;
  79 + struct net_device_stats stats;
  80 +
  81 + struct timer_list timer;
  82 + unsigned int timer_val;
  83 +
  84 + int index;
  85 + int mtu;
  86 +
  87 + unsigned char mac[ETH_ALEN];
  88 + int have_mac;
  89 +
  90 + struct {
  91 + union {
  92 + struct tuntap_info tuntap;
  93 + } info;
  94 +
  95 + int (*open)(struct iss_net_private *lp);
  96 + void (*close)(struct iss_net_private *lp);
  97 + int (*read)(struct iss_net_private *lp, struct sk_buff **skb);
  98 + int (*write)(struct iss_net_private *lp, struct sk_buff **skb);
  99 + unsigned short (*protocol)(struct sk_buff *skb);
  100 + int (*poll)(struct iss_net_private *lp);
  101 + } tp;
  102 +
  103 +};
  104 +
  105 +/* ======================= ISS SIMCALL INTERFACE =========================== */
  106 +
  107 +/* Note: __simc must _not_ be declared inline! */
  108 +
  109 +static int errno;
  110 +
  111 +static int __simc (int a, int b, int c, int d, int e, int f)
  112 +{
  113 + int ret;
  114 + __asm__ __volatile__ ("simcall\n"
  115 + "mov %0, a2\n"
  116 + "mov %1, a3\n" : "=a" (ret), "=a" (errno)
  117 + : : "a2", "a3");
  118 + return ret;
  119 +}
  120 +
  121 +static int inline simc_open(char *file, int flags, int mode)
  122 +{
  123 + return __simc(SYS_open, (int) file, flags, mode, 0, 0);
  124 +}
  125 +
  126 +static int inline simc_close(int fd)
  127 +{
  128 + return __simc(SYS_close, fd, 0, 0, 0, 0);
  129 +}
  130 +
  131 +static int inline simc_ioctl(int fd, int request, void *arg)
  132 +{
  133 + return __simc(SYS_ioctl, fd, request, (int) arg, 0, 0);
  134 +}
  135 +
  136 +static int inline simc_read(int fd, void *buf, size_t count)
  137 +{
  138 + return __simc(SYS_read, fd, (int) buf, count, 0, 0);
  139 +}
  140 +
  141 +static int inline simc_write(int fd, void *buf, size_t count)
  142 +{
  143 + return __simc(SYS_write, fd, (int) buf, count, 0, 0);
  144 +}
  145 +
  146 +static int inline simc_poll(int fd)
  147 +{
  148 + struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
  149 +
  150 + return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv,0,0);
  151 +}
  152 +
  153 +/* ================================ HELPERS ================================ */
  154 +
  155 +
  156 +static char *split_if_spec(char *str, ...)
  157 +{
  158 + char **arg, *end;
  159 + va_list ap;
  160 +
  161 + va_start(ap, str);
  162 + while ((arg = va_arg(ap, char**)) != NULL) {
  163 + if (*str == '\0')
  164 + return NULL;
  165 + end = strchr(str, ',');
  166 + if (end != str)
  167 + *arg = str;
  168 + if (end == NULL)
  169 + return NULL;
  170 + *end ++ = '\0';
  171 + str = end;
  172 + }
  173 + va_end(ap);
  174 + return str;
  175 +}
  176 +
  177 +
  178 +#if 0
  179 +/* Adjust SKB. */
  180 +
  181 +struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra)
  182 +{
  183 + if ((skb != NULL) && (skb_tailroom(skb) < extra)) {
  184 + struct sk_buff *skb2;
  185 +
  186 + skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC);
  187 + dev_kfree_skb(skb);
  188 + skb = skb2;
  189 + }
  190 + if (skb != NULL)
  191 + skb_put(skb, extra);
  192 +
  193 + return skb;
  194 +}
  195 +#endif
  196 +
  197 +/* Return the IP address as a string for a given device. */
  198 +
  199 +static void dev_ip_addr(void *d, char *buf, char *bin_buf)
  200 +{
  201 + struct net_device *dev = d;
  202 + struct in_device *ip = dev->ip_ptr;
  203 + struct in_ifaddr *in;
  204 + u32 addr;
  205 +
  206 + if ((ip == NULL) || ((in = ip->ifa_list) == NULL)) {
  207 + printk(KERN_WARNING "Device not assigned an IP address!\n");
  208 + return;
  209 + }
  210 +
  211 + addr = in->ifa_address;
  212 + sprintf(buf, "%d.%d.%d.%d", addr & 0xff, (addr >> 8) & 0xff,
  213 + (addr >> 16) & 0xff, addr >> 24);
  214 +
  215 + if (bin_buf) {
  216 + bin_buf[0] = addr & 0xff;
  217 + bin_buf[1] = (addr >> 8) & 0xff;
  218 + bin_buf[2] = (addr >> 16) & 0xff;
  219 + bin_buf[3] = addr >> 24;
  220 + }
  221 +}
  222 +
  223 +/* Set Ethernet address of the specified device. */
  224 +
  225 +static void inline set_ether_mac(void *d, unsigned char *addr)
  226 +{
  227 + struct net_device *dev = d;
  228 + memcpy(dev->dev_addr, addr, ETH_ALEN);
  229 +}
  230 +
  231 +
  232 +/* ======================= TUNTAP TRANSPORT INTERFACE ====================== */
  233 +
  234 +static int tuntap_open(struct iss_net_private *lp)
  235 +{
  236 + struct ifreq ifr;
  237 + char *dev_name = lp->tp.info.tuntap.dev_name;
  238 + int err = -EINVAL;
  239 + int fd;
  240 +
  241 + /* We currently only support a fixed configuration. */
  242 +
  243 + if (!lp->tp.info.tuntap.fixed_config)
  244 + return -EINVAL;
  245 +
  246 + if ((fd = simc_open("/dev/net/tun", 02, 0)) < 0) { /* O_RDWR */
  247 + printk("Failed to open /dev/net/tun, returned %d "
  248 + "(errno = %d)\n", fd, errno);
  249 + return fd;
  250 + }
  251 +
  252 + memset(&ifr, 0, sizeof ifr);
  253 + ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
  254 + strlcpy(ifr.ifr_name, dev_name, sizeof ifr.ifr_name - 1);
  255 +
  256 + if ((err = simc_ioctl(fd, TUNSETIFF, (void*) &ifr)) < 0) {
  257 + printk("Failed to set interface, returned %d "
  258 + "(errno = %d)\n", err, errno);
  259 + simc_close(fd);
  260 + return err;
  261 + }
  262 +
  263 + lp->tp.info.tuntap.fd = fd;
  264 + return err;
  265 +}
  266 +
  267 +static void tuntap_close(struct iss_net_private *lp)
  268 +{
  269 +#if 0
  270 + if (lp->tp.info.tuntap.fixed_config)
  271 + iter_addresses(lp->tp.info.tuntap.dev, close_addr, lp->host.dev_name);
  272 +#endif
  273 + simc_close(lp->tp.info.tuntap.fd);
  274 + lp->tp.info.tuntap.fd = -1;
  275 +}
  276 +
  277 +static int tuntap_read (struct iss_net_private *lp, struct sk_buff **skb)
  278 +{
  279 +#if 0
  280 + *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
  281 + if (*skb == NULL)
  282 + return -ENOMEM;
  283 +#endif
  284 +
  285 + return simc_read(lp->tp.info.tuntap.fd,
  286 + (*skb)->data, (*skb)->dev->mtu + ETH_HEADER_OTHER);
  287 +}
  288 +
  289 +static int tuntap_write (struct iss_net_private *lp, struct sk_buff **skb)
  290 +{
  291 + return simc_write(lp->tp.info.tuntap.fd, (*skb)->data, (*skb)->len);
  292 +}
  293 +
  294 +unsigned short tuntap_protocol(struct sk_buff *skb)
  295 +{
  296 + return eth_type_trans(skb, skb->dev);
  297 +}
  298 +
  299 +static int tuntap_poll(struct iss_net_private *lp)
  300 +{
  301 + return simc_poll(lp->tp.info.tuntap.fd);
  302 +}
  303 +
  304 +/*
  305 + * Currently only a device name is supported.
  306 + * ethX=tuntap[,[mac address][,[device name]]]
  307 + */
  308 +
  309 +static int tuntap_probe(struct iss_net_private *lp, int index, char *init)
  310 +{
  311 + const int len = strlen(TRANSPORT_TUNTAP_NAME);
  312 + char *dev_name = NULL, *mac_str = NULL, *rem = NULL;
  313 +
  314 + /* Transport should be 'tuntap': ethX=tuntap,mac,dev_name */
  315 +
  316 + if (strncmp(init, TRANSPORT_TUNTAP_NAME, len))
  317 + return 0;
  318 +
  319 + if (*(init += strlen(TRANSPORT_TUNTAP_NAME)) == ',') {
  320 + if ((rem=split_if_spec(init+1, &mac_str, &dev_name)) != NULL) {
  321 + printk("Extra garbage on specification : '%s'\n", rem);
  322 + return 0;
  323 + }
  324 + } else if (*init != '\0') {
  325 + printk("Invalid argument: %s. Skipping device!\n", init);
  326 + return 0;
  327 + }
  328 +
  329 + if (dev_name) {
  330 + strncpy(lp->tp.info.tuntap.dev_name, dev_name,
  331 + sizeof lp->tp.info.tuntap.dev_name);
  332 + lp->tp.info.tuntap.fixed_config = 1;
  333 + } else
  334 + strcpy(lp->tp.info.tuntap.dev_name, TRANSPORT_TUNTAP_NAME);
  335 +
  336 +
  337 +#if 0
  338 + if (setup_etheraddr(mac_str, lp->mac))
  339 + lp->have_mac = 1;
  340 +#endif
  341 + lp->mtu = TRANSPORT_TUNTAP_MTU;
  342 +
  343 + //lp->info.tuntap.gate_addr = gate_addr;
  344 +
  345 + lp->tp.info.tuntap.fd = -1;
  346 +
  347 + lp->tp.open = tuntap_open;
  348 + lp->tp.close = tuntap_close;
  349 + lp->tp.read = tuntap_read;
  350 + lp->tp.write = tuntap_write;
  351 + lp->tp.protocol = tuntap_protocol;
  352 + lp->tp.poll = tuntap_poll;
  353 +
  354 + printk("TUN/TAP backend - ");
  355 +#if 0
  356 + if (lp->host.gate_addr != NULL)
  357 + printk("IP = %s", lp->host.gate_addr);
  358 +#endif
  359 + printk("\n");
  360 +
  361 + return 1;
  362 +}
  363 +
  364 +/* ================================ ISS NET ================================ */
  365 +
  366 +static int iss_net_rx(struct net_device *dev)
  367 +{
  368 + struct iss_net_private *lp = dev->priv;
  369 + int pkt_len;
  370 + struct sk_buff *skb;
  371 +
  372 + /* Check if there is any new data. */
  373 +
  374 + if (lp->tp.poll(lp) == 0)
  375 + return 0;
  376 +
  377 + /* Try to allocate memory, if it fails, try again next round. */
  378 +
  379 + if ((skb = dev_alloc_skb(dev->mtu + 2 + ETH_HEADER_OTHER)) == NULL) {
  380 + lp->stats.rx_dropped++;
  381 + return 0;
  382 + }
  383 +
  384 + skb_reserve(skb, 2);
  385 +
  386 + /* Setup skb */
  387 +
  388 + skb->dev = dev;
  389 + skb->mac.raw = skb->data;
  390 + pkt_len = lp->tp.read(lp, &skb);
  391 + skb_put(skb, pkt_len);
  392 +
  393 + if (pkt_len > 0) {
  394 + skb_trim(skb, pkt_len);
  395 + skb->protocol = lp->tp.protocol(skb);
  396 + // netif_rx(skb);
  397 + netif_rx_ni(skb);
  398 +
  399 + lp->stats.rx_bytes += skb->len;
  400 + lp->stats.rx_packets++;
  401 + return pkt_len;
  402 + }
  403 + kfree_skb(skb);
  404 + return pkt_len;
  405 +}
  406 +
  407 +static int iss_net_poll(void)
  408 +{
  409 + struct list_head *ele;
  410 + int err, ret = 0;
  411 +
  412 + spin_lock(&opened_lock);
  413 +
  414 + list_for_each(ele, &opened) {
  415 + struct iss_net_private *lp;
  416 +
  417 + lp = list_entry(ele, struct iss_net_private, opened_list);
  418 +
  419 + if (!netif_running(lp->dev))
  420 + break;
  421 +
  422 + spin_lock(&lp->lock);
  423 +
  424 + while ((err = iss_net_rx(lp->dev)) > 0)
  425 + ret++;
  426 +
  427 + spin_unlock(&lp->lock);
  428 +
  429 + if (err < 0) {
  430 + printk(KERN_ERR "Device '%s' read returned %d, "
  431 + "shutting it down\n", lp->dev->name, err);
  432 + dev_close(lp->dev);
  433 + } else {
  434 + // FIXME reactivate_fd(lp->fd, ISS_ETH_IRQ);
  435 + }
  436 + }
  437 +
  438 + spin_unlock(&opened_lock);
  439 + return ret;
  440 +}
  441 +
  442 +
  443 +static void iss_net_timer(unsigned long priv)
  444 +{
  445 + struct iss_net_private* lp = (struct iss_net_private*) priv;
  446 +
  447 + spin_lock(&lp->lock);
  448 +
  449 + iss_net_poll();
  450 +
  451 + mod_timer(&lp->timer, jiffies + lp->timer_val);
  452 +
  453 + spin_unlock(&lp->lock);
  454 +}
  455 +
  456 +
  457 +static int iss_net_open(struct net_device *dev)
  458 +{
  459 + struct iss_net_private *lp = dev->priv;
  460 + char addr[sizeof "255.255.255.255\0"];
  461 + int err;
  462 +
  463 + spin_lock(&lp->lock);
  464 +
  465 + if ((err = lp->tp.open(lp)) < 0)
  466 + goto out;
  467 +
  468 + if (!lp->have_mac) {
  469 + dev_ip_addr(dev, addr, &lp->mac[2]);
  470 + set_ether_mac(dev, lp->mac);
  471 + }
  472 +
  473 + netif_start_queue(dev);
  474 +
  475 + /* clear buffer - it can happen that the host side of the interface
  476 + * is full when we gethere. In this case, new data is never queued,
  477 + * SIGIOs never arrive, and the net never works.
  478 + */
  479 + while ((err = iss_net_rx(dev)) > 0)
  480 + ;
  481 +
  482 + spin_lock(&opened_lock);
  483 + list_add(&lp->opened_list, &opened);
  484 + spin_unlock(&opened_lock);
  485 +
  486 + init_timer(&lp->timer);
  487 + lp->timer_val = ISS_NET_TIMER_VALUE;
  488 + lp->timer.data = (unsigned long) lp;
  489 + lp->timer.function = iss_net_timer;
  490 + mod_timer(&lp->timer, jiffies + lp->timer_val);
  491 +
  492 +out:
  493 + spin_unlock(&lp->lock);
  494 + return err;
  495 +}
  496 +
  497 +static int iss_net_close(struct net_device *dev)
  498 +{
  499 + struct iss_net_private *lp = dev->priv;
  500 +printk("iss_net_close!\n");
  501 + netif_stop_queue(dev);
  502 + spin_lock(&lp->lock);
  503 +
  504 + spin_lock(&opened_lock);
  505 + list_del(&opened);
  506 + spin_unlock(&opened_lock);
  507 +
  508 + del_timer_sync(&lp->timer);
  509 +
  510 + lp->tp.close(lp);
  511 +
  512 + spin_unlock(&lp->lock);
  513 + return 0;
  514 +}
  515 +
  516 +static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
  517 +{
  518 + struct iss_net_private *lp = dev->priv;
  519 + unsigned long flags;
  520 + int len;
  521 +
  522 + netif_stop_queue(dev);
  523 + spin_lock_irqsave(&lp->lock, flags);
  524 +
  525 + len = lp->tp.write(lp, &skb);
  526 +
  527 + if (len == skb->len) {
  528 + lp->stats.tx_packets++;
  529 + lp->stats.tx_bytes += skb->len;
  530 + dev->trans_start = jiffies;
  531 + netif_start_queue(dev);
  532 +
  533 + /* this is normally done in the interrupt when tx finishes */
  534 + netif_wake_queue(dev);
  535 +
  536 + } else if (len == 0) {
  537 + netif_start_queue(dev);
  538 + lp->stats.tx_dropped++;
  539 +
  540 + } else {
  541 + netif_start_queue(dev);
  542 + printk(KERN_ERR "iss_net_start_xmit: failed(%d)\n", len);
  543 + }
  544 +
  545 + spin_unlock_irqrestore(&lp->lock, flags);
  546 +
  547 + dev_kfree_skb(skb);
  548 + return 0;
  549 +}
  550 +
  551 +
  552 +static struct net_device_stats *iss_net_get_stats(struct net_device *dev)
  553 +{
  554 + struct iss_net_private *lp = dev->priv;
  555 + return &lp->stats;
  556 +}
  557 +
  558 +static void iss_net_set_multicast_list(struct net_device *dev)
  559 +{
  560 +#if 0
  561 + if (dev->flags & IFF_PROMISC)
  562 + return;
  563 + else if (dev->mc_count)
  564 + dev->flags |= IFF_ALLMULTI;
  565 + else
  566 + dev->flags &= ~IFF_ALLMULTI;
  567 +#endif
  568 +}
  569 +
  570 +static void iss_net_tx_timeout(struct net_device *dev)
  571 +{
  572 +#if 0
  573 + dev->trans_start = jiffies;
  574 + netif_wake_queue(dev);
  575 +#endif
  576 +}
  577 +
  578 +static int iss_net_set_mac(struct net_device *dev, void *addr)
  579 +{
  580 +#if 0
  581 + struct iss_net_private *lp = dev->priv;
  582 + struct sockaddr *hwaddr = addr;
  583 +
  584 + spin_lock(&lp->lock);
  585 + memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN);
  586 + spin_unlock(&lp->lock);
  587 +#endif
  588 +
  589 + return 0;
  590 +}
  591 +
  592 +static int iss_net_change_mtu(struct net_device *dev, int new_mtu)
  593 +{
  594 +#if 0
  595 + struct iss_net_private *lp = dev->priv;
  596 + int err = 0;
  597 +
  598 + spin_lock(&lp->lock);
  599 +
  600 + // FIXME not needed new_mtu = transport_set_mtu(new_mtu, &lp->user);
  601 +
  602 + if (new_mtu < 0)
  603 + err = new_mtu;
  604 + else
  605 + dev->mtu = new_mtu;
  606 +
  607 + spin_unlock(&lp->lock);
  608 + return err;
  609 +#endif
  610 + return -EINVAL;
  611 +}
  612 +
  613 +static int iss_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  614 +{
  615 +#if 0
  616 + static const struct ethtool_drvinfo info = {
  617 + .cmd = ETHTOOL_GDRVINFO,
  618 + .driver = DRIVER_NAME,
  619 + .version = "42",
  620 + };
  621 + void *useraddr;
  622 + u32 ethcmd;
  623 +
  624 + switch (cmd) {
  625 + case SIOCETHTOOL:
  626 + useraddr = ifr->ifr_data;
  627 + if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
  628 + return -EFAULT;
  629 +
  630 + switch (ethcmd) {
  631 + case ETHTOOL_GDRVINFO:
  632 + if (copy_to_user(useraddr, &info, sizeof(info)))
  633 + return -EFAULT;
  634 + return 0;
  635 + default:
  636 + return -EOPNOTSUPP;
  637 + }
  638 + default:
  639 + return -EINVAL;
  640 + }
  641 +#endif
  642 + return -EINVAL;
  643 +}
  644 +
  645 +void iss_net_user_timer_expire(unsigned long _conn)
  646 +{
  647 +}
  648 +
  649 +
  650 +static struct device_driver iss_net_driver = {
  651 + .name = DRIVER_NAME,
  652 + .bus = &platform_bus_type,
  653 +};
  654 +
  655 +static int driver_registered;
  656 +
  657 +static int iss_net_configure(int index, char *init)
  658 +{
  659 + struct net_device *dev;
  660 + struct iss_net_private *lp;
  661 + int err;
  662 +
  663 + if ((dev = alloc_etherdev(sizeof *lp)) == NULL) {
  664 + printk(KERN_ERR "eth_configure: failed to allocate device\n");
  665 + return 1;
  666 + }
  667 +
  668 + /* Initialize private element. */
  669 +
  670 + lp = dev->priv;
  671 + *lp = ((struct iss_net_private) {
  672 + .device_list = LIST_HEAD_INIT(lp->device_list),
  673 + .opened_list = LIST_HEAD_INIT(lp->opened_list),
  674 + .lock = SPIN_LOCK_UNLOCKED,
  675 + .dev = dev,
  676 + .index = index,
  677 + //.fd = -1,
  678 + .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 },
  679 + .have_mac = 0,
  680 + });
  681 +
  682 + /*
  683 + * Try all transport protocols.
  684 + * Note: more protocols can be added by adding '&& !X_init(lp, eth)'.
  685 + */
  686 +
  687 + if (!tuntap_probe(lp, index, init)) {
  688 + printk("Invalid arguments. Skipping device!\n");
  689 + goto errout;
  690 + }
  691 +
  692 + printk(KERN_INFO "Netdevice %d ", index);
  693 + if (lp->have_mac)
  694 + printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
  695 + lp->mac[0], lp->mac[1],
  696 + lp->mac[2], lp->mac[3],
  697 + lp->mac[4], lp->mac[5]);
  698 + printk(": ");
  699 +
  700 + /* sysfs register */
  701 +
  702 + if (!driver_registered) {
  703 + driver_register(&iss_net_driver);
  704 + driver_registered = 1;
  705 + }
  706 +
  707 + spin_lock(&devices_lock);
  708 + list_add(&lp->device_list, &devices);
  709 + spin_unlock(&devices_lock);
  710 +
  711 + lp->pdev.id = index;
  712 + lp->pdev.name = DRIVER_NAME;
  713 + platform_device_register(&lp->pdev);
  714 + SET_NETDEV_DEV(dev,&lp->pdev.dev);
  715 +
  716 + /*
  717 + * If this name ends up conflicting with an existing registered
  718 + * netdevice, that is OK, register_netdev{,ice}() will notice this
  719 + * and fail.
  720 + */
  721 + snprintf(dev->name, sizeof dev->name, "eth%d", index);
  722 +
  723 + dev->mtu = lp->mtu;
  724 + dev->open = iss_net_open;
  725 + dev->hard_start_xmit = iss_net_start_xmit;
  726 + dev->stop = iss_net_close;
  727 + dev->get_stats = iss_net_get_stats;
  728 + dev->set_multicast_list = iss_net_set_multicast_list;
  729 + dev->tx_timeout = iss_net_tx_timeout;
  730 + dev->set_mac_address = iss_net_set_mac;
  731 + dev->change_mtu = iss_net_change_mtu;
  732 + dev->do_ioctl = iss_net_ioctl;
  733 + dev->watchdog_timeo = (HZ >> 1);
  734 + dev->irq = -1;
  735 +
  736 + rtnl_lock();
  737 + err = register_netdevice(dev);
  738 + rtnl_unlock();
  739 +
  740 + if (err) {
  741 + printk("Error registering net device!\n");
  742 + /* XXX: should we call ->remove() here? */
  743 + free_netdev(dev);
  744 + return 1;
  745 + }
  746 +
  747 + init_timer(&lp->tl);
  748 + lp->tl.function = iss_net_user_timer_expire;
  749 +
  750 +#if 0
  751 + if (lp->have_mac)
  752 + set_ether_mac(dev, lp->mac);
  753 +#endif
  754 + return 0;
  755 +
  756 +errout:
  757 + // FIXME: unregister; free, etc..
  758 + return -EIO;
  759 +
  760 +}
  761 +
  762 +/* ------------------------------------------------------------------------- */
  763 +
  764 +/* Filled in during early boot */
  765 +
  766 +struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line);
  767 +
  768 +struct iss_net_init {
  769 + struct list_head list;
  770 + char *init; /* init string */
  771 + int index;
  772 +};
  773 +
  774 +/*
  775 + * Parse the command line and look for 'ethX=...' fields, and register all
  776 + * those fields. They will be later initialized in iss_net_init.
  777 + */
  778 +
  779 +#define ERR KERN_ERR "iss_net_setup: "
  780 +
  781 +static int iss_net_setup(char *str)
  782 +{
  783 + struct iss_net_private *device = NULL;
  784 + struct iss_net_init *new;
  785 + struct list_head *ele;
  786 + char *end;
  787 + int n;
  788 +
  789 + n = simple_strtoul(str, &end, 0);
  790 + if (end == str) {
  791 + printk(ERR "Failed to parse '%s'\n", str);
  792 + return 1;
  793 + }
  794 + if (n < 0) {
  795 + printk(ERR "Device %d is negative\n", n);
  796 + return 1;
  797 + }
  798 + if (*(str = end) != '=') {
  799 + printk(ERR "Expected '=' after device number\n");
  800 + return 1;
  801 + }
  802 +
  803 + spin_lock(&devices_lock);
  804 +
  805 + list_for_each(ele, &devices) {
  806 + device = list_entry(ele, struct iss_net_private, device_list);
  807 + if (device->index == n)
  808 + break;
  809 + }
  810 +
  811 + spin_unlock(&devices_lock);
  812 +
  813 + if (device && device->index == n) {
  814 + printk(ERR "Device %d already configured\n", n);
  815 + return 1;
  816 + }
  817 +
  818 + if ((new = alloc_bootmem(sizeof new)) == NULL) {
  819 + printk("Alloc_bootmem failed\n");
  820 + return 1;
  821 + }
  822 +
  823 + INIT_LIST_HEAD(&new->list);
  824 + new->index = n;
  825 + new->init = str + 1;
  826 +
  827 + list_add_tail(&new->list, &eth_cmd_line);
  828 + return 1;
  829 +}
  830 +
  831 +#undef ERR
  832 +
  833 +__setup("eth", iss_net_setup);
  834 +
  835 +/*
  836 + * Initialize all ISS Ethernet devices previously registered in iss_net_setup.
  837 + */
  838 +
  839 +static int iss_net_init(void)
  840 +{
  841 + struct list_head *ele, *next;
  842 +
  843 + /* Walk through all Ethernet devices specified in the command line. */
  844 +
  845 + list_for_each_safe(ele, next, &eth_cmd_line) {
  846 + struct iss_net_init *eth;
  847 + eth = list_entry(ele, struct iss_net_init, list);
  848 + iss_net_configure(eth->index, eth->init);
  849 + }
  850 +
  851 + return 1;
  852 +}
  853 +
  854 +module_init(iss_net_init);
arch/xtensa/platform-iss/setup.c
  1 +/*
  2 + *
  3 + * arch/xtensa/platform-iss/setup.c
  4 + *
  5 + * Platform specific initialization.
  6 + *
  7 + * Authors: Chris Zankel <chris@zankel.net>
  8 + * Joe Taylor <joe@tensilica.com>
  9 + *
  10 + * Copyright 2001 - 2005 Tensilica Inc.
  11 + *
  12 + * This program is free software; you can redistribute it and/or modify it
  13 + * under the terms of the GNU General Public License as published by the
  14 + * Free Software Foundation; either version 2 of the License, or (at your
  15 + * option) any later version.
  16 + *
  17 + */
  18 +#include <linux/config.h>
  19 +#include <linux/stddef.h>
  20 +#include <linux/kernel.h>
  21 +#include <linux/init.h>
  22 +#include <linux/errno.h>
  23 +#include <linux/reboot.h>
  24 +#include <linux/pci.h>
  25 +#include <linux/kdev_t.h>
  26 +#include <linux/types.h>
  27 +#include <linux/major.h>
  28 +#include <linux/blkdev.h>
  29 +#include <linux/console.h>
  30 +#include <linux/delay.h>
  31 +#include <linux/stringify.h>
  32 +#include <linux/notifier.h>
  33 +
  34 +#include <asm/platform.h>
  35 +#include <asm/bootparam.h>
  36 +
  37 +
  38 +void __init platform_init(bp_tag_t* bootparam)
  39 +{
  40 +
  41 +}
  42 +
  43 +void platform_halt(void)
  44 +{
  45 + printk (" ** Called platform_halt(), looping forever! **\n");
  46 + while (1);
  47 +}
  48 +
  49 +void platform_power_off(void)
  50 +{
  51 + printk (" ** Called platform_power_off(), looping forever! **\n");
  52 + while (1);
  53 +}
  54 +void platform_restart(void)
  55 +{
  56 + /* Flush and reset the mmu, simulate a processor reset, and
  57 + * jump to the reset vector. */
  58 +
  59 + __asm__ __volatile__("movi a2, 15\n\t"
  60 + "wsr a2, " __stringify(ICOUNTLEVEL) "\n\t"
  61 + "movi a2, 0\n\t"
  62 + "wsr a2, " __stringify(ICOUNT) "\n\t"
  63 + "wsr a2, " __stringify(IBREAKENABLE) "\n\t"
  64 + "wsr a2, " __stringify(LCOUNT) "\n\t"
  65 + "movi a2, 0x1f\n\t"
  66 + "wsr a2, " __stringify(PS) "\n\t"
  67 + "isync\n\t"
  68 + "jx %0\n\t"
  69 + :
  70 + : "a" (XCHAL_RESET_VECTOR_VADDR)
  71 + : "a2");
  72 +
  73 + /* control never gets here */
  74 +}
  75 +
  76 +extern void iss_net_poll(void);
  77 +
  78 +const char twirl[]="|/-\\|/-\\";
  79 +
  80 +void platform_heartbeat(void)
  81 +{
  82 +#if 0
  83 + static int i = 0, j = 0;
  84 +
  85 + if (--i < 0) {
  86 + i = 99;
  87 + printk("\r%c\r", twirl[j++]);
  88 + if (j == 8)
  89 + j = 0;
  90 + }
  91 +#endif
  92 +}
  93 +
  94 +
  95 +
  96 +static int
  97 +iss_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
  98 +{
  99 + __asm__ __volatile__("movi a2, -1; simcall\n");
  100 + return NOTIFY_DONE;
  101 +}
  102 +
  103 +static struct notifier_block iss_panic_block = {
  104 + iss_panic_event,
  105 + NULL,
  106 + 0
  107 +};
  108 +
  109 +void __init platform_setup(char **p_cmdline)
  110 +{
  111 + notifier_chain_register(&panic_notifier_list, &iss_panic_block);
  112 +}
include/asm-xtensa/platform-iss/hardware.h
  1 +/*
  2 + * include/asm-xtensa/platform-iss/hardware.h
  3 + *
  4 + * This file is subject to the terms and conditions of the GNU General Public
  5 + * License. See the file "COPYING" in the main directory of this archive
  6 + * for more details.
  7 + *
  8 + * Copyright (C) 2001 Tensilica Inc.
  9 + */
  10 +
  11 +/*
  12 + * This file contains the default configuration of ISS.
  13 + */
  14 +
  15 +#ifndef __ASM_XTENSA_ISS_HARDWARE
  16 +#define __ASM_XTENSA_ISS_HARDWARE
  17 +
  18 +/*
  19 + * Memory configuration.
  20 + */
  21 +
  22 +#define PLATFORM_DEFAULT_MEM_START XSHAL_RAM_PADDR
  23 +#define PLATFORM_DEFAULT_MEM_SIZE XSHAL_RAM_VSIZE
  24 +
  25 +/*
  26 + * Interrupt configuration.
  27 + */
  28 +
  29 +#endif /* __ASM_XTENSA_ISS_HARDWARE */
include/asm-xtensa/platform.h
  1 +/*
  2 + * include/asm-xtensa/platform.h
  3 + *
  4 + * Platform specific functions
  5 + *
  6 + * This file is subject to the terms and conditions of the GNU General
  7 + * Public License. See the file "COPYING" in the main directory of
  8 + * this archive for more details.
  9 + *
  10 + * Copyright (C) 2001 - 2005 Tensilica Inc.
  11 + */
  12 +
  13 +#ifndef _XTENSA_PLATFORM_H
  14 +#define _XTENSA_PLATFORM_H
  15 +
  16 +#include <linux/config.h>
  17 +#include <linux/types.h>
  18 +#include <linux/pci.h>
  19 +
  20 +#include <asm/bootparam.h>
  21 +
  22 +/*
  23 + * platform_init is called before the mmu is initialized to give the
  24 + * platform a early hook-up. bp_tag_t is a list of configuration tags
  25 + * passed from the boot-loader.
  26 + */
  27 +extern void platform_init(bp_tag_t*);
  28 +
  29 +/*
  30 + * platform_setup is called from setup_arch with a pointer to the command-line
  31 + * string.
  32 + */
  33 +extern void platform_setup (char **);
  34 +
  35 +/*
  36 + * platform_init_irq is called from init_IRQ.
  37 + */
  38 +extern void platform_init_irq (void);
  39 +
  40 +/*
  41 + * platform_restart is called to restart the system.
  42 + */
  43 +extern void platform_restart (void);
  44 +
  45 +/*
  46 + * platform_halt is called to stop the system and halt.
  47 + */
  48 +extern void platform_halt (void);
  49 +
  50 +/*
  51 + * platform_power_off is called to stop the system and power it off.
  52 + */
  53 +extern void platform_power_off (void);
  54 +
  55 +/*
  56 + * platform_idle is called from the idle function.
  57 + */
  58 +extern void platform_idle (void);
  59 +
  60 +/*
  61 + * platform_heartbeat is called every HZ
  62 + */
  63 +extern void platform_heartbeat (void);
  64 +
  65 +/*
  66 + * platform_pcibios_init is called to allow the platform to setup the pci bus.
  67 + */
  68 +extern void platform_pcibios_init (void);
  69 +
  70 +/*
  71 + * platform_pcibios_fixup allows to modify the PCI configuration.
  72 + */
  73 +extern int platform_pcibios_fixup (void);
  74 +
  75 +/*
  76 + * platform_calibrate_ccount calibrates cpu clock freq (CONFIG_XTENSA_CALIBRATE)
  77 + */
  78 +extern void platform_calibrate_ccount (void);
  79 +
  80 +/*
  81 + * platform_get_rtc_time returns RTC seconds (returns 0 for no error)
  82 + */
  83 +extern int platform_get_rtc_time(time_t*);
  84 +
  85 +/*
  86 + * platform_set_rtc_time set RTC seconds (returns 0 for no error)
  87 + */
  88 +extern int platform_set_rtc_time(time_t);
  89 +
  90 +
  91 +#endif /* _XTENSA_PLATFORM_H */