diff options
author | Chris Zankel <czankel@tensilica.com> | 2005-06-24 01:01:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-24 03:05:22 -0400 |
commit | 7282bee78798294bb1f0211a842cdb9f4872db3d (patch) | |
tree | 7a659275aaa7f4c741bd24eeb9f827b2f0a926d5 /arch | |
parent | e344b63eeec7850b5e900e10c8a6c61d083fd3a4 (diff) |
[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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/xtensa/configs/iss_defconfig | 531 | ||||
-rw-r--r-- | arch/xtensa/platform-iss/Makefile | 13 | ||||
-rw-r--r-- | arch/xtensa/platform-iss/console.c | 303 | ||||
-rw-r--r-- | arch/xtensa/platform-iss/io.c | 32 | ||||
-rw-r--r-- | arch/xtensa/platform-iss/network.c | 855 | ||||
-rw-r--r-- | arch/xtensa/platform-iss/setup.c | 112 |
6 files changed, 1846 insertions, 0 deletions
diff --git a/arch/xtensa/configs/iss_defconfig b/arch/xtensa/configs/iss_defconfig new file mode 100644 index 000000000000..802621dd4867 --- /dev/null +++ b/arch/xtensa/configs/iss_defconfig | |||
@@ -0,0 +1,531 @@ | |||
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 | ||
diff --git a/arch/xtensa/platform-iss/Makefile b/arch/xtensa/platform-iss/Makefile new file mode 100644 index 000000000000..5b394e9620e5 --- /dev/null +++ b/arch/xtensa/platform-iss/Makefile | |||
@@ -0,0 +1,13 @@ | |||
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 | |||
diff --git a/arch/xtensa/platform-iss/console.c b/arch/xtensa/platform-iss/console.c new file mode 100644 index 000000000000..9e2b53f6a907 --- /dev/null +++ b/arch/xtensa/platform-iss/console.c | |||
@@ -0,0 +1,303 @@ | |||
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 | |||
diff --git a/arch/xtensa/platform-iss/io.c b/arch/xtensa/platform-iss/io.c new file mode 100644 index 000000000000..5b161a5cb65f --- /dev/null +++ b/arch/xtensa/platform-iss/io.c | |||
@@ -0,0 +1,32 @@ | |||
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 | |||
diff --git a/arch/xtensa/platform-iss/network.c b/arch/xtensa/platform-iss/network.c new file mode 100644 index 000000000000..498d7dced1f4 --- /dev/null +++ b/arch/xtensa/platform-iss/network.c | |||
@@ -0,0 +1,855 @@ | |||
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(ðcmd, 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, ð_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, ð_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 | |||
diff --git a/arch/xtensa/platform-iss/setup.c b/arch/xtensa/platform-iss/setup.c new file mode 100644 index 000000000000..2e6dcbf0cc04 --- /dev/null +++ b/arch/xtensa/platform-iss/setup.c | |||
@@ -0,0 +1,112 @@ | |||
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 | } | ||