Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Chris Zankel and committed by
Linus Torvalds
7282bee7 e344b63e

+1967
+531
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
+13
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 13 +
+303
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 */ 303 +
+32
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 32 +
+855
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); 855 +
+112
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 + }
+29
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 */
+92
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 */ 92 +