diff -u --recursive --new-file v2.1.100/linux/Documentation/ARM-README linux/Documentation/ARM-README --- v2.1.100/linux/Documentation/ARM-README Sat May 2 14:19:50 1998 +++ linux/Documentation/ARM-README Fri May 8 00:42:37 1998 @@ -1,15 +1,12 @@ - ARM Linux 2.1.78 + ARM Linux 2.1.99 ================ - ** The ARM support contained within is NOT complete - it will not build. ** - ** If you want to build it, then please obtain a full copy of the ARM ** - ** patches from ftp://ftp.arm.uk.linux.org/pub/armlinux/kernel-sources/v2.1 ** - Since this is a development kernel, it will not be as stable as the 2.0 series, and can cause very nasty problems (eg, trashing your hard disk). When running one of these kernels, I advise you to back up the complete contents of all your hard disks. + Contributors ------------ @@ -28,26 +25,16 @@ Mail: Philip.Blundell@pobox.com Desc: Architecture and processor selection during make config. + Todo list --------- This is the list of changes to be done (roughly prioritorised): - * fully test new A5000 & older MEMC translation code + * fully test new MEMC translation code * fully test new AcornSCSI driver. * reply to email ;) -Bugs ----- - - Fixed bugs in this version 2.1.76: - - Modules believed to be buggy (please report your successes/failures): - - * AcornSCSI believed to occasionally corrupt hard drives. - * All NCR5380-based SCSI devices [Cumana I, Oak, EcoSCSI] are slow, - and may not allow write access. - * A5000 and older machine kernel builds may not be as stable as they were. Notes ===== @@ -76,12 +63,13 @@ to CROSS_COMPILE= eg. - CROSS_COMPILE=/usr/src/bin/arm/arm-linuxelf- + CROSS_COMPILE=/usr/bin/arm-unknown-linuxelf- Do a 'make config', followed by 'make dep', and finally 'make all' to build the kernel (vmlinux). A compressed image can be built by doing a 'make zImage' instead of 'make all'. + Bug reports etc --------------- @@ -96,6 +84,7 @@ For patches, please include some explanation as to what the patch does and why (if relevant). + Modules ------- @@ -108,6 +97,7 @@ as such Acorn RiscPCs and other architectures using these processors can make good use of modularisation. + ADFS Image files ---------------- @@ -118,6 +108,7 @@ Please note that the PCEmulator DOS partitions have a partition table at the start, and as such, you will have to give '-o offset' to losetup. + Kernel initialisation abort codes --------------------------------- @@ -128,17 +119,19 @@ Stripes of White,Red,Yellow,Green: Kernel does not support the processor architecture detected. + Request to developers --------------------- When writing device drivers which include a separate assember file, please include it in with the C file, and not the arch/arm/lib directory. This allows the driver to be compiled as a loadable module without requiring - half the code to be needlessly compiled into the kernel image. + half the code to be compiled into the kernel image. In general, try to avoid using assembler unless it is really necessary. It makes drivers far less easy to port to other hardware. + ST506 hard drives ----------------- @@ -167,3 +160,22 @@ hasn't got any code for disc change detection in there at the moment which could be a bit of a problem! Suggestions on the correct way to do this are welcome. + + +Kernel entry (head-armv.S) +-------------------------- + The initial entry into the kernel made via head-armv.S uses architecture + independent code. The architecture is selected by the value of 'r1' on + entry, which must be kept unique. You can register a new architecture + by mailing the following details to rmk@arm.uk.linux.org. Please give + the mail a subject of 'Register new architecture': + + Name: + ARCHDIR: + Description: + + + Please follow this format - it is an automated system. You should + receive a reply the next day. +--- +Russell King (03/05/1998) diff -u --recursive --new-file v2.1.100/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.1.100/linux/Documentation/Configure.help Thu May 7 22:51:45 1998 +++ linux/Documentation/Configure.help Fri May 8 00:42:38 1998 @@ -742,6 +742,24 @@ want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say Y. +IDE card support +CONFIG_BLK_DEV_IDE_CARDS + On Acorn systems, enable this if you wish to use an IDE interface + expansion card. If you do not or are unsure, say N to this. + +ICS IDE interface +CONFIG_BLK_DEV_IDE_ICS + On Acorn systems, enable this if you wish to use the ICS IDE + interface card. This is not required for ICS partition support. + If you are unsure, say N to this. + +ADFS partition support +CONFIG_BLK_DEV_PART + This allows Linux on Acorn systems to determine its partitions in + the 'non-ADFS' partition area of the hard disk - usually located + after the ADFS partition. You are probably using this system, so + you should enable it. + Boot support (linear, striped) CONFIG_MD_BOOT To boot with an initial linear or striped md device you have to say @@ -3585,6 +3603,51 @@ important data. This is primarily of use to people trying to debug the middle and upper layers of the SCSI subsystem. If unsure, say N. +AcornSCSI support +CONFIG_SCSI_ACORNSCSI_3 + This enables support for the Acorn SCSI card (aka30). If you have an + Acorn system with one of these, say Y. If unsure, say N. + +Acorn SCSI tagged queue support +CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE + Say Y here to enable tagged queuing support on the Acorn SCSI card. + +Acorn SCSI Synchronous transfers support +CONFIG_SCSI_ACORNSCSI_SYNC + Say Y here to enable synchronous transfer negociation with all targets + on the Acorn SCSI card. + +Oak SCSI support +CONFIG_SCSI_OAK1 + This enables support for the Oak SCSI card. If you have an Acorn system + with one of these, say Y. If unsure, say N. + +Cumana SCSI I support +CONFIG_SCSI_CUMANA_1 + This enables support for the Cumana SCSI I card. If you have an Acorn + system with one of these, say Y. If unsure, say N. + +Cumana SCSI II support +CONFIG_SCSI_CUMANA_2 + This enables support for the Cumana SCSI II card. If you have an Acorn + system with one of these, say Y. If unsure, say N. + +EcoSCSI support +CONFIG_SCSI_ECOSCSI + This enables support for the EcoSCSI card - a small card that sits in + the Econet socket. If you have an Acorn system with one of these, + say Y. If unsure, say N. + +EESOX SCSI support +CONFIG_SCSI_EESOXSCSI + This enables support for the EESOX SCSI card. If you have an Acorn + system with one of these, say Y, otherwise say N. + +Powertec SCSI support +CONFIG_SCSI_POWERTECSCSI + This enables support for the Powertec SCSI card on Acorn systems. If + you have one of these, say Y. If unsure, say N. + Network device support? CONFIG_NETDEVICES You can say N here if you don't intend to connect to any other @@ -3816,6 +3879,17 @@ Enter either 0x30f or 0x20f here. The card default is 0x30f, if you haven't changed the jumper setting on the card. +Aztech/Packard Bell Radio +CONFIG_RADIO_AZTECH + Choose Y here if you have one of these, and then fill in the port + address below. + +Aztech/Packard Bell radio card i/o port +CONFIG_RADIO_AZTECH_PORT + Enter either 0x350 or 0x358 here. The card default is 0x350, if you + haven't changed the setting of jumper JP3 on the card. Removing the + jumper sets the card to 0x358. + LAPB over Ethernet driver CONFIG_LAPBETHER This is a driver for a pseudo device (typically called /dev/lapb0) @@ -5061,6 +5135,26 @@ This is support for the DIGITAL series of EISA (DEFEA) and PCI (DEFPA) controllers which can connect you to a local FDDI network. +Acorn Ether1 card +CONFIG_ARM_ETHER1 + If you have an Acorn system with one of these (AKA25) network cards, + you should say Y to this option if you wish to use it with Linux. + +Acorn/ANT Ether3 card +CONFIG_ARM_ETHER3 + If you have an Acorn system with one of these network cards, you + should say Y to this option if you wish to use it with Linux. + +I Cubed EtherH card +CONFIG_ARM_ETHERH + If you have an Acorn system with one of these network cards, you + should say Y to this option if you wish to use it with Linux. + +EBSA-110 ethernet interface +CONFIG_AM79C961A + If you wish to compile a kernel for the EBSA-110, then you should + always answer Y to this. + Support CDROM drives that are not SCSI or IDE/ATAPI CONFIG_CD_NO_IDESCSI If you have a CDROM drive that is neither SCSI nor IDE/ATAPI, say Y @@ -6441,6 +6535,13 @@ or change their color depending on the virtual console you're on. See Documentation/VGA-softcursor.txt for more information. +Acorn's ADFS filesystem support (read only) (EXPERIMENTAL) +CONFIG_ADFS_FS + The Advanced Disk File System is the filesystem used on floppy and + hard disks by Acorn Systems. Currently in development, as a read- + only driver for hard disks. These should be the first partition + (eg. /dev/[sh]d?1) on each of your drives. If unsure, say N. + Standard/generic serial support CONFIG_SERIAL This selects whether you want to include the driver for the standard @@ -7413,6 +7514,17 @@ inserted in and removed from the running kernel whenever you want). The module will be called joystick.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. + +Atomwide Serial Support +CONFIG_ATOMWIDE_SERIAL + If you have an Atomwide Serial card for an Acorn system, say Y to + this option. The driver can handle 1, 2, or 3 port cards. + If unsure, say N + +The Serial Port Dual Serial Port +CONFIG_DUALSP_SERIAL + If you have the Serial Port's dual serial card for an Acorn system, + say Y to this option. If unsure, say N Sound card support CONFIG_SOUND diff -u --recursive --new-file v2.1.100/linux/Documentation/filesystems/affs.txt linux/Documentation/filesystems/affs.txt --- v2.1.100/linux/Documentation/filesystems/affs.txt Sat May 2 14:19:51 1998 +++ linux/Documentation/filesystems/affs.txt Thu May 7 22:58:04 1998 @@ -26,7 +26,7 @@ All of the above filesystems allow block sizes from 512 to 32K bytes. Supported block sizes are: 512, 1024, 2048 and 4096 bytes. Larger blocks -speed up almost everything with the expense of wasted disk space. The speed +speed up almost everything at the expense of wasted disk space. The speed gain above 4K seems not really worth the price, so you don't lose too much here, either. @@ -45,12 +45,13 @@ mode=mode Sets the mode flags to the given (octal) value, regardless of the original permissions. Directories will get an x - permission, if the corresponding r bit is set. + permission if the corresponding r bit is set. This is useful since most of the plain AmigaOS files will map to 600. reserved=num Sets the number of reserved blocks at the start of the - partition to num. Default is 2. + partition to num. You should never need this option. + Default is 2. root=block Sets the block number of the root block. This should never be necessary. @@ -71,11 +72,13 @@ as one. prefix=path Path will be prefixed to every absolute path name of - symbolic links on an AFFS partition. Default = / + symbolic links on an AFFS partition. Default = "/". + (See below.) volume=name When symbolic links with an absolute path are created - on an AFFS partition, volume will be prepended as the + on an AFFS partition, name will be prepended as the volume name. Default = "" (empty string). + (See below.) Handling of the Users/Groups and protection flags ================================================= @@ -92,11 +95,13 @@ - H and P are always retained and ignored under Linux. - - A is always reset when written. + - A is always reset when a file is written to. User id and group id will be used unless set[gu]id are given as mount options. Since most of the Amiga file systems are single user systems -they will be owned by root. +they will be owned by root. The root directory of the Amiga filesystem +(i. e. the mount point) will be owned by the user who actually mounts +the filesystem (the root directory doesn't have uid/gid fields). Linux -> Amiga: @@ -139,12 +144,12 @@ Examples ======== -Command line - mount Archive/Amiga/Workbench3.1.adf /mnt -t affs -o loop,reserved=4 +Command line: + mount Archive/Amiga/Workbench3.1.adf /mnt -t affs -o loop,verbose mount /dev/sda3 /Amiga -t affs -/etc/fstab example - /dev/sdb5 /d/f affs ro +/etc/fstab entry: + /dev/sdb5 /amiga/Workbench affs noauto,user,exec,verbose 0 0 Bugs, Restrictions, Caveats =========================== @@ -159,10 +164,10 @@ in include/linux/amigaffs.h). Case is ignored by the affs in filename matching, but Linux shells -do care about the case. Example (with /mnt being an affs mounted fs): - rm /mnt/WRONGCASE +do care about the case. Example (with /wb being an affs mounted fs): + rm /wb/WRONGCASE will remove /mnt/wrongcase, but - rm /mnt/WR* + rm /wb/WR* will not since the names are matched by the shell. The block allocation is designed for hard disk partitions. If more @@ -170,14 +175,20 @@ in an ugly way (but the real AFFS doesn't do much better). This is also true when space gets tight. +You cannot execute programs on an OFS (Old File System), since the +program files cannot be memory mapped due to the 488 byte blocks. +For the same reason you cannot mount an image on such a filesystem +via the loopback device. + The bitmap valid flag in the root block may not be accurate when the system crashes while an affs partition is mounted. There's currently -no way to fix this without an Amiga (disk validator) or manually -(who would do this?). Maybe later. +no way to fix a garbled filesystem without an Amiga (disk validator) +or manually (who would do this?). Maybe later. A fsck.affs and mkfs.affs will probably be available in the future. -Until then, you should do - ln -s /bin/true /etc/fs/mkfs.affs +If you mount them on system startup, you may want to tell fsck +that the fs should not be checked (place a '0' in the sixth field +of /etc/fstab). It's not possible to read floppy disks with a normal PC or workstation due to an incompatibility with the Amiga floppy controller. diff -u --recursive --new-file v2.1.100/linux/Documentation/transname.txt linux/Documentation/transname.txt --- v2.1.100/linux/Documentation/transname.txt Sat May 2 14:19:52 1998 +++ linux/Documentation/transname.txt Wed Dec 31 16:00:00 1969 @@ -1,264 +0,0 @@ -Transname version 1.9 (C) 1997 Thomas Schoebel-Theuer - -transname enables diskless clients, X-terminals etc to mount the -*root filesystem* of the server. This make administration of -large pools a lot easier. - -Wherefore is linux-2.0.21-transname.patch? - -Currently different diskless clients must have their root / on different -directories on the server, beause each client has _some_ different -configuration files. However, most files (typically about 99%) have the same -contents on the clients and on the server, but have to be replicated -(and maintained separately) just because of the 1% differences. -This duplication causes very large efforts in practise, since at least -the /etc directory has to be duplicated for every client. Even in /etc -many files are identical, for example sendmail.cf, initrc scripts and -others. Maintaining a large pool requires means to ensure coherence among -the duplicates. Classical methods like symlinks are inconvenient -for this task because they have to be valid in the view of mounted -filesystems at all clients, not at the server. - -Linux transname overcomes this problem by allowing filenames -to be context-dependent. For example, if you have a file /etc/config -that should differ on the hosts "myserver" and "myclient", you just -create two different files named /etc/config#host=myserver# and -/etc/config#host=myclient# . On host "myserver", the file -/etc/config#host=myserver# will appear as if it were hardlinked to -file /etc/config (without the #...=...# suffix). On host "myclient", -the corresponding other file will appear as /etc/config. So you -can access the right file contents under the _same_ name, depending -on which host you are working on. - -A similar concept can be found in older HP-UX versions, but with -so-called "hidden directories" which don't allow contemporary viewing of -all versions by default. In contrast, transname shows all context-dependent -files in the dir listing and they can be edited using the -fully qualified name. - -Transname was developed for and is used at our Linux pool at the -University of Stuttgart with good results. Maintenance of the pool is -at a minimum, and adding new clients is child's play. No worry with -keeping up mail configurations, newly installed tools, changed /etc/services, -/etc/shells, /etc/resolv.conf and many, many others. In contrast to a -sophisticated symlink solution, adding a new file to the /etc directory -is seen immediately by all clients. - -An example for the use of linux-2.0-transname.patch: - -For example, you can make your /etc/fstab context-dependent. If you want -to do that, you should create an /etc/fstab#ktype=default# for the -server and an /etc/fstab#ktype=diskless# for all clients. This is because -your clients may not yet know their own hostname when they attempt to mount -the root filesystem. You can compile in the kerneltypes "default" and -"diskless" into different kernels for servers and clients. Of course, -if your clients boot via bootp and know their names when mounting the root, -you can use /etc/fstab#host=myclient# instead. But at least servers -booting from disk normally don't know their hostname at root mount time, -so you can mix methods and use /etc/fstab#ktype=default# for the server, -/etc/fstab#ktype=diskless# for the majority of the clients and -/etc/fstab#host=myclient# for some specific client, because translation -of #host=...# is given precedence over #ktype=...# by default. - -This sort of name translation works with any underlying file system -and with any inode type (i.e. with directories, symlinks, devices etc), -because it is implemented in the VFS layer of the kernel. Currently, -five types of default translations are supported: - - * #host=# depends on the hostname, see "uname -n" - * #kname=# works with a hard compiled-in string - * #ktype=# works with a hard compiled-in string - * #machine=# depends on architecture, see "uname -m" - * #system=# currently only supported by Linux, see "uname -s" - -Others may be added in future. - -The current translations are displayed at boot time in the kernel messages -for easier debugging, and can be retrieved by reading -/proc/sys/kernel/nametrans which is a special file containing the currently -valid translations. - -The default translations change whenever the hostname(1) is set or changed. -Thus, the hostname is not set (or set to the name "(none)") at boot time -before init(8) sets it. So, if you want to use the hostname before that -moment, there are three ways: - - a) set the hostname before via bootp or similar. - b) use the compiled-in translations kname and ktype solely. - c) set all translations by lilo (or on the boot command line) with - kernel parameter nametrans=#host=banana#:#ktype=diskless# , - thus overriding and hiding the default (built-in) translations. - -Note that by supplying the colon-separated list of at most 16 suffixes, you -can also use other translation types that are not defined in the default -translations. However, you must ensure that the syntax #...=...# is correct. -The specified contexts will be tried in the specified order *instead* of the -default translations. - -You can override the default (or parameter-supplied) translations at runtime -by executing -echo "#host=$HOST#:#ktype=diskless#:#myconfig=something#" > /proc/sys/kernel/nametrans -However, after doing this (or setting as kernel parameter) the built-in -default translations have no effect any more, thus changing the hostname -will not be reflected in the overridden translations. You can switch -back to the default translations by executing -echo "" > /proc/sys/kernel/nametrans - -Another drawback is that administration tools currently are not aware of -context-dependent files, so you cannot switch between contexts inside -one tool session. However, you can simulate administration sessions -on the server as if they were running on some client. To do this, -you have to set an environment variable NAMETRANS which has to be the -*first* environment variable in the list. For example, you can execute -'env - NAMETRANS=#host=mango#:#ktype=diskless# "`env`" command ...' -where the command will see the same files as if it had been executed on host -"mango" with a "diskless" kernel. To switch off translations entirely, use -an empty list, e.g. 'env - NAMETRANS= "`env`" command ...'. - -Hopefully the creators of administration tools and maintainers of Linux -distributions will support changing environments in future, so that -maintaining different views will be very easy. - -Some hints: - -Archivers like tar, dump, restore should be used with translation -switched off, in order to avoid doubled space in archive files and when -extracting from them. Also, make sure that nfsd, mountd (and similar ones -like samba daemons) run without translation, in order to avoid doubled -(or even wrong) translation at the server and at the client. You can -automatically force the creation of context-dependent filenames if there -exists a template filename like /etc/mtab#host=CREATE#. As soon as a -process running on "mango" tries to create a file /etc/mtab, the version -/etc/mtab#host=mango# is created instead (which appears in turn as -hardlinked to /etc/mtab). Note that if you want to make /etc/fstab -context-dependent, you should execute "touch /etc/mtab#host=CREATE#" and -"touch /etc/mtab.tmp#host=CREATE#", because mount, umount and others -running on different hosts would otherwise try to create one shared -/etc/mtab which would result in a clash. Also one should execute -"touch /etc/nologin#host=CREATE#" to prevent global side effects from -shutdown resp. runlevel. - -Which files you have to make context-dependent will differ for different -needs and different applications. Hopefully some day a standard will -cover the most common cases and the mist common Linux distributions. -A HOWTO on this subject is in preparation. - -How to install linux-2.0.21-transname.patch? - -First of all, keep a backup of your kernel on your disk. Second, keep a -floppy with a miniroot handy, so you can boot from the floppy, mount -your harddisk root filesystem and change the names of your configuration -files back to their old names in case of emergency. - -Then, make a kernel with transname support enabled. With "make config" -or "make xconfig", just go to the section "filesystems". Take a look at -the help texts that are associated with the transname options, they tell -you further hints not mentioned in this README. Then build your kernel as -usual, install it with a *new* kernel-filename, add a *new* entry to -/etc/lilo.conf and run lilo. **DON'T CHANGE** any configuration files for the -first reboot! - -Just reboot the new kernel and play a little bit around with -creating context-dependent filenames in your home directory. -Try all modes including setting NAMETRANS to different values. - -As an example for the changes necessary on our LST-1.8-based Linux pool, -here is the output of the command -find / /tmp -xdev -name "*#*#" -print | sort -u | xargs ls -ld - --r--r--r-- 1 root root 1725 Dec 21 1995 /etc/X11R6/xdm/xdm-config#host=eiche# --r--r--r-- 3 root root 9509 Feb 15 17:35 /etc/XF86Config#host=balsa# --r--r--r-- 1 root root 9401 Feb 15 17:34 /etc/XF86Config#host=eiche# --rw-r--r-- 1 root root 9820 Feb 21 17:00 /etc/XF86Config#host=fichte# --rw-r--r-- 1 root root 9822 Feb 14 15:45 /etc/XF86Config#host=laerche# --r--r--r-- 3 root root 9509 Feb 15 17:35 /etc/XF86Config#host=mahagoni# --r--r--r-- 3 root root 9509 Feb 15 17:35 /etc/XF86Config#host=palisander# --r--r--r-- 2 root root 9509 Feb 15 17:41 /etc/XF86Config#host=pcbs10# --r--r--r-- 2 root root 9509 Feb 15 17:41 /etc/XF86Config#host=pcbs11# --rw-r--r-- 1 root root 586 Jun 11 23:13 /etc/fstab#ktype=default# --rw-r--r-- 1 root root 242 May 29 17:35 /etc/fstab#ktype=diskless# --rw------- 1 root root 338 Jun 14 16:37 /etc/lilo.conf#host=eiche# --rw------- 1 root root 5236 Dec 16 1995 /etc/lst.cnf#host=balsa# --rw------- 1 root root 5254 Dec 16 1995 /etc/lst.cnf#host=eiche# --rw------- 1 root root 5236 Dec 19 1995 /etc/lst.cnf#host=fichte# --rw------- 1 root root 5236 Jan 11 13:47 /etc/lst.cnf#host=laerche# --rw------- 1 root root 5236 Feb 14 16:57 /etc/lst.cnf#host=mahagoni# --rw------- 1 root root 5236 Jan 4 1996 /etc/lst.cnf#host=palisander# --rw------- 1 root root 5236 Feb 15 13:57 /etc/lst.cnf#host=pcbs10# --rw------- 1 root root 5236 Feb 14 17:06 /etc/lst.cnf#host=pcbs11# --rw-r--r-- 1 root root 0 Dec 18 1995 /etc/mtab#host=CREATE# --rw-r--r-- 1 root root 157 Jun 23 21:16 /etc/mtab#host=balsa# --rw-r--r-- 1 root root 466 Jul 1 16:15 /etc/mtab#host=eiche# --rw-r--r-- 1 root root 239 Jul 4 11:10 /etc/mtab#host=fichte# --rw-r--r-- 1 root root 239 Jun 18 14:17 /etc/mtab#host=laerche# --rw-r--r-- 1 root root 239 May 23 10:50 /etc/mtab#host=mahagoni# --rw-r--r-- 1 root root 239 Jul 3 10:36 /etc/mtab#host=palisander# --rw-r--r-- 1 root root 47 Feb 15 14:57 /etc/mtab#host=pcbs10# --rw-r--r-- 1 root root 47 Feb 14 20:04 /etc/mtab#host=pcbs11# --rw-r--r-- 1 root root 0 Dec 18 1995 /etc/mtab.tmp#host=CREATE# --rw-r--r-- 1 root root 0 Dec 19 1995 /etc/nologin#host=CREATE# ----------- 1 root root 115 Feb 15 14:57 /etc/nologin#host=pcbs10# ----------- 1 root root 115 Feb 14 20:04 /etc/nologin#host=pcbs11# --rw-r--r-- 1 root root 4818 Dec 16 1995 /etc/system.cnf#host=balsa# -lrwxrwxrwx 1 root root 25 Dec 22 1995 /etc/system.cnf#host=eiche# -> system.cnf#ktype=default# --rw-r--r-- 1 root root 4821 Dec 19 1995 /etc/system.cnf#host=fichte# --rw-r--r-- 1 root root 4824 Jan 11 13:47 /etc/system.cnf#host=laerche# --rw-r--r-- 1 root root 4827 Feb 14 16:57 /etc/system.cnf#host=mahagoni# --rw-r--r-- 1 root root 4833 Jan 4 1996 /etc/system.cnf#host=palisander# --rw-r--r-- 1 root root 4840 Feb 15 14:10 /etc/system.cnf#host=pcbs10# --rw-r--r-- 1 root root 4846 Feb 14 18:23 /etc/system.cnf#host=pcbs11# --rw-r--r-- 1 root root 4818 Dec 13 1995 /etc/system.cnf#ktype=default# -drwxrwxrwt 16 root root 3072 Jul 4 14:29 /tmp#ktype=default# -lrwxrwxrwx 1 root root 26 Jul 4 14:22 /tmp#ktype=diskless# -> /tmp#ktype=default#/client --rw-rw-rw- 1 root root 0 Feb 15 14:57 /tmp/client#host=CREATE# -drwxrwxrwx 4 root root 1024 Jun 28 12:15 /tmp/client#host=balsa# -drwxrwxrwx 3 root root 1024 Jul 4 11:10 /tmp/client#host=fichte# -drwxrwxrwx 3 root root 1024 Jun 18 14:18 /tmp/client#host=laerche# -drwxrwxrwx 3 root root 1024 May 24 13:06 /tmp/client#host=mahagoni# -drwxrwxrwx 3 root root 1024 Jul 3 10:37 /tmp/client#host=palisander# -drwxrwxrwx 4 root root 1024 Feb 15 14:57 /tmp/client#host=pcbs10# -drwxrwxrwx 3 root root 1024 Feb 20 06:43 /tmp/client#host=pcbs11# -lrwxrwxrwx 1 root root 9 Feb 15 13:58 /usr/X11R6/bin/X#host=pcbs10# -> XF86_SVGA -lrwxrwxrwx 1 root root 9 Feb 14 17:37 /usr/X11R6/bin/X#host=pcbs11# -> XF86_SVGA -lrwxrwxrwx 1 root root 7 Feb 14 17:15 /usr/X11R6/bin/X#ktype=diskless# -> XF86_S3 -drwxr-xr-x 22 root root 1024 Dec 13 1995 /var#host=balsa# -drwxr-xr-x 23 root root 1024 Jan 12 14:22 /var#host=eiche# -drwxr-xr-x 22 root root 1024 Dec 13 1995 /var#host=fichte# -drwxr-xr-x 22 root root 1024 Dec 13 1995 /var#host=laerche# -drwxr-xr-x 22 root root 1024 Dec 13 1995 /var#host=mahagoni# -drwxr-xr-x 22 root root 1024 Dec 13 1995 /var#host=palisander# -drwxr-xr-x 22 root root 1024 Dec 13 1995 /var#host=pcbs10# -drwxr-xr-x 22 root root 1024 Dec 13 1995 /var#host=pcbs11# - -Notes: The /tmp directory has an own filesystem on server "eiche", -in order to prevent users from filling the whole filestore (we dont use -quotas). Each client needs a different /tmp because of possible name clashes. -Also, the whole /var hierarchy is kept differently to prevent any risk, but -that could be optimized perhaps. Note that nfsd and mountd have been -replaced by a script which switches off translations, in the style - --rwxr-xr-x 2 root root 70 Mar 22 12:54 /usr/sbin/rpc.mountd --rwxr-xr-x 1 root root 32772 Jun 11 1995 /usr/sbin/rpc.mountd.notrans --rwxr-xr-x 2 root root 70 Mar 22 12:54 /usr/sbin/rpc.nfsd --rwxr-xr-x 1 root root 45060 Jun 11 1995 /usr/sbin/rpc.nfsd.notrans - -where /usr/sbin/rpc.mountd has the contents - -#!/bin/sh -exec /usr/bin/env - NAMETRANS= "`/usr/bin/env`" $0.notrans $* - -Of course, that could be improved, but is a quick hack to get things to work. - -Enjoy, - --- Thomas - - -The author can be contacted under - schoebel@informatik.uni-stuttgart.de -or snailmail - Thomas Schoebel-Theuer - Institut fuer Informatik - Breitwiesenstr. 20-22 - D-70565 Stuttgart - diff -u --recursive --new-file v2.1.100/linux/Makefile linux/Makefile --- v2.1.100/linux/Makefile Thu May 7 22:51:46 1998 +++ linux/Makefile Fri May 8 00:09:20 1998 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 100 +SUBLEVEL = 101 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) @@ -355,7 +355,7 @@ fi rm -f submenu* -mrproper: clean +mrproper: clean archmrproper rm -f include/linux/autoconf.h include/linux/version.h rm -f drivers/net/hamradio/soundmodem/sm_tbl_{afsk1200,afsk2666,fsk9600}.h rm -f drivers/net/hamradio/soundmodem/sm_tbl_{hapn4800,psk4800}.h diff -u --recursive --new-file v2.1.100/linux/arch/alpha/Makefile linux/arch/alpha/Makefile --- v2.1.100/linux/arch/alpha/Makefile Sat Apr 25 18:13:10 1998 +++ linux/arch/alpha/Makefile Fri May 8 00:09:20 1998 @@ -76,6 +76,8 @@ archclean: @$(MAKEBOOT) clean +archmrproper: + archdep: @$(MAKEBOOT) dep diff -u --recursive --new-file v2.1.100/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v2.1.100/linux/arch/alpha/config.in Sat May 2 14:19:52 1998 +++ linux/arch/alpha/config.in Fri May 8 17:54:39 1998 @@ -184,6 +184,7 @@ fi bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC +bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL tristate 'Kernel support for a.out (ECOFF) binaries' CONFIG_BINFMT_AOUT tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF diff -u --recursive --new-file v2.1.100/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c --- v2.1.100/linux/arch/alpha/kernel/alpha_ksyms.c Wed Apr 8 19:36:24 1998 +++ linux/arch/alpha/kernel/alpha_ksyms.c Fri May 8 00:23:41 1998 @@ -23,6 +23,7 @@ #include #include #include +#include #define __KERNEL_SYSCALLS__ #include @@ -43,6 +44,8 @@ EXPORT_SYMBOL(local_bh_count); EXPORT_SYMBOL(local_irq_count); +EXPORT_SYMBOL(enable_irq); +EXPORT_SYMBOL(disable_irq); /* platform dependent support */ EXPORT_SYMBOL(_inb); diff -u --recursive --new-file v2.1.100/linux/arch/arm/Makefile linux/arch/arm/Makefile --- v2.1.100/linux/arch/arm/Makefile Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/Makefile Fri May 8 00:42:38 1998 @@ -12,52 +12,54 @@ # # Copyright (C) 1995, 1996 by Russell King -CFLAGS_PROC := -ASFLAGS_PROC := +CFLAGS_PROC := +ASFLAGS_PROC := -ifeq ($(CONFIG_CPU_ARM2),y) -PROCESSOR = armo -ASFLAGS_PROC += -m2 -ifeq ($(CONFIG_BINUTILS_NEW),y) -CFLAGS_PROC += -mcpu=arm2 -ASFLAGS_PROC += -m2 -else -CFLAGS_PROC += -m2 -ASFLAGS_PROC += -m2 -endif -endif - -ifeq ($(CONFIG_CPU_ARM3),y) -PROCESSOR = armo -ifeq ($(CONFIG_BINUTILS_NEW),y) -CFLAGS_PROC += -mcpu=arm3 -ASFLAGS_PROC += -m3 -else -CFLAGS_PROC += -m3 -ASFLAGS_PROC += -m3 -endif -endif - -ifeq ($(CONFIG_CPU_ARM6),y) -PROCESSOR = armv -ifeq ($(CONFIG_BINUTILS_NEW),y) -CFLAGS_PROC += -mcpu=arm6 -ASFLAGS_PROC += -m6 -else -CFLAGS_PROC += -m6 -ASFLAGS_PROC += -m6 -endif -endif - -ifeq ($(CONFIG_CPU_SA110),y) -PROCESSOR = armv -ifeq ($(CONFIG_BINUTILS_NEW),y) -CFLAGS_PROC += -mcpu=strongarm110 -ASFLAGS_PROC += -m6 -else -CFLAGS_PROC += -m6 -ASFLAGS_PROC += -m6 -endif +# All processors get `-mshort-load-bytes' for now, to work around alignment +# problems. This is more of a hack that just happens to work than a real fix +# but it will do for now. + +ifeq ($(CONFIG_CPU_26),y) + PROCESSOR = armo + ifeq ($(CONFIG_BINUTILS_NEW),y) + CFLAGS_PROC += -mapcs-26 -mshort-load-bytes + ifeq ($(CONFIG_CPU_ARM2),y) + CFLAGS_PROC += -mcpu=arm2 + ASFLAGS_PROC += -m2 + endif + ifeq ($(CONFIG_CPU_ARM3),y) + CFLAGS_PROC += -mcpu=arm3 + ASFLAGS_PROC += -m3 + endif + else + ifeq ($(CONFIG_CPU_ARM2),y) + CFLAGS_PROC += -m2 + ASFLAGS_PROC += -m2 + endif + ifeq ($(CONFIG_CPU_ARM3),y) + CFLAGS_PROC += -m3 + ASFLAGS_PROC += -m3 + endif + endif +endif + +ifeq ($(CONFIG_CPU_32),y) + PROCESSOR = armv + ifeq ($(CONFIG_BINUTILS_NEW),y) + CFLAGS_PROC += -mapcs-32 -mshort-load-bytes + ifeq ($(CONFIG_CPU_ARM6),y) + CFLAGS_PROC += -mcpu=arm6 + endif + ifeq ($(CONFIG_CPU_ARM7),y) + CFLAGS_PROC += -mcpu=arm7 + endif + ifeq ($(CONFIG_CPU_SA110),y) + CFLAGS_PROC += -mcpu=strongarm110 + endif + else + CFLAGS_PROC += -m6 + endif + ASFLAGS_PROC += -m6 endif # Processor Architecture @@ -71,9 +73,6 @@ COMPRESSED_HEAD = head.o ifeq ($(PROCESSOR),armo) -ifeq ($(CONFIG_BINUTILS_NEW),y) -CFLAGS_PROC += -mapcs-26 -mshort-load-bytes -endif TEXTADDR = 0x02080000 ZTEXTADDR = 0x01800000 ZRELADDR = 0x02080000 @@ -92,11 +91,7 @@ endif ifeq ($(PROCESSOR),armv) -ifeq ($(CONFIG_BINUTILS_NEW),y) -CFLAGS_PROC += -mapcs-32 -mshort-load-bytes -endif TEXTADDR = 0xC0008000 -endif ifeq ($(CONFIG_ARCH_RPC),y) MACHINE = rpc @@ -122,21 +117,27 @@ ifeq ($(CONFIG_ARCH_NEXUSPCI),y) MACHINE = nexuspci +ARCHDIR = nexuspci TEXTADDR = 0xc0000000 ZTEXTADDR = 0x40200000 ZRELADDR = 0x40000000 COMPRESSED_EXTRA = $(TOPDIR)/arch/arm/lib/ll_char_wr_scc.o COMPRESSED_HEAD = head-nexuspci.o endif +endif -OBJDUMP = $(CROSS_COMPILE)objdump PERL = perl +ifeq ($(CONFIG_BINUTILS_NEW),y) +LD = $(CROSS_COMPILE)ld -m elf32arm +else LD = $(CROSS_COMPILE)ld -m elf_arm -CPP = $(CC) -E +endif OBJCOPY = $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S +OBJDUMP = $(CROSS_COMPILE)objdump +CPP = $(CC) -E ARCHCC := $(word 1,$(CC)) GCCLIB := `$(ARCHCC) $(CFLAGS_PROC) --print-libgcc-file-name` -GCCARCH := -B/usr/src/bin/arm/arm-linuxelf- +#GCCARCH := -B/usr/bin/arm-linuxelf- HOSTCFLAGS := $(CFLAGS:-fomit-frame-pointer=) ifeq ($(CONFIG_FRAME_POINTER),y) CFLAGS := $(CFLAGS:-fomit-frame-pointer=) @@ -225,5 +226,8 @@ @$(MAKEBOOT) clean $(RM) arch/arm/lib/constants.h +archmrproper: + archdep: @$(MAKEBOOT) dep +sed -e /^MACHINE..*=/s,= .*,= rpc,;/^PROCESSOR..*=/s,= .*,= armv, linux/arch/arm/Makefile.normal diff -u --recursive --new-file v2.1.100/linux/arch/arm/boot/tools/build.c linux/arch/arm/boot/tools/build.c --- v2.1.100/linux/arch/arm/boot/tools/build.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/boot/tools/build.c Fri May 8 00:42:38 1998 @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned long u32; + +void die(const char * str, ...) +{ + va_list args; + va_start(args, str); + vfprintf(stderr, str, args); + fputc('\n', stderr); + exit (1); +} + +int main(int argc, char **argv) +{ + void *data; + struct exec ex; + FILE *f; + int totlen; + + if (argc < 2) { + fprintf(stderr, "Usage: build kernel-name\n"); + exit(1); + } + + f = fopen(argv[1], "rb"); + if (!f) + die("Unable to open `%s': %m", argv[1]); + + fread(&ex, 1, sizeof(ex), f); + + if(N_MAGIC(ex) == ZMAGIC) { + fseek(f, 4096, SEEK_SET); + totlen = ex.a_text + ex.a_data; + } else + if(N_MAGIC(ex) == QMAGIC) { + unsigned long my_header; + + fseek(f, 4, SEEK_SET); + + my_header = 0xea000006; + + fwrite(&my_header, 4, 1, stdout); + + totlen = ex.a_text + ex.a_data - 4; + } else { + fprintf(stderr, "Unacceptable a.out header on kernel\n"); + fclose(f); + exit(1); + } + + fprintf(stderr, "Kernel is %dk (%dk text, %dk data, %dk bss)\n", + (ex.a_text + ex.a_data + ex.a_bss)/1024, + ex.a_text/1024, ex.a_data/1024, ex.a_bss/1024); + + data = malloc(totlen); + fread(data, 1, totlen, f); + fwrite(data, 1, totlen, stdout); + + free(data); + fclose(f); + fflush(stdout); + return 0; +} diff -u --recursive --new-file v2.1.100/linux/arch/arm/config.in linux/arch/arm/config.in --- v2.1.100/linux/arch/arm/config.in Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/config.in Fri May 8 00:42:38 1998 @@ -7,7 +7,7 @@ define_bool CONFIG_ARM y mainmenu_option next_comment -comment 'System type and processor type' +comment 'System and processor type' choice 'ARM system type' \ "Archimedes CONFIG_ARCH_ARC \ A5000 CONFIG_ARCH_A5K \ @@ -20,29 +20,55 @@ else define_bool CONFIG_ARCH_ACORN n fi -if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o "$CONFIG_ARCH_EBSA285" = "y" ]; then +if [ "$CONFIG_ARCH_NEXUSPCI" = "y" ]; then define_bool CONFIG_PCI y else - define_bool CONFIG_PCI n + if [ "$CONFIG_ARCH_EBSA285" = "y" ]; then + bool "PCI support" CONFIG_PCI + fi fi -if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o "$CONFIG_ARCH_EBSA110" = "y" -o "$CONFIG_ARCH_EBSA285" = "y" ]; then - define_bool CONFIG_CPU_SA110 y + +# Figure out whether this system uses 26-bit or 32-bit CPUs. Nobody has +# ever built a machine that can take both, and now that ARM3 is obsolete +# nobody is likely to either. + +if [ "$CONFIG_ARCH_RPC" = "y" -o "$CONFIG_ARCH_NEXUSPCI" = "y" -o "$CONFIG_ARCH_EBSA110" = "y" -o "$CONFIG_ARCH_EBSA285" = "y" ]; then + define_bool CONFIG_CPU_32 y + define_bool CONFIG_CPU_26 n else - if [ "$CONFIG_ARCH_A5K" = "y" ]; then - define_bool CONFIG_CPU_ARM3 y - else - choice 'ARM cpu type' \ - "ARM2 CONFIG_CPU_ARM2 \ - ARM3 CONFIG_CPU_ARM3 \ - ARM6/7 CONFIG_CPU_ARM6 \ - StrongARM CONFIG_CPU_SA110" StrongARM + if [ "$CONFIG_ARCH_ARC" = "y" -o "$CONFIG_ARCH_A5K" = "y" ]; then + define_bool CONFIG_CPU_32 n + define_bool CONFIG_CPU_26 y fi fi + +# Now allow the user to choose a more precise CPU. This is only used to set +# the flags we pass to GCC, not in any code. + +choice 'Optimise for CPU' \ + "ARM2 CONFIG_CPU_ARM2 \ + ARM3 CONFIG_CPU_ARM3 \ + ARM6 CONFIG_CPU_ARM6 \ + ARM7 CONFIG_CPU_ARM7 \ + SA110 CONFIG_CPU_SA110" ARM6 + +if [ "$CONFIG_CPU_26" = "y" ]; then + +# For 26-bit CPUs, the page size changes with the amount of physical RAM! +# The default is 4MB but if the user has less they have to own up to it here. + + choice 'Physical memory size' \ + "4MB+ CONFIG_PAGESIZE_32 \ + 2MB CONFIG_PAGESIZE_16 \ + 1MB/512K CONFIG_PAGESIZE_8" 4MB+ +fi endmenu mainmenu_option next_comment comment 'Code maturity level options' bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL +bool 'Use new compilation options (for GCC 2.8)' CONFIG_BINUTILS_NEW +bool 'Compile kernel with frame pointer (for useful debugging)' CONFIG_FRAME_POINTER endmenu mainmenu_option next_comment @@ -56,33 +82,50 @@ mainmenu_option next_comment comment 'General setup' -bool 'Compile kernel with frame pointer (for useful debugging)' CONFIG_FRAME_POINTER -bool 'Use new compilation options (for GCC 2.8)' CONFIG_BINUTILS_NEW -bool 'Debug kernel errors' CONFIG_DEBUG_ERRORS bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC -# This needs kernel/acct.c to be updated -#bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -# tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA - define_bool CONFIG_BINFMT_JAVA n -fi +tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC + tristate 'Parallel port support' CONFIG_PARPORT if [ "$CONFIG_PARPORT" != "n" ]; then dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT + dep_tristate ' Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT +# If exactly one hardware type is selected then parport will optimise away +# support for loading any others. Defeat this if the user is keen. + if [ "$CONFIG_PARPORT_PC" = "n" -o "$CONFIG_PARPORT_ARC" = "n" ]; then + if [ "$CONFIG_PARPORT_PC" != "n" -o "$CONFIG_PARPORT_ARC" != "n" ]; then + bool ' Support foreign hardware' CONFIG_PARPORT_OTHER + fi + fi fi endmenu source arch/arm/drivers/block/Config.in source drivers/acorn/block/Config.in +source arch/arm/drivers/char/Config.in +bool 'Support Frame buffer devices' CONFIG_FB +source drivers/video/Config.in + if [ "$CONFIG_NET" = "y" ]; then source net/Config.in fi +if [ "$CONFIG_NET" = "y" ]; then + mainmenu_option next_comment + comment 'Network device support' + + bool 'Network device support?' CONFIG_NETDEVICES + if [ "$CONFIG_NETDEVICES" = "y" ]; then + source drivers/net/Config.in + fi + endmenu +fi + mainmenu_option next_comment comment 'SCSI support' @@ -93,13 +136,13 @@ fi endmenu -if [ "$CONFIG_NET" = "y" ]; then +if [ "$CONFIG_ARCH_ACORN" = "y" ]; then mainmenu_option next_comment - comment 'Network device support' + comment 'Sound' - bool 'Network device support?' CONFIG_NETDEVICES - if [ "$CONFIG_NETDEVICES" = "y" ]; then - source drivers/net/Config.in + tristate 'Sound support' CONFIG_SOUND + if [ "$CONFIG_SOUND" != "n" ]; then + source drivers/sound/Config.in fi endmenu fi @@ -113,37 +156,14 @@ # fi # endmenu -# Conditionally compile in the Uniform CD-ROM driver -if [ "$CONFIG_BLK_DEV_IDECD" = "y" -o "$CONFIG_BLK_DEV_SR" = "y" ]; then - define_bool CONFIG_CDROM y -else - if [ "$CONFIG_BLK_DEV_IDECD" = "m" -o "$CONFIG_BLK_DEV_SR" = "m" ]; then - define_bool CONFIG_CDROM m - else - define_bool CONFIG_CDROM n - fi -fi - source fs/Config.in source fs/nls/Config.in -source arch/arm/drivers/char/Config.in - -if [ "$CONFIG_ARCH_ACORN" = "y" ]; then - mainmenu_option next_comment - comment 'Sound' - - tristate 'Sound support' CONFIG_SOUND - if [ "$CONFIG_SOUND" != "n" ]; then - source drivers/sound/Config.in - fi - endmenu -fi - mainmenu_option next_comment comment 'Kernel hacking' +bool 'Debug kernel errors' CONFIG_DEBUG_ERRORS #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC bool 'Kernel profiling support' CONFIG_PROFILE if [ "$CONFIG_PROFILE" = "y" ]; then diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile --- v2.1.100/linux/arch/arm/kernel/Makefile Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/kernel/Makefile Fri May 8 00:42:38 1998 @@ -11,7 +11,7 @@ O_TARGET := kernel.o O_OBJS := $(ENTRY_OBJ) ioport.o irq.o process.o ptrace.o signal.o sys_arm.o time.o traps.o -all: kernel.o $(HEAD_OBJ) init_task.o +all: lib kernel.o $(HEAD_OBJ) init_task.o ifeq ($(CONFIG_MODULES),y) OX_OBJS = armksyms.o @@ -19,28 +19,31 @@ O_OBJS += armksyms.o endif -ifdef CONFIG_PCI - O_OBJS += bios32.o -endif - ifdef CONFIG_ARCH_ACORN - O_OBJS += setup.o ecard.o iic.o dma.o + O_OBJS += setup.o ecard.o iic.o ifdef CONFIG_ARCH_ARC O_OBJS += oldlatches.o endif O_OBJS += dma-$(MACHINE).o + OX_OBJS += dma.o endif ifeq ($(MACHINE),ebsa110) - O_OBJS += setup-ebsa110.o dma.o dma-dummy.o + O_OBJS += setup-ebsa110.o dma-dummy.o endif ifeq ($(MACHINE),ebsa285) - O_OBJS += dma.o dma-dummy.o leds-ebsa285.o setup-ebsa110.o + O_OBJS += dma-dummy.o leds-ebsa285.o setup-ebsa110.o + ifdef CONFIG_PCI + O_OBJS += dec21285.o + endif endif ifeq ($(MACHINE),nexuspci) - O_OBJS += setup-ebsa110.o + O_OBJS += setup-ebsa110.o dma-dummy.o + ifdef CONFIG_PCI + O_OBJS += plx9080.o + endif endif $(HEAD_OBJ): $(HEAD_OBJ:.o=.S) @@ -53,7 +56,7 @@ $(ENTRY_OBJ): ../lib/constants.h -.PHONY: ../lib/constants.h +.PHONY: lib -../lib/constants.h: +lib: $(MAKE) -C ../lib constants.h diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/armksyms.c linux/arch/arm/kernel/armksyms.c --- v2.1.100/linux/arch/arm/kernel/armksyms.c Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/kernel/armksyms.c Fri May 8 00:42:38 1998 @@ -100,16 +100,6 @@ EXPORT_SYMBOL(__bad_pmd); EXPORT_SYMBOL(__bad_pmd_kernel); -/* dma */ -EXPORT_SYMBOL(dma_str); -EXPORT_SYMBOL(enable_dma); -EXPORT_SYMBOL(disable_dma); -EXPORT_SYMBOL(set_dma_addr); -EXPORT_SYMBOL(set_dma_count); -EXPORT_SYMBOL(set_dma_mode); -EXPORT_SYMBOL(get_dma_residue); -EXPORT_SYMBOL(set_dma_sg); - /* * floating point math emulator support. * These symbols will never change their calling convention... @@ -155,12 +145,12 @@ EXPORT_SYMBOL_NOVERS(memzero); /* user mem (segment) */ -#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110) +#if defined(CONFIG_CPU_32) EXPORT_SYMBOL(__arch_copy_from_user); EXPORT_SYMBOL(__arch_copy_to_user); EXPORT_SYMBOL(__arch_clear_user); EXPORT_SYMBOL(__arch_strlen_user); -#elif defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3) +#elif defined(CONFIG_CPU_26) EXPORT_SYMBOL(uaccess_kernel); EXPORT_SYMBOL(uaccess_user); #endif diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/bios32.c linux/arch/arm/kernel/bios32.c --- v2.1.100/linux/arch/arm/kernel/bios32.c Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/kernel/bios32.c Wed Dec 31 16:00:00 1969 @@ -1,144 +0,0 @@ -/* - * arch/arm/kernel/bios32.c: PCI functions for ARM - * - * Copyright (C) 1998 Russell King - */ -#include -#include -#include - -int pcibios_present(void) -{ - return 1; -} - -static unsigned long pcibios_base_address(unsigned char dev_fn) -{ - int slot = PCI_SLOT(dev_fn); - - if (slot < 4) - return 0xf8000000 + (1 << (19 - slot)); - else - return 0; -} - -int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned char *val) -{ - unsigned long addr = pcibios_base_address(dev_fn); - unsigned char v; - - if (addr) { - __asm__("ldr%?b %0, [%1, %2]" - : "=r" (v) - : "r" (addr), "r" (where)); - *val = v; - } else - *val = 0xff; - return PCIBIOS_SUCCESSFUL; -} - -int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned short *val) -{ - unsigned long addr = pcibios_base_address(dev_fn); - unsigned short v; - - if (addr) { - __asm__("ldrh%? %0, [%1, %2]" - : "=r" (v) - : "r" (addr), "r" (where)); - *val = v; - } else - *val = 0xffff; - return PCIBIOS_SUCCESSFUL; -} - -int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned int *val) -{ - unsigned long addr = pcibios_base_address(dev_fn); - unsigned int v; - - if (addr) { - __asm__("ldr%? %0, [%1, %2]" - : "=r" (v) - : "r" (addr), "r" (where)); - *val = v; - } else - *val = 0xffffffff; - return PCIBIOS_SUCCESSFUL; -} - -int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned char val) -{ - unsigned long addr = pcibios_base_address(dev_fn); - - if (addr) - __asm__("str%?b %0, [%1, %2]" - : : "r" (val), "r" (addr), "r" (where)); - return PCIBIOS_SUCCESSFUL; -} - -int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned short val) -{ - unsigned long addr = pcibios_base_address(dev_fn); - - if (addr) - __asm__("strh%? %0, [%1, %2]" - : : "r" (val), "r" (addr), "r" (where)); - return PCIBIOS_SUCCESSFUL; -} - -int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned int val) -{ - unsigned long addr = pcibios_base_address(dev_fn); - - if (addr) - __asm__("str%? %0, [%1, %2]" - : : "r" (val), "r" (addr), "r" (where)); - return PCIBIOS_SUCCESSFUL; -} - -static int irq[] = { 18, 8, 9, 11 }; - -__initfunc(void pcibios_fixup(void)) -{ - struct pci_dev *dev; - unsigned char pin; - - for (dev = pci_devices; dev; dev = dev->next) { - pcibios_read_config_byte(dev->bus->number, - dev->devfn, - PCI_INTERRUPT_PIN, - &pin); - - dev->irq = irq[(PCI_SLOT(dev->devfn) + pin) & 3]; - - pcibios_write_config_byte(dev->bus->number, - dev->devfn, - PCI_INTERRUPT_LINE, - dev->irq); - - printk("PCI: %02x:%02x [%04x/%04x] pin %d irq %d\n", - dev->bus->number, dev->devfn, - dev->vendor, dev->device, - pin, dev->irq); - } -} - -__initfunc(void pcibios_init(void)) -{ - int rev; - - rev = *(unsigned char *)0xfe000008; - printk("DEC21285 PCI revision %02X\n", rev); -} - -__initfunc(char *pcibios_setup(char *str)) -{ - return str; -} diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/calls.S linux/arch/arm/kernel/calls.S --- v2.1.100/linux/arch/arm/kernel/calls.S Wed Apr 8 19:36:24 1998 +++ linux/arch/arm/kernel/calls.S Fri May 8 00:42:38 1998 @@ -190,7 +190,11 @@ .long SYMBOL_NAME(sys_rt_sigsuspend_wrapper) /* 180 */ .long SYMBOL_NAME(sys_pread) .long SYMBOL_NAME(sys_pwrite) +#if 0 .long SYMBOL_NAME(sys_xstat) .long SYMBOL_NAME(sys_xmknod) +#else + .space 8 +#endif .space (NR_syscalls - 184) * 4 #endif diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/dec21285.c linux/arch/arm/kernel/dec21285.c --- v2.1.100/linux/arch/arm/kernel/dec21285.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/dec21285.c Fri May 8 00:42:38 1998 @@ -0,0 +1,145 @@ +/* + * arch/arm/kernel/dec21285.c: PCI functions for DEC 21285 + * + * Copyright (C) 1998 Russell King + */ +#include +#include +#include +#include + +int pcibios_present(void) +{ + return 1; +} + +static unsigned long pcibios_base_address(unsigned char dev_fn) +{ + int slot = PCI_SLOT(dev_fn); + + if (slot < 4) + return 0xf8000000 + (1 << (19 - slot)); + else + return 0; +} + +int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned char *val) +{ + unsigned long addr = pcibios_base_address(dev_fn); + unsigned char v; + + if (addr) + __asm__("ldr%?b %0, [%1, %2]" + : "=r" (v) + : "r" (addr), "r" (where)); + else + v = 0xff; + *val = v; + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned short *val) +{ + unsigned long addr = pcibios_base_address(dev_fn); + unsigned short v; + + if (addr) + __asm__("ldr%?h %0, [%1, %2]" + : "=r" (v) + : "r" (addr), "r" (where)); + else + v = 0xffff; + *val = v; + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned int *val) +{ + unsigned long addr = pcibios_base_address(dev_fn); + unsigned int v; + + if (addr) + __asm__("ldr%? %0, [%1, %2]" + : "=r" (v) + : "r" (addr), "r" (where)); + else + v = 0xffffffff; + *val = v; + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned char val) +{ + unsigned long addr = pcibios_base_address(dev_fn); + + if (addr) + __asm__("str%?b %0, [%1, %2]" + : : "r" (val), "r" (addr), "r" (where)); + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned short val) +{ + unsigned long addr = pcibios_base_address(dev_fn); + + if (addr) + __asm__("str%?h %0, [%1, %2]" + : : "r" (val), "r" (addr), "r" (where)); + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned int val) +{ + unsigned long addr = pcibios_base_address(dev_fn); + + if (addr) + __asm__("str%? %0, [%1, %2]" + : : "r" (val), "r" (addr), "r" (where)); + return PCIBIOS_SUCCESSFUL; +} + +static int irq[] = { 18, 8, 9, 11 }; + +__initfunc(void pcibios_fixup(void)) +{ + struct pci_dev *dev; + unsigned char pin; + + for (dev = pci_devices; dev; dev = dev->next) { + pcibios_read_config_byte(dev->bus->number, + dev->devfn, + PCI_INTERRUPT_PIN, + &pin); + + dev->irq = irq[(PCI_SLOT(dev->devfn) + pin) & 3]; + + pcibios_write_config_byte(dev->bus->number, + dev->devfn, + PCI_INTERRUPT_LINE, + dev->irq); + + printk("PCI: %02x:%02x [%04x/%04x] pin %d irq %d\n", + dev->bus->number, dev->devfn, + dev->vendor, dev->device, + pin, dev->irq); + } +} + +__initfunc(void pcibios_init(void)) +{ + int rev; + + rev = *(unsigned char *)0xfe000008; + printk("DEC21285 PCI revision %02X\n", rev); +} + +__initfunc(char *pcibios_setup(char *str)) +{ + return str; +} diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/dma-a5k.c linux/arch/arm/kernel/dma-a5k.c --- v2.1.100/linux/arch/arm/kernel/dma-a5k.c Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/kernel/dma-a5k.c Fri May 8 00:42:38 1998 @@ -11,12 +11,13 @@ #include #include #include +#include #include "dma.h" -int arch_request_dma(dmach_t channel, dma_t *dma) +int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id) { - if (channel == DMA_VIRTUAL_FLOPPY0) + if (channel == DMA_VIRTUAL_FLOPPY) return 0; else return -EINVAL; @@ -24,14 +25,14 @@ void arch_free_dma(dmach_t channel, dma_t *dma) { - if (channel != DMA_VIRTUAL_FLOPPY0) + if (channel != DMA_VIRTUAL_FLOPPY) printk ("arch_free_dma: invalid channel %d\n", channel); } int arch_get_dma_residue(dmach_t channel, dma_t *dma) { - if (channel != DMA_VIRTUAL_FLOPPY0) - printk ("arch_dma_count: invalid channel %d\n", dmanr); + if (channel != DMA_VIRTUAL_FLOPPY) + printk ("arch_dma_count: invalid channel %d\n", channel); else { extern int floppy_fiqresidual(void); return floppy_fiqresidual(); @@ -41,7 +42,7 @@ void arch_enable_dma(dmach_t channel, dma_t *dma) { - if (channel != DMA_VIRTUAL_FLOPPY0) + if (channel != DMA_VIRTUAL_FLOPPY) printk ("arch_enable_dma: invalid channel %d\n", channel); else { void *fiqhandler_start; @@ -67,7 +68,7 @@ void arch_disable_dma(dmach_t channel, dma_t *dma) { - if (channel != DMA_VIRTUAL_FLOPPY0) + if (channel != DMA_VIRTUAL_FLOPPY) printk ("arch_disable_dma: invalid channel %d\n", channel); else disable_irq (dma->dma_irq); @@ -75,5 +76,5 @@ __initfunc(void arch_dma_init(dma_t *dma)) { - dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64; + dma[DMA_VIRTUAL_FLOPPY].dma_irq = 64; } diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/dma-dummy.c linux/arch/arm/kernel/dma-dummy.c --- v2.1.100/linux/arch/arm/kernel/dma-dummy.c Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/kernel/dma-dummy.c Fri May 8 00:42:38 1998 @@ -1,45 +1,28 @@ /* * arch/arm/kernel/dma-dummy.c * - * Copyright (C) 1998 Russell King + * Copyright (C) 1998 Philip Blundell + * Copyright (c) 1998 Russell King * * Dummy DMA functions */ -#include +#include #include -#include -#include -#include - -#include "dma.h" - -int arch_request_dma(dmach_t channel, dma_t *dma, const char *devname) +int request_dma(int channel, const char *device_id) { return -EINVAL; } -void arch_free_dma(dmach_t channel, dma_t *dma) -{ - printk ("arch_free_dma: invalid channel %d\n", channel); -} - -void arch_enable_dma(dmach_t channel, dma_t *dma) -{ - printk ("arch_enable_dma: invalid channel %d\n", channel); -} - -void arch_disable_dma(dmach_t channel, dma_t *dma) +void free_dma(int channel) { - printk ("arch_disable_dma: invalid channel %d\n", channel); } -int arch_get_dma_residue(dmach_t channel, dma_t *dma) +int get_dma_list(char *buf) { - printk ("arch_get_dma_residue: invalid channel %d\n", channel); return 0; } -__initfunc(void arch_dma_init(dma_t *dma)) +__initfunc(void init_dma(void)) { } diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/dma.c linux/arch/arm/kernel/dma.c --- v2.1.100/linux/arch/arm/kernel/dma.c Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/kernel/dma.c Fri May 8 00:42:38 1998 @@ -15,6 +15,7 @@ * Moved DMA resource allocation here... */ #include +#include #include #include #include @@ -28,6 +29,8 @@ #include "dma.h" +const char dma_str[] = "%s: dma %d not supported\n"; + static dma_t dma_chan[MAX_DMA_CHANNELS]; /* Get dma list @@ -182,6 +185,15 @@ { return arch_get_dma_residue(channel, &dma_chan[channel]); } + +EXPORT_SYMBOL(dma_str); +EXPORT_SYMBOL(enable_dma); +EXPORT_SYMBOL(disable_dma); +EXPORT_SYMBOL(set_dma_addr); +EXPORT_SYMBOL(set_dma_count); +EXPORT_SYMBOL(set_dma_mode); +EXPORT_SYMBOL(get_dma_residue); +EXPORT_SYMBOL(set_dma_sg); __initfunc(void init_dma(void)) { diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/entry-armo.S linux/arch/arm/kernel/entry-armo.S --- v2.1.100/linux/arch/arm/kernel/entry-armo.S Tue Jan 20 16:39:41 1998 +++ linux/arch/arm/kernel/entry-armo.S Fri May 8 00:42:38 1998 @@ -189,7 +189,7 @@ */ .macro adrsvc, cond, reg, label adr\cond \reg, \label - orr\cond \reg, \reg, #3 + orr\cond \reg, \reg, #0x08000003 .endm #if 0 @@ -422,7 +422,7 @@ @ routine called with r0 = irq number, r1 = struct pt_regs * @ adr lr, 1b - orr lr, lr, #3 @ Force SVC + orr lr, lr, #0x08000003 @ Force SVC bne do_IRQ b ret_with_reschedule @@ -442,7 +442,7 @@ @ routine called with r0 = irq number, r1 = struct pt_regs * @ adr lr, 1b - orr lr, lr, #3 @ Force SVC + orr lr, lr, #0x08000003 @ Force SVC bne do_IRQ @ Returns to 1b SVC_RESTORE_ALL @@ -512,17 +512,11 @@ b Ldata_ldcstc_pre @ ldc rd, [rn, #m] b Ldata_unknown Ldata_unknown: @ Part of jumptable - ldr r3, [sp, #15 * 4] - str r3, [sp, #-4]! - mov r1, r1, lsr #2 - mov r2, r0 - mov r3, r4 - adr r0, Ltt - bl SYMBOL_NAME(printk) -Llpxx: b Llpxx - -Ltt: .ascii "Unknown data abort code %d [pc=%p, *pc=%p]\nLR=%p\0" - .align + mov r0, r1 + mov r1, r4 + mov r2, r3 + mov r3, lr + b baddataabort Ldata_ldrstr_post: mov r0, r4, lsr #14 @ Get Rn diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S --- v2.1.100/linux/arch/arm/kernel/entry-armv.S Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/kernel/entry-armv.S Fri May 8 00:42:38 1998 @@ -206,6 +206,26 @@ .macro irq_prio_table .endm +#elif defined(CONFIG_ARCH_NEXUSPCI) + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base + ldr r4, =0xffe00000 + ldr \irqstat, [r4, #0x180] @ get interrupts + mov \irqnr, #0 +1001: tst \irqstat, #1 + addeq \irqnr, \irqnr, #1 + moveq \irqstat, \irqstat, lsr #1 + tsteq \irqnr, #32 + beq 1001b + teq \irqnr, #32 + .endm + + .macro irq_prio_table + .endm + #else #error Unknown architecture #endif diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/entry-common.S linux/arch/arm/kernel/entry-common.S --- v2.1.100/linux/arch/arm/kernel/entry-common.S Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/kernel/entry-common.S Fri May 8 00:42:38 1998 @@ -207,6 +207,7 @@ * 0x1c onwards is reserved for FIQ, so I think that I will allocate 0xe0 onwards for * the actuall address to jump to. */ +#if defined(CONFIG_CPU_32) /* * these go into 0x00 */ @@ -237,13 +238,42 @@ initialise_traps_extra mov r0, #0xe4 adr r1, .Ljump_addresses - ldmia r1, {r1 - r6} - stmia r0, {r1 - r6} + ldmia r1, {r1 - r7} + stmia r0, {r1 - r7} mov r0, #0 adr r1, .Lbranches ldmia r1, {r1 - r7} stmia r0, {r1 - r7} LOADREGS(fd, sp!, {r4 - r7, pc}) +#elif defined(CONFIG_CPU_26) +.Ljump_addresses: + swi SYS_ERROR0 + .word vector_undefinstr - 12 + .word vector_swi - 16 + .word vector_prefetch - 20 + .word vector_data - 24 + .word vector_addrexcptn - 28 + .word vector_IRQ - 32 + .word _unexp_fiq - 36 + b . + 8 +/* + * initialise the trap system + */ +ENTRY(trap_init) + stmfd sp!, {r4 - r7, lr} + adr r1, .Ljump_addresses + ldmia r1, {r1 - r7, ip, lr} + orr r2, lr, r2, lsr #2 + orr r3, lr, r3, lsr #2 + orr r4, lr, r4, lsr #2 + orr r5, lr, r5, lsr #2 + orr r6, lr, r6, lsr #2 + orr r7, lr, r7, lsr #2 + orr ip, lr, ip, lsr #2 + mov r0, #0 + stmia r0, {r1 - r7, ip} + ldmfd sp!, {r4 - r7, pc}^ +#endif /*============================================================================ * FP support diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/head-armv.S linux/arch/arm/kernel/head-armv.S --- v2.1.100/linux/arch/arm/kernel/head-armv.S Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/kernel/head-armv.S Fri May 8 00:42:38 1998 @@ -7,6 +7,9 @@ */ #include #include + +#define DEBUG + .text .align @@ -245,8 +248,11 @@ mov fp, #0 b SYMBOL_NAME(start_kernel) -#if 1 - +#ifdef DEBUG +/* + * Some debugging routines (useful if you've got MM problems and + * printk isn't working). For DEBUGGING ONLY!!! + */ #if defined(CONFIG_ARCH_RPC) .macro addruart,rx mov \rx, #0xe0000000 @@ -309,6 +315,26 @@ .macro waituart,rd,rx .endm + +#elif defined(CONFIG_ARCH_NEXUSPCI) + .macro addruart,rx + ldr \rx, =0xfff00000 + .endm + + .macro senduart,rd,rx + str \rd, [\rx, #0xc] + .endm + + .macro busyuart,rd,rx +1001: ldr \rd, [\rx, #0x4] + tst \rd, #1 << 0 + bne 1001b + .endm + + .macro waituart,rd,rx + .endm +#else +#error Unknown architecture #endif /* @@ -358,6 +384,8 @@ mov r1, r0 mov r0, #0 b 1b + + .ltorg .bss hexbuf: .space 16 diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c --- v2.1.100/linux/arch/arm/kernel/process.c Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/kernel/process.c Fri May 8 00:42:38 1998 @@ -112,9 +112,7 @@ flags = condition_codes(regs); - printk("\n" - "pc : [<%08lx>]\n" - "lr : [<%08lx>]\n" + printk( "pc : [<%08lx>] lr : [<%08lx>]\n" "sp : %08lx ip : %08lx fp : %08lx\n", instruction_pointer(regs), regs->ARM_lr, regs->ARM_sp, @@ -133,22 +131,23 @@ flags & CC_Z_BIT ? 'Z' : 'z', flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v'); - printk(" IRQs %s FIQs %s Mode %s\n", + printk(" IRQs %s FIQs %s Mode %s Segment %s\n", interrupts_enabled(regs) ? "on" : "off", fast_interrupts_enabled(regs) ? "on" : "off", - processor_modes[processor_mode(regs)]); -#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110) -{ int ctrl, transbase, dac; - __asm__ ( -" mrc p15, 0, %0, c1, c0\n" -" mrc p15, 0, %1, c2, c0\n" -" mrc p15, 0, %2, c3, c0\n" - : "=r" (ctrl), "=r" (transbase), "=r" (dac)); - printk("Control: %04X Table: %08X DAC: %08X ", - ctrl, transbase, dac); - } + processor_modes[processor_mode(regs)], + get_fs() == get_ds() ? "kernel" : "user"); +#if defined(CONFIG_CPU_32) + { + int ctrl, transbase, dac; + __asm__ ( + " mrc p15, 0, %0, c1, c0\n" + " mrc p15, 0, %1, c2, c0\n" + " mrc p15, 0, %2, c3, c0\n" + : "=r" (ctrl), "=r" (transbase), "=r" (dac)); + printk("Control: %04X Table: %08X DAC: %08X\n", + ctrl, transbase, dac); + } #endif - printk ("Segment %s\n", get_fs() == get_ds() ? "kernel" : "user"); } /* @@ -172,7 +171,15 @@ current->flags &= ~PF_USEDFPU; } +void release_segments(struct mm_struct *mm) +{ +} + void release_thread(struct task_struct *dead_task) +{ +} + +void copy_segments(int nr, struct task_struct *p, struct mm_struct *new_mm) { } diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/setup-ebsa110.c linux/arch/arm/kernel/setup-ebsa110.c --- v2.1.100/linux/arch/arm/kernel/setup-ebsa110.c Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/kernel/setup-ebsa110.c Fri May 8 00:42:38 1998 @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -30,6 +29,7 @@ #include #include +#include #include #include #include @@ -41,17 +41,25 @@ #define MEM_SIZE (16*1024*1024) -static char command_line[COMMAND_LINE_SIZE] = { 0, }; - char saved_command_line[COMMAND_LINE_SIZE]; - -struct processor processor; struct screen_info screen_info; +struct processor processor; unsigned char aux_device_present; + +extern const struct processor sa110_processor_functions; + +struct armversions armidlist[] = { + { 0x4401a100, 0xfffffff0, F_MMU|F_32BIT , "DEC", "sa110" , &sa110_processor_functions , "sa1x"}, + { 0x00000000, 0x00000000, 0 , "***", "*unknown*" , NULL , NULL } +}; + unsigned long arm_id; +int armidindex; extern int root_mountflags; extern int _etext, _edata, _end; -extern const struct processor sa110_processor_functions; + +static char command_line[COMMAND_LINE_SIZE] = { 0, }; + char saved_command_line[COMMAND_LINE_SIZE]; #ifdef CONFIG_BLK_DEV_RAM extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ @@ -110,6 +118,8 @@ int len = 0; memory_start = (unsigned long)&_end; + + armidindex = 0; processor = sa110_processor_functions; processor._proc_init(); diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c --- v2.1.100/linux/arch/arm/kernel/setup.c Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/kernel/setup.c Fri May 8 00:42:38 1998 @@ -50,19 +50,18 @@ extern const struct processor sa110_processor_functions; struct armversions armidlist[] = { -#if defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3) - { 0x41560200, 0xfffffff0, F_MEMC , "ARM/VLSI", "arm2" , &arm2_processor_functions }, - { 0x41560250, 0xfffffff0, F_MEMC , "ARM/VLSI", "arm250" , &arm250_processor_functions }, - { 0x41560300, 0xfffffff0, F_MEMC|F_CACHE, "ARM/VLSI", "arm3" , &arm3_processor_functions }, +#if defined(CONFIG_CPU_26) + { 0x41560200, 0xfffffff0, F_MEMC , "ARM/VLSI", "arm2" , &arm2_processor_functions , "arm2"}, + { 0x41560250, 0xfffffff0, F_MEMC , "ARM/VLSI", "arm250" , &arm250_processor_functions , "arm3"}, + { 0x41560300, 0xfffffff0, F_MEMC|F_CACHE, "ARM/VLSI", "arm3" , &arm3_processor_functions , "arm3"}, +#elif defined(CONFIG_CPU_32) + { 0x41560600, 0xfffffff0, F_MMU|F_32BIT , "ARM/VLSI", "arm6" , &arm6_processor_functions , "arm6"}, + { 0x41560610, 0xfffffff0, F_MMU|F_32BIT , "ARM/VLSI", "arm610" , &arm6_processor_functions , "arm6"}, + { 0x41007000, 0xffffff00, F_MMU|F_32BIT , "ARM/VLSI", "arm7" , &arm7_processor_functions , "arm6"}, + { 0x41007100, 0xffffff00, F_MMU|F_32BIT , "ARM/VLSI", "arm710" , &arm7_processor_functions , "arm6"}, + { 0x4401a100, 0xfffffff0, F_MMU|F_32BIT , "DEC", "sa110" , &sa110_processor_functions , "sa1x"}, #endif -#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110) - { 0x41560600, 0xfffffff0, F_MMU|F_32BIT , "ARM/VLSI", "arm6" , &arm6_processor_functions }, - { 0x41560610, 0xfffffff0, F_MMU|F_32BIT , "ARM/VLSI", "arm610" , &arm6_processor_functions }, - { 0x41007000, 0xffffff00, F_MMU|F_32BIT , "ARM/VLSI", "arm7" , &arm7_processor_functions }, - { 0x41007100, 0xffffff00, F_MMU|F_32BIT , "ARM/VLSI", "arm710" , &arm7_processor_functions }, - { 0x4401a100, 0xfffffff0, F_MMU|F_32BIT , "DEC", "sa110" , &sa110_processor_functions }, -#endif - { 0x00000000, 0x00000000, 0 , "***", "*unknown*" , NULL } + { 0x00000000, 0x00000000, 0 , "***", "*unknown*" , NULL , NULL } }; static struct param_struct *params = (struct param_struct *)PARAMS_BASE; diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/signal.c linux/arch/arm/kernel/signal.c --- v2.1.100/linux/arch/arm/kernel/signal.c Mon Feb 23 18:12:01 1998 +++ linux/arch/arm/kernel/signal.c Fri May 8 00:42:38 1998 @@ -154,7 +154,7 @@ __get_user(regs->ARM_sp, &sc->arm_sp); __get_user(regs->ARM_lr, &sc->arm_lr); __get_user(regs->ARM_pc, &sc->arm_pc); /* security! */ -#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110) +#ifdef CONFIG_CPU_32 __get_user(regs->ARM_cpsr, &sc->arm_cpsr); /* security! */ #endif @@ -238,7 +238,7 @@ __put_user (regs->ARM_sp, &sc->arm_sp); __put_user (regs->ARM_lr, &sc->arm_lr); __put_user (regs->ARM_pc, &sc->arm_pc); /* security! */ -#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110) +#ifdef CONFIG_CPU_32 __put_user (regs->ARM_cpsr, &sc->arm_cpsr); /* security! */ #endif diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/sys_arm.c linux/arch/arm/kernel/sys_arm.c --- v2.1.100/linux/arch/arm/kernel/sys_arm.c Tue Jan 20 16:39:41 1998 +++ linux/arch/arm/kernel/sys_arm.c Fri May 8 00:42:38 1998 @@ -30,8 +30,6 @@ */ /* proc/system.h */ const char xchg_str[] = "xchg"; -/* arch/dma.h */ -const char dma_str[] = "%s: dma %d not supported\n"; /* * sys_pipe() is the normal C calling standard for creating diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c --- v2.1.100/linux/arch/arm/kernel/traps.c Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/kernel/traps.c Fri May 8 00:42:38 1998 @@ -49,7 +49,7 @@ static int verify_stack_pointer (unsigned long stackptr, int size) { -#if defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3) +#ifdef CONFIG_CPU_26 if (stackptr < 0x02048000 || stackptr + size > 0x03000000) return -EFAULT; #else @@ -90,38 +90,52 @@ #define VMALLOC_OFFSET (8*1024*1024) #define MODULE_RANGE (8*1024*1024) -static void dump_instr (unsigned long pc) +static void dump_instr(unsigned long pc, int user) { unsigned long module_start, module_end; int pmin = -2, pmax = 3, ok = 0; extern char start_kernel, _etext; - module_start = VMALLOC_START; - module_end = module_start + MODULE_RANGE; + if (!user) { + module_start = VMALLOC_START; + module_end = module_start + MODULE_RANGE; + + if ((pc >= (unsigned long) &start_kernel) && + (pc <= (unsigned long) &_etext)) { + if (pc + pmin < (unsigned long) &start_kernel) + pmin = ((unsigned long) &start_kernel) - pc; + if (pc + pmax > (unsigned long) &_etext) + pmax = ((unsigned long) &_etext) - pc; + ok = 1; + } else if (pc >= module_start && pc <= module_end) { + if (pc + pmin < module_start) + pmin = module_start - pc; + if (pc + pmax > module_end) + pmax = module_end - pc; + ok = 1; + } + } else + ok = verify_area(VERIFY_READ, (void *)(pc + pmin), pmax - pmin) == 0; - if ((pc >= (unsigned long) &start_kernel) && - (pc <= (unsigned long) &_etext)) { - if (pc + pmin < (unsigned long) &start_kernel) - pmin = ((unsigned long) &start_kernel) - pc; - if (pc + pmax > (unsigned long) &_etext) - pmax = ((unsigned long) &_etext) - pc; - ok = 1; - } else if (pc >= module_start && pc <= module_end) { - if (pc + pmin < module_start) - pmin = module_start - pc; - if (pc + pmax > module_end) - pmax = module_end - pc; - ok = 1; - } printk ("Code: "); if (ok) { int i; for (i = pmin; i < pmax; i++) - printk("%08lx ", ((unsigned long *)pc)[i]); + printk(i == 0 ? "(%08lx) " : "%08lx ", ((unsigned long *)pc)[i]); printk ("\n"); } else printk ("pc not in code space\n"); -} +} + +static void dump_state(char *str, struct pt_regs *regs, int err) +{ + console_verbose(); + printk("Internal error: %s: %x\n", str, err); + printk("CPU: %d\n", smp_processor_id()); + show_regs(regs); + printk("Process %s (pid: %d, stackpage=%08lx)\n", + current->comm, current->pid, 4096+(unsigned long)current); +} /* * This function is protected against kernel-mode re-entrancy. If it @@ -149,12 +163,7 @@ break; } - console_verbose(); - printk("Internal error: %s: %x\n", str, err); - printk("CPU: %d", smp_processor_id()); - show_regs(regs); - printk("Process %s (pid: %d, stackpage=%08lx)\n", - current->comm, current->pid, 4096+(unsigned long)current); + dump_state(str, regs, err); cstack = (unsigned long)(regs + 1); sstack = 4096+(unsigned long)current; @@ -180,7 +189,7 @@ } } - dump_instr(instruction_pointer(regs)); + dump_instr(instruction_pointer(regs), 0); died = 0; if (ret != -1) do_exit (ret); @@ -268,13 +277,13 @@ { switch (no) { case 0: /* branch through 0 */ - printk ("[%d] %s: branch through zero\n", current->pid, current->comm); - force_sig (SIGILL, current); - if (user_mode(regs)) { - show_regs (regs); - c_backtrace (regs->ARM_fp, processor_mode(regs)); - } - die_if_kernel ("Oops", regs, 0, SIGILL); + force_sig(SIGSEGV, current); +// if (user_mode(regs)) { +// dump_state("branch through zero", regs, 0); +// if (regs->ARM_fp) +// c_backtrace (regs->ARM_fp, processor_mode(regs)); +// } + die_if_kernel ("branch through zero", regs, 0, SIGSEGV); break; case 1: /* SWI_BREAK_POINT */ @@ -297,8 +306,7 @@ asmlinkage void deferred(int n, struct pt_regs *regs) { - printk ("[%d] %s: old system call %X\n", current->pid, current->comm, n); - show_regs (regs); + dump_state("old system call", regs, 0); force_sig (SIGILL, current); } @@ -312,3 +320,37 @@ printk ("Invalid pointer size in %s (PC=%p) size %d\n", function, __builtin_return_address(0), size); } + +#ifdef CONFIG_CPU_26 +asmlinkage void baddataabort(int code, unsigned long instr, struct pt_regs *regs) +{ + unsigned long phys, addr = instruction_pointer(regs); + +#ifdef CONFIG_DEBUG_ERRORS + printk("pid=%d\n", current->pid); + + show_regs(regs); + dump_instr(instruction_pointer(regs), 1); + { + pgd_t *pgd; + + printk ("current->tss.memmap = %08lX\n", current->tss.memmap); + pgd = pgd_offset(current->mm, addr); + printk ("*pgd = %08lx", pgd_val (*pgd)); + if (!pgd_none (*pgd)) { + pmd_t *pmd; + pmd = pmd_offset (pgd, addr); + printk (", *pmd = %08lx", pmd_val (*pmd)); + if (!pmd_none (*pmd)) { + unsigned long ptr = pte_page(*pte_offset(pmd, addr)); + printk (", *pte = %08lx", pte_val (*pte_offset (pmd, addr))); + phys = ptr + (addr & 0x7fff); + } + } + printk ("\n"); + } +#endif + panic("unknown data abort code %d [pc=%08lx *pc=%08lx lr=%08lx sp=%08lx]", + code, regs->ARM_pc, instr, regs->ARM_lr, regs->ARM_sp); +} +#endif diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile --- v2.1.100/linux/arch/arm/lib/Makefile Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/lib/Makefile Fri May 8 00:42:38 1998 @@ -6,7 +6,7 @@ L_TARGET := lib.a L_OBJS := backtrace.o bitops.o checksum.o delay.o fp_support.o \ - loaders.o memcpy.o memfastset.o system.o string.o uaccess.o + loaders.o memcpy.o system.o string.o uaccess.o ifeq ($(PROCESSOR),armo) L_OBJS += uaccess-armo.o @@ -37,6 +37,8 @@ getconsdata.o: getconsdata.c $(CC) $(CFLAGS) -c getconsdata.c + +checksum.o: constants.h %.o: %.S ifneq ($(CONFIG_BINUTILS_NEW),y) diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/backtrace.S linux/arch/arm/lib/backtrace.S --- v2.1.100/linux/arch/arm/lib/backtrace.S Tue Jan 20 16:39:41 1998 +++ linux/arch/arm/lib/backtrace.S Fri May 8 00:42:38 1998 @@ -3,6 +3,7 @@ * * Copyright (C) 1995, 1996 Russell King */ +#include #include #include .text @@ -21,9 +22,13 @@ ENTRY(c_backtrace) stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location... +#ifdef CONFIG_CPU_32 tst r1, #0x10 @ 26 or 32-bit? moveq mask, #0xfc000003 movne mask, #0 +#else + mov mask, #0xfc000003 +#endif tst mask, r0 movne r0, #0 movs frame, r0 diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/checksum.S linux/arch/arm/lib/checksum.S --- v2.1.100/linux/arch/arm/lib/checksum.S Tue Jan 20 16:39:41 1998 +++ linux/arch/arm/lib/checksum.S Fri May 8 00:42:38 1998 @@ -3,9 +3,11 @@ * * Copyright (C) 1995, 1996, 1997, 1998 Russell King */ +#include #include #include #include +#include "constants.h" .text @@ -66,25 +68,147 @@ * Params : r0 = src, r1 = dst, r2 = len, r3 = sum, [sp, #0] = &err * Returns : r0 = checksum, [[sp, #0], #0] = 0 or -EFAULT */ +#if defined(CONFIG_CPU_32) -#define USER_LDR(instr...) \ -9999: instr; \ - .section __ex_table, "a"; \ - .align 3; \ - .long 9999b, 6001f; \ - .previous; + .macro save_regs + stmfd sp!, {r4 - r8, fp, ip, lr, pc} + .endm + +#define LOAD_REGS(cond) \ + LOADREGS(##cond##ea,fp,{r4 - r8, fp, sp, pc}) + + .macro load1b, reg1 +9999: ldrbt \reg1, [r0], $1 + .section __ex_table, "a" + .align 3 + .long 9999b, 6001f + .previous + .endm + + .macro load2b, reg1, reg2 +9999: ldrbt \reg1, [r0], $1 +9998: ldrbt \reg2, [r0], $1 + .section __ex_table, "a" + .long 9999b, 6001f + .long 9998b, 6001f + .previous + .endm + + .macro load1l, reg1 +9999: ldrt \reg1, [r0], $4 + .section __ex_table, "a" + .align 3 + .long 9999b, 6001f + .previous + .endm + + .macro load2l, reg1, reg2 +9999: ldrt \reg1, [r0], $4 +9998: ldrt \reg2, [r0], $4 + .section __ex_table, "a" + .long 9999b, 6001f + .long 9998b, 6001f + .previous + .endm + + .macro load4l, reg1, reg2, reg3, reg4 +9999: ldrt \reg1, [r0], $4 +9998: ldrt \reg2, [r0], $4 +9997: ldrt \reg3, [r0], $4 +9996: ldrt \reg4, [r0], $4 + .section __ex_table, "a" + .long 9999b, 6001f + .long 9998b, 6001f + .long 9997b, 6001f + .long 9996b, 6001f + .previous + .endm + +#elif defined(CONFIG_CPU_26) + + .macro save_regs + stmfd sp!, {r4 - r9, fp, ip, lr, pc} + mov r9, sp, lsr #13 + mov r9, r9, lsl #13 + ldr r9, [r9, #TSK_ADDR_LIMIT] + mov r9, r9, lsr #24 + .endm + +#define LOAD_REGS(cond) \ + LOADREGS(##cond##ea,fp,{r4 - r9, fp, sp, pc}) + + .macro load1b, reg1 + tst r9, #0x01 +9999: ldreqbt \reg1, [r0], #1 + ldrneb \reg1, [r0], #1 + .section __ex_table, "a" + .align 3 + .long 9999b, 6001f + .previous + .endm + + .macro load2b, reg1, reg2 + tst r9, #0x01 +9999: ldreqbt \reg1, [r0], #1 + ldrneb \reg1, [r0], #1 +9998: ldreqbt \reg2, [r0], #1 + ldrneb \reg2, [r0], #1 + .section __ex_table, "a" + .long 9999b, 6001f + .long 9998b, 6001f + .previous + .endm + + .macro load1l, reg1 + tst r9, #0x01 +9999: ldreqt \reg1, [r0], #4 + ldrne \reg1, [r0], #4 + .section __ex_table, "a" + .align 3 + .long 9999b, 6001f + .previous + .endm + + .macro load2l, reg1, reg2 + tst r9, #0x01 + ldmneia r0!, {\reg1, \reg2} +9999: ldreqt \reg1, [r0], #4 +9998: ldreqt \reg2, [r0], #4 + .section __ex_table, "a" + .long 9999b, 6001f + .long 9998b, 6001f + .previous + .endm + + .macro load4l, reg1, reg2, reg3, reg4 + tst r9, #0x01 + ldmneia r0!, {\reg1, \reg2, \reg3, \reg4} +9999: ldreqt \reg1, [r0], #4 +9998: ldreqt \reg2, [r0], #4 +9997: ldreqt \reg3, [r0], #4 +9996: ldreqt \reg4, [r0], #4 + .section __ex_table, "a" + .long 9999b, 6001f + .long 9998b, 6001f + .long 9997b, 6001f + .long 9996b, 6001f + .previous + .endm + +#else +#error Unknown CPU architecture +#endif ENTRY(csum_partial_copy_from_user) mov ip, sp - stmfd sp!, {r4 - r8, fp, ip, lr, pc} + save_regs sub fp, ip, #4 cmp r2, #4 blt .too_small_user tst r1, #2 @ Test destination alignment beq .dst_aligned_user subs r2, r2, #2 @ We dont know if SRC is aligned... -USER_LDR( ldrbt ip, [r0], #1) -USER_LDR( ldrbt r8, [r0], #1) + load2b ip, r8 orr ip, ip, r8, lsl #8 adds r3, r3, ip adcs r3, r3, #0 @@ -97,11 +221,7 @@ adds r3, r3, #0 bics ip, r2, #15 @ Routine for src & dst aligned beq 2f -1: -USER_LDR( ldrt r4, [r0], #4) -USER_LDR( ldrt r5, [r0], #4) -USER_LDR( ldrt r6, [r0], #4) -USER_LDR( ldrt r7, [r0], #4) +1: load4l r4, r5, r6, r7 stmia r1!, {r4, r5, r6, r7} adcs r3, r3, r4 adcs r3, r3, r5 @@ -114,21 +234,19 @@ beq 4f tst ip, #8 beq 3f -USER_LDR( ldrt r4, [r0], #4) -USER_LDR( ldrt r5, [r0], #4) + load2l r4, r5 stmia r1!, {r4, r5} adcs r3, r3, r4 adcs r3, r3, r5 tst ip, #4 beq 4f -3: -USER_LDR( ldrt r4, [r0], #4) +3: load1l r4 str r4, [r1], #4 adcs r3, r3, r4 4: ands r2, r2, #3 adceq r0, r3, #0 - LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) -USER_LDR( ldrt r4, [r0], #4) + LOAD_REGS(eq) + load1l r4 tst r2, #2 beq .exit adcs r3, r3, r4, lsl #16 @@ -141,33 +259,33 @@ andne r4, r4, #255 adcnes r3, r3, r4 adcs r0, r3, #0 - LOADREGS(ea,fp,{r4 - r8, fp, sp, pc}) + LOAD_REGS(al) .too_small_user: teq r2, #0 - LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + LOAD_REGS(eq) cmp r2, #2 blt .too_small_user1 -USER_LDR( ldrbt ip, [r0], #1) -USER_LDR( ldrbt r8, [r0], #1) + load2b ip, r8 orr ip, ip, r8, lsl #8 adds r3, r3, ip strb ip, [r1], #1 strb r8, [r1], #1 tst r2, #1 -.too_small_user1: -USER_LDR( ldrnebt ip, [r0], #1) - strneb ip, [r1], #1 - adcnes r3, r3, ip - adcs r0, r3, #0 - LOADREGS(ea,fp,{r4 - r8, fp, sp, pc}) +.too_small_user1: @ C = 0 + beq .csum_exit + load1b ip + strb ip, [r1], #1 + adcs r3, r3, ip +.csum_exit: adc r0, r3, #0 + LOAD_REGS(al) .src_not_aligned_user: cmp r2, #4 blt .too_small_user and ip, r0, #3 bic r0, r0, #3 -USER_LDR( ldrt r4, [r0], #4) + load1l r4 cmp ip, #2 beq .src2_aligned_user bhi .src3_aligned_user @@ -175,11 +293,7 @@ adds r3, r3, #0 bics ip, r2, #15 beq 2f -1: -USER_LDR( ldrt r5, [r0], #4) -USER_LDR( ldrt r6, [r0], #4) -USER_LDR( ldrt r7, [r0], #4) -USER_LDR( ldrt r8, [r0], #4) +1: load4l r5, r6, r7, r8 orr r4, r4, r5, lsl #24 mov r5, r5, lsr #8 orr r5, r5, r6, lsl #24 @@ -200,8 +314,7 @@ beq 4f tst ip, #8 beq 3f -USER_LDR( ldrt r5, [r0], #4) -USER_LDR( ldrt r6, [r0], #4) + load2l r5, r6 orr r4, r4, r5, lsl #24 mov r5, r5, lsr #8 orr r5, r5, r6, lsl #24 @@ -211,15 +324,14 @@ mov r4, r6, lsr #8 tst ip, #4 beq 4f -3: -USER_LDR( ldrt r5, [r0], #4) +3: load1l r5 orr r4, r4, r5, lsl #24 str r4, [r1], #4 adcs r3, r3, r4 mov r4, r5, lsr #8 4: ands r2, r2, #3 adceq r0, r3, #0 - LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + LOAD_REGS(eq) tst r2, #2 beq .exit adcs r3, r3, r4, lsl #16 @@ -234,11 +346,7 @@ adds r3, r3, #0 bics ip, r2, #15 beq 2f -1: -USER_LDR( ldrt r5, [r0], #4) -USER_LDR( ldrt r6, [r0], #4) -USER_LDR( ldrt r7, [r0], #4) -USER_LDR( ldrt r8, [r0], #4) +1: load4l r5, r6, r7, r8 orr r4, r4, r5, lsl #16 mov r5, r5, lsr #16 orr r5, r5, r6, lsl #16 @@ -259,8 +367,7 @@ beq 4f tst ip, #8 beq 3f -USER_LDR( ldrt r5, [r0], #4) -USER_LDR( ldrt r6, [r0], #4) + load2l r5, r6 orr r4, r4, r5, lsl #16 mov r5, r5, lsr #16 orr r5, r5, r6, lsl #16 @@ -270,22 +377,21 @@ mov r4, r6, lsr #16 tst ip, #4 beq 4f -3: -USER_LDR( ldrt r5, [r0], #4) +3: load1l r5 orr r4, r4, r5, lsl #16 str r4, [r1], #4 adcs r3, r3, r4 mov r4, r5, lsr #16 4: ands r2, r2, #3 adceq r0, r3, #0 - LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + LOAD_REGS(eq) tst r2, #2 beq .exit adcs r3, r3, r4, lsl #16 strb r4, [r1], #1 mov r4, r4, lsr #8 strb r4, [r1], #1 -USER_LDR( ldrb r4, [r0], #1) + load1b r4 b .exit .src3_aligned_user: @@ -293,11 +399,7 @@ adds r3, r3, #0 bics ip, r2, #15 beq 2f -1: -USER_LDR( ldrt r5, [r0], #4) -USER_LDR( ldrt r6, [r0], #4) -USER_LDR( ldrt r7, [r0], #4) -USER_LDR( ldrt r8, [r0], #4) +1: load4l r5, r6, r7, r8 orr r4, r4, r5, lsl #8 mov r5, r5, lsr #24 orr r5, r5, r6, lsl #8 @@ -318,8 +420,7 @@ beq 4f tst ip, #8 beq 3f -USER_LDR( ldrt r5, [r0], #4) -USER_LDR( ldrt r6, [r0], #4) + load2l r5, r6 orr r4, r4, r5, lsl #8 mov r5, r5, lsr #24 orr r5, r5, r6, lsl #8 @@ -329,20 +430,19 @@ mov r4, r6, lsr #24 tst ip, #4 beq 4f -3: -USER_LDR( ldrt r5, [r0], #4) +3: load1l r5 orr r4, r4, r5, lsl #8 str r4, [r1], #4 adcs r3, r3, r4 mov r4, r5, lsr #24 4: ands r2, r2, #3 adceq r0, r3, #0 - LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + LOAD_REGS(eq) tst r2, #2 beq .exit adcs r3, r3, r4, lsl #16 strb r4, [r1], #1 -USER_LDR( ldrt r4, [r0], #4) + load1l r4 strb r4, [r1], #1 adcs r3, r3, r4, lsl #24 mov r4, r4, lsr #8 @@ -351,14 +451,16 @@ .section .fixup,"ax" .align 4 6001: mov r4, #-EFAULT - ldr r5, [sp, #4*8] + ldr r5, [fp, #4] str r4, [r5] - LOADREGS(ea,fp,{r4 - r8, fp, sp, pc}) + LOAD_REGS(al) + .previous /* Function: __u32 csum_partial_copy (const char *src, char *dst, int len, __u32 sum) * Params : r0 = src, r1 = dst, r2 = len, r3 = checksum * Returns : r0 = new checksum */ +ENTRY(csum_partial_copy_nocheck) ENTRY(csum_partial_copy) mov ip, sp stmfd sp!, {r4 - r8, fp, ip, lr, pc} @@ -598,3 +700,21 @@ adcs r3, r3, r4, lsl #24 mov r4, r4, lsr #8 b Lexit + +ENTRY(csum_ipv6_magic) + stmfd sp!, {lr} + adds ip, r2, r3 + ldmia r1, {r1 - r3, lr} + adcs ip, ip, r1 + adcs ip, ip, r2 + adcs ip, ip, r3 + adcs ip, ip, lr + ldmia r0, {r0 - r3} + adcs r0, ip, r0 + adcs r0, r0, r1 + adcs r0, r0, r2 + adcs r0, r0, r3 + ldr r3, [sp, #4] + adcs r0, r0, r3 + adcs r0, r0, #0 + LOADREGS(fd, sp!, {pc}) diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/extractconstants.pl linux/arch/arm/lib/extractconstants.pl --- v2.1.100/linux/arch/arm/lib/extractconstants.pl Tue Apr 14 14:29:19 1998 +++ linux/arch/arm/lib/extractconstants.pl Fri May 8 00:42:38 1998 @@ -34,7 +34,7 @@ if ($elf) { chomp; $addr = substr ($_, 0, 8); - $name = substr ($_, 32); + $name = substr ($_, rindex($_, " ") + 1); $nam[hex($addr)] = $name; } } diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/extractinfo.perl linux/arch/arm/lib/extractinfo.perl --- v2.1.100/linux/arch/arm/lib/extractinfo.perl Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/extractinfo.perl Fri May 8 00:42:38 1998 @@ -0,0 +1,45 @@ +#!/usr/bin/perl + +$OBJDUMP=$ARGV[0]; + +sub swapdata { + local ($num) = @_; + + return substr($num, 6, 2).substr($num, 4, 2).substr ($num, 2, 2).substr ($num, 0, 2); +} + +open (DATA, $OBJDUMP.' --full-contents --section=.data getconsdata.o | grep \'^ 00\' |') || + die ('Cant objdump!'); +while () { + ($addr, $data0, $data1, $data2, $data3) = split (' '); + $dat[hex($addr)] = hex(&swapdata($data0)); + $dat[hex($addr)+4] = hex(&swapdata($data1)); + $dat[hex($addr)+8] = hex(&swapdata($data2)); + $dat[hex($addr)+12] = hex(&swapdata($data3)); +} +close (DATA); + +open (DATA, $OBJDUMP.' --syms getconsdata.o |') || die ('Cant objdump!'); +while () { + /elf32/ && ( $elf = 1 ); + /a.out/ && ( $aout = 1 ); + next if ($aout && ! / 07 /); + next if ($elf && ! (/^00...... g/ && /.data/)); + next if (!$aout && !$elf); + + ($addr, $flags, $sect, $a1, $a2, $a3, $name) = split (' ') if $aout; + $nam[hex($addr)] = substr($name, 1) if $aout; + if ($elf) { + chomp; + $addr = substr ($_, 0, 8); + $name = substr ($_, 32); + $nam[hex($addr)] = $name; + } +} +close (DATA); + +print "/*\n * *** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT! ***\n */\n"; +for ($i = 0; $i < hex($addr)+12; $i ++) { + print "unsigned long $nam[$i] = $dat[$i];\n" if $dat[$i]; + print "#define __HAS_$nam[$i]\n" if $dat[$i]; +} diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/getconsdata.c linux/arch/arm/lib/getconsdata.c --- v2.1.100/linux/arch/arm/lib/getconsdata.c Tue Apr 14 14:29:20 1998 +++ linux/arch/arm/lib/getconsdata.c Fri May 8 00:42:38 1998 @@ -10,6 +10,8 @@ #include #include +#undef PAGE_READONLY + #define OFF_TSK(n) (unsigned long)&(((struct task_struct *)0)->n) #define OFF_MM(n) (unsigned long)&(((struct mm_struct *)0)->n) @@ -31,7 +33,7 @@ unsigned long TSS_MEMMAP = OFF_TSK(tss.memmap); unsigned long TSS_SAVE = OFF_TSK(tss.save); unsigned long TSS_FPESAVE = OFF_TSK(tss.fpstate.soft.save); -#if defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3) +#ifdef CONFIG_CPU_26 unsigned long TSS_MEMCMAP = OFF_TSK(tss.memcmap); #endif diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/getconstants.c linux/arch/arm/lib/getconstants.c --- v2.1.100/linux/arch/arm/lib/getconstants.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/getconstants.c Fri May 8 00:42:38 1998 @@ -0,0 +1,74 @@ +/* + * linux/arch/arm/lib/getconstants.c + * + * Copyright (C) 1995, 1996 Russell King + */ + +#include +#include +#include +#include + +void printdef(char *def, int no) +{ + printf("#define %s\t%d\n", def, no); +} + +#include "getconstants.h" + +int main() +{ + printf("/*\n * contants.h generated by getconstants\n * DO NOT EDIT!\n */\n"); + + printf("#define _current\t_%s\n", "current_set"); + +#ifdef _PAGE_PRESENT + printdef("PAGE_PRESENT", _PAGE_PRESENT); +#endif +#ifdef _PAGE_RW + printdef("PAGE_RW", _PAGE_RW); +#endif +#ifdef _PAGE_USER + printdef("PAGE_USER", _PAGE_USER); +#endif +#ifdef _PAGE_ACCESSED + printdef("PAGE_ACCESSED", _PAGE_ACCESSED); +#endif +#ifdef _PAGE_DIRTY + printdef("PAGE_DIRTY", _PAGE_DIRTY); +#endif +#ifdef _PAGE_READONLY + printdef("PAGE_READONLY", _PAGE_READONLY); +#endif +#ifdef _PAGE_NOT_USER + printdef("PAGE_NOT_USER", _PAGE_NOT_USER); +#endif +#ifdef _PAGE_OLD + printdef("PAGE_OLD", _PAGE_OLD); +#endif +#ifdef _PAGE_CLEAN + printdef("PAGE_CLEAN", _PAGE_CLEAN); +#endif + printdef("TSS_MEMMAP", (int)tss_memmap); + printdef("TSS_SAVE", (int)tss_save); +#ifdef __HAS_tss_memcmap + printdef("TSS_MEMCMAP", (int)tss_memcmap); +#endif +#ifdef __HAS_addr_limit + printdef("ADDR_LIMIT", (int)addr_limit); +#endif +#ifdef __HAS_kernel_domain + printdef("KERNEL_DOMAIN", kernel_domain); +#endif +#ifdef __HAS_user_domain + printdef("USER_DOMAIN", user_domain); +#endif + printdef("TSS_FPESAVE", (int)tss_fpesave); + printdef("MM", (int)mm); + printdef("PGD", (int)pgd); + + printf("#define KSWI_BASE 0x900000\n"); + printf("#define KSWI_SYS_BASE 0x9F0000\n"); + printf("#define SYS_ERROR0 0x9F0000\n"); + return 0; +} diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/getconstants.h linux/arch/arm/lib/getconstants.h --- v2.1.100/linux/arch/arm/lib/getconstants.h Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/getconstants.h Fri May 8 00:42:38 1998 @@ -0,0 +1,17 @@ +/* + * *** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT! *** + */ +unsigned long addr_limit = 56; +#define __HAS_addr_limit +unsigned long tss_memmap = 640; +#define __HAS_tss_memmap +unsigned long mm = 1676; +#define __HAS_mm +unsigned long pgd = 8; +#define __HAS_pgd +unsigned long tss_save = 636; +#define __HAS_tss_save +unsigned long tss_fpesave = 492; +#define __HAS_tss_fpesave +unsigned long tss_memcmap = 644; +#define __HAS_tss_memcmap diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/io-acorn.S linux/arch/arm/lib/io-acorn.S --- v2.1.100/linux/arch/arm/lib/io-acorn.S Tue Apr 14 14:29:20 1998 +++ linux/arch/arm/lib/io-acorn.S Fri May 8 00:42:38 1998 @@ -3,7 +3,7 @@ * * Copyright (C) 1995, 1996 Russell King */ -#include /* for CONFIG_CPU_ARM2 and CONFIG_CPU_ARM3 */ +#include /* for CONFIG_CPU_nn */ #include #include #include @@ -171,7 +171,7 @@ @ Proto : void memc_write(int register, int value); @ Returns: nothing -#if defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3) +#if defined(CONFIG_CPU_26) ENTRY(memc_write) cmp r0, #7 RETINSTR(movgt,pc,lr) diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/io-ebsa285.S linux/arch/arm/lib/io-ebsa285.S --- v2.1.100/linux/arch/arm/lib/io-ebsa285.S Tue Apr 14 14:29:20 1998 +++ linux/arch/arm/lib/io-ebsa285.S Fri May 8 00:42:38 1998 @@ -1,4 +1,3 @@ -#define __ASSEMBLER__ #include ENTRY(insl) diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/ll_char_wr.S linux/arch/arm/lib/ll_char_wr.S --- v2.1.100/linux/arch/arm/lib/ll_char_wr.S Tue Apr 14 14:29:20 1998 +++ linux/arch/arm/lib/ll_char_wr.S Fri May 8 00:42:38 1998 @@ -100,13 +100,13 @@ Lrow8bpplp: mov ip, r7, lsr #4 ldr ip, [lr, ip, lsl #2] mul r4, r2, ip - and ip, r7, #15 - eor r4, r3, r4 - ldr ip, [lr, ip, lsl #2] - mul ip, r2, ip - tst r1, #7 + and ip, r7, #15 @ avoid r4 + ldr ip, [lr, ip, lsl #2] @ avoid r4 + mul ip, r2, ip @ avoid r4 + eor r4, r3, r4 @ avoid ip + tst r1, #7 @ avoid ip + sub r0, r0, r5 @ avoid ip eor ip, r3, ip - sub r0, r0, r5 stmia r0, {r4, ip} LOADREGS(eqfd, sp!, {r4 - r7, pc}) sub r1, r1, #1 @@ -114,13 +114,13 @@ mov ip, r7, lsr #4 ldr ip, [lr, ip, lsl #2] mul r4, r2, ip - and ip, r7, #15 - eor r4, r3, r4 - ldr ip, [lr, ip, lsl #2] - mul ip, r2, ip - tst r1, #7 + and ip, r7, #15 @ avoid r4 + ldr ip, [lr, ip, lsl #2] @ avoid r4 + mul ip, r2, ip @ avoid r4 + eor r4, r3, r4 @ avoid ip + tst r1, #7 @ avoid ip + sub r0, r0, r5 @ avoid ip eor ip, r3, ip - sub r0, r0, r5 stmia r0, {r4, ip} subne r1, r1, #1 ldrneb r7, [r6, r1] diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/memfastset.S linux/arch/arm/lib/memfastset.S --- v2.1.100/linux/arch/arm/lib/memfastset.S Tue Jan 20 16:39:42 1998 +++ linux/arch/arm/lib/memfastset.S Wed Dec 31 16:00:00 1969 @@ -1,35 +0,0 @@ -/* - * linux/arch/arm/lib/memfastset.S - * - * Copyright (C) 1995, 1996 Russell King - */ -#include -#include - .text -@ Prototype: void memsetl (unsigned long *d, unsigned long c, size_t n); - -ENTRY(memsetl) - stmfd sp!, {lr} - cmp r2, #16 - blt 5f - mov r3, r1 - mov ip, r1 - mov lr, r1 - subs r2, r2, #32 - bmi 2f -1: stmia r0!, {r1, r3, ip, lr} - stmia r0!, {r1, r3, ip, lr} - LOADREGS(eqfd, sp!, {pc}) - subs r2, r2, #32 - bpl 1b -2: adds r2, r2, #16 - bmi 4f -3: stmia r0!, {r1, r3, ip, lr} - LOADREGS(eqfd, sp!, {pc}) - subs r2, r2, #16 - bpl 3b -4: add r2, r2, #16 -5: subs r2, r2, #4 - strge r1, [r0], #4 - bgt 5b - LOADREGS(fd, sp!, {pc}) diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/string.S linux/arch/arm/lib/string.S --- v2.1.100/linux/arch/arm/lib/string.S Tue Jan 20 16:39:42 1998 +++ linux/arch/arm/lib/string.S Fri May 8 00:42:38 1998 @@ -1,24 +1,55 @@ /* * linux/arch/arm/lib/string.S * - * Copyright (C) 1995, 1996 Russell King + * Copyright (C) 1995-1998 Russell King + * + * This is commonly used to clear the frame buffer and the frame + * backing buffer. As such, it will be rarely called with r2 < 32. + * + * Optimisations by Matthew Wilcox */ #include #include .text # Prototype: char *strrchr(const char *s,char c); -@ r0 = pointer, r1 = length - .global memzero -memzero: stmfd sp!, {lr} - mov r2, #0 - mov r3, #0 - mov ip, #0 - mov lr, #0 -1: subs r1, r1, #4*8 - stmgeia r0!, {r2, r3, ip, lr} - stmgeia r0!, {r2, r3, ip, lr} +/* + * Prototype: void memzero(void *d, size_t n) + */ +ENTRY(memzero) + mov r2, r1 + mov r1, #0 +/* + * Prototype: void memsetl(unsigned long *d, unsigned long c, size_t n) + */ +ENTRY(memsetl) + teq r2, #0 + RETINSTR(moveq,pc,lr) + stmfd sp!, {lr} + mov lr, r1 + mov r3, r1 + mov ip, r1 + + @ r2 = {32 ... 4} + +1: subs r2, r2, #32 + stmgeia r0!, {r1, r3, ip, lr} + stmgeia r0!, {r1, r3, ip, lr} bgt 1b + LOADREGS(eqfd, sp!, {pc}) + + @ r2 can be {-4 ... -28} + + cmp r2, #-16 + stmgeia r0!, {r1, r3, ip, lr} + addlts r2, r2, #16 + LOADREGS(eqfd, sp!, {pc}) + + @ r2 can be {-4 ... -12} + + cmp r2, #-8 + stmgeia r0!, {r1, r3} + strne r1, [r0] LOADREGS(fd, sp!, {pc}) .global __page_memcpy diff -u --recursive --new-file v2.1.100/linux/arch/arm/mm/Makefile linux/arch/arm/mm/Makefile --- v2.1.100/linux/arch/arm/mm/Makefile Tue Apr 14 14:29:20 1998 +++ linux/arch/arm/mm/Makefile Fri May 8 00:42:38 1998 @@ -7,6 +7,7 @@ # # Note 2! The CFLAGS definition is now in the main makefile... +all: lib first_rule ifeq ($(MACHINE),a5k) MMARCH=arc else @@ -30,13 +31,14 @@ proc-arm6,7.o: ../lib/constants.h proc-sa110.o: ../lib/constants.h -.PHONY: ../lib/constants.h -../lib/constants.h: - @$(MAKE) -C ../lib constants.h - -ifneq ($(CONFIG_BINUTILS_NEW),y) %.o: %.S +ifneq ($(CONFIG_BINUTILS_NEW),y) $(CC) $(CFLAGS) -D__ASSEMBLY__ -E $< | tr ';$$' '\n#' > ..$@.tmp.s $(CC) $(CFLAGS:-pipe=) -c -o $@ ..$@.tmp.s $(RM) ..$@.tmp.s +else + $(CC) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $< endif + +.PHONY: lib +lib:; @$(MAKE) -C ../lib constants.h diff -u --recursive --new-file v2.1.100/linux/arch/arm/mm/fault-armo.c linux/arch/arm/mm/fault-armo.c --- v2.1.100/linux/arch/arm/mm/fault-armo.c Wed Apr 8 19:36:24 1998 +++ linux/arch/arm/mm/fault-armo.c Fri May 8 00:42:38 1998 @@ -27,11 +27,25 @@ #define FAULT_CODE_WRITE 0x02 #define FAULT_CODE_USER 0x01 +#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) + struct pgtable_cache_struct quicklists; -void __bad_pte(pmd_t *pmd) +void __bad_pmd(pmd_t *pmd) { printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); +#ifdef CONFIG_DEBUG_ERRORS + __backtrace(); +#endif + set_pmd(pmd, mk_pmd(BAD_PAGETABLE)); +} + +void __bad_pmd_kernel(pmd_t *pmd) +{ + printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd)); +#ifdef CONFIG_DEBUG_ERRORS + __backtrace(); +#endif set_pmd(pmd, mk_pmd(BAD_PAGETABLE)); } @@ -65,7 +79,7 @@ } kfree (pte); if (pmd_bad(*pmd)) { - __bad_pte(pmd); + __bad_pmd(pmd); return NULL; } return (pte_t *) pmd_page(*pmd) + offset; @@ -145,11 +159,11 @@ bad_area: up(&mm->mmap_sem); if (mode & FAULT_CODE_USER) { -extern int console_loglevel; -cli(); +//extern int console_loglevel; +//cli(); tsk->tss.error_code = mode; tsk->tss.trap_no = 14; -console_loglevel = 9; +//console_loglevel = 9; printk ("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n", tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode); //#ifdef DEBUG @@ -157,7 +171,7 @@ c_backtrace (regs->ARM_fp, 0); //#endif force_sig(SIGSEGV, tsk); -while (1); +//while (1); goto out; } diff -u --recursive --new-file v2.1.100/linux/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c --- v2.1.100/linux/arch/arm/mm/fault-armv.c Tue Apr 14 14:29:20 1998 +++ linux/arch/arm/mm/fault-armv.c Fri May 8 00:42:38 1998 @@ -25,6 +25,8 @@ #define FAULT_CODE_READ 0x02 #define FAULT_CODE_USER 0x01 +#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) + struct pgtable_cache_struct quicklists; void __bad_pmd(pmd_t *pmd) diff -u --recursive --new-file v2.1.100/linux/arch/arm/mm/init.c linux/arch/arm/mm/init.c --- v2.1.100/linux/arch/arm/mm/init.c Tue Apr 14 14:29:20 1998 +++ linux/arch/arm/mm/init.c Fri May 8 00:42:38 1998 @@ -119,10 +119,10 @@ memzero (empty_zero_page, PAGE_SIZE); start_mem = setup_pagetables (start_mem, end_mem); - flush_tlb_all (); - update_mm_cache_all (); + flush_tlb_all(); + update_memc_all(); - return free_area_init (start_mem, end_mem); + return free_area_init(start_mem, end_mem); } /* diff -u --recursive --new-file v2.1.100/linux/arch/arm/mm/mm-a5k.c linux/arch/arm/mm/mm-a5k.c --- v2.1.100/linux/arch/arm/mm/mm-a5k.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mm/mm-a5k.c Fri May 8 00:42:38 1998 @@ -0,0 +1,7 @@ +/* + * arch/arm/mm/mm-a5k.c + * + * Extra MM routines for the Archimedes architecture + * + * Copyright (C) 1998 Russell King + */ diff -u --recursive --new-file v2.1.100/linux/arch/arm/mm/mm-arc.c linux/arch/arm/mm/mm-arc.c --- v2.1.100/linux/arch/arm/mm/mm-arc.c Tue Apr 14 14:29:20 1998 +++ linux/arch/arm/mm/mm-arc.c Fri May 8 00:42:38 1998 @@ -5,4 +5,78 @@ * * Copyright (C) 1998 Russell King */ -#include +#include +#include + +unsigned long phys_screen_end; + +/* + * This routine needs more work to make it dynamically release/allocate mem! + */ +unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update) +{ + static int updated = 0; + + if (updated) + return 0; + + updated = update; + + if (update) { + unsigned long address = log_start, offset; + pgd_t *pgdp; + + kmem = (kmem + 3) & ~3; + + pgdp = pgd_offset (&init_mm, address); /* +31 */ + offset = SCREEN_START; + while (address < SCREEN1_END) { + unsigned long addr_pmd, end_pmd; + pmd_t *pmdp; + + /* if (pgd_none (*pgdp)) alloc pmd */ + pmdp = pmd_offset (pgdp, address); /* +0 */ + addr_pmd = address & ~PGDIR_MASK; /* 088000 */ + end_pmd = addr_pmd + SCREEN1_END - address; /* 100000 */ + if (end_pmd > PGDIR_SIZE) + end_pmd = PGDIR_SIZE; + + do { + unsigned long addr_pte, end_pte; + pte_t *ptep; + + if (pmd_none (*pmdp)) { + pte_t *new_pte = (pte_t *)kmem; + kmem += PTRS_PER_PTE * BYTES_PER_PTR; + memzero (new_pte, PTRS_PER_PTE * BYTES_PER_PTR); + set_pmd (pmdp, mk_pmd(new_pte)); + } + + ptep = pte_offset (pmdp, addr_pmd); /* +11 */ + addr_pte = addr_pmd & ~PMD_MASK; /* 088000 */ + end_pte = addr_pte + end_pmd - addr_pmd; /* 100000 */ + if (end_pte > PMD_SIZE) + end_pte = PMD_SIZE; + + do { + set_pte (ptep, mk_pte(offset, PAGE_KERNEL)); + addr_pte += PAGE_SIZE; + offset += PAGE_SIZE; + ptep++; + } while (addr_pte < end_pte); + + pmdp++; + addr_pmd = (addr_pmd + PMD_SIZE) & PMD_MASK; + } while (addr_pmd < end_pmd); + + address = (address + PGDIR_SIZE) & PGDIR_MASK; + pgdp ++; + } + + phys_screen_end = offset; + flush_tlb_all (); + update_mm_cache_all (); + } + return kmem; +} + diff -u --recursive --new-file v2.1.100/linux/arch/arm/mm/proc-arm2,3.S linux/arch/arm/mm/proc-arm2,3.S --- v2.1.100/linux/arch/arm/mm/proc-arm2,3.S Tue Jan 20 16:39:42 1998 +++ linux/arch/arm/mm/proc-arm2,3.S Fri May 8 00:42:38 1998 @@ -383,13 +383,13 @@ mov r0, #0x001f0000 orr r0, r0, #0x0000ff00 orr r0, r0, #0x000000ff - mcr p15, 0, r0, c3, c0 - mcr p15, 0, r0, c4, c0 + mcr p15, 0, r0, c3, c0 @ ARM3 Cacheable + mcr p15, 0, r0, c4, c0 @ ARM3 Updateable mov r0, #0 - mcr p15, 0, r0, c5, c0 + mcr p15, 0, r0, c5, c0 @ ARM3 Disruptive + mcr p15, 0, r0, c1, c0 @ ARM3 Flush mov r0, #3 - mcr p15, 0, r0, c1, c0 - mcr p15, 0, r0, c2, c0 + mcr p15, 0, r0, c2, c0 @ ARM3 Control movs pc, lr /* diff -u --recursive --new-file v2.1.100/linux/arch/i386/Makefile linux/arch/i386/Makefile --- v2.1.100/linux/arch/i386/Makefile Wed Apr 8 19:36:24 1998 +++ linux/arch/i386/Makefile Fri May 8 00:09:20 1998 @@ -92,5 +92,7 @@ archclean: @$(MAKEBOOT) clean +archmrproper: + archdep: @$(MAKEBOOT) dep diff -u --recursive --new-file v2.1.100/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.1.100/linux/arch/i386/defconfig Sat May 2 14:19:52 1998 +++ linux/arch/i386/defconfig Fri May 8 18:21:04 1998 @@ -73,6 +73,7 @@ # Additional Block Devices # # CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_XD is not set diff -u --recursive --new-file v2.1.100/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c --- v2.1.100/linux/arch/i386/kernel/i386_ksyms.c Sat May 2 14:19:52 1998 +++ linux/arch/i386/kernel/i386_ksyms.c Fri May 8 00:23:41 1998 @@ -16,6 +16,7 @@ #include #include #include +#include extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu(elf_fpregset_t *); @@ -37,6 +38,9 @@ EXPORT_SYMBOL(iounmap); EXPORT_SYMBOL(local_bh_count); EXPORT_SYMBOL(local_irq_count); +EXPORT_SYMBOL(enable_irq); +EXPORT_SYMBOL(disable_irq); + EXPORT_SYMBOL_NOVERS(__down_failed); EXPORT_SYMBOL_NOVERS(__down_failed_interruptible); EXPORT_SYMBOL_NOVERS(__up_wakeup); diff -u --recursive --new-file v2.1.100/linux/arch/m68k/Makefile linux/arch/m68k/Makefile --- v2.1.100/linux/arch/m68k/Makefile Tue Feb 17 13:12:44 1998 +++ linux/arch/m68k/Makefile Fri May 8 00:09:20 1998 @@ -107,4 +107,6 @@ archclean: rm -f vmlinux.gz +archmrproper: + archdep: diff -u --recursive --new-file v2.1.100/linux/arch/m68k/amiga/config.c linux/arch/m68k/amiga/config.c --- v2.1.100/linux/arch/m68k/amiga/config.c Tue Feb 17 13:12:44 1998 +++ linux/arch/m68k/amiga/config.c Fri May 8 00:15:21 1998 @@ -76,7 +76,6 @@ #endif static void amiga_reset (void); static int amiga_wait_key (struct console *co); -extern struct consw fb_con; extern void zorro_init(void); extern void amiga_init_sound(void); static void amiga_savekmsg_init(void); diff -u --recursive --new-file v2.1.100/linux/arch/m68k/apollo/config.c linux/arch/m68k/apollo/config.c --- v2.1.100/linux/arch/m68k/apollo/config.c Tue Feb 17 13:12:44 1998 +++ linux/arch/m68k/apollo/config.c Fri May 8 00:15:21 1998 @@ -14,7 +14,6 @@ #include #include -extern struct consw fb_con; extern void dn_sched_init(void (*handler)(int,void *,struct pt_regs *)); extern int dn_keyb_init(void); extern int dn_dummy_kbdrate(struct kbd_repeat *); diff -u --recursive --new-file v2.1.100/linux/arch/m68k/atari/config.c linux/arch/m68k/atari/config.c --- v2.1.100/linux/arch/m68k/atari/config.c Tue Feb 17 13:12:44 1998 +++ linux/arch/m68k/atari/config.c Fri May 8 00:15:21 1998 @@ -70,7 +70,6 @@ #ifdef CONFIG_HEARTBEAT static void atari_heartbeat( int on ); #endif -extern struct consw fb_con; /* atari specific timer functions (in time.c) */ extern void atari_sched_init(void (*)(int, void *, struct pt_regs *)); diff -u --recursive --new-file v2.1.100/linux/arch/m68k/config.in linux/arch/m68k/config.in --- v2.1.100/linux/arch/m68k/config.in Wed Apr 1 20:11:48 1998 +++ linux/arch/m68k/config.in Fri May 8 00:15:21 1998 @@ -196,7 +196,7 @@ bool 'A4000T SCSI support' CONFIG_A4000T_SCSI bool 'A4091 SCSI support' CONFIG_A4091_SCSI bool 'WarpEngine SCSI support' CONFIG_WARPENGINE_SCSI -# bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI + bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI # bool 'GVP Turbo 040/060 SCSI support' CONFIG_GVP_TURBO_SCSI fi fi @@ -286,7 +286,6 @@ if [ "$CONFIG_VT" = "y" ]; then bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE fi - define_bool CONFIG_FB_CONSOLE y fi if [ "$CONFIG_ATARI" = "y" ]; then diff -u --recursive --new-file v2.1.100/linux/arch/m68k/kernel/m68k_ksyms.c linux/arch/m68k/kernel/m68k_ksyms.c --- v2.1.100/linux/arch/m68k/kernel/m68k_ksyms.c Thu Mar 26 15:57:02 1998 +++ linux/arch/m68k/kernel/m68k_ksyms.c Fri May 8 00:15:21 1998 @@ -1,4 +1,3 @@ -#include #include #include #include @@ -44,6 +43,8 @@ EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(local_bh_count); +EXPORT_SYMBOL(enable_irq); +EXPORT_SYMBOL(disable_irq); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy); diff -u --recursive --new-file v2.1.100/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c --- v2.1.100/linux/arch/m68k/kernel/process.c Tue Mar 17 22:18:14 1998 +++ linux/arch/m68k/kernel/process.c Fri May 8 00:15:21 1998 @@ -66,6 +66,7 @@ current->priority = -100; current->counter = -100; for (;;){ + check_pgt_cache(); if (!need_resched) #if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC) /* block out HSYNC on the atari (falcon) */ diff -u --recursive --new-file v2.1.100/linux/arch/m68k/mac/adb-bus.c linux/arch/m68k/mac/adb-bus.c --- v2.1.100/linux/arch/m68k/mac/adb-bus.c Tue Feb 17 13:12:45 1998 +++ linux/arch/m68k/mac/adb-bus.c Fri May 8 00:15:22 1998 @@ -6,9 +6,11 @@ * Copyright (C) 1996 Paul Mackerras. * * MSch (9/97) Partial rewrite of interrupt handler to MacII style - * ADB handshake, based on: - * - Guide to Mac Hardware - * - Guido Koerber's session with a logic analyzer + * ADB handshake, based on: + * - Guide to Mac Hardware + * - Guido Koerber's session with a logic analyzer + * + * MSch (1/98) Integrated start of IIsi driver by Robert Thompson */ #include @@ -63,6 +65,9 @@ #define SR_DATA 0x08 /* Shift register data */ #define SR_CLOCK 0x10 /* Shift register clock */ +/* JRT */ +#define ADB_DELAY 150 + static struct adb_handler { void (*handler)(unsigned char *, int, struct pt_regs *); } adb_handler[16]; @@ -98,6 +103,8 @@ extern void adb_data_interrupt(int irq, void *arg, struct pt_regs *regs); static void adb_input(unsigned char *buf, int nb, struct pt_regs *regs); +static void adb_hw_setup_IIsi(void); + /* * Misc. defines for testing */ @@ -118,11 +125,13 @@ #define ADBDEBUG_INPUT (2048) #define ADBDEBUG_DEVICE (4096) +#define ADBDEBUG_IISI (8192) + #define DEBUG_ADB #ifdef DEBUG_ADB -#define ADBDEBUG (ADBDEBUG_READ | ADBDEBUG_START | ADBDEBUG_WRITE | ADBDEBUG_SRQ | ADBDEBUG_REQUEST) +#define ADBDEBUG (ADBDEBUG_INPUT | ADBDEBUG_READ | ADBDEBUG_START | ADBDEBUG_WRITE | ADBDEBUG_SRQ | ADBDEBUG_REQUEST) #else #define ADBDEBUG (0) #endif @@ -132,7 +141,7 @@ void adb_bus_init(void) { unsigned long flags; - unsigned char c; + unsigned char c, i; save_flags(flags); cli(); @@ -174,31 +183,7 @@ via_write(via1, vIER, IER_SET|SR_INT); /* This clears the interrupt bit */ via_write(via1, vIFR, SR_INT); -#if 0 - ct=1000; - while( ct-- && (via_read(via1, vBufB)&TREQ)) - udelay(1000); - if(ct<0) - printk("No sync occured\n"); - ct=1000; - while( ct-- && !(via_read(via1, vIFR)&SR_INT)) - udelay(1000); - if(ct<0) - printk("No sync 2 occured\n"); - via_read(via1, vSR); - via_write(via1, vBufB, via_read(via1, vBufB)|TACK); - while( ct-- && !(via_read(via1, vBufB)&TREQ)) - udelay(1000); - if(ct<0) - printk("No sync 3 occured\n"); - ct=1000; - while( ct-- && !(via_read(via1, vIFR)&SR_INT)) - udelay(1000); - if(ct<0) - printk("No sync 4 occured\n"); - via_read(via1, vSR); - via_write(via1, vBufB, via_read(via1, vBufB)|TIP); -#endif + /* * Ok we probably ;) have a ready to use adb bus. Its also * hopefully idle (Im assuming the mac didnt leave a half @@ -214,7 +199,6 @@ */ case MAC_ADB_CUDA: printk("adb: CUDA interface.\n"); -#ifdef TRY_CUDA /* don't know what to set up here ... */ adb_state = idle; /* Set the lines up. We want TREQ as input TACK|TIP as output */ @@ -222,12 +206,47 @@ request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK, "adb CUDA interrupt", adb_cuda_interrupt); break; -#else - goto nosupp; -#endif case MAC_ADB_IISI: printk("adb: Using IIsi hardware.\n"); - goto nosupp; + printk("\tDEBUG_JRT\n"); + /* Set the lines up. We want TREQ as input TACK|TIP as output */ + via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ)); + + /* + * MSch: I'm pretty sure the setup is mildly wrong + * for the IIsi. + */ + /* Initial state: idle (clear state bits) */ + via_write(via1, vBufB, (via_read(via1, vBufB) & ~(TIP|TACK)) ); + last_status = (via_read(via1, vBufB)&~ST_MASK); + /* Shift register on input */ + c=via_read(via1, vACR); + c&=~SR_CTRL; /* Clear shift register bits */ + c|=SR_EXT; /* Shift on external clock; out or in? */ + via_write(via1, vACR, c); + /* Wipe any pending data and int */ + via_read(via1, vSR); + + /* This is interrupts on enable SR for keyboard */ + via_write(via1, vIER, IER_SET|SR_INT); + /* This clears the interrupt bit */ + via_write(via1, vIFR, SR_INT); + + /* get those pesky clock ticks we missed while booting */ + for ( i = 0; i < 30; i++) { + udelay(ADB_DELAY); + adb_hw_setup_IIsi(); + udelay(ADB_DELAY); + if (via_read(via1, vBufB) & TREQ) + break; + } + /* + * Ok we probably ;) have a ready to use adb bus. Its also + */ + request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK, + "adb interrupt", adb_cuda_interrupt); + adb_state = idle; + break; default: printk("adb: Unknown hardware interface.\n"); nosupp: @@ -255,6 +274,62 @@ restore_flags(flags); } +void adb_hw_setup_IIsi(void) +{ + int dummy; + long poll_timeout; + + printk("adb_IIsi: cleanup!\n"); + + /* ??? */ + udelay(ADB_DELAY); + + /* disable SR int. */ + via_write(via1, vIER, IER_CLR|SR_INT); + /* set SR to shift in */ + via_write(via1, vACR, via_read(via1, vACR ) & ~SR_OUT); + + /* this is required, especially on faster machines */ + udelay(ADB_DELAY); + + if (!(via_read(via1, vBufB) & TREQ)) { /* IRQ on */ + /* start frame */ + via_write(via1, vBufB,via_read(via1,vBufB) | TIP); + + while (1) { + /* poll for ADB interrupt and watch for timeout */ + /* if time out, keep going in hopes of not hanging the + * ADB chip - I think */ + poll_timeout = ADB_DELAY * 5; + while ( !(via_read(via1, vIFR) & SR_INT) + && (poll_timeout-- > 0) ) + dummy = via_read(via1, vBufB); + + dummy = via_read(via1, vSR); /* reset interrupt flag */ + + /* perhaps put in a check here that ignores all data + * after the first ADB_MAX_MSG_LENGTH bytes ??? */ + + /* end of frame reached ?? */ + if (via_read(via1, vBufB) & TREQ) + break; + + /* set ACK */ + via_write(via1,vBufB,via_read(via1, vBufB) | TACK); + /* delay */ + udelay(ADB_DELAY); + /* clear ACK */ + via_write(via1,vBufB,via_read(via1, vBufB) & ~TACK); + } + /* end frame */ + via_write(via1, vBufB,via_read(via1,vBufB) & ~TIP); + /* probably don't need to delay this long */ + udelay(ADB_DELAY); + } + /* re-enable SR int. */ + via_write(via1, vIER, IER_SET|SR_INT); +} + #define WAIT_FOR(cond, what) \ do { \ for (x = 1000; !(cond); --x) { \ @@ -288,7 +363,7 @@ /* * skip first byte if not CUDA */ - if (macintosh_config->adb_type != MAC_ADB_CUDA) { + if (macintosh_config->adb_type == MAC_ADB_II) { start = va_arg(list, int); nbytes--; } @@ -390,8 +465,12 @@ printk("adb: Polling %d\n",pod); #endif - /* XXX: that's a TALK, register 0, MacII version */ - adb_build_request(&r,NULL, 1, (pod<<4|0xC)); + if (macintosh_config->adb_type == MAC_ADB_II) + /* XXX: that's a TALK, register 0, MacII version */ + adb_build_request(&r,NULL, 1, (pod<<4|0xC)); + else + /* CUDA etc. version */ + adb_build_request(&r,NULL, 2, 0, (pod<<4|0xC)); r.reply_expected=0; r.done=NULL; @@ -545,7 +624,7 @@ * IRQ signaled ?? (means ADB controller wants to send, or might * be end of packet if we were reading) */ - if ((via_read(via1, vBufB)& TREQ) == 0) + if ((via_read(via1, vBufB) & TREQ) == 0) { switch(macintosh_config->adb_type) { @@ -560,7 +639,12 @@ /* printk("device busy - fail\n"); */ restore_flags(flags); /* a byte is coming in from the CUDA */ - return; + return; + case MAC_ADB_IISI: + printk("adb_start: device busy - fail\n"); + retry_req = req; + restore_flags(flags); + return; case MAC_ADB_II: /* * if the interrupt handler set the need_poll @@ -635,6 +719,19 @@ via_write(via1, vSR, req->data[0]); via_write(via1, vBufB, via_read(via1, vBufB)&~TIP); break; + case MAC_ADB_IISI: + /* store command byte (first byte is 'type' byte) */ + command_byte = req->data[1]; + /* set ADB state to 'active' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TIP); + /* switch ACK off (in case it was left on) */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* set the shift register to shift out and send a byte */ + via_write(via1, vACR, via_read(via1, vACR) | SR_OUT); + via_write(via1, vSR, req->data[0]); + /* signal 'byte ready' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + break; case MAC_ADB_II: /* store command byte */ command_byte = req->data[0]; @@ -653,14 +750,14 @@ #endif break; } + adb_state = sent_first_byte; + data_index = 1; #if (ADBDEBUG & ADBDEBUG_START) if (console_loglevel == 10) printk("sent first byte of %d: %x, (%x %x) ... ", req->nbytes, req->data[0], adb_state, (via_read(via1, vBufB) & (ST_MASK|TREQ)) ); #endif - adb_state = sent_first_byte; - data_index = 1; restore_flags(flags); } @@ -748,6 +845,12 @@ * and retransmit (Talk to the last active device). Cleanup of code and * testing of the CUDA functionality is required, though. * Note2: As of 13/12/97, CUDA support is definitely broken ... + * Note3: As of 21/12/97, CUDA works on a P475. What was broken? The assumption + * that Q700 and Q800 use CUDA :-( + * + * 27/01/98: IIsi driver implemented (thanks to Robert Thompson for the + * initial bits). See adb_cuda_interrupts ... + * * Next TODO: implementation of IIsi ADB protocol (maybe the USE_ORIG * conditionals can be a start?) */ @@ -786,6 +889,26 @@ x = via_read(via1, vSR); via_write(via1, vBufB, via_read(via1,vBufB)&~TIP); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + udelay(150); + /* set SR to IN (??? no byte received else) */ + via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT); + /* signal start of frame */ + via_write(via1, vBufB, via_read(via1, vBufB) | TIP); + /* read first byte */ + x = via_read(via1, vSR); + first_byte = x; +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_macIIsi : receiving unsol. packet: %x (%x %x) ", + x, adb_state, status); +#endif + /* ACK adb chip */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + } else if(macintosh_config->adb_type==MAC_ADB_II) { #if (ADBDEBUG & ADBDEBUG_STATUS) @@ -801,12 +924,8 @@ printk("adb_macII: receiving unsol. packet: %x (%x %x) ", x, adb_state, status); #endif -#ifdef USE_ORIG - via_write(via1, vBufB, via_read(via1, vBufB)&~(TIP|TACK)); -#else /* set ADB state = even for first data byte */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN); -#endif } adb_state = reading; reply_ptr = cuda_rbuf; @@ -831,7 +950,34 @@ x = via_read(via1, vSR); via_write(via1,vBufB, via_read(via1, vBufB)&~TIP); - } else if(macintosh_config->adb_type==MAC_ADB_II) { + } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* set SR to IN */ + via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT); + /* signal start of frame */ + via_write(via1, vBufB, via_read(via1, vBufB) | TIP); + /* read first byte */ + x = via_read(via1, vSR); + first_byte = x; +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_macIIsi: reading reply: %x (%x %x) ", + x, adb_state, status); +#endif +#if 0 + if( via_read(via1,vBufB) & TREQ) + ending = 1; + else + ending = 0; +#endif + /* ACK adb chip */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + } + else if(macintosh_config->adb_type==MAC_ADB_II) + { /* handshake etc. for II ?? */ x = via_read(via1, vSR); first_byte = x; @@ -840,12 +986,8 @@ printk("adb_macII: reading reply: %x (%x %x) ", x, adb_state, status); #endif -#ifdef USE_ORIG - via_write(via1, vBufB, via_read(via1, vBufB)&~(TIP|TACK)); -#else /* set ADB state = even for first data byte */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN); -#endif } adb_state = reading; reply_ptr = current_req->reply; @@ -862,6 +1004,11 @@ break; case sent_first_byte: +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" sending: %x (%x %x) ", + current_req->data[1], adb_state, status); +#endif if(macintosh_config->adb_type==MAC_ADB_CUDA) { if (status == TREQ + TIP + SR_OUT) @@ -886,14 +1033,45 @@ adb_state = sending; } } - else if(macintosh_config->adb_type==MAC_ADB_II) + else if(macintosh_config->adb_type==MAC_ADB_IISI) { - /* how to detect a collision here ?? */ + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + if ( !(via_read(via1, vBufB) & TREQ) ) + { + /* collision */ #if (ADBDEBUG & ADBDEBUG_WRITE) - if (console_loglevel == 10) - printk(" sending: %x (%x %x) ", - current_req->data[1], adb_state, status); + if (console_loglevel == 10) + printk("adb_macIIsi: send collison, aborting!\n"); #endif + /* set shift in */ + via_write(via1, vACR, + via_read(via1, vACR)&~SR_OUT); + /* clear SR int. */ + x = via_read(via1, vSR); + /* set ADB state to 'idle' */ + via_write(via1, vBufB, + via_read(via1,vBufB) & ~(TIP|TACK)); + adb_state = idle; + } + else + { + /* delay */ + udelay(ADB_DELAY); + /* set the shift register to shift out and send a byte */ +#if 0 + via_write(via1, vACR, via_read(via1, vACR) | SR_OUT); +#endif + via_write(via1, vSR, current_req->data[1]); + /* signal 'byte ready' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + data_index=2; + adb_state = sending; + } + } + else if(macintosh_config->adb_type==MAC_ADB_II) + { + /* how to detect a collision here ?? */ /* maybe we're already done (Talk, or Poll)? */ if (data_index >= current_req->nbytes) { @@ -934,14 +1112,9 @@ via_write(via1, vACR, via_read(via1, vACR) & ~SR_OUT); x=via_read(via1, vSR); -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)|TACK|TIP); -#else /* set ADB state idle - might get SRQ */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE); -#endif break; } #if (ADBDEBUG & ADBDEBUG_STATUS) @@ -951,14 +1124,9 @@ #endif /* SR already set to shift out; send byte */ via_write(via1, vSR, current_req->data[1]); -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)^TACK); -#else /* set state to ST_EVEN (first byte was: ST_CMD) */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN); -#endif data_index=2; adb_state = sending; } @@ -968,6 +1136,11 @@ req = current_req; if (data_index >= req->nbytes) { +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" -> end (%d of %d) (%x %x)!\n", + data_index-1, req->nbytes, adb_state, status); +#endif /* end of packet */ if(macintosh_config->adb_type==MAC_ADB_CUDA) { @@ -977,29 +1150,34 @@ via_write(via1, vBufB, via_read(via1,vBufB)|TACK|TIP); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* XXX maybe clear ACK here ??? */ + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* delay */ + udelay(ADB_DELAY); + /* set the shift register to shift in */ + via_write(via1, vACR, via_read(via1, vACR)|SR_OUT); + /* clear SR int. */ + x = via_read(via1, vSR); + /* set ADB state 'idle' (end of frame) */ + via_write(via1, vBufB, + via_read(via1,vBufB) & ~(TACK|TIP)); + } else if(macintosh_config->adb_type==MAC_ADB_II) { /* * XXX Not sure: maybe only switch to * input mode on Talk ?? */ -#if (ADBDEBUG & ADBDEBUG_WRITE) - if (console_loglevel == 10) - printk(" -> end (%d of %d) (%x %x)!\n", - data_index-1, req->nbytes, adb_state, status); -#endif /* set to shift in */ via_write(via1, vACR, via_read(via1, vACR) & ~SR_OUT); x=via_read(via1, vSR); -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)|TACK|TIP); -#else /* set ADB state idle - might get SRQ */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE); -#endif } req->sent = 1; if (req->reply_expected) @@ -1008,7 +1186,12 @@ * maybe fake a reply here on Listen ?? * Otherwise, a Listen hangs on success */ - if ( ((req->data[0]&0xc) == 0xc) ) + if ( macintosh_config->adb_type==MAC_ADB_II + && ((req->data[0]&0xc) == 0xc) ) + adb_state = awaiting_reply; + else if ( macintosh_config->adb_type != MAC_ADB_II + && ( req->data[0] == 0x0) + && ((req->data[1]&0xc) == 0xc) ) adb_state = awaiting_reply; else { /* @@ -1063,34 +1246,46 @@ } else { +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" %x (%x %x) ", + req->data[data_index], adb_state, status); +#endif if(macintosh_config->adb_type==MAC_ADB_CUDA) { via_write(via1, vSR, req->data[data_index++]); via_write(via1, vBufB, via_read(via1, vBufB)^TACK); } - else if(macintosh_config->adb_type==MAC_ADB_II) + else if(macintosh_config->adb_type==MAC_ADB_IISI) { -#if (ADBDEBUG & ADBDEBUG_WRITE) - if (console_loglevel == 10) - printk(" %x (%x %x) ", - req->data[data_index], adb_state, status); + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* delay */ + udelay(ADB_DELAY); + /* XXX: need to check for collision?? */ + /* set the shift register to shift out and send a byte */ +#if 0 + via_write(via1, vACR, via_read(via1, vACR)|SR_OUT); #endif via_write(via1, vSR, req->data[data_index++]); -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)^TACK); -#else + /* signal 'byte ready' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + } + else if(macintosh_config->adb_type==MAC_ADB_II) + { + via_write(via1, vSR, req->data[data_index++]); /* invert state bits, toggle ODD/EVEN */ x = via_read(via1, vBufB); via_write(via1, vBufB, (x&~ST_MASK)|~(x&ST_MASK)); -#endif } } break; case reading: + + /* timeout / SRQ handling for II hw */ #ifdef POLL_ON_TIMEOUT if((reply_len-prefix_len)==3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0) #else @@ -1128,16 +1323,12 @@ x, adb_state, status); #endif -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)|TACK|TIP); -#else #if 0 /* XXX leave status unchanged!! - need to check this again! */ + /* XXX Only touch status on II !!! */ /* set ADB state to idle (required by adb_start()) */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE); #endif -#endif /* * What if the timeout happens on reading a @@ -1206,6 +1397,7 @@ */ break; } + /* end timeout / SRQ handling for II hw. */ if((reply_len-prefix_len)>3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0) { /* SRQ tacked on data packet */ @@ -1241,7 +1433,7 @@ reply_len++; } /* The usual handshake ... */ - if(macintosh_config->adb_type==MAC_ADB_CUDA) + if (macintosh_config->adb_type==MAC_ADB_CUDA) { if (status == TIP) { @@ -1259,7 +1451,27 @@ via_read(via1, vBufB)^TACK); } } - if(macintosh_config->adb_type==MAC_ADB_II) + else if (macintosh_config->adb_type==MAC_ADB_IISI) + { + /* ACK adb chip (maybe check for end first?) */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* end of frame?? */ + if (status & TREQ) + { +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_IIsi: end of frame!\n"); +#endif + /* that's all folks */ + via_write(via1, vBufB, + via_read(via1, vBufB) & ~(TACK|TIP)); + adb_state = read_done; + /* maybe process read_done here?? Handshake anyway?? */ + } + } + else if (macintosh_config->adb_type==MAC_ADB_II) { /* * NetBSD hints that the next to last byte @@ -1277,10 +1489,6 @@ if (console_loglevel == 10) printk(" -> read done!\n"); #endif -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)|TACK|TIP); -#else #if 0 /* XXX: we take one more byte (why?), so handshake! */ /* set ADB state to idle */ via_write(via1, vBufB, @@ -1291,7 +1499,6 @@ via_write(via1, vBufB, (x&~ST_MASK)|~(x&ST_MASK)); #endif -#endif /* adjust packet length */ reply_len--; reply_ptr--; @@ -1303,10 +1510,6 @@ if(status!=TIP+TREQ) printk("macII_adb: state=reading status=%x\n", status); #endif -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)^TACK); -#else /* not caught: ST_CMD */ /* required for re-entry 'reading'! */ if ((status&ST_MASK) == ST_IDLE) { @@ -1319,7 +1522,6 @@ via_write(via1, vBufB, (x&~ST_MASK)|~(x&ST_MASK)); } -#endif } } break; @@ -1352,7 +1554,6 @@ last_reply = command_byte; last_active = (command_byte&0xf0)>>4; - /* * Assert status = ST_IDLE ?? */ @@ -1374,15 +1575,6 @@ break; } -#ifdef USE_ORIG - /* - * This will fail - TREQ is active low -> 0 is IRQ !! - */ - if (status == TREQ) - { - via_write(via1, vBufB, - via_read(via1, vBufB)|~TIP); -#else /* * /IRQ seen, so the ADB controller has data for us */ @@ -1391,7 +1583,7 @@ /* set ADB state to idle */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE); -#endif + adb_state = reading; reply_ptr = cuda_rbuf; reply_len = 0; @@ -1428,29 +1620,72 @@ * Restart of CUDA support: please modify this interrupt handler while * working at the Quadra etc. ADB driver. We can try to merge them later, or * remove the CUDA stuff from the MacII handler + * + * MSch 27/01/98: Implemented IIsi driver based on initial code by Robert + * Thompson and hints from the NetBSD driver. CUDA and IIsi seem more closely + * related than to the MacII code, so merging all three might be a bad + * idea. */ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) { int x, status; struct adb_request *req; + unsigned long flags; + + save_flags(flags); + cli(); - status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT); + if(macintosh_config->adb_type==MAC_ADB_CUDA) + status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT); + else + status = via_read(via1, vBufB) & (TIP|TREQ); + +#if (ADBDEBUG & ADBDEBUG_INT) if (console_loglevel == 10) printk("adb_interrupt: state=%d status=%x\n", adb_state, status); +#endif switch (adb_state) { case idle: + first_byte = 0; if(macintosh_config->adb_type==MAC_ADB_CUDA) { +#if (ADBDEBUG & ADBDEBUG_STATUS) /* CUDA has sent us the first byte of data - unsolicited */ if (status != TREQ) printk("cuda: state=idle, status=%x want=%x\n", status, TREQ); +#endif x = via_read(via1, vSR); +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_cuda: receiving unsol. packet: %x (%x %x) ", + x, adb_state, status); +#endif via_write(via1, vBufB, via_read(via1,vBufB)&~TIP); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + udelay(150); + /* set SR to IN */ + via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT); + /* signal start of frame */ + via_write(via1, vBufB, via_read(via1, vBufB) | TIP); + /* read first byte */ + x = via_read(via1, vSR); + first_byte = x; +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_IIsi : receiving unsol. packet: %x (%x %x) ", + x, adb_state, status); +#endif + /* ACK adb chip */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + } else if(macintosh_config->adb_type==MAC_ADB_II) { if (status != TREQ) @@ -1469,13 +1704,46 @@ if(macintosh_config->adb_type==MAC_ADB_CUDA) { /* CUDA has sent us the first byte of data of a reply */ +#if (ADBDEBUG & ADBDEBUG_STATUS) if (status != TREQ) printk("cuda: state=awaiting_reply, status=%x want=%x\n", status, TREQ); +#endif x = via_read(via1, vSR); +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_cuda: reading reply: %x (%x %x) ", + x, adb_state, status); +#endif via_write(via1,vBufB, via_read(via1, vBufB)&~TIP); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* udelay(150);*/ + /* set SR to IN */ + via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT); + /* signal start of frame */ + via_write(via1, vBufB, via_read(via1, vBufB) | TIP); + /* read first byte */ + x = via_read(via1, vSR); + first_byte = x; +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_IIsi: reading reply: %x (%x %x) ", + x, adb_state, status); +#endif +#if 0 + if( via_read(via1,vBufB) & TREQ) + ending = 1; + else + ending = 0; +#endif + /* ACK adb chip */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + } adb_state = reading; reply_ptr = current_req->reply; reading_reply = 1; @@ -1485,11 +1753,16 @@ case sent_first_byte: if(macintosh_config->adb_type==MAC_ADB_CUDA) { +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" sending: %x (%x %x) ", + current_req->data[1], adb_state, status); +#endif if (status == TREQ + TIP + SR_OUT) { /* collision */ if (console_loglevel == 10) - printk("cuda: send collision!\n"); + printk("adb_cuda: send collision!\n"); via_write(via1, vACR, via_read(via1, vACR)&~SR_OUT); x = via_read(via1, vSR); @@ -1500,9 +1773,11 @@ else { /* assert status == TIP + SR_OUT */ +#if (ADBDEBUG & ADBDEBUG_STATUS) if (status != TIP + SR_OUT) - printk("cuda: state=sent_first_byte status=%x want=%x\n", + printk("adb_cuda: state=sent_first_byte status=%x want=%x\n", status, TIP + SR_OUT); +#endif via_write(via1,vSR,current_req->data[1]); via_write(via1, vBufB, via_read(via1, vBufB)^TACK); @@ -1510,6 +1785,42 @@ adb_state = sending; } } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + if ( !(via_read(via1, vBufB) & TREQ) ) + { + /* collision */ +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk("adb_macIIsi: send collison, aborting!\n"); +#endif + /* set shift in */ + via_write(via1, vACR, + via_read(via1, vACR)&~SR_OUT); + /* clear SR int. */ + x = via_read(via1, vSR); + /* set ADB state to 'idle' */ + via_write(via1, vBufB, + via_read(via1,vBufB) & ~(TIP|TACK)); + adb_state = idle; + } + else + { + /* delay */ + udelay(ADB_DELAY); + /* set the shift register to shift out and send a byte */ +#if 0 + via_write(via1, vACR, via_read(via1, vACR) | SR_OUT); +#endif + via_write(via1, vSR, current_req->data[1]); + /* signal 'byte ready' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + data_index=2; + adb_state = sending; + } + } else if(macintosh_config->adb_type==MAC_ADB_II) { if(status!=TIP+SR_OUT) @@ -1527,6 +1838,11 @@ req = current_req; if (data_index >= req->nbytes) { +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" -> end (%d of %d) (%x %x)!\n", + data_index-1, req->nbytes, adb_state, status); +#endif if(macintosh_config->adb_type==MAC_ADB_CUDA) { via_write(via1, vACR, @@ -1535,6 +1851,21 @@ via_write(via1, vBufB, via_read(via1,vBufB)|TACK|TIP); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* XXX maybe clear ACK here ??? */ + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* delay */ + udelay(ADB_DELAY); + /* set the shift register to shift in */ + via_write(via1, vACR, via_read(via1, vACR)|SR_OUT); + /* clear SR int. */ + x = via_read(via1, vSR); + /* set ADB state 'idle' (end of frame) */ + via_write(via1, vBufB, + via_read(via1,vBufB) & ~(TACK|TIP)); + } else if(macintosh_config->adb_type==MAC_ADB_II) { via_write(via1, vACR, @@ -1546,7 +1877,40 @@ req->sent = 1; if (req->reply_expected) { - adb_state = awaiting_reply; + /* + * maybe fake a reply here on Listen ?? + * Otherwise, a Listen hangs on success + * CUDA+IIsi: only ADB Talk considered + * RTC/PRAM read (0x1 0x3) to follow. + */ + if ( (req->data[0] == 0x0) && ((req->data[1]&0xc) == 0xc) ) + adb_state = awaiting_reply; + else { + /* + * Reply expected, but none + * possible -> fake reply. + */ +#if (ADBDEBUG & ADBDEBUG_PROT) + printk("ADB: reply expected on Listen, faking reply\n"); +#endif + /* make it look weird */ + /* XXX: return reply_len -1? */ + /* XXX: fake ADB header? */ + req->reply[0] = req->reply[1] = req->reply[2] = 0xFF; + req->reply_len = 3; + req->got_reply = 1; + current_req = req->next; + if (req->done) + (*req->done)(req); + /* + * ready with this one, run + * next command ! + */ + /* set state to idle !! */ + adb_state = idle; + if (current_req || retry_req) + adb_start(); + } } else { @@ -1560,12 +1924,32 @@ } else { +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" %x (%x %x) ", + req->data[data_index], adb_state, status); +#endif if(macintosh_config->adb_type==MAC_ADB_CUDA) { via_write(via1, vSR, req->data[data_index++]); via_write(via1, vBufB, via_read(via1, vBufB)^TACK); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* delay */ + udelay(ADB_DELAY); + /* XXX: need to check for collision?? */ + /* set the shift register to shift out and send a byte */ +#if 0 + via_write(via1, vACR, via_read(via1, vACR)|SR_OUT); +#endif + via_write(via1, vSR, req->data[data_index++]); + /* signal 'byte ready' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + } else if(macintosh_config->adb_type==MAC_ADB_II) { via_write(via1, vSR, req->data[data_index++]); @@ -1579,14 +1963,17 @@ if(reply_len==3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0) { /* Terminate the SRQ packet */ - printk("CUDA: Got an SRQ\n"); +#if (ADBDEBUG & ADBDEBUG_SRQ) + if (console_loglevel == 10) + printk("adb: Got an SRQ\n"); +#endif adb_state = idle; adb_queue_poll(); break; } /* Sanity check - botched in orig. code! */ if(reply_len>15) { - printk("CUDA: reply buffer overrun!\n"); + printk("adb_cuda: reply buffer overrun!\n"); /* wrap buffer */ reply_len=0; if (reading_reply) @@ -1595,9 +1982,11 @@ reply_ptr = cuda_rbuf; } *reply_ptr = via_read(via1, vSR); +#if (ADBDEBUG & ADBDEBUG_READ) if (console_loglevel == 10) - printk(" %p-> %x (%x %x) ", - reply_ptr, *reply_ptr, adb_state, status); + printk(" %x (%x %x) ", + *reply_ptr, adb_state, status); +#endif reply_ptr++; reply_len++; if(macintosh_config->adb_type==MAC_ADB_CUDA) @@ -1612,13 +2001,36 @@ else { /* assert status == TIP | TREQ */ +#if (ADBDEBUG & ADBDEBUG_STATUS) if (status != TIP + TREQ) printk("cuda: state=reading status=%x want=%x\n", status, TIP + TREQ); +#endif via_write(via1, vBufB, via_read(via1, vBufB)^TACK); } } + else if (macintosh_config->adb_type==MAC_ADB_IISI) + { + /* ACK adb chip (maybe check for end first?) */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* end of frame?? */ + if (status & TREQ) + { +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_IIsi: end of frame!\n"); +#endif + /* that's all folks */ + via_write(via1, vBufB, + via_read(via1, vBufB) & ~(TACK|TIP)); + adb_state = read_done; + /* XXX maybe process read_done here?? + Handshake anyway?? */ + } + } if(macintosh_config->adb_type==MAC_ADB_II) { if( status == TIP) @@ -1629,16 +2041,26 @@ } else { +#if (ADBDEBUG & ADBDEBUG_STATUS) if(status!=TIP+TREQ) printk("macII_adb: state=reading status=%x\n", status); +#endif via_write(via1, vBufB, via_read(via1, vBufB)^TACK); } } - break; + /* fall through for IIsi on end of frame */ + if (macintosh_config->adb_type != MAC_ADB_IISI + || adb_state != read_done) + break; case read_done: x = via_read(via1, vSR); +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb: read done: %x (%x %x)!\n", + x, adb_state, status); +#endif if (reading_reply) { req = current_req; @@ -1653,10 +2075,21 @@ adb_input(cuda_rbuf, reply_ptr - cuda_rbuf, regs); } - if (status == TREQ) + if (macintosh_config->adb_type==MAC_ADB_CUDA + && status & TREQ) { via_write(via1, vBufB, - via_read(via1, vBufB)|~TIP); + via_read(via1, vBufB)&~TIP); + adb_state = reading; + reply_ptr = cuda_rbuf; + reading_reply = 0; + } + else if (macintosh_config->adb_type==MAC_ADB_IISI + && !(status & TREQ)) + { + udelay(150); + via_write(via1, vBufB, + via_read(via1, vBufB) | TIP); adb_state = reading; reply_ptr = cuda_rbuf; reading_reply = 0; @@ -1669,8 +2102,11 @@ break; default: - printk("adb_interrupt: unknown adb_state %d?\n", adb_state); + printk("adb_cuda_interrupt: unknown adb_state %d?\n", adb_state); } + + restore_flags(flags); + } /* diff -u --recursive --new-file v2.1.100/linux/arch/m68k/mac/config.c linux/arch/m68k/mac/config.c --- v2.1.100/linux/arch/m68k/mac/config.c Tue Feb 17 13:12:45 1998 +++ linux/arch/m68k/mac/config.c Fri May 8 00:15:22 1998 @@ -59,6 +59,12 @@ void *mac_env; /* Loaded by the boot asm */ +/* The locgial video addr. determined by head.S - testing */ +extern unsigned long mac_videobase; + +/* The phys. video addr. - might be bogus on some machines */ +unsigned long mac_orig_videoaddr; + extern int mac_keyb_init(void); extern int mac_kbdrate(struct kbd_repeat *k); extern void mac_kbd_leds(unsigned int leds); @@ -183,8 +189,6 @@ ; } -extern struct consw fb_con; -extern struct fb_info *mac_fb_init(long *); extern void mac_video_setup(char *, int *); void mac_debug_init (void) @@ -213,15 +217,13 @@ int unknown = 0; const u_long *data = record->data; - if (compat_bi) - return(unknown); - switch (record->tag) { case BI_MAC_MODEL: mac_bi_data.id = *data; break; case BI_MAC_VADDR: - mac_bi_data.videoaddr = *data; + mac_orig_videoaddr = *data; + mac_bi_data.videoaddr = mac_videobase; break; case BI_MAC_VDEPTH: mac_bi_data.videodepth = *data; @@ -256,39 +258,6 @@ return(unknown); } -__initfunc(void mac_copy_compat(void)) -{ - int i; - - compat_bi = 1; - - for (i=0; i> 16); + printk (" Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n", + mac_bi_data.videological, mac_orig_videoaddr, + mac_bi_data.sccbase); printk (" Boottime: 0x%lx GMTBias: 0x%lx \n", mac_bi_data.boottime, mac_bi_data.gmtbias); - printk (" Videological 0x%lx, SCC at 0x%lx \n", - mac_bi_data.videological, mac_bi_data.sccbase); printk (" Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n", mac_bi_data.id, mac_bi_data.cpuid, mac_bi_data.memsize); +#if 0 printk ("Ramdisk: addr 0x%lx size 0x%lx\n", m68k_ramdisk.addr, m68k_ramdisk.size); +#endif /* * Save the pointer diff -u --recursive --new-file v2.1.100/linux/arch/m68k/mac/debug.c linux/arch/m68k/mac/debug.c --- v2.1.100/linux/arch/m68k/mac/debug.c Tue Feb 17 13:12:45 1998 +++ linux/arch/m68k/mac/debug.c Fri May 8 00:15:22 1998 @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -131,7 +132,7 @@ if (!MACH_IS_MAC) return; - if (compat_boot_info.bi_mac.videodepth ==1) + if (mac_videodepth ==1) pengoffset=(unsigned char *)(mac_videobase+80*mac_rowbytes) +5*peng; else @@ -163,13 +164,13 @@ int i; if(!boomoffset) - if (compat_boot_info.bi_mac.videodepth == 1) { + if (mac_videodepth == 1) { boomoffset=(unsigned char *)(mac_videobase+160*mac_rowbytes); } else { boomoffset=(unsigned char *)(mac_videobase+256*mac_rowbytes); } else - if (compat_boot_info.bi_mac.videodepth == 1) + if (mac_videodepth == 1) boomoffset+=5; else boomoffset+=32; diff -u --recursive --new-file v2.1.100/linux/arch/m68k/mac/macints.c linux/arch/m68k/mac/macints.c --- v2.1.100/linux/arch/m68k/mac/macints.c Tue Feb 17 13:12:45 1998 +++ linux/arch/m68k/mac/macints.c Fri May 8 00:15:22 1998 @@ -174,8 +174,6 @@ { int i; - mac_debugging_penguin(6); - #ifdef DEBUG_MACINTS printk("Mac interrupt stuff initializing ...\n"); #endif @@ -274,7 +272,6 @@ param_table[2] = &rbv_param[0]; param_table[3] = &nubus_param[0]; - mac_debugging_penguin(7); #ifdef DEBUG_MACINTS printk("Mac interrupt init done!\n"); #endif @@ -626,7 +623,7 @@ if(events==0) { - printk("via_irq: nothing pending!\n"); + printk("via%d_irq: nothing pending!\n", *viaidx + 1); return; } @@ -869,14 +866,14 @@ static int nubus_active=0; -int nubus_request_irq(int slot, void (*handler)(int,void *,struct pt_regs *)) +int nubus_request_irq(int slot, void *dev_id, void (*handler)(int,void *,struct pt_regs *)) { slot-=9; /* printk("Nubus request irq for slot %d\n",slot);*/ if(nubus_handler[slot].handler!=nubus_wtf) return -EBUSY; nubus_handler[slot].handler=handler; - nubus_handler[slot].dev_id =handler; + nubus_handler[slot].dev_id =dev_id; nubus_param[slot].flags = IRQ_FLG_LOCK; nubus_param[slot].devname = "nubus"; @@ -964,7 +961,7 @@ { if(map&(1< -#include -#include -#include -#include -#include -#include - -/* - * dec_entry: Called by the boot PROM loader to do DECStation setup, prior - * to calling dec_setup() to fill in the boot_info structure. - * - * This code should also go in the boot loader for loading off - * floppy and HD... in addition to the tags code in dec_setup(). - * - * FIXME: arrange for this code only to be linked in when building a - * kernel image to be booted via tftp from the boot prom?? - */ - .text - .globl dec_entry -dec_entry: - /* Save the address of the REX call vector for later - * use in printing debug messages. - */ - sw a3,pmax_rex_base - sw a2,rex_prom_magic - la a0,dec_signon - jal pmax_printf - nop - - /* Now set up the bootinfo with things that - * should be loaded by the boot loader, except that - * for the moment we're booting using tftp. - */ - jal dec_setup - nop -/* - * Now we need to move exception vector handler routines that appear - * in head.S down to the right addresses, 'cos the DECStation loads - * kernels at 0x80030000... - */ - -/* - * First move the TLB refill code down to offset 0x000, at addr 0x80000000 - */ - la t0,except_vec0 # begining of exception code - la t1,except_vec1 # end of exception code - la t2,0x80000000 # where the code should live - lw t3,(t0) # get first word -1: sw t3,(t2) # put it where it should go - addiu t0,4 # increment both pointers - addiu t2,4 - lw t3,(t0) # will be in the delay slot - bne t0,t1,1b -/* - * Now move the General Exception code down to offset 0x080 at 0x80000000 - */ - la t0,except_vec3 # begining of general exception code - la t1,end_except # end of general exception code - la t2,0x80000080 # where the code should live - lw t3,(t0) # get first word -1: sw t3,(t2) - addiu t0,4 - addiu t2,4 - lw t3,(t0) - bne t0,t1,1b - - la a0,dec_launch # say where we are going - jal pmax_printf - nop - - la t0,mach_mem_upper # get upper memory bound - lw a0,(t0) - j kernel_entry - nop - - .data - .align 2 -dec_signon: .ascii "\n\nLinux/MIPS DECStation Boot\n"; - .asciiz "Copyright (C) Paul M. Antoine 1995, 1996 and others, 1994, 1995, 1996\n\n"; -dec_launch: .asciiz "Setup complete, launching kernel...\n"; diff -u --recursive --new-file v2.1.100/linux/arch/mips/dec/decstation.S linux/arch/mips/dec/decstation.S --- v2.1.100/linux/arch/mips/dec/decstation.S Thu Jun 26 12:33:36 1997 +++ linux/arch/mips/dec/decstation.S Wed Dec 31 16:00:00 1969 @@ -1,369 +0,0 @@ -/* - * arch/mips/kernel/decstation.S - * - * Copyright (C) 1995, 1996 Paul M. Antoine - * - * Written by Ralf Baechle and Andreas Busse, modified for DECStation - * support by Paul Antoine. - * - * NOTE: There are references to R4X00 code in here, because I believe - * that there is an upgrade module for Personal DECStations with - * such CPU's! - * - * FIXME: still plenty to do in this file, as much of the code towards - * the end hasn't been modified to suit the DECStation's interrupts. - * (Paul, you need to fix this file to comply with NAPS. Won't be - * too hard - Ralf) - */ -#include -#include -#include -#include -#include -#include -#include - -/* - * dec_entry: Called at boot in head.S to do DECStation setup, and to - * fill in the boot_info structure. - */ - .text - .globl dec_entry -dec_entry: - /* Save the address of the REX call vector for later - * use in printing debug messages. - */ - sw a3,pmax_rex_base - la a0,dec_signon - jal pmax_printf - nop - /* Now set up the bootinfo structure with things that - * should be loaded by the boot loader, except that - * for the moment we're booting using tftp. - */ - la t0,boot_info - li t1,0x40 # 64 TLB entries -/* - * FIXME: Ideally, all DEC workstations should be supported, so here we - * should put some clevernesses to determine machine type and CPU - * type. Needs a hierarchy of DEC machine types. Perhaps Machine - * AND Model fields in bootinfo structure? - */ - sw t1,OFFSET_BOOTINFO_TLB_ENTRIES(t0) - li t1,MACH_DECSTATION # Machine type - sw t1,(t0) - li t1,CPU_R3000A # CPU type - sw t1,OFFSET_BOOTINFO_CPUTYPE(t0) -/* - * FIXME: the following should find the memory size from the boot PROM - */ - li t1,0x80000000 # Lower memory bound - sw t1,OFFSET_BOOTINFO_MEMLOWER(t0) - li t1,0x88000000 # Upper memory bound (8MB) - sw t1,OFFSET_BOOTINFO_MEMUPPER(t0) -/* - * FIXME: the following should determine the cache size a la the method - * used in MACH. For now we just guess - PMA. - */ - li t1,0x100000 # 64K icache - sw t1,OFFSET_BOOTINFO_ICACHE_SIZE(t0) - li t1,0x100000 # 64K dcache - sw t1,OFFSET_BOOTINFO_DCACHE_SIZE(t0) - -/* - * FIXME: template for other bootinfo fields that probably need filling in... - * - li t1,0x80000000 - sw t1,OFFSET_BOOTINFO_(t0) -*/ - -/* - * Now we need to move exception vector handler routines that appear - * in head.S down to the right addresses, 'cos the DECStation loads - * kernels at 0x80030000... - */ - -/* - * First move the TLB refill code down to offset 0x000, at addr 0x80000000 - */ - la t0,except_vec0 # begining of TLB exception code - la t1,except_vec1 # end of TLB exception code - la t2,0x80000000 # where the code should live - lw t3,(t0) # get first word -1: sw t3,(t2) # put it where it should go - addiu t0,4 # increment both pointers - addiu t2,4 - lw t3,(t0) # will be in the delay slot - bne t0,t1,1b - -/* - * Now move the General Exception code down to offset 0x080 at 0x80000000 - */ - la t0,except_vec3 # begining of general exception code - la t1,kernel_entry # end of general exception code - la t2,0x80000080 # where the code should live - lw t3,(t0) # get first word -1: sw t3,(t2) - addiu t0,4 - addiu t2,4 - lw t3,(t0) - bne t0,t1,1b - -/* - * FIXME: Don't forget to set the gp regster... why do I need this? - */ - la gp,_gp - la a0,dec_launch # say where we are going - jal pmax_printf - nop - j kernel_entry - nop - - .data - .align 2 -dec_signon: .ascii "\n\nLinux/MIPS DECStation Boot\n"; - .asciiz "Copyright (C) Paul M. Antoine 1995, 1996 and others, 1994, 1995, 1996\n\n"; -dec_launch: .asciiz "Launching kernel...\n"; - .text - .set noreorder -/* - * decstation_handle_int: Interrupt handler for Personal DECStation 5000/2x - * - * FIXME: this is *extremely* experimental, though it is probably o.k. for - * most DECStation models. - */ - NESTED(decstation_handle_int, FR_SIZE, ra) - .set noat - SAVE_ALL - REG_S sp,FR_ORIG_REG2(sp) - CLI - .set at - - /* - * Get pending interrupts - */ - mfc0 t0,CP0_CAUSE # get pending interrupts - mfc0 t1,CP0_STATUS # get enabled interrupts - and t0,t1 # isolate allowed ones - andi t0,0xff00 # isolate pending bits -/* - * FIXME: The following branch was: - * beqz t0,spurious_interrupt - * - * ...but the wonders of ecoff cause the gas assembler (ver 2.5.1 ) - * to complain: - * - * "Can not represent relocation in this object file format"... - * - * hence this hack to branch foward a bit, and then jump - * Perhaps a later version of gas will cope? - Paul - * (No, this is impossible in COFF as well as in ELF. - Ralf) - */ - beqz t0,3f; - sll t0,16 # delay slot - - /* - * Find irq with highest priority - * FIXME: This is slow - */ - la t1,ll_vectors -1: bltz t0,2f # found pending irq - sll t0,1 - b 1b - subu t1,PTRSIZE # delay slot - - /* - * Do the low-level stuff - */ - .set reorder -2: LOAD_L t0,(t1) - jr t0 - .set noreorder - END(decstation_handle_int) - -/* - * FIXME: The hack mentioned above. - */ -3: j spurious_interrupt - nop - -/* - * FIXME: the rest of this is pretty suspect, as it's straight from - * jazz.S... and I really haven't altered it at all - Paul - */ - -/* - * Used for keyboard driver's fake_keyboard_interrupt() - * (Paul, even for i386 this is no longer being used -- Ralf) - */ -ll_sw0: li s1,~IE_SW0 - mfc0 t0,CP0_CAUSE - and t0,s1 - mtc0 t0,CP0_CAUSE - PRINT("sw0 received...\n") - li t1,1 - b call_real - li t3,PTRSIZE # delay slot, re-map to irq level 1 - -ll_sw1: li s1,~IE_SW1 - PANIC("Unimplemented sw1 handler") - -loc_no_irq: PANIC("Unimplemented loc_no_irq handler") -loc_sound: PANIC("Unimplemented loc_sound handler") -loc_video: PANIC("Unimplemented loc_video handler") -loc_scsi: PANIC("Unimplemented loc_scsi handler") - -/* - * Ethernet interrupt, remapped to level 15 - * NOTE: Due to a bug somewhere in the kernel I was not able - * to figure out, the PRINT() is necessary. Without this, - * I get a "gfp called nonatomically from interrupt 00000000". - * Only god knows why... Tell me if you find the reason! - * (You were fouled by the caches and this is the wrong file for this - * comment - Ralf) - * Andy, 6/16/95 - */ -loc_ethernet: PANIC("Unimplemented loc_ethernet\n") - -/* - * Keyboard interrupt, remapped to level 1 - */ -loc_keyboard: PANIC("Unimplemented loc_keyboard\n") - -loc_mouse: PANIC("Unimplemented loc_mouse handler") - -/* - * Serial port 1 IRQ, remapped to level 3 - */ -loc_serial1: PANIC("Unimplemented loc_serial handler") - -/* - * Serial port 2 IRQ, remapped to level 4 - */ -loc_serial2: PANIC("Unimplemented loc_serial handler") - -/* - * Parallel port IRQ, remapped to level 5 - */ -loc_parallel: PANIC("Unimplemented loc_parallel handler") - -/* - * Floppy IRQ, remapped to level 6 - */ -loc_floppy: PANIC("Unimplemented loc_floppy handler") - -/* - * Now call the real handler - */ -loc_call: la t0,IRQ_vectors # delay slot - - /* - * Temporarily disable interrupt source - */ -/* lhu t2,JAZZ_IO_IRQ_ENABLE -*/ - addu t0,t3 # make ptr to IRQ handler - LOAD_L t0,(t0) - and t2,s1 # delay slot -/* sh t2,JAZZ_IO_IRQ_ENABLE */ - jalr t0 # call IRQ handler - nor s1,zero,s1 # delay slot - - /* - * Reenable interrupt - */ -/* lhu t2,JAZZ_IO_IRQ_ENABLE */ - or t2,s1 -/* sh t2,JAZZ_IO_IRQ_ENABLE */ - - jr v0 - nop # delay slot - -ll_tc3: PANIC("Unimplemented tc3 interrupt handler") - -ll_fpu: PANIC("Unimplemented fpu interrupt handler") - -ll_io_error: PANIC("Unimplemented I/O write timeout interrupt handler") - -ll_rtc: PANIC("Unimplemented RTC interrupt handler") - -/* - * Timer IRQ - * We remap the timer irq to be more similar to a IBM compatible - */ -ll_timer: PANIC("Timer interrupt!\n"); -/* - * CPU count/compare IRQ (unused) - */ -ll_reset: li a0,0 - jal pmax_halt - li a1,0 # delay slot - -/* - * Now call the real handler - */ -call_real: la t0,IRQ_vectors # delay slot - - /* - * temporarily disable interrupt - */ - mfc0 t2,CP0_STATUS - and t2,s1 - - addu t0,t3 - LOAD_L t0,(t0) - mtc0 t2,CP0_STATUS # delay slot - jalr t0 - nor s1,zero,s1 # delay slot - - /* - * reenable interrupt - */ - mfc0 t2,CP0_STATUS - or t2,s1 - mtc0 t2,CP0_STATUS - - jr v0 - nop # delay slot - -/* - * Just for debugging... load a0 with address of the point inside the - * framebuffer at which you want to draw a line of 16x32 pixels. - * Maxine's framebuffer starts at 0xaa000000. - */ - .set reorder - LEAF(drawline) - li t1,0xffffffff # set all pixels on - li t2,0x10 # we will write 16 words -1: sw t1,(a0) # write the first word - addiu a0,a0,4 # move our framebuffer pointer - addiu t2,t2,-1 # one less to do - bnez t2,1b # finished? - jr ra - END(drawline) - -/* - * FIXME: I have begun to alter this table to reflect Personal DECStation - * (i.e. Maxine) interrupts... Paul. - */ - .data - PTR ll_sw0 # SW0 - PTR ll_sw1 # SW1 - PTR ll_timer # Periodic interrupt - PTR ll_rtc # RTC periodic interrupt - PTR ll_io_error # Timeout on I/O writes - PTR ll_tc3 # TC slot 3, motherboard - PTR ll_reset # Halt keycode (CTRL+ALT+ENTER) -ll_vectors: PTR ll_fpu # FPU - -local_vector: PTR loc_no_irq - PTR loc_parallel - PTR loc_floppy - PTR loc_sound - PTR loc_video - PTR loc_ethernet - PTR loc_scsi - PTR loc_keyboard - PTR loc_mouse - PTR loc_serial1 - PTR loc_serial2 diff -u --recursive --new-file v2.1.100/linux/arch/mips/dec/decstation.c linux/arch/mips/dec/decstation.c --- v2.1.100/linux/arch/mips/dec/decstation.c Thu Jun 26 12:33:36 1997 +++ linux/arch/mips/dec/decstation.c Wed Dec 31 16:00:00 1969 @@ -1,200 +0,0 @@ -/* - * arch/mips/dec/decstation.c - * - * Copyright (C) 1996 Paul M. Antoine - * - * Written by Paul Antoine. - * - * FIXME: still plenty to do in this file, as we don't yet fully fill - * the boot info structure with DEC-specific tags. Also still - * too specific to the Person Decstattion 5000/2x!! - */ - -#include -#include /* FIXME: what about other decstations? */ -#include - -/* - * dec_setup: Called at boot from dec_entry() in boot.S to do - * DECStation-specific setup, and to fill in the kernel argument - * tags. - * - * FIXME: I'm not sure all DEC workstations are correctly supported. This - * code may not need to be here when booting off floppy or HD?? - */ - -unsigned long mach_mem_upper = 0; -unsigned long mach_mem_lower = 0; -unsigned long mips_dcache_size = 0; -unsigned long mips_icache_size = 0; -unsigned long rex_prom_magic; /* from boot.S */ -unsigned long dec_get_memory_size(void); - -void dec_setup(void) -{ - unsigned long int mem_mask = 0; - unsigned long tag_data_dummy, dec_sysid; - unsigned char dec_cpunum, dec_systype, dec_firmrev, dec_etc; - extern const char *linux_banner; - - pmax_printf("%s\n", linux_banner); - /* First we need the memory upper bound before we can add tag entries... */ - mach_mem_lower = 0x80000000L; - mach_mem_upper = mach_mem_lower + dec_get_memory_size(); - - /* First tag is always memory upper limit, right Stoned?? */ - (void)bi_TagAdd(tag_memupper, ULONGSIZE, &mach_mem_upper); - - /* We're obviously one of the DEC machines */ - tag_data_dummy = MACH_GROUP_DEC; - (void)bi_TagAdd(tag_machgroup, ULONGSIZE, &tag_data_dummy); - - /* Now let's try to figure out what type of DECStation we are */ - pmax_printf("System id is: "); - if ((dec_sysid = pmax_getsysid()) != 0) - pmax_printf("%x\n", dec_sysid); - else - pmax_printf("unknown\n"); - - dec_cpunum = (dec_sysid & 0xff000000) >> 24; - dec_systype = (dec_sysid & 0xff0000) >> 16; - dec_firmrev = (dec_sysid & 0xff00) >> 8; - dec_etc = dec_sysid & 0xff; - - /* - * FIXME: for now use the PROM to determine the CPU type - should - * probably just get the CPU to tell us. - */ - pmax_printf("System has an "); - switch(dec_cpunum) - { - case 0x82: - { - pmax_printf("R3000 CPU\n"); - tag_data_dummy = CPU_R3000A; - break; - } - case 0x84: - { - pmax_printf("R4000 CPU\n"); - /* FIXME: assume a plain R4000PC for now */ - tag_data_dummy = CPU_R4000PC; - break; - } - default: - { - pmax_printf("unknown CPU, code is %x\n", dec_cpunum); - /* FIXME: assume an R2000 for now */ - tag_data_dummy = CPU_R2000; - break; - } - } - /* Add the CPU type */ - (void)bi_TagAdd(tag_cputype, ULONGSIZE, &tag_data_dummy); - - pmax_printf("System has firmware type: "); - if (dec_firmrev == 2) - pmax_printf("TCF0\n"); - else - pmax_printf("TCF1\n"); - - pmax_printf("This DECStation is a: "); - switch(dec_systype) { - case 1: /* DS2100/3100 Pmax */ - pmax_printf("DS2100/3100\n"); - tag_data_dummy = MACH_DECSTATION; - break; - case 2: /* DS5000 3max */ - pmax_printf("DS5000\n"); - tag_data_dummy = MACH_DECSTATION; - break; - case 3: /* DS5000/100 3min */ - pmax_printf("DS5000/1x0\n"); - tag_data_dummy = MACH_DECSTATION; - break; - case 7: /* Personal DS5000/2x */ - pmax_printf("Personal DS5000/2x\n"); - tag_data_dummy = MACH_DECSTATION; - break; - default: - pmax_printf("unknown, id is: %x\n", dec_systype); - tag_data_dummy = MACH_UNKNOWN; - break; - } - - /* Add the machine type */ - (void)bi_TagAdd(tag_machtype, ULONGSIZE, &tag_data_dummy); - - /* Add the number of tlb entries */ - tag_data_dummy = 64; - (void)bi_TagAdd(tag_tlb_entries, ULONGSIZE, &tag_data_dummy); - - /* - * Add the instruction cache size - * FIXME: should determine this somehow - */ - tag_data_dummy = 0x100000; /* set it to 64K for now */ - (void)bi_TagAdd(tag_icache_size, ULONGSIZE, &tag_data_dummy); - mips_icache_size = tag_data_dummy; - - /* - * Add the data cache size - * FIXME: should determine this somehow - */ - tag_data_dummy = 0x100000; /* set it to 64K for now */ - (void)bi_TagAdd(tag_dcache_size, ULONGSIZE, &tag_data_dummy); - mips_dcache_size = tag_data_dummy; - - /* FIXME: should determine vram_base properly */ - tag_data_dummy = 0xa8000000; - (void)bi_TagAdd(tag_vram_base, ULONGSIZE, &tag_data_dummy); - - /* FIXME: dummy drive info tag */ - tag_data_dummy = 0; - (void)bi_TagAdd(tag_drive_info, ULONGSIZE, &tag_data_dummy); - - /* FIXME: do we need a dummy tag at the end? */ - tag_data_dummy = 0; - (void)bi_TagAdd(tag_dummy, 0, &tag_data_dummy); - - pmax_printf("Added tags\n"); -} /* dec_setup */ - -unsigned long dec_get_memory_size() -{ - int i, bitmap_size; - unsigned long mem_size = 0; - struct pmax_bitmap { - int pagesize; - unsigned char bitmap[64*1024*1024 - 4]; - } *bm; - - /* some free 64k */ - bm = (struct pmax_bitmap *)0x8002f000; - bitmap_size = pmax_getbitmap(bm); - - pmax_printf("Page size is: %x\n", bm->pagesize); - pmax_printf("Bitmap size is: %d bytes\n", bitmap_size); - - for (i = 0; i < bitmap_size; i++) - { - /* FIXME: very simplistically only add full sets of pages */ - if (bm->bitmap[i] == 0xff) - mem_size += (8 * bm->pagesize); - } - pmax_printf("Main memory size is: %d KB\n", (mem_size / 1024)); - return(mem_size); -} /* dec_get_memory_size */ - -unsigned char maxine_rtc_read_data(unsigned long addr) -{ - char *rtc = (char *)(PMAX_RTC_BASE); - return(rtc[addr * 4]); -} /* maxine_rtc_read_data */ - -void maxine_rtc_write_data(unsigned char data, unsigned long addr) -{ - char *rtc = (char *)(PMAX_RTC_BASE); - rtc[addr * 4] = data; -} /* maxine_rtc_read_data */ - diff -u --recursive --new-file v2.1.100/linux/arch/mips/dec/hw-access.c linux/arch/mips/dec/hw-access.c --- v2.1.100/linux/arch/mips/dec/hw-access.c Thu Jun 26 12:33:36 1997 +++ linux/arch/mips/dec/hw-access.c Wed Dec 31 16:00:00 1969 @@ -1,26 +0,0 @@ -/* - * DECstation specific hardware access code. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1996 by Paul Antoine - */ -#include -#include -#include -#include - -asmlinkage void decstation_handle_int(void); -extern unsigned char maxine_rtc_read_data(unsigned long); -extern void maxine_rtc_write_data(unsigned char, unsigned long); - -/* - * FIXME: Don't have any of the goo required to access fd etc. - */ -struct feature decstation_feature = { - 0,0,0,0,0,0,0,0,0,0,0,0,0, - maxine_rtc_read_data, - maxine_rtc_write_data -}; diff -u --recursive --new-file v2.1.100/linux/arch/mips/dec/int-handler.S linux/arch/mips/dec/int-handler.S --- v2.1.100/linux/arch/mips/dec/int-handler.S Thu Jun 26 12:33:36 1997 +++ linux/arch/mips/dec/int-handler.S Wed Dec 31 16:00:00 1969 @@ -1,260 +0,0 @@ -/* - * arch/mips/dec/int-handler.S - * - * Copyright (C) 1995, 1996 Paul M. Antoine - * - * Written by Ralf Baechle and Andreas Busse, modified for DECStation - * support by Paul Antoine. - * - * NOTE: There are references to R4X00 code in here, because there is an - * upgrade module for Personal DECStations with such a CPU! - * - * FIXME: still plenty to do in this file, as much of the code hasn't been - * modified to suit the DECStation's interrupts. - */ -#include -#include -#include -#include -#include -#include -#include - - .text - .set noreorder -/* - * decstation_handle_int: Interrupt handler for Personal DECStation 5000/2x - * - * FIXME: this is *extremely* experimental, though it is probably o.k. for - * most DECStation models. - */ - NESTED(decstation_handle_int, FR_SIZE, ra) - .set noat - SAVE_ALL - CLI - .set at - - /* - * Get pending interrupts - */ - mfc0 t0,CP0_CAUSE # get pending interrupts - mfc0 t1,CP0_STATUS # get enabled interrupts - and t0,t1 # isolate allowed ones - andi t0,0xff00 # isolate pending bits -/* - * FIXME: The following branch was: - * beqz t0,spurious_interrupt - * - * ...but the wonders of ecoff cause the gas assembler (ver 2.5.1 ) - * to complain: - * - * "Can not represent relocation in this object file format"... - * - * hence this hack to branch foward a bit, and then jump - * Perhaps a later version of gas will cope? - Paul - */ - beqz t0,3f; - sll t0,16 # delay slot - - /* - * Find irq with highest priority - * FIXME: This is slow - */ - la t1,ll_vectors -1: bltz t0,2f # found pending irq - sll t0,1 - b 1b - subu t1,PTRSIZE # delay slot - - /* - * Do the low-level stuff - */ -2: lw t0,(t1) - jr t0 - nop # delay slot - END(decstation_handle_int) - -/* - * FIXME: The hack mentioned above. - */ -3: j spurious_interrupt - nop - -/* - * FIXME: the rest of this is pretty suspect, as it's straight from - * jazz.S... and I really haven't altered it at all - Paul - */ - -/* - * Used for keyboard driver's fake_keyboard_interrupt() - * (Paul, even for i386 this is no longer being used -- Ralf) - */ -ll_sw0: li s1,~IE_SW0 - mfc0 t0,CP0_CAUSE - and t0,s1 - mtc0 t0,CP0_CAUSE - PRINT("sw0 received...\n") - li t1,1 - b call_real - li t3,PTRSIZE # delay slot, re-map to irq level 1 - -ll_sw1: li s1,~IE_SW1 - PANIC("Unimplemented sw1 handler") - -loc_no_irq: PANIC("Unimplemented loc_no_irq handler") -loc_sound: PANIC("Unimplemented loc_sound handler") -loc_video: PANIC("Unimplemented loc_video handler") -loc_scsi: PANIC("Unimplemented loc_scsi handler") - -/* - * Ethernet interrupt, remapped to level 15 - * NOTE: Due to a bug somewhere in the kernel I was not able - * to figure out, the PRINT() is necessary. Without this, - * I get a "gfp called nonatomically from interrupt 00000000". - * Only god knows why... Tell me if you find the reason! - * Andy, 6/16/95 - */ -loc_ethernet: PANIC("Unimplemented loc_ethernet\n") - -/* - * Keyboard interrupt, remapped to level 1 - */ -loc_keyboard: PANIC("Unimplemented loc_keyboard\n") - -loc_mouse: PANIC("Unimplemented loc_mouse handler") - -/* - * Serial port 1 IRQ, remapped to level 3 - */ -loc_serial1: PANIC("Unimplemented loc_serial handler") - -/* - * Serial port 2 IRQ, remapped to level 4 - */ -loc_serial2: PANIC("Unimplemented loc_serial handler") - -/* - * Parallel port IRQ, remapped to level 5 - */ -loc_parallel: PANIC("Unimplemented loc_parallel handler") - -/* - * Floppy IRQ, remapped to level 6 - */ -loc_floppy: PANIC("Unimplemented loc_floppy handler") - -/* - * Now call the real handler - */ -loc_call: la t0,IRQ_vectors # delay slot - - /* - * Temporarily disable interrupt source - */ -/* lhu t2,JAZZ_IO_IRQ_ENABLE -*/ - addu t0,t3 # make ptr to IRQ handler - lw t0,(t0) - and t2,s1 # delay slot -/* sh t2,JAZZ_IO_IRQ_ENABLE */ - jalr t0 # call IRQ handler - nor s1,zero,s1 # delay slot - - /* - * Reenable interrupt - */ -/* lhu t2,JAZZ_IO_IRQ_ENABLE */ - or t2,s1 -/* sh t2,JAZZ_IO_IRQ_ENABLE */ - - jr v0 - nop # delay slot - -ll_tc3: PANIC("Unimplemented tc3 interrupt handler") - -ll_fpu: PANIC("Unimplemented fpu interrupt handler") - -ll_io_error: PANIC("Unimplemented I/O write timeout interrupt handler") - -ll_rtc: PANIC("Unimplemented RTC interrupt handler") - -/* - * Timer IRQ - * We remap the timer irq to be more similar to a IBM compatible - */ -ll_timer: PANIC("Timer interrupt!\n"); -/* - * CPU count/compare IRQ (unused) - */ -ll_reset: li a0,0 - jal pmax_halt - li a1,0 # delay slot - -/* - * Now call the real handler - */ -call_real: la t0,IRQ_vectors # delay slot - - /* - * temporarily disable interrupt - */ - mfc0 t2,CP0_STATUS - and t2,s1 - - addu t0,t3 - lw t0,(t0) - mtc0 t2,CP0_STATUS # delay slot - jalr t0 - nor s1,zero,s1 # delay slot - - /* - * reenable interrupt - */ - mfc0 t2,CP0_STATUS - or t2,s1 - mtc0 t2,CP0_STATUS - - jr v0 - nop # delay slot - -/* - * Just for debugging... load a0 with address of the point inside the - * framebuffer at which you want to draw a line of 16x32 pixels. - * Maxine's framebuffer starts at 0xaa000000. - */ - .set reorder - LEAF(drawline) - li t1,0xffffffff # set all pixels on - li t2,0x10 # we will write 16 words -1: sw t1,(a0) # write the first word - addiu a0,a0,4 # move our framebuffer pointer - addiu t2,t2,-1 # one less to do - bnez t2,1b # finished? - jr ra - END(drawline) - -/* - * FIXME: I have begun to alter this table to reflect Personal DECStation - * (i.e. Maxine) interrupts... Paul. - */ - .data - PTR ll_sw0 # SW0 - PTR ll_sw1 # SW1 - PTR ll_timer # Periodic interrupt - PTR ll_rtc # RTC periodic interrupt - PTR ll_io_error # Timeout on I/O writes - PTR ll_tc3 # TC slot 3, motherboard - PTR ll_reset # Halt keycode (CTRL+ALT+ENTER) -ll_vectors: PTR ll_fpu # FPU - -local_vector: PTR loc_no_irq - PTR loc_parallel - PTR loc_floppy - PTR loc_sound - PTR loc_video - PTR loc_ethernet - PTR loc_scsi - PTR loc_keyboard - PTR loc_mouse - PTR loc_serial1 - PTR loc_serial2 diff -u --recursive --new-file v2.1.100/linux/arch/mips/dec/ld.script linux/arch/mips/dec/ld.script --- v2.1.100/linux/arch/mips/dec/ld.script Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/dec/ld.script Wed Dec 31 16:00:00 1969 @@ -1,47 +0,0 @@ -OUTPUT_FORMAT("ecoff-littlemips") -OUTPUT_ARCH(mips) -ENTRY(dec_entry) -SECTIONS -{ - /* This is probably a little simplistic, and is based on work by - * Chris Fraser of Softway Pty Ltd as used in his port of Vsta to - * the DECStation - Paul M. Antoine 21/1/96. - */ - . = 0x80030000; - .text : - { - *(.text) - . = ALIGN(0x10); - _etext = .; - __etext = .; - } - .lit8 : { - *(.lit8) - } - .lit4 : { - *(.lit4) - } - . = ALIGN(0x1000); - .data : - { - *(.data .rdata .rodata) - _edata = .; - __edata = .; - } - __bss_start = ALIGN(16) + 0x8000; - .sbss : - { - *(.sbss) - *(.scommon) - } - .bss : - { - *(.bss) - *(COMMON) - _end = ALIGN(4) ; - __end = ALIGN(4) ; - } - .reginfo : { - *(.reginfo) - } -} diff -u --recursive --new-file v2.1.100/linux/arch/mips/dec/reset.c linux/arch/mips/dec/reset.c --- v2.1.100/linux/arch/mips/dec/reset.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/dec/reset.c Wed Dec 31 16:00:00 1969 @@ -1,28 +0,0 @@ -/* - * linux/arch/mips/dec/process.c - * - * Reset a DECstation. - */ -#include -#include - -void dec_machine_restart(char *command) -{ - printk("Implement dec_machine_restart().\n"); - printk("Press reset to continue.\n"); - while(1); -} - -void dec_machine_halt(void) -{ - printk("Implement dec_machine_halt().\n"); - printk("Press reset to continue.\n"); - while(1); -} - -void dec_machine_power_off(void) -{ - printk("Implement dec_machine_power_off().\n"); - printk("Press reset to continue.\n"); - while(1); -} diff -u --recursive --new-file v2.1.100/linux/arch/mips/dec/setup.c linux/arch/mips/dec/setup.c --- v2.1.100/linux/arch/mips/dec/setup.c Tue Mar 10 10:03:30 1998 +++ linux/arch/mips/dec/setup.c Wed Dec 31 16:00:00 1969 @@ -1,50 +0,0 @@ -/* - * Setup pointers to hardware-dependent routines. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1996 by Ralf Baechle - */ -#include -#include -#include -#include -#include -#include -#include -#include - -extern struct feature decstation_feature; - -static void -dec_irq_setup(void) -{ - /* FIXME: should set up the clock as per above? */ - pmax_printf("Please write the IRQ setup code for the DECStation!\n"); -} - -void (*board_time_init)(struct irqaction *irq); - -static void dec_time_init(struct irqaction *irq) -{ - pmax_printf("Please write the time init code for the DECStation!\n"); -} - -extern void dec_machine_restart(char *command); -extern void dec_machine_halt(void); -extern void dec_machine_power_off(void). - -void -decstation_setup(void) -{ - irq_setup = dec_irq_setup; - board_time_init = dec_time_init; - /* FIXME: Setup fd_cacheflush */ - feature = &decstation_feature; /* FIXME: Will go away */ - - _machine_restart = dec_machine_restart; - _machine_halt = dec_machine_halt; - _machine_power_off = dec_machine_power_off; -} diff -u --recursive --new-file v2.1.100/linux/arch/mips/defconfig linux/arch/mips/defconfig --- v2.1.100/linux/arch/mips/defconfig Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/defconfig Fri May 8 00:13:23 1998 @@ -13,8 +13,10 @@ CONFIG_ACER_PICA_61=y # CONFIG_MIPS_MAGNUM_4000 is not set # CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI is not set CONFIG_SNI_RM200_PCI=y CONFIG_MIPS_JAZZ=y +CONFIG_VGA_CONSOLE=y CONFIG_PCI=y # @@ -39,6 +41,7 @@ # CONFIG_BINFMT_MISC is not set CONFIG_NET=y CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_PARPORT is not set @@ -64,7 +67,7 @@ # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_RZ1000 is not set -# CONFIG_BLK_DEV_TRITON is not set +# CONFIG_BLK_DEV_IDEPCI is not set # CONFIG_IDE_CHIPSETS is not set # @@ -74,28 +77,34 @@ # CONFIG_BLK_DEV_MD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_XD is not set -# CONFIG_BLK_DEV_EZ is not set +CONFIG_PARIDE_PARPORT=y +# CONFIG_PARIDE is not set # CONFIG_BLK_DEV_HD is not set # # Networking options # +# CONFIG_PACKET is not set # CONFIG_NETLINK is not set # CONFIG_FIREWALL is not set # CONFIG_NET_ALIAS is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y CONFIG_INET=y # CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set # CONFIG_IP_ACCT is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_ALIAS is not set # CONFIG_SYN_COOKIES is not set # # (it is safe to leave these untouched) # -# CONFIG_INET_PCTCP is not set # CONFIG_INET_RARP is not set -CONFIG_PATH_MTU_DISCOVERY=y CONFIG_IP_NOSR=y # CONFIG_SKB_LARGE is not set @@ -104,12 +113,68 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set -# CONFIG_AX25 is not set # # SCSI support # -# CONFIG_SCSI is not set +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA_DMA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR53C7xx is not set +CONFIG_SCSI_NCR53C8XX=y +# CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT is not set +# CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE is not set +# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set +CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4 +CONFIG_SCSI_NCR53C8XX_SYNC=5 +# CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_SEAGATE is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set +CONFIG_JAZZ_ESP=y # # Network device support @@ -138,14 +203,26 @@ # CONFIG_FDDI is not set # CONFIG_DLCI is not set # CONFIG_PPP is not set -# CONFIG_NET_RADIO is not set # CONFIG_SLIP is not set +# CONFIG_NET_RADIO is not set # CONFIG_TR is not set # CONFIG_WAN_DRIVERS is not set # CONFIG_LAPBETHER is not set # CONFIG_X25_ASY is not set # +# AX.25 network device drivers +# +# CONFIG_MKISS is not set +# CONFIG_BPQETHER is not set +# CONFIG_DMASCC is not set +# CONFIG_SCC is not set +# CONFIG_BAYCOM_SER_FDX is not set +# CONFIG_BAYCOM_SER_HDX is not set +# CONFIG_BAYCOM_PAR is not set +# CONFIG_SOUNDMODEM is not set + +# # ISDN subsystem # # CONFIG_ISDN is not set @@ -154,6 +231,7 @@ # CD-ROM drivers (not for SCSI or IDE/ATAPI drives) # # CONFIG_CD_NO_IDESCSI is not set +CONFIG_CDROM=y # # Filesystems @@ -169,25 +247,25 @@ CONFIG_VFAT_FS=y CONFIG_PROC_FS=y CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_RNFS_BOOTP=y -# CONFIG_RNFS_RARP is not set CONFIG_NFSD=y CONFIG_SUNRPC=y CONFIG_LOCKD=y +# CONFIG_CODA_FS is not set # CONFIG_SMB_FS is not set # CONFIG_HPFS_FS is not set +# CONFIG_NTFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_AUTOFS_FS is not set # CONFIG_UFS_FS is not set # CONFIG_MAC_PARTITION is not set +CONFIG_NLS=y # # Native Language Support # -CONFIG_NLS=y # CONFIG_NLS_CODEPAGE_437 is not set # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set @@ -221,6 +299,7 @@ CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_SERIAL=y +# CONFIG_SERIAL_CONSOLE is not set # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_MOUSE is not set @@ -228,6 +307,7 @@ # CONFIG_APM is not set # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set +# CONFIG_VIDEO_DEV is not set # CONFIG_NVRAM is not set # CONFIG_JOYSTICK is not set # CONFIG_MISC_RADIO is not set diff -u --recursive --new-file v2.1.100/linux/arch/mips/deskstation/Makefile linux/arch/mips/deskstation/Makefile --- v2.1.100/linux/arch/mips/deskstation/Makefile Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/deskstation/Makefile Wed Dec 31 16:00:00 1969 @@ -1,22 +0,0 @@ -# -# Makefile for the Deskstation family specific parts of the kernel -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# - -.S.s: - $(CPP) $(CFLAGS) $< -o $*.s -.S.o: - $(CC) $(CFLAGS) -c $< -o $*.o - -all: deskstation.o -O_TARGET := deskstation.o -O_OBJS := hw-access.o int-handler.o reset.o setup.o - -int-handler.o: int-handler.S - -clean: - -include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.100/linux/arch/mips/deskstation/hw-access.c linux/arch/mips/deskstation/hw-access.c --- v2.1.100/linux/arch/mips/deskstation/hw-access.c Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/deskstation/hw-access.c Wed Dec 31 16:00:00 1969 @@ -1,228 +0,0 @@ -/* - * Low-level hardware access stuff for Deskstation rPC44/Tyne - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1996, 1997 by Ralf Baechle - * - * $Id: hw-access.c,v 1.3 1997/07/29 17:46:42 ralf Exp $ - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern int FLOPPY_IRQ; -extern int FLOPPY_DMA; - -asmlinkage extern void deskstation_handle_int(void); - -/* - * How to access the FDC's registers. - */ -static unsigned char -fd_inb(unsigned int port) -{ - return inb_p(port); -} - -static void -fd_outb(unsigned char value, unsigned int port) -{ - outb_p(value, port); -} - -/* - * How to access the floppy DMA functions. - */ -static void -fd_enable_dma(int channel) -{ - enable_dma(channel); -} - -static void -fd_disable_dma(int channel) -{ - disable_dma(int channel); -} - -static int -fd_request_dma(int channel) -{ - return request_dma(channel, "floppy"); -} - -static void -fd_free_dma(int channel) -{ - free_dma(channel); -} - -static void -fd_clear_dma_ff(int channel) -{ - clear_dma_ff(channel); -} - -static void -fd_set_dma_mode(int channel, char mode) -{ - set_dma_mode(channel, mode); -} - -static void -fd_set_dma_addr(int channel, unsigned int addr) -{ - set_dma_addr(channel, addr); -} - -static void -fd_set_dma_count(int channel, unsigned int count) -{ - set_dma_count(channel, count); -} - -static int -fd_get_dma_residue(int channel) -{ - return get_dma_residue(channel); -} - -static void -fd_enable_irq(int irq) -{ - enable_irq(irq); -} - -static void -fd_disable_irq(int irq) -{ - disable_irq(irq); -} - -void -deskstation_fd_cacheflush(const void *addr, size_t size) -{ - flush_cache_all(); -} - -/* - * RTC stuff - */ -static unsigned char * -rtc_read_data() -{ - return 0; -} - -static void -rtc_write_data(unsigned char data) -{ -} - -/* - * KLUDGE - */ -static unsigned long -vdma_alloc(unsigned long paddr, unsigned long size) -{ - return 0; -} - -#ifdef CONFIG_DESKSTATION_TYNE -struct feature deskstation_tyne_feature = { - /* - * How to access the floppy controller's ports - */ - fd_inb, - fd_outb, - /* - * How to access the floppy DMA functions. - */ - fd_enable_dma, - fd_disable_dma, - fd_request_dma, - fd_free_dma, - fd_clear_dma_ff, - fd_set_dma_mode, - fd_set_dma_addr, - fd_set_dma_count, - fd_get_dma_residue, - fd_enable_irq, - fd_disable_irq, - /* - * How to access the RTC functions. - */ - rtc_read_data, - rtc_write_data -}; -#endif - -#ifdef CONFIG_DESKSTATION_RPC44 -struct feature deskstation_rpc44_feature = { - /* - * How to access the floppy controller's ports - */ - fd_inb, - fd_outb, - /* - * How to access the floppy DMA functions. - */ - fd_enable_dma, - fd_disable_dma, - fd_request_dma, - fd_free_dma, - fd_clear_dma_ff, - fd_set_dma_mode, - fd_set_dma_addr, - fd_set_dma_count, - fd_get_dma_residue, - fd_enable_irq, - fd_disable_irq, - /* - * How to access the RTC functions. - */ - rtc_read_data, - rtc_write_data -}; -#endif - -static unsigned char dtc_read_input(void) -{ - return inb(KBD_DATA_REG); -} - -static void dtc_write_output(unsigned char val) -{ - outb(val, KBD_DATA_REG); -} - -static void dtc_write_command(unsigned char val) -{ - outb(val, KBD_CNTL_REG); -} - -static unsigned char dtc_read_status(void) -{ - return inb(KBD_STATUS_REG); -} - -static void dtc_rm200_keyboard_setup(void) -{ - kbd_read_input = dtc_read_input; - kbd_write_output = dtc_write_output; - kbd_write_command = dtc_write_command; - kbd_read_status = dtc_read_status; - request_region(0x60, 16, "keyboard"); -} diff -u --recursive --new-file v2.1.100/linux/arch/mips/deskstation/int-handler.S linux/arch/mips/deskstation/int-handler.S --- v2.1.100/linux/arch/mips/deskstation/int-handler.S Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/deskstation/int-handler.S Wed Dec 31 16:00:00 1969 @@ -1,104 +0,0 @@ -/* - * Deskstation rPC44/Tyne specific interrupt handler code - * - * Copyright (C) 1994, 1995, 1996, 1997 by Ralf Baechle - * - * $Id: int-handler.S,v 1.3 1997/09/20 19:20:09 root Exp $ - */ -#include -#include -#include -#include -#include - -#error "FIXME - PORT_BASE is defined to mips_io_port_base which breaks this file" - - .text - .set noreorder - .set noat - .align 5 - NESTED(deskstation_handle_int, PT_SIZE, sp) - SAVE_ALL - REG_S sp,PT_OR2(sp) - CLI - .set at - lui s0,%hi(PORT_BASE) - li a0,0x0f - sb a0,%lo(PORT_BASE+0x20)(s0) # poll command - lb a0,%lo(PORT_BASE+0x20)(s0) # read result - bgtz a0,poll_second - andi a0,7 - beq a0,2,poll_second # cascade? - li s1,1 # delay slot - /* - * Acknowledge first pic - */ - lb t2,%lo(PORT_BASE+0x21)(s0) - lui s4,%hi(cache_21) - lb t0,%lo(cache_21)(s4) - sllv s1,s1,a0 - or t0,s1 - sb t0,%lo(cache_21)(s4) - sb t0,%lo(PORT_BASE+0x21)(s0) - li t2,0x20 - sb t2,%lo(PORT_BASE+0x20)(s0) - /* - * Now call the real handler - */ - jal do_IRQ - move a1,sp - /* - * Unblock first pic - */ - lbu t1,%lo(PORT_BASE+0x21)(s0) - lb t1,%lo(cache_21)(s4) - nor s1,zero,s1 - and t1,s1 - sb t1,%lo(cache_21)(s4) - j ret_from_irq - sb t1,%lo(PORT_BASE+0x21)(s0) # delay slot - - /* - * Cascade interrupt from second PIC - */ - .align 5 -poll_second: li a0,0x0f - sb a0,%lo(PORT_BASE+0xa0)(s0) # poll command - lb a0,%lo(PORT_BASE+0xa0)(s0) # read result - bgtz a0,3f - andi a0,7 - /* - * Acknowledge second pic - */ - lbu t2,%lo(PORT_BASE+0xa1)(s0) - lui s4,%hi(cache_A1) - lb t3,%lo(cache_A1)(s4) - sllv s1,s1,a0 - or t3,s1 - sb t3,%lo(cache_A1)(s4) - sb t3,%lo(PORT_BASE+0xa1)(s0) - li t3,0x20 - sb t3,%lo(PORT_BASE+0xa0)(s0) - sb t3,%lo(PORT_BASE+0x20)(s0) - /* - * Now call the real handler - */ - jal do_IRQ - nop - /* - * Unblock second pic - */ - lb t1,%lo(PORT_BASE+0xa1)(s0) - lb t1,%lo(cache_A1)(s4) - nor s1,zero,s1 - and t1,t1,s1 - sb t1,%lo(cache_A1)(s4) - j ret_from_irq - sb t1,%lo(PORT_BASE+0xa1)(s0) - -/* - * "Jump extender" to reach spurious_interrupt - */ -3: j spurious_interrupt - nop - END(deskstation_handle_int) diff -u --recursive --new-file v2.1.100/linux/arch/mips/deskstation/io.c linux/arch/mips/deskstation/io.c --- v2.1.100/linux/arch/mips/deskstation/io.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/deskstation/io.c Wed Dec 31 16:00:00 1969 @@ -1,68 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Low level I/O functions for Jazz family machine. - * - * FIXME: This implementation fits the Tyne. How does the EISA rPC44 handle - * the eight high address bits? - */ -#include -#include -#include -#include - -/* - * isa_slot_offset is the address where E(ISA) busaddress 0 is is mapped - * for the processor. - */ -extern unsigned long isa_slot_offset; - -static unsigned char deskstation_readb(unsigned long addr) -{ - return *(volatile unsigned char *) (isa_slot_offset + addr); -} - -static unsigned short deskstation_readw(unsigned long addr) -{ - return *(volatile unsigned short *) (isa_slot_offset + addr); -} - -static unsigned int deskstation_readl(unsigned long addr) -{ - return *(volatile unsigned int *) (isa_slot_offset + addr); -} - -static void deskstation_writeb(unsigned char val, unsigned long addr) -{ - *(volatile unsigned char *) (isa_slot_offset + addr) = val; -} - -static void deskstation_writew(unsigned short val, unsigned long addr) -{ - *(volatile unsigned char *) (isa_slot_offset + addr) = val; -} - -static void deskstation_writel(unsigned int val, unsigned long addr) -{ - *(volatile unsigned char *) (isa_slot_offset + addr) = val; -} - -static void deskstation_memset_io(unsigned long addr, int val, unsigned long len) -{ - addr += isa_slot_offset; - memset((void *)addr, val, len); -} - -static void deskstation_memcpy_fromio(unsigned long to, unsigned long from, unsigned long len) -{ - from += isa_slot_offset; - memcpy((void *)to, (void *)from, len); -} - -static void deskstation_memcpy_toio(unsigned long to, unsigned long from, unsigned long len) -{ - to += isa_slot_offset; - memcpy((void *)to, (void *)from, len); -} diff -u --recursive --new-file v2.1.100/linux/arch/mips/deskstation/reset.c linux/arch/mips/deskstation/reset.c --- v2.1.100/linux/arch/mips/deskstation/reset.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/deskstation/reset.c Wed Dec 31 16:00:00 1969 @@ -1,29 +0,0 @@ -/* - * linux/arch/mips/deskstation/process.c - * - * Reset a Deskstation. - */ -#include -#include -#include - -void deskstation_machine_restart(void) -{ - printk("Implement deskstation_machine_restart().\n"); - printk("Press reset to continue.\n"); - while(1); -} - -void deskstation_machine_halt(void) -{ - printk("Implement deskstation_machine_halt().\n"); - printk("Press reset to continue.\n"); - while(1); -} - -void deskstation_machine_power_off(void) -{ - printk("Implement dec_machine_power_off().\n"); - printk("Press reset to continue.\n"); - while(1); -} diff -u --recursive --new-file v2.1.100/linux/arch/mips/deskstation/setup.c linux/arch/mips/deskstation/setup.c --- v2.1.100/linux/arch/mips/deskstation/setup.c Tue Mar 10 10:03:30 1998 +++ linux/arch/mips/deskstation/setup.c Wed Dec 31 16:00:00 1969 @@ -1,113 +0,0 @@ -/* - * Setup pointers to hardware-dependent routines. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1996, 1997 by Ralf Baechle - * - * $Id: setup.c,v 1.2 1997/07/23 17:40:54 ralf Exp $ - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Initial irq handlers. - */ -static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } - -/* - * IRQ2 is cascade interrupt to second interrupt controller - */ -static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL}; - -extern asmlinkage void deskstation_handle_int(void); -extern asmlinkage void deskstation_fd_cacheflush(const void *addr, size_t size); -extern struct feature deskstation_tyne_feature; -extern struct feature deskstation_rpc44_feature; - -extern void deskstation_machine_reboot(void); -extern void deskstation_machine_halt(void); -extern void deskstation_machine_power_off(void); - -#ifdef CONFIG_DESKSTATION_TYNE -unsigned long mips_dma_cache_size = 0; -unsigned long mips_dma_cache_base = KSEG0; - -__initfunc(static void tyne_irq_setup(void)) -{ - set_except_vector(0, deskstation_handle_int); - /* set the clock to 100 Hz */ - outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ - outb_p(LATCH & 0xff , 0x40); /* LSB */ - outb(LATCH >> 8 , 0x40); /* MSB */ - request_region(0x20,0x20, "pic1"); - request_region(0xa0,0x20, "pic2"); - setup_x86_irq(2, &irq2); -} -#endif - -#ifdef CONFIG_DESKSTATION_RPC44 -__initfunc(static void rpc44_irq_setup(void)) -{ - /* - * For the moment just steal the TYNE support. In the - * future, we need to consider merging the two -- imp - */ - set_except_vector(0, deskstation_handle_int); - /* set the clock to 100 Hz */ - outb_p(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */ - outb_p(LATCH & 0xff , 0x40); /* LSB */ - outb(LATCH >> 8 , 0x40); /* MSB */ - request_region(0x20,0x20, "pic1"); - request_region(0xa0,0x20, "pic2"); - setup_x86_irq(2, &irq2); - set_cp0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1); -} -#endif - -__initfunc(void deskstation_setup(void)) -{ - switch(mips_machtype) { -#ifdef CONFIG_DESKSTATION_TYNE - case MACH_DESKSTATION_TYNE: - atag = bi_TagFind(tag_dma_cache_size); - memcpy(&mips_dma_cache_size, TAGVALPTR(atag), atag->size); - - atag = bi_TagFind(tag_dma_cache_base); - memcpy(&mips_dma_cache_base, TAGVALPTR(atag), atag->size); - - irq_setup = tyne_irq_setup; - feature = &deskstation_tyne_feature; - isa_slot_offset = 0xe3000000; // Will go away - break; -#endif -#ifdef CONFIG_DESKSTATION_RPC44 - case MACH_DESKSTATION_RPC44: - irq_setup = rpc44_irq_setup; - mips_memory_upper = KSEG0 + (32 << 20); /* xxx fixme imp */ - feature = &deskstation_rpc44_feature; // Will go away - isa_slot_offset = 0xa0000000; - break; -#endif - } - fd_cacheflush = deskstation_fd_cacheflush; - keyboard_setup = dtc_keyboard_setup; - request_region(0x00,0x20,"dma1"); - request_region(0x40,0x20,"timer"); - request_region(0x70,0x10,"rtc"); - request_region(0x80,0x10,"dma page reg"); - request_region(0xc0,0x20,"dma2"); -} diff -u --recursive --new-file v2.1.100/linux/arch/mips/jazz/g364.c linux/arch/mips/jazz/g364.c --- v2.1.100/linux/arch/mips/jazz/g364.c Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/jazz/g364.c Fri May 8 00:13:23 1998 @@ -10,6 +10,8 @@ * Olivetti M700-10 ie. an Inmos G364 based card in a dedicated video slot, * 2MB dual ported VRAM with a 64 bit data path, 256 color lookup table, * palette of 16.7M and a user definable 64x64 hardware cursor. + * + * $Id: g364.c,v 1.7 1998/05/01 01:33:35 ralf Exp $ */ #include #include @@ -431,4 +433,12 @@ void set_vesa_blanking(const unsigned long arg) { +} + +/* + * FIXME: how can we probe for the video board? + */ +__initfunc(int con_is_present()) +{ + return; } diff -u --recursive --new-file v2.1.100/linux/arch/mips/jazz/hw-access.c linux/arch/mips/jazz/hw-access.c --- v2.1.100/linux/arch/mips/jazz/hw-access.c Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/jazz/hw-access.c Fri May 8 00:13:23 1998 @@ -7,9 +7,10 @@ * * Copyright (C) 1995, 1996, 1997 by Ralf Baechle * - * $Id: hw-access.c,v 1.4 1997/07/29 17:46:45 ralf Exp $ + * $Id: hw-access.c,v 1.4 1998/05/01 01:33:36 ralf Exp $ */ #include +#include #include #include #include @@ -173,11 +174,12 @@ return jazz_kh->command; } -void jazz_keyboard_setup(void) +__initfunc(void jazz_keyboard_setup(void)) { kbd_read_input = jazz_read_input; kbd_write_output = jazz_write_output; kbd_write_command = jazz_write_command; kbd_read_status = jazz_read_status; request_region(0x60, 16, "keyboard"); + r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | JAZZ_IE_KEYBOARD); } diff -u --recursive --new-file v2.1.100/linux/arch/mips/jazz/int-handler.S linux/arch/mips/jazz/int-handler.S --- v2.1.100/linux/arch/mips/jazz/int-handler.S Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/jazz/int-handler.S Fri May 8 00:13:23 1998 @@ -10,7 +10,7 @@ * Squeeze the last cycles out of the handlers. Only a dead * cycle is a good cycle. * - * $Id: int-handler.S,v 1.3 1997/09/20 19:20:11 root Exp $ + * $Id: int-handler.S,v 1.5 1998/05/01 01:33:37 ralf Exp $ */ #include #include @@ -114,16 +114,8 @@ */ jal do_IRQ move a1,sp - /* - * Unblock first pic - */ - lbu a0,%lo(JAZZ_PORT_BASE)+0x21(s0) - lb a0,%lo(cache_21)(s4) - nor s1,zero,s1 - and a0,s1 - sb a0,%lo(cache_21)(s4) j ret_from_irq - sb a0,%lo(JAZZ_PORT_BASE)+0x21(s0) + nop .align 5 ack_second: /* @@ -142,19 +134,12 @@ /* * Now call the real handler */ + or a0, 8 jal do_IRQ move a1,sp - /* - * Unblock second pic - */ - lb a0,%lo(JAZZ_PORT_BASE)+0xa1(s0) - lb a0,%lo(cache_A1)(s4) - nor s1,zero,s1 - and a0,s1 - sb a0,%lo(cache_A1)(s4) j ret_from_irq - sb a0,%lo(JAZZ_PORT_BASE)+0xa1(s0) + nop /* * Hmm... This is not just a plain PC clone so the question is @@ -236,7 +221,7 @@ .set reorder loc_no_irq: PANIC("Unimplemented loc_no_irq handler") /* - * Parallel port IRQ, remapped to level 5 + * Parallel port IRQ */ loc_parallel: li s1,~JAZZ_IE_PARALLEL li a0,JAZZ_PARALLEL_IRQ @@ -256,14 +241,17 @@ loc_video: PANIC("Unimplemented loc_video handler") /* - * Ethernet interrupt handler, remapped to level 13 + * Ethernet interrupt handler */ loc_ethernet: li s1,~JAZZ_IE_ETHERNET li a0,JAZZ_ETHERNET_IRQ b loc_call +/* + * SCSI interrupt handler + */ loc_scsi: li s1,~JAZZ_IE_SCSI - li a0,12 # JAZZ_SCSI_IRQ + li a0,JAZZ_SCSI_IRQ b loc_call /* @@ -276,14 +264,14 @@ loc_mouse: PANIC("Unimplemented loc_mouse handler") /* - * Serial port 1 IRQ, remapped to level 3 + * Serial port 1 IRQ */ loc_serial1: li s1,~JAZZ_IE_SERIAL1 li a0,JAZZ_SERIAL1_IRQ b loc_call /* - * Serial port 2 IRQ, remapped to level 4 + * Serial port 2 IRQ */ loc_serial2: li s1,~JAZZ_IE_SERIAL2 li a0,JAZZ_SERIAL2_IRQ diff -u --recursive --new-file v2.1.100/linux/arch/mips/jazz/jazzdma.c linux/arch/mips/jazz/jazzdma.c --- v2.1.100/linux/arch/mips/jazz/jazzdma.c Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/jazz/jazzdma.c Fri May 8 00:13:23 1998 @@ -514,3 +514,18 @@ return residual; } + +/* + * Get DMA channel enable register + */ +int vdma_get_enable(int channel) +{ + int enable; + + enable = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)); + + if (vdma_debug) + printk("vdma_get_enable: channel %d: enable=%d\n",channel,enable); + + return enable; +} diff -u --recursive --new-file v2.1.100/linux/arch/mips/jazz/reset.c linux/arch/mips/jazz/reset.c --- v2.1.100/linux/arch/mips/jazz/reset.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/jazz/reset.c Fri May 8 00:13:23 1998 @@ -2,16 +2,36 @@ * linux/arch/mips/jazz/process.c * * Reset a Jazz machine. + * + * $Id: reset.c,v 1.2 1998/05/01 01:33:40 ralf Exp $ */ + +#include +#include #include #include #include +#include +#include + +static inline void kb_wait(void) +{ + unsigned long start = jiffies; + + do { + if (! (kbd_read_status() & 0x02)) + return; + } while (jiffies - start < 50); +} void jazz_machine_restart(char *command) { - printk("Implement jazz_machine_restart().\n"); - printk("Press reset to continue.\n"); - while(1); + while (1) { + kb_wait (); + kbd_write_command (0xd1); + kb_wait (); + kbd_write_output (0x00); + } } void jazz_machine_halt(void) diff -u --recursive --new-file v2.1.100/linux/arch/mips/jazz/setup.c linux/arch/mips/jazz/setup.c --- v2.1.100/linux/arch/mips/jazz/setup.c Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/jazz/setup.c Fri May 8 00:13:23 1998 @@ -1,5 +1,5 @@ /* - * Setup pointers to hardware dependand routines. + * Setup pointers to hardware dependant routines. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -7,20 +7,25 @@ * * Copyright (C) 1996, 1997 by Ralf Baechle * - * $Id: setup.c,v 1.5 1997/12/02 05:51:05 ralf Exp $ + * $Id: setup.c,v 1.6 1998/05/04 09:17:45 ralf Exp $ */ +#include +#include #include #include #include #include +#include #include #include +#include #include #include #include #include #include #include +#include /* * Initial irq handlers. @@ -41,6 +46,8 @@ extern void jazz_machine_halt(void); extern void jazz_machine_power_off(void); +extern struct ide_ops std_ide_ops; + void (*board_time_init)(struct irqaction *irq); __initfunc(static void jazz_time_init(struct irqaction *irq)) @@ -118,4 +125,8 @@ _machine_restart = jazz_machine_restart; _machine_halt = jazz_machine_halt; _machine_power_off = jazz_machine_power_off; + +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &std_ide_ops; +#endif } diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/Makefile linux/arch/mips/kernel/Makefile --- v2.1.100/linux/arch/mips/kernel/Makefile Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/Makefile Fri May 8 00:13:23 1998 @@ -14,8 +14,8 @@ O_TARGET := kernel.o O_OBJS := branch.o process.o signal.o entry.o traps.o ptrace.o vm86.o \ ioport.o pci.o reset.o setup.o syscall.o sysmips.o ipc.o \ - r4k_switch.o r4k_misc.o r4k_scall.o r4k_fpu.o r2300_switch.o \ - r2300_misc.o r2300_scall.o r2300_fpu.o r6000_fpu.o unaligned.o + r4k_switch.o r4k_misc.o r4k_fpu.o r2300_switch.o r2300_misc.o \ + r2300_fpu.o r6000_fpu.o scall_o32.o unaligned.o OX_OBJS := mips_ksyms.o ifdef CONFIG_MIPS_FPE_MODULE @@ -68,15 +68,11 @@ # #r4k_misc.o: r4k_misc.S # -#r4k_scall.o: r4k_scall.S -# #r4k_fpu.o: r4k_fpu.S # #r2300_switch.o: r2300_switch.S # #r2300_misc.o: r2300_misc.S -# -#r2300_scall.o: r2300_scall.S # #r2300_fpu.o: r2300_fpu.S # diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/entry.S linux/arch/mips/kernel/entry.S --- v2.1.100/linux/arch/mips/kernel/entry.S Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/entry.S Fri May 8 00:13:23 1998 @@ -7,7 +7,7 @@ * * Copyright (C) 1994, 1995 by Ralf Baechle * - * $Id: entry.S,v 1.4 1997/09/20 19:20:13 root Exp $ + * $Id: entry.S,v 1.9 1998/05/04 09:17:50 ralf Exp $ */ /* @@ -40,7 +40,7 @@ .set noreorder .set mips3 .align 4 -handle_bottom_half: +EXPORT(handle_bottom_half) jal do_bottom_half nop b 9f @@ -57,24 +57,16 @@ bnez t0,handle_bottom_half 9: lw t0,PT_STATUS(sp) # returning to kernel mode? - andi t1,t0, 0x10 - beqz t1,return # -> yes - lw t1,need_resched - bnez t1,reschedule - GET_CURRENT(s0) - lw t0,task - lw a0,TASK_BLOCKED(s0) - - beq s0,t0,return # task[0] cannot have signals - lw t0,TASK_SIGNAL(s0) - - nor t1,zero,a0 - and t1,t0,t1 - beqz t1,return + andi t1, t0, 0x10 + beqz t1, return # -> yes + lw t1, need_resched + bnez t1, reschedule + lw v0, TASK_SIGPENDING($28) + move a0, zero + beqz v0, return nop - jal do_signal - move a1,sp + move a1, sp EXPORT(return) .set noat RESTORE_ALL @@ -104,14 +96,22 @@ * the C preprocessor ... */ #define __BUILD_clear_none(exception) +#define __BUILD_clear_sti(exception) \ + STI +#define __BUILD_clear_cli(exception) \ + CLI +#define __BUILD_clear_kmode(exception) \ + KMODE #define __BUILD_clear_fpe(exception) \ cfc1 a1,fcr31; \ li a2,~(0x3f<<12); \ and a2,a1; \ - ctc1 a2,fcr31; + ctc1 a2,fcr31; \ + STI #define __BUILD_clear_ade(exception) \ MFC0 t0,CP0_BADVADDR; \ - REG_S t0,PT_BVADDR(sp); + REG_S t0,PT_BVADDR(sp); \ + STI #define __BUILD_silent(exception) #define fmt "Got %s at %08lx.\n" @@ -137,32 +137,28 @@ .set noat; \ SAVE_ALL; \ __BUILD_clear_##clear(exception); \ - STI; \ .set at; \ __BUILD_##verbose(exception); \ - li t0,-1; /* not a sys call */ \ - REG_S t0,PT_OR2(sp); \ jal do_##handler; \ move a0,sp; \ j ret_from_sys_call; \ nop; \ END(handle_##exception) - BUILD_HANDLER(adel,ade,ade,silent) /* #4 */ - BUILD_HANDLER(ades,ade,ade,silent) /* #5 */ - BUILD_HANDLER(ibe,ibe,none,verbose) /* #6 */ - BUILD_HANDLER(dbe,dbe,none,verbose) /* #7 */ - BUILD_HANDLER(sys,sys,none,silent) /* #8 */ - BUILD_HANDLER(bp,bp,none,silent) /* #9 */ - BUILD_HANDLER(ri,ri,none,silent) /* #10 */ - BUILD_HANDLER(cpu,cpu,none,silent) /* #11 */ - BUILD_HANDLER(ov,ov,none,silent) /* #12 */ - BUILD_HANDLER(tr,tr,none,silent) /* #13 */ - BUILD_HANDLER(vcei,vcei,none,verbose) /* #14 */ + BUILD_HANDLER(adel,ade,kmode,silent) /* #4 */ + BUILD_HANDLER(ades,ade,kmode,silent) /* #5 */ + BUILD_HANDLER(ibe,ibe,cli,verbose) /* #6 */ + BUILD_HANDLER(dbe,dbe,cli,verbose) /* #7 */ + BUILD_HANDLER(bp,bp,sti,silent) /* #9 */ + BUILD_HANDLER(ri,ri,sti,silent) /* #10 */ + BUILD_HANDLER(cpu,cpu,sti,silent) /* #11 */ + BUILD_HANDLER(ov,ov,sti,silent) /* #12 */ + BUILD_HANDLER(tr,tr,sti,silent) /* #13 */ + BUILD_HANDLER(vcei,vcei,sti,verbose) /* #14 */ BUILD_HANDLER(fpe,fpe,fpe,silent) /* #15 */ - BUILD_HANDLER(watch,watch,none,verbose) /* #23 */ - BUILD_HANDLER(vced,vced,none,verbose) /* #31 */ - BUILD_HANDLER(reserved,reserved,none,verbose) /* others */ + BUILD_HANDLER(watch,watch,sti,verbose) /* #23 */ + BUILD_HANDLER(vced,vced,sti,verbose) /* #31 */ + BUILD_HANDLER(reserved,reserved,sti,verbose) /* others */ /* * Table of syscalls diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/fpe.c linux/arch/mips/kernel/fpe.c --- v2.1.100/linux/arch/mips/kernel/fpe.c Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/fpe.c Fri May 8 00:13:23 1998 @@ -6,7 +6,7 @@ * * Copyright (C) 1997 Ralf Baechle * - * $Id: fpe.c,v 1.1 1997/08/11 04:17:18 ralf Exp $ + * $Id: fpe.c,v 1.2 1998/05/01 01:33:48 ralf Exp $ */ #include #include @@ -18,7 +18,7 @@ #include #include -MODULE_AUTHOR("Ralf Baechle "); +MODULE_AUTHOR("Ralf Baechle "); MODULE_DESCRIPTION("Experimental floating point exception handler"); MODULE_SUPPORTED_DEVICE("MIPS FPU"); diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/gdb-low.S linux/arch/mips/kernel/gdb-low.S --- v2.1.100/linux/arch/mips/kernel/gdb-low.S Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/gdb-low.S Fri May 8 00:13:23 1998 @@ -5,7 +5,7 @@ * * Copyright (C) 1995 Andreas Busse * - * $Id: gdb-low.S,v 1.3 1997/12/02 05:51:05 ralf Exp $ + * $Id: gdb-low.S,v 1.4 1998/05/01 01:33:50 ralf Exp $ */ #include diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/gdb-stub.c linux/arch/mips/kernel/gdb-stub.c --- v2.1.100/linux/arch/mips/kernel/gdb-stub.c Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/gdb-stub.c Fri May 8 00:13:23 1998 @@ -12,7 +12,7 @@ * * Copyright (C) 1995 Andreas Busse * - * $Id: gdb-stub.c,v 1.4 1997/12/02 05:51:06 ralf Exp $ + * $Id: gdb-stub.c,v 1.7 1998/05/01 01:33:51 ralf Exp $ */ /* diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/head.S linux/arch/mips/kernel/head.S --- v2.1.100/linux/arch/mips/kernel/head.S Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/head.S Fri May 8 00:13:23 1998 @@ -8,7 +8,7 @@ * * Head.S contains the MIPS exception handler and startup code. * - * $Id: head.S,v 1.10 1997/11/13 12:55:29 ralf Exp $ + * $Id: head.S,v 1.9 1998/05/01 01:33:53 ralf Exp $ */ #include #include @@ -397,6 +397,11 @@ nop #endif +#ifdef CONFIG_COBALT_MICRO_SERVER + jal SetUpBootInfo + nop +#endif + /* Get the very one tags we need early in the boot process */ nop jal bi_EarlySnarf @@ -442,9 +447,10 @@ nop /* - * Stack for kernel and init + * Stack for kernel and init, current variable */ -9: la t0, init_task_union+KERNEL_STACK_SIZE-32 +9: la $28, init_task_union + addiu t0, $28, KERNEL_STACK_SIZE-32 sw t0, kernelsp subu sp, t0, 4*SZREG diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/init_task.c linux/arch/mips/kernel/init_task.c --- v2.1.100/linux/arch/mips/kernel/init_task.c Tue Mar 17 22:18:14 1998 +++ linux/arch/mips/kernel/init_task.c Fri May 8 00:13:23 1998 @@ -1,6 +1,7 @@ #include #include +#include #include static struct vm_area_struct init_mmap = INIT_MMAP; diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/ipc.c linux/arch/mips/kernel/ipc.c --- v2.1.100/linux/arch/mips/kernel/ipc.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/kernel/ipc.c Fri May 8 00:13:23 1998 @@ -101,7 +101,7 @@ } case 1: /* iBCS2 emulator entry point */ ret = -EINVAL; - if (get_fs() != get_ds()) + if (!segment_eq(get_fs(), get_ds())) goto out; ret = sys_shmat (first, (char *) ptr, second, (ulong *) third); goto out; diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/irix5sys.h linux/arch/mips/kernel/irix5sys.h --- v2.1.100/linux/arch/mips/kernel/irix5sys.h Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/irix5sys.h Fri May 8 00:13:23 1998 @@ -1,4 +1,4 @@ -/* $Id: irix5sys.h,v 1.1.1.1 1997/06/01 03:16:43 ralf Exp $ +/* $Id: irix5sys.h,v 1.3 1998/05/01 01:33:55 ralf Exp $ * irix5sys.h: 32-bit IRIX5 ABI system call table. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/irixelf.c linux/arch/mips/kernel/irixelf.c --- v2.1.100/linux/arch/mips/kernel/irixelf.c Mon Jan 12 14:52:46 1998 +++ linux/arch/mips/kernel/irixelf.c Fri May 8 00:13:23 1998 @@ -30,6 +30,8 @@ #include #include +#include +#include #include @@ -52,6 +54,11 @@ #endif }; +#ifndef elf_addr_t +#define elf_addr_t unsigned long +#define elf_caddr_t char * +#endif + #ifdef DEBUG_ELF /* Debugging routines. */ static char *get_elf_p_type(Elf32_Word p_type) @@ -152,68 +159,67 @@ unsigned int interp_load_addr, struct pt_regs *regs, struct elf_phdr *ephdr) { - char **argv, **envp; - unsigned long *sp; - unsigned long *csp; - + elf_caddr_t *argv; + elf_caddr_t *envp; + elf_addr_t *sp, *csp; + #ifdef DEBUG_ELF printk("create_irix_tables: p[%p] argc[%d] envc[%d] " "load_addr[%08x] interp_load_addr[%08x]\n", p, argc, envc, load_addr, interp_load_addr); #endif - sp = (unsigned long *) (0xfffffffc & (unsigned long) p); - - /* Make sure we will be aligned properly at the end of this. */ + sp = (elf_addr_t *) (~15UL & (unsigned long) p); csp = sp; csp -= exec ? DLINFO_ITEMS*2 : 2; - csp -= envc + 1; + csp -= envc+1; csp -= argc+1; - if (!(((unsigned long) csp) & 4)) - sp--; - - sp -= exec ? DLINFO_ITEMS*2 : 2; - sp -= envc+1; - envp = (char **) sp; - sp -= argc+1; - argv = (char **) sp; - - __put_user((unsigned long)argc, --sp); + csp -= 1; /* argc itself */ + if ((unsigned long)csp & 15UL) { + sp -= (16UL - ((unsigned long)csp & 15UL)) / sizeof(*sp); + } + /* + * Put the ELF interpreter info on the stack + */ #define NEW_AUX_ENT(nr, id, val) \ - __put_user ((id), sp+(nr*2)); \ - __put_user ((val), sp+(nr*2+1)); \ + __put_user ((id), sp+(nr*2)); \ + __put_user ((val), sp+(nr*2+1)); \ -#define INTERP_ALIGN (~((64 * 1024) - 1)) + sp -= 2; + NEW_AUX_ENT(0, AT_NULL, 0); - NEW_AUX_ENT (0, AT_NULL, 0); if(exec) { - struct elf_phdr * eppnt; - eppnt = (struct elf_phdr *) exec->e_phoff; + sp -= 11*2; - /* Put this here for an ELF program interpreter */ - NEW_AUX_ENT (0, AT_PHDR, ephdr->p_vaddr); + NEW_AUX_ENT (0, AT_PHDR, load_addr + exec->e_phoff); NEW_AUX_ENT (1, AT_PHENT, sizeof (struct elf_phdr)); NEW_AUX_ENT (2, AT_PHNUM, exec->e_phnum); - NEW_AUX_ENT (3, AT_PAGESZ, PAGE_SIZE); - NEW_AUX_ENT (4, AT_BASE, (interp_load_addr & (INTERP_ALIGN))); + NEW_AUX_ENT (3, AT_PAGESZ, ELF_EXEC_PAGESIZE); + NEW_AUX_ENT (4, AT_BASE, interp_load_addr); NEW_AUX_ENT (5, AT_FLAGS, 0); - NEW_AUX_ENT (6, AT_ENTRY, (unsigned long) exec->e_entry); - NEW_AUX_ENT (7, AT_UID, (unsigned long) current->uid); - NEW_AUX_ENT (8, AT_EUID, (unsigned long) current->euid); - NEW_AUX_ENT (9, AT_GID, (unsigned long) current->gid); - NEW_AUX_ENT (10, AT_EGID, (unsigned long) current->egid); + NEW_AUX_ENT (6, AT_ENTRY, (elf_addr_t) exec->e_entry); + NEW_AUX_ENT (7, AT_UID, (elf_addr_t) current->uid); + NEW_AUX_ENT (8, AT_EUID, (elf_addr_t) current->euid); + NEW_AUX_ENT (9, AT_GID, (elf_addr_t) current->gid); + NEW_AUX_ENT (10, AT_EGID, (elf_addr_t) current->egid); } #undef NEW_AUX_ENT + sp -= envc+1; + envp = (elf_caddr_t *) sp; + sp -= argc+1; + argv = (elf_caddr_t *) sp; + + __put_user((elf_addr_t)argc,--sp); current->mm->arg_start = (unsigned long) p; while (argc-->0) { - __put_user(p, argv++); + __put_user((elf_caddr_t)(unsigned long)p,argv++); p += strlen_user(p); } __put_user(NULL, argv); current->mm->arg_end = current->mm->env_start = (unsigned long) p; while (envc-->0) { - __put_user(p, envp++); + __put_user((elf_caddr_t)(unsigned long)p,envp++); p += strlen_user(p); } __put_user(NULL, envp); @@ -441,7 +447,8 @@ struct elf_phdr *epp, struct linux_binprm *bprm, int pnum) { - int i, old_fs; + mm_segment_t old_fs; + int i; int retval = -EINVAL; struct dentry *dentry = NULL; @@ -473,9 +480,8 @@ retval = PTR_ERR(dentry); goto out; } - retval = read_exec(dentry, 0, bprm->buf, 128, 1); - if(retval) + if(retval < 0) goto dput_and_out; *interp_elf_ex = *((struct elfhdr *) bprm->buf); @@ -546,7 +552,7 @@ static inline int map_interpreter(struct elf_phdr *epp, struct elfhdr *ihp, struct dentry *identry, unsigned int *iladdr, - int pnum, int old_fs, + int pnum, mm_segment_t old_fs, unsigned int *eentry) { int i; @@ -573,6 +579,32 @@ return 0; } +/* + * IRIX maps a page at 0x200000 that holds information about the + * process and the system, here we map the page and fill the + * structure + */ +void irix_map_prda_page (void) +{ + unsigned long v; + struct prda *pp; + + v = do_mmap (NULL, PRDA_ADDRESS, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, 0); + + if (v < 0) + return; + + pp = (struct prda *) v; + pp->prda_sys.t_pid = current->pid; + pp->prda_sys.t_prid = read_32bit_cp0_register (CP0_PRID); + pp->prda_sys.t_rpid = current->pid; + + /* We leave the rest set to zero */ +} + + + /* These are the functions used to load ELF style executables and shared * libraries. There is no binary dependent code anywhere else. */ @@ -585,8 +617,9 @@ unsigned int load_addr, elf_bss, elf_brk; unsigned int elf_entry, interp_load_addr = 0; unsigned int start_code, end_code, end_data, elf_stack; - int old_fs, elf_exec_fileno, retval, has_interp, has_ephdr, i; + int elf_exec_fileno, retval, has_interp, has_ephdr, i; char *elf_interpreter; + mm_segment_t old_fs; load_addr = 0; has_interp = has_ephdr = 0; @@ -760,6 +793,12 @@ */ set_brk(elf_bss, elf_brk); + /* + * IRIX maps a page at 0x200000 which holds some system + * information. Programs depend on this. + */ + irix_map_prda_page (); + padzero(elf_bss); #ifdef DEBUG_ELF @@ -1086,7 +1125,7 @@ struct file file; struct dentry *dentry; struct inode *inode; - unsigned short fs; + mm_segment_t fs; char corefile[6+sizeof(current->comm)]; int segs; int i; @@ -1190,8 +1229,8 @@ notes[0].datasz = sizeof(prstatus); notes[0].data = &prstatus; prstatus.pr_info.si_signo = prstatus.pr_cursig = signr; - prstatus.pr_sigpend = current->signal; - prstatus.pr_sighold = current->blocked; + prstatus.pr_sigpend = current->signal.sig[0]; + prstatus.pr_sighold = current->blocked.sig[0]; psinfo.pr_pid = prstatus.pr_pid = current->pid; psinfo.pr_ppid = prstatus.pr_ppid = current->p_pptr->pid; psinfo.pr_pgrp = prstatus.pr_pgrp = current->pgrp; diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/irixinv.c linux/arch/mips/kernel/irixinv.c --- v2.1.100/linux/arch/mips/kernel/irixinv.c Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/irixinv.c Fri May 8 00:13:23 1998 @@ -5,9 +5,10 @@ * * Miguel de Icaza, 1997. * - * $Id: irixinv.c,v 1.2 1997/12/06 21:29:58 ralf Exp $ + * $Id: irixinv.c,v 1.2 1998/05/01 01:33:58 ralf Exp $ */ #include +#include #include #include #include @@ -52,8 +53,7 @@ return inventory_items * sizeof (inventory_t); } -void -init_inventory (void) +__initfunc(void init_inventory (void)) { /* gross hack while we put the right bits all over the kernel * most likely this will not let just anyone run the X server diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/irixioctl.c linux/arch/mips/kernel/irixioctl.c --- v2.1.100/linux/arch/mips/kernel/irixioctl.c Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/irixioctl.c Fri May 8 00:13:23 1998 @@ -1,4 +1,4 @@ -/* $Id: irixioctl.c,v 1.2 1997/12/02 05:51:06 ralf Exp $ +/* $Id: irixioctl.c,v 1.6 1998/05/01 01:33:59 ralf Exp $ * irixioctl.c: A fucking mess... * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -56,8 +56,8 @@ asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg) { struct tty_struct *tp, *rtp; + mm_segment_t old_fs; int error = 0; - int old_fs; lock_kernel(); #ifdef DEBUG_IOCTLS @@ -237,7 +237,7 @@ default: { #ifdef DEBUG_MISSING_IOCTL - char *msg = "Unimplemented IOCTL cmd tell dm@engr.sgi.com\n"; + char *msg = "Unimplemented IOCTL cmd tell linux@engr.sgi.com\n"; #ifdef DEBUG_IOCTLS printk("UNIMP_IOCTL, %08lx)\n", arg); diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/irixsig.c linux/arch/mips/kernel/irixsig.c --- v2.1.100/linux/arch/mips/kernel/irixsig.c Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/irixsig.c Fri May 8 00:13:23 1998 @@ -1,7 +1,9 @@ -/* $Id: irixsig.c,v 1.5 1997/12/06 09:57:38 ralf Exp $ +/* * irixsig.c: WHEEE, IRIX signals! YOW, am I compatable or what?!?! * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: irixsig.c,v 1.8 1998/05/01 01:34:00 ralf Exp $ */ #include @@ -15,12 +17,19 @@ #include #include +asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, + int options, unsigned long *ru); + #undef DEBUG_SIG #define _S(nr) (1<<((nr)-1)) #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) +typedef struct { + unsigned long sig[4]; +} irix_sigset_t; + struct sigctx_irix5 { u32 rmask, cp0_status; u64 pc; @@ -29,7 +38,7 @@ u32 usedfp, fpcsr, fpeir, sstk_flags; u64 hi, lo; u64 cp0_cause, cp0_badvaddr, _unused0; - u32 sigset[4]; + irix_sigset_t sigset; u64 weird_fpu_thing; u64 _unused1[31]; }; @@ -63,14 +72,15 @@ (unsigned long) c->hi, (unsigned long) c->lo, (unsigned long) c->cp0_cause, (unsigned long) c->cp0_badvaddr); printk("misc: sigset<0>[%08lx] sigset<1>[%08lx] sigset<2>[%08lx] " - "sigset<3>[%08lx]\n", (unsigned long) c->sigset[0], - (unsigned long) c->sigset[1], (unsigned long) c->sigset[2], - (unsigned long) c->sigset[3]); + "sigset<3>[%08lx]\n", (unsigned long) c->sigset.sig[0], + (unsigned long) c->sigset.sig[1], + (unsigned long) c->sigset.sig[2], + (unsigned long) c->sigset.sig[3]); } #endif -static void setup_irix_frame(struct sigaction * sa, struct pt_regs *regs, - int signr, unsigned long oldmask) +static void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs, + int signr, sigset_t *oldmask) { unsigned long sp; struct sigctx_irix5 *ctx; @@ -98,10 +108,7 @@ __put_user(0, &ctx->sstk_flags); /* XXX sigstack unimp... todo... */ - __put_user(0, &ctx->sigset[1]); - __put_user(0, &ctx->sigset[2]); - __put_user(0, &ctx->sigset[3]); - __put_user(oldmask, &ctx->sigset[0]); + __copy_to_user(&ctx->sigset, oldmask, sizeof(irix_sigset_t)); #ifdef DEBUG_SIG dump_irix5_sigctx(ctx); @@ -110,7 +117,7 @@ regs->regs[5] = 0; /* XXX sigcode XXX */ regs->regs[4] = (unsigned long) signr; regs->regs[6] = regs->regs[29] = sp; - regs->regs[7] = (unsigned long) sa->sa_handler; + regs->regs[7] = (unsigned long) ka->sa.sa_handler; regs->regs[25] = regs->cp0_epc = current->tss.irix_trampoline; return; @@ -120,52 +127,121 @@ unlock_kernel(); } -asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, - int options, unsigned long *ru); +static void inline +setup_irix_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *oldmask, siginfo_t *info) +{ + lock_kernel(); + printk("Aiee: setup_tr_frame wants to be written"); + do_exit(SIGSEGV); + unlock_kernel(); +} + +static inline void handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) +{ + if (ka->sa.sa_flags & SA_SIGINFO) + setup_irix_rt_frame(ka, regs, sig, oldset, info); + else + setup_irix_frame(ka, regs, sig, oldset); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + if (!(ka->sa.sa_flags & SA_NODEFER)) { + spin_lock_irq(¤t->sigmask_lock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked,sig); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + } +} + +static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) +{ + switch(regs->regs[0]) { + case ERESTARTNOHAND: + regs->regs[2] = EINTR; + break; + case ERESTARTSYS: + if(!(ka->sa.sa_flags & SA_RESTART)) { + regs->regs[2] = EINTR; + break; + } + /* fallthrough */ + case ERESTARTNOINTR: /* Userland will reload $v0. */ + regs->cp0_epc -= 8; + } -asmlinkage int do_irix_signal(unsigned long oldmask, struct pt_regs * regs) + regs->regs[0] = 0; /* Don't deal with this again. */ +} + +asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) { - unsigned long mask = ~current->blocked; - unsigned long handler_signal = 0; - unsigned long signr; - struct sigaction * sa; + struct k_sigaction *ka; + siginfo_t info; + + if (!oldset) + oldset = ¤t->blocked; + + for (;;) { + unsigned long signr; + + spin_lock_irq(¤t->sigmask_lock); + signr = dequeue_signal(¤t->blocked, &info); + spin_unlock_irq(¤t->sigmask_lock); + + if (!signr) + break; -#ifdef DEBUG_SIG - printk("[%s:%d] Delivering IRIX signal oldmask=%08lx\n", - current->comm, current->pid, oldmask); -#endif - while ((signr = current->signal & mask)) { - signr = ffz(~signr); - clear_bit(signr, ¤t->signal); - sa = current->sig->action + signr; - signr++; if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + /* Let the debugger run. */ current->exit_code = signr; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); + + /* We're back. Did the debugger cancel the sig? */ if (!(signr = current->exit_code)) continue; current->exit_code = 0; + + /* The debugger continued. Ignore SIGSTOP. */ if (signr == SIGSTOP) continue; - if (_S(signr) & current->blocked) { - current->signal |= _S(signr); + + /* Update the siginfo structure. Is this good? */ + if (signr != info.si_signo) { + info.si_signo = signr; + info.si_errno = 0; + info.si_code = SI_USER; + info.si_pid = current->p_pptr->pid; + info.si_uid = current->p_pptr->uid; + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(¤t->blocked, signr)) { + send_sig_info(signr, &info, current); continue; } - sa = current->sig->action + signr - 1; } - if (sa->sa_handler == SIG_IGN) { + + ka = ¤t->sig->action[signr-1]; + if (ka->sa.sa_handler == SIG_IGN) { if (signr != SIGCHLD) continue; - /* check for SIGCHLD: it's special */ - while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0) + /* Check for SIGCHLD: it's special. */ + while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) /* nothing */; continue; } - if (sa->sa_handler == SIG_DFL) { + + if (ka->sa.sa_handler == SIG_DFL) { + int exit_code = signr; + + /* Init gets no signals it doesn't want. */ if (current->pid == 1) continue; + switch (signr) { case SIGCONT: case SIGCHLD: case SIGWINCH: continue; @@ -173,78 +249,55 @@ case SIGTSTP: case SIGTTIN: case SIGTTOU: if (is_orphaned_pgrp(current->pgrp)) continue; + /* FALLTHRU */ + case SIGSTOP: - if (current->flags & PF_PTRACED) - continue; current->state = TASK_STOPPED; current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & - SA_NOCLDSTOP)) + if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; case SIGQUIT: case SIGILL: case SIGTRAP: - case SIGIOT: case SIGFPE: case SIGSEGV: case SIGBUS: + case SIGABRT: case SIGFPE: case SIGSEGV: lock_kernel(); - if (current->binfmt && current->binfmt->core_dump) { - if (current->binfmt->core_dump(signr, regs)) - signr |= 0x80; - } + if (current->binfmt + && current->binfmt->core_dump + && current->binfmt->core_dump(signr, regs)) + exit_code |= 0x80; unlock_kernel(); - /* fall through */ + /* FALLTHRU */ + default: - current->signal |= _S(signr & 0x7f); + lock_kernel(); + sigaddset(¤t->signal, signr); current->flags |= PF_SIGNALED; - lock_kernel(); /* 8-( */ - do_exit(signr); - unlock_kernel(); + do_exit(exit_code); + /* NOTREACHED */ } } - /* - * OK, we're invoking a handler - */ - if (regs->orig_reg2 >= 0) { - if (regs->regs[2] == ERESTARTNOHAND) { - regs->regs[2] = EINTR; - } else if((regs->regs[2] == ERESTARTSYS && - !(sa->sa_flags & SA_RESTART))) { - regs->regs[2] = regs->orig_reg2; - regs->cp0_epc -= 8; - } - } - handler_signal |= 1 << (signr-1); - mask &= ~sa->sa_mask; + + if (regs->regs[0]) + syscall_restart(regs, ka); + /* Whee! Actually deliver the signal. */ + handle_signal(signr, ka, &info, oldset, regs); + return 1; } + /* * Who's code doesn't conform to the restartable syscall convention * dies here!!! The li instruction, a single machine instruction, * must directly be followed by the syscall instruction. */ - if (regs->orig_reg2 >= 0 && - (regs->regs[2] == ERESTARTNOHAND || - regs->regs[2] == ERESTARTSYS || - regs->regs[2] == ERESTARTNOINTR)) { - regs->regs[2] = regs->orig_reg2; - regs->cp0_epc -= 8; - } - if (!handler_signal) /* no handler will be called - return 0 */ - return 0; - signr = 1; - sa = current->sig->action; - for (mask = 1 ; mask ; sa++,signr++,mask += mask) { - if (mask > handler_signal) - break; - if (!(mask & handler_signal)) - continue; - setup_irix_frame(sa, regs, signr, oldmask); - if (sa->sa_flags & SA_ONESHOT) - sa->sa_handler = NULL; - current->blocked |= sa->sa_mask; - oldmask |= sa->sa_mask; + if (regs->regs[0]) { + if (regs->regs[2] == ERESTARTNOHAND || + regs->regs[2] == ERESTARTSYS || + regs->regs[2] == ERESTARTNOINTR) { + regs->cp0_epc -= 8; + } } - - return 1; + return 0; } asmlinkage unsigned long irix_sigreturn(struct pt_regs *regs) @@ -253,6 +306,7 @@ unsigned long umask, mask; u64 *fregs, res; int sig, i, base = 0; + sigset_t blocked; if(regs->regs[2] == 1000) base = 1; @@ -291,11 +345,24 @@ /* XXX do sigstack crapola here... XXX */ - regs->orig_reg2 = -1; - __get_user(current->blocked, &context->sigset[0]); - current->blocked &= _BLOCKABLE; - __get_user(res, &context->regs[2]); - return res; + if (__copy_from_user(&blocked, &context->sigset, sizeof(blocked))) + goto badframe; + + sigdelsetmask(&blocked, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = blocked; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + /* + * Don't let your children do this ... + */ + __asm__ __volatile__( + "move\t$29,%0\n\t" + "j\tret_from_sys_call" + :/* no outputs */ + :"r" (®s)); + /* Unreached */ badframe: lock_kernel(); @@ -321,27 +388,12 @@ } #endif -static inline void check_pending(int signum) +asmlinkage int +irix_sigaction(int sig, const struct sigaction *act, + struct sigaction *oact, unsigned long trampoline) { - struct sigaction *p; - - p = signum - 1 + current->sig->action; - spin_lock(¤t->sigmask_lock); - if (p->sa_handler == SIG_IGN) { - current->signal &= ~_S(signum); - } else if (p->sa_handler == SIG_DFL) { - if (signum != SIGCONT && signum != SIGCHLD && signum != SIGWINCH) - return; - current->signal &= ~_S(signum); - } - spin_unlock(¤t->sigmask_lock); -} - -asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new, - struct sigact_irix5 *old, unsigned long trampoline) -{ - struct sigaction new_sa, *p; - int res; + struct k_sigaction new_ka, old_ka; + int ret; #ifdef DEBUG_SIG printk(" (%d,%s,%s,%08lx) ", sig, (!new ? "0" : "NEW"), @@ -350,110 +402,103 @@ dump_sigact_irix5(new); printk(" "); } #endif - if(sig < 1 || sig > 32) { - return -EINVAL; - } - p = sig - 1 + current->sig->action; + if (act) { + sigset_t mask; + if (verify_area(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags)) + return -EFAULT; - if(new) { - res = verify_area(VERIFY_READ, new, sizeof(*new)); - if(res) - return res; - if(sig == SIGKILL || sig == SIGSTOP) { - return -EINVAL; - } - __get_user(new_sa.sa_flags, &new->flags); - __get_user(new_sa.sa_handler, &(__sighandler_t) new->handler); - __get_user(new_sa.sa_mask, &new->sigset[0]); - - if(new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) { - res = verify_area(VERIFY_READ, new_sa.sa_handler, 1); - if(res) - return res; - } + __copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t)); + new_ka.ka_restorer = NULL; } - /* Hmmm... methinks IRIX libc always passes a valid trampoline + + /* + * Hmmm... methinks IRIX libc always passes a valid trampoline * value for all invocations of sigaction. Will have to * investigate. POSIX POSIX, die die die... */ current->tss.irix_trampoline = trampoline; - if(old) { - int res = verify_area(VERIFY_WRITE, old, sizeof(*old)); - if(res) - return res; - __put_user(p->sa_flags, &old->flags); - __put_user(p->sa_handler, &old->handler); - __put_user(p->sa_mask, &old->sigset[0]); - __put_user(0, &old->sigset[1]); - __put_user(0, &old->sigset[2]); - __put_user(0, &old->sigset[3]); - __put_user(0, &old->_unused0[0]); - __put_user(0, &old->_unused0[1]); - } - if(new) { - spin_lock_irq(¤t->sig->siglock); - *p = new_sa; - check_pending(sig); - spin_unlock_irq(¤t->sig->siglock); + +/* XXX Implement SIG_SETMASK32 for IRIX compatibility */ + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags)) + return -EFAULT; + __copy_to_user(&old_ka.sa.sa_mask, &oact->sa_mask, + sizeof(sigset_t)); } - return 0; + return ret; } -asmlinkage int irix_sigpending(unsigned long *set) +asmlinkage int irix_sigpending(irix_sigset_t *set) { - int res; - lock_kernel(); - res = verify_area(VERIFY_WRITE, set, (sizeof(unsigned long) * 4)); - if(!res) { - /* fill in "set" with signals pending but blocked. */ - spin_lock_irq(¤t->sigmask_lock); - __put_user(0, &set[1]); - __put_user(0, &set[2]); - __put_user(0, &set[3]); - __put_user((current->blocked & current->signal), &set[0]); - spin_unlock_irq(¤t->sigmask_lock); - } - return res; + if (verify_area(VERIFY_WRITE, set, sizeof(*set)) < 0) + return -EFAULT; + + /* fill in "set" with signals pending but blocked. */ + spin_lock_irq(¤t->sigmask_lock); + __put_user(current->blocked.sig[0] & current->signal.sig[0], + &set->sig[0]); + __put_user(current->blocked.sig[1] & current->signal.sig[1], + &set->sig[1]); + __put_user(current->blocked.sig[2] & current->signal.sig[2], + &set->sig[2]); + __put_user(current->blocked.sig[3] & current->signal.sig[3], + &set->sig[3]); + spin_unlock_irq(¤t->sigmask_lock); + + return 0; } -asmlinkage int irix_sigprocmask(int how, unsigned long *new, unsigned long *old) +asmlinkage int irix_sigprocmask(int how, irix_sigset_t *new, irix_sigset_t *old) { - unsigned long bits, oldbits = current->blocked; + sigset_t oldbits, newbits; int error; + if(new) { - error = verify_area(VERIFY_READ, new, (sizeof(unsigned long) * 4)); + error = verify_area(VERIFY_READ, new, sizeof(*new)); if(error) return error; - bits = new[0] & _BLOCKABLE; + __copy_from_user(&newbits, new, sizeof(unsigned long)*4); + sigdelsetmask(&newbits, ~_BLOCKABLE); + + spin_lock_irq(¤t->sigmask_lock); + oldbits = current->blocked; + switch(how) { case 1: - current->blocked |= bits; + sigorsets(&newbits, &oldbits, &newbits); break; case 2: - current->blocked &= ~bits; + sigandsets(&newbits, &oldbits, &newbits); break; case 3: + break; + case 256: - current->blocked = bits; + siginitset(&newbits, newbits.sig[0]); break; default: return -EINVAL; } + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); } if(old) { - error = verify_area(VERIFY_WRITE, old, (sizeof(unsigned long) * 4)); + error = verify_area(VERIFY_WRITE, old, sizeof(*old)); if(error) return error; - __put_user(0, &old[1]); - __put_user(0, &old[2]); - __put_user(0, &old[3]); - __put_user(oldbits, &old[0]); + __copy_to_user(old, ¤t->blocked, sizeof(unsigned long)*4); } return 0; @@ -461,26 +506,25 @@ asmlinkage int irix_sigsuspend(struct pt_regs *regs) { - unsigned int mask; - unsigned long *uset; - int base = 0, error; + sigset_t *uset, saveset, newset; - if(regs->regs[2] == 1000) - base = 1; - - uset = (unsigned long *) regs->regs[base + 4]; - if(verify_area(VERIFY_READ, uset, (sizeof(unsigned long) * 4))) + uset = (sigset_t *) regs->regs[4]; + if (copy_from_user(&newset, uset, sizeof(sigset_t))) return -EFAULT; - mask = current->blocked; + sigdelsetmask(&newset, ~_BLOCKABLE); - current->blocked = uset[0] & _BLOCKABLE; - while(1) { + spin_lock_irq(¤t->sigmask_lock); + saveset = current->blocked; + current->blocked = newset; + spin_unlock_irq(¤t->sigmask_lock); + + regs->regs[2] = -EINTR; + while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if(do_irix_signal(mask, regs)) + if (do_irix_signal(&saveset, regs)) return -EINTR; } - return error; } /* hate hate hate... */ @@ -524,8 +568,9 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info, struct timespec *tp) { - unsigned long mask, kset, expire = 0; - int sig, error, timeo = 0; + unsigned long expire = 0; + sigset_t kset; + int i, sig, error, timeo = 0; lock_kernel(); #ifdef DEBUG_SIG @@ -537,11 +582,15 @@ if(!set) return -EINVAL; - error = get_user(kset, &set[0]); - if(error) + error = verify_area(VERIFY_READ, set, sizeof(kset)); + if (error) goto out; - if(info && clear_user(info, sizeof(*info))) { + __copy_from_user(&kset, set, sizeof(set)); + if (error) + goto out; + + if (info && clear_user(info, sizeof(*info))) { error = -EFAULT; goto out; } @@ -559,21 +608,32 @@ } while(1) { + long tmp = 0; + current->state = TASK_INTERRUPTIBLE; schedule(); - if(current->signal & kset) break; - if(tp && expire <= jiffies) { + + for (i=0; i<=4; i++) + tmp |= (current->signal.sig[i] & kset.sig[i]); + + if (tmp) + break; + if (tp && expire <= jiffies) { timeo = 1; break; } - if(signal_pending(current)) return -EINTR; + if (signal_pending(current)) + return -EINTR; } + if (timeo) + return -EAGAIN; - if(timeo) return -EAGAIN; - for(sig = 1, mask = 2; mask; mask <<= 1, sig++) { - if(!(mask & kset)) continue; - if(mask & current->signal) { + for(sig = 1; i <= 65 /* IRIX_NSIG */; sig++) { + if (sigismember (&kset, sig)) + continue; + if (sigismember (¤t->signal, sig)) { /* XXX need more than this... */ - if(info) info->sig = sig; + if (info) + info->sig = sig; error = 0; goto out; } @@ -724,6 +784,7 @@ { int error, i, base = 0; struct irix5_context *ctx; + unsigned long flags; lock_kernel(); if(regs->regs[2] == 1000) @@ -738,28 +799,32 @@ error = verify_area(VERIFY_WRITE, ctx, sizeof(*ctx)); if(error) goto out; - ctx->flags = 0x0f; - ctx->link = current->tss.irix_oldctx; - ctx->sigmask[1] = ctx->sigmask[2] = ctx->sigmask[4] = 0; - ctx->sigmask[0] = current->blocked; + __put_user(current->tss.irix_oldctx, &ctx->link); + + __copy_to_user(&ctx->sigmask, ¤t->blocked, sizeof(irix_sigset_t)); /* XXX Do sigstack stuff someday... */ - ctx->stack.sp = ctx->stack.size = ctx->stack.flags = 0; + __put_user(0, &ctx->stack.sp); + __put_user(0, &ctx->stack.size); + __put_user(0, &ctx->stack.flags); - ctx->weird_graphics_thing = 0; - ctx->regs[0] = 0; + __put_user(0, &ctx->weird_graphics_thing); + __put_user(0, &ctx->regs[0]); for(i = 1; i < 32; i++) - ctx->regs[i] = regs->regs[i]; - ctx->regs[32] = regs->lo; - ctx->regs[33] = regs->hi; - ctx->regs[34] = regs->cp0_cause; - ctx->regs[35] = regs->cp0_epc; + __put_user(regs->regs[i], &ctx->regs[i]); + __put_user(regs->lo, &ctx->regs[32]); + __put_user(regs->hi, &ctx->regs[33]); + __put_user(regs->cp0_cause, &ctx->regs[34]); + __put_user(regs->cp0_epc, &ctx->regs[35]); + + flags = 0x0f; if(!current->used_math) { - ctx->flags &= ~(0x08); + flags &= ~(0x08); } else { /* XXX wheee... */ printk("Wheee, no code for saving IRIX FPU context yet.\n"); } + __put_user(flags, &ctx->flags); error = 0; out: diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c --- v2.1.100/linux/arch/mips/kernel/irq.c Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/irq.c Fri May 8 00:13:23 1998 @@ -4,7 +4,7 @@ * Copyright (C) 1992 Linus Torvalds * Copyright (C) 1994, 1995, 1996, 1997 Ralf Baechle * - * $Id: irq.c,v 1.7 1997/09/26 11:51:33 ralf Exp $ + * $Id: irq.c,v 1.11 1998/05/01 01:34:02 ralf Exp $ */ #include #include @@ -29,6 +29,7 @@ unsigned char cache_21 = 0xff; unsigned char cache_A1 = 0xff; +unsigned int local_bh_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; @@ -104,7 +105,7 @@ if (!action) continue; len += sprintf(buf+len, "%2d: %8d %c %s", - i, kstat.interrupts[i], + i, kstat.irqs[0][i], (action->flags & SA_INTERRUPT) ? '+' : ' ', action->name); for (action=action->next; action; action = action->next) { @@ -133,7 +134,7 @@ cpu = smp_processor_id(); irq_enter(cpu, irq); - kstat.interrupts[irq]++; + kstat.irqs[cpu][irq]++; /* * mask and ack quickly, we don't want the irq controller @@ -162,6 +163,7 @@ } while (action); if (do_random & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); + unmask_irq (irq); __cli(); } irq_exit(cpu, irq); diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/mips_ksyms.c linux/arch/mips/kernel/mips_ksyms.c --- v2.1.100/linux/arch/mips/kernel/mips_ksyms.c Tue Mar 17 22:18:14 1998 +++ linux/arch/mips/kernel/mips_ksyms.c Fri May 8 00:13:23 1998 @@ -7,7 +7,7 @@ * * Copyright (C) 1996, 1997 by Ralf Baechle * - * $Id: mips_ksyms.c,v 1.4 1997/08/11 04:17:18 ralf Exp $ + * $Id: mips_ksyms.c,v 1.7 1998/05/04 09:17:52 ralf Exp $ */ #include #include @@ -32,7 +32,6 @@ /* * String functions */ -EXPORT_SYMBOL_NOVERS(bcopy); EXPORT_SYMBOL_NOVERS(memcmp); EXPORT_SYMBOL_NOVERS(memset); EXPORT_SYMBOL_NOVERS(memcpy); @@ -47,13 +46,13 @@ EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(__mips_bh_counter); +EXPORT_SYMBOL(local_bh_count); EXPORT_SYMBOL(local_irq_count); /* * Userspace access stuff. */ EXPORT_SYMBOL(__copy_user); -EXPORT_SYMBOL(active_ds); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy); diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/pci.c linux/arch/mips/kernel/pci.c --- v2.1.100/linux/arch/mips/kernel/pci.c Mon Apr 6 17:40:59 1998 +++ linux/arch/mips/kernel/pci.c Fri May 8 00:13:24 1998 @@ -5,6 +5,7 @@ * * MIPS implementation of PCI BIOS services for PCI support. */ +#include #include #include #include @@ -35,6 +36,53 @@ } /* + * Given the vendor and device ids, find the n'th instance of that device + * in the system. + */ +int pcibios_find_device (unsigned short vendor, unsigned short device_id, + unsigned short index, unsigned char *bus, + unsigned char *devfn) +{ + unsigned int curr = 0; + struct pci_dev *dev; + + for (dev = pci_devices; dev; dev = dev->next) { + if (dev->vendor == vendor && dev->device == device_id) { + if (curr == index) { + *devfn = dev->devfn; + *bus = dev->bus->number; + return PCIBIOS_SUCCESSFUL; + } + ++curr; + } + } + return PCIBIOS_DEVICE_NOT_FOUND; +} + +/* + * Given the class, find the n'th instance of that device + * in the system. + */ +int pcibios_find_class (unsigned int class_code, unsigned short index, + unsigned char *bus, unsigned char *devfn) +{ + unsigned int curr = 0; + struct pci_dev *dev; + + for (dev = pci_devices; dev; dev = dev->next) { + if (dev->class == class_code) { + if (curr == index) { + *devfn = dev->devfn; + *bus = dev->bus->number; + return PCIBIOS_SUCCESSFUL; + } + ++curr; + } + } + return PCIBIOS_DEVICE_NOT_FOUND; +} + +/* * The functions below are machine specific and must be reimplented for * each PCI chipset configuration. We just run the hook to the machine * specific implementation. @@ -79,11 +127,6 @@ unsigned char where, unsigned int val) { return pci_ops->pcibios_write_config_dword(bus, dev_fn, where, val); -} - -__initfunc(char *pcibios_setup(char *str)) -{ - return str; } #endif /* defined(CONFIG_PCI) */ diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c --- v2.1.100/linux/arch/mips/kernel/process.c Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/process.c Fri May 8 00:13:24 1998 @@ -1,13 +1,13 @@ /* - * linux/arch/mips/kernel/process.c + * linux/arch/mips/kernel/process.c * - * Copyright (C) 1995 Ralf Baechle + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. * - * Modified for R3000/DECStation support by Paul M. Antoine 1995, 1996 + * Copyright (C) 1994 - 1998 by Ralf Baechle and others. * - * This file handles the architecture-dependent parts of initialization, - * though it does not yet currently fully support the DECStation, - * or R3000 - PMA. + * $Id: process.c,v 1.10 1998/05/04 09:17:53 ralf Exp $ */ #include #include @@ -32,11 +32,6 @@ #include #include #include -#ifdef CONFIG_SGI -#include -#endif - -int active_ds = USER_DS; asmlinkage void ret_from_sys_call(void); @@ -54,10 +49,22 @@ void exit_thread(void) { + /* Forget lazy fpu state */ + if (last_task_used_math == current) { + set_cp0_status(ST0_CU1, ST0_CU1); + __asm__ __volatile__("cfc1\t$0,$31"); + last_task_used_math = NULL; + } } void flush_thread(void) { + /* Forget lazy fpu state */ + if (last_task_used_math == current) { + set_cp0_status(ST0_CU1, ST0_CU1); + __asm__ __volatile__("cfc1\t$0,$31"); + last_task_used_math = NULL; + } } void release_thread(struct task_struct *dead_task) @@ -72,6 +79,10 @@ childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32; + if (last_task_used_math == current) { + set_cp0_status(ST0_CU1, ST0_CU1); + r4xx0_save_fp(p); + } /* set up new TSS. */ childregs = (struct pt_regs *) childksp - 1; *childregs = *regs; @@ -87,13 +98,13 @@ regs->regs[3] = 0; } if (childregs->cp0_status & ST0_CU0) { + childregs->regs[28] = (unsigned long) p; childregs->regs[29] = childksp; p->tss.current_ds = KERNEL_DS; } else { childregs->regs[29] = usp; p->tss.current_ds = USER_DS; } - p->tss.ksp = childksp; p->tss.reg29 = (unsigned long) childregs; p->tss.reg31 = (unsigned long) ret_from_sys_call; @@ -102,7 +113,7 @@ * switching for most programs since they don't use the fpu. */ p->tss.cp0_status = read_32bit_cp0_register(CP0_STATUS) & - ~(ST0_CU3|ST0_CU2|ST0_CU1|ST0_KSU|ST0_ERL|ST0_EXL); + ~(ST0_CU3|ST0_CU2|ST0_CU1|ST0_KSU); childregs->cp0_status &= ~(ST0_CU3|ST0_CU2|ST0_CU1); p->mm->context = 0; diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c --- v2.1.100/linux/arch/mips/kernel/ptrace.c Thu May 7 22:51:46 1998 +++ linux/arch/mips/kernel/ptrace.c Fri May 8 00:13:24 1998 @@ -343,8 +343,8 @@ struct pt_regs *regs; unsigned long tmp; - regs = (struct pt_regs *) - (child->tss.ksp - sizeof(struct pt_regs)); + regs = (struct pt_regs *) ((unsigned long) child + + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); tmp = 0; /* Default return value. */ if(addr < 32 && addr >= 0) { tmp = regs->regs[addr]; @@ -399,8 +399,8 @@ struct pt_regs *regs; int res = 0; - regs = (struct pt_regs *) - (child->tss.ksp - sizeof(struct pt_regs)); + regs = (struct pt_regs *) ((unsigned long) child + + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); if(addr < 32 && addr >= 0) { regs->regs[addr] = data; } else if(addr >= 32 && addr < 64) { @@ -436,7 +436,7 @@ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ - if ((unsigned long) data > NSIG) { + if ((unsigned long) data > _NSIG) { res = -EIO; goto out; } @@ -465,7 +465,7 @@ } case PTRACE_DETACH: { /* detach a process that was attached. */ - if ((unsigned long) data > NSIG) { + if ((unsigned long) data > _NSIG) { res = -EIO; goto out; } @@ -503,9 +503,7 @@ * stopping signal is not SIGTRAP. -brl */ if (current->exit_code) { - spin_lock_irq(¤t->sigmask_lock); - current->signal |= (1 << (current->exit_code - 1)); - spin_unlock_irq(¤t->sigmask_lock); + send_sig(current->exit_code, current, 1); + current->exit_code = 0; } - current->exit_code = 0; } diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r2300_fpu.S linux/arch/mips/kernel/r2300_fpu.S --- v2.1.100/linux/arch/mips/kernel/r2300_fpu.S Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/r2300_fpu.S Fri May 8 00:13:24 1998 @@ -10,7 +10,7 @@ * Multi-arch abstraction and asm macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r2300_fpu.S,v 1.3 1997/12/01 16:54:20 ralf Exp $ + * $Id: r2300_fpu.S,v 1.4 1998/05/01 01:34:08 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r2300_misc.S linux/arch/mips/kernel/r2300_misc.S --- v2.1.100/linux/arch/mips/kernel/r2300_misc.S Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/r2300_misc.S Fri May 8 00:13:24 1998 @@ -1,4 +1,4 @@ -/* $Id: r2300_misc.S,v 1.1.1.1 1997/06/01 03:16:42 ralf Exp $ +/* $Id: r2300_misc.S,v 1.2 1998/05/01 01:34:10 ralf Exp $ * r2300_misc.S: Misc. exception handling code for R3000/R2000. * * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r2300_scall.S linux/arch/mips/kernel/r2300_scall.S --- v2.1.100/linux/arch/mips/kernel/r2300_scall.S Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/r2300_scall.S Wed Dec 31 16:00:00 1969 @@ -1,84 +0,0 @@ -/* $Id: r2300_scall.S,v 1.1.1.1 1997/06/01 03:16:42 ralf Exp $ - * r2300_scall.S: R2000/R3000 specific code to handle system calls. - * - * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse - * - * Multi-arch abstraction and beautification: - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * do_syscall calls the function in a1 with upto 7 arguments. If over - * four arguments are being requested, the additional arguments will - * be copied from the user stack pointed to by a0->reg29. - * - * a0 (struct pt_regs *) pointer to user registers - * a1 (syscall_t) pointer to syscall to do - * a2 (int) number of arguments to syscall - */ - .set noreorder -NESTED(r2300_do_syscalls, 32, sp) - subu sp,32 - sw ra,28(sp) - sll a2,a2,PTRLOG - lw t0,dst(a2) - move t2,a1 - jalr t0 - lw t0,PT_R29(a0) # get old user stack pointer - -7: - lw t1,24(t0) # parameter #7 from usp - nop # delay slot - sw t1,24(sp) -6: - lw t1,20(t0) # parameter #6 from usp - nop # delay slot - sw t1,20(sp) -5: - lw t1,16(t0) # parameter #5 from usp - nop # delay slot - sw t1,16(sp) -4: - lw a3,PT_R7(a0) # 4 args -3: - lw a2,PT_R6(a0) # 3 args -2: - lw a1,PT_R5(a0) # 2 args -1: - jalr t2 # 1 args - lw a0,PT_R4(a0) - - lw ra,28(sp) - addiu sp,32 - jr ra - nop - -0: - jalr t2 # 0 args, just pass a0 - lw ra,28(sp) - addiu sp,32 - - jr ra - nop # delay slot - END(r2300_do_syscalls) - - .rdata - .align PTRLOG -dst: PTR 0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b - - .section __ex_table,"a" - PTR 7b,bad_stack - PTR 6b,bad_stack - PTR 5b,bad_stack - .previous diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r2300_switch.S linux/arch/mips/kernel/r2300_switch.S --- v2.1.100/linux/arch/mips/kernel/r2300_switch.S Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/r2300_switch.S Fri May 8 00:13:24 1998 @@ -1,10 +1,12 @@ -/* $Id: r2300_switch.S,v 1.1.1.1 1997/06/01 03:16:43 ralf Exp $ +/* * r2300_switch.S: R3000/R2000 specific task switching code. * * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse * * Multi-cpu abstraction and macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: r2300_switch.S,v 1.2 1998/05/01 01:34:14 ralf Exp $ */ #include #include @@ -25,40 +27,34 @@ MODE_ALIAS = 0x00e0 # uncachable, dirty, valid .text - .set mips3 + .set mips1 + .set noreorder /* * Code necessary to switch tasks on an Linux/MIPS machine. * FIXME: We don't need to disable interrupts anymore. */ .align 5 LEAF(r2300_resume) - GET_CURRENT(t0) mfc0 t1,CP0_STATUS # Save status register - addu t0,a1 # Add tss offset - sw t1,THREAD_STATUS(t0) + sw t1,THREAD_STATUS($28) ori t2,t1,0x1f # Disable interrupts xori t2,0x1e mtc0 t2,CP0_STATUS - CPU_SAVE_NONSCRATCH(t0) + CPU_SAVE_NONSCRATCH($28) sll t2,t1,2 # Save floating point state - bgez t2,2f - sw ra,THREAD_REG31(t0) - sll t2,t1,5 bgez t2,1f - swc1 $f0, (THREAD_FPU + 0x00)(t0) - FPU_SAVE_16ODD(t0) + sw ra,THREAD_REG31($28) + FPU_SAVE($28, t0) 1: - FPU_SAVE_16EVEN(t0, t1) -2: - addu a0,a1 # Add tss offset - lw t0,THREAD_PGDIR(a0) # Switch the root pointer + move $28, a0 + lw t0,THREAD_PGDIR($28) # Switch the root pointer li t1,TLB_ROOT # get PFN mtc0 t1,CP0_ENTRYHI mtc0 zero,CP0_INDEX srl t0,12 # PFN is 12 bits west ori t0,MODE_ALIAS # want uncachable, dirty, valid mtc0 t0,CP0_ENTRYLO0 - lw a2,THREAD_STATUS(a0) + lw a2,THREAD_STATUS($28) tlbwi /* Flush TLB. */ @@ -82,19 +78,13 @@ xori t1,1 mtc0 t1,CP0_STATUS sll t0,a2,2 - bgez t0,2f - sll t0,a2,5 bgez t0,1f - lwc1 $f0, (THREAD_FPU + 0x00)(a0) - FPU_RESTORE_16ODD(a0) + lw ra,THREAD_REG31($28) + FPU_RESTORE($28, t0) 1: - FPU_RESTORE_16EVEN(a0, t0) -2: - CPU_RESTORE_NONSCRATCH(a0) - lw t0,THREAD_KSP(a0) # Restore status register + CPU_RESTORE_NONSCRATCH($28) + addiu t0, $28, KERNEL_STACK_SIZE-32 sw t0,kernelsp jr ra - mtc0 a2,CP0_STATUS + mtc0 a2,CP0_STATUS # Restore status register END(r2300_resume) - - diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r4k_fpu.S linux/arch/mips/kernel/r4k_fpu.S --- v2.1.100/linux/arch/mips/kernel/r4k_fpu.S Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/r4k_fpu.S Fri May 8 00:13:24 1998 @@ -5,12 +5,12 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996 by Ralf Baechle + * Copyright (C) 1996, 1998 by Ralf Baechle * * Multi-arch abstraction and asm macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r4k_fpu.S,v 1.3 1997/12/01 16:56:06 ralf Exp $ + * $Id: r4k_fpu.S,v 1.4 1998/05/01 01:34:15 ralf Exp $ */ #include #include @@ -18,65 +18,63 @@ #include #include +#define EX(a,b) \ +9: a,##b; \ + .section __ex_table,"a"; \ + PTR 9b,bad_stack; \ + .previous + .set noreorder .set mips3 /* Save floating point context */ LEAF(r4k_save_fp_context) mfc0 t1,CP0_STATUS - sll t2,t1,2 - bgez t2,2f sll t2,t1,5 - cfc1 t1,fcr31 bgez t2,1f - nop + cfc1 t1,fcr31 /* Store the 16 odd double precision registers */ - sdc1 $f1,(SC_FPREGS+8)(a0) - sdc1 $f3,(SC_FPREGS+24)(a0) - sdc1 $f5,(SC_FPREGS+40)(a0) - sdc1 $f7,(SC_FPREGS+56)(a0) - sdc1 $f9,(SC_FPREGS+72)(a0) - sdc1 $f11,(SC_FPREGS+88)(a0) - sdc1 $f13,(SC_FPREGS+104)(a0) - sdc1 $f15,(SC_FPREGS+120)(a0) - sdc1 $f17,(SC_FPREGS+136)(a0) - sdc1 $f19,(SC_FPREGS+152)(a0) - sdc1 $f21,(SC_FPREGS+168)(a0) - sdc1 $f23,(SC_FPREGS+184)(a0) - sdc1 $f25,(SC_FPREGS+200)(a0) - sdc1 $f27,(SC_FPREGS+216)(a0) - sdc1 $f29,(SC_FPREGS+232)(a0) - sdc1 $f31,(SC_FPREGS+248)(a0) + EX(sdc1 $f1,(SC_FPREGS+8)(a0)) + EX(sdc1 $f3,(SC_FPREGS+24)(a0)) + EX(sdc1 $f5,(SC_FPREGS+40)(a0)) + EX(sdc1 $f7,(SC_FPREGS+56)(a0)) + EX(sdc1 $f9,(SC_FPREGS+72)(a0)) + EX(sdc1 $f11,(SC_FPREGS+88)(a0)) + EX(sdc1 $f13,(SC_FPREGS+104)(a0)) + EX(sdc1 $f15,(SC_FPREGS+120)(a0)) + EX(sdc1 $f17,(SC_FPREGS+136)(a0)) + EX(sdc1 $f19,(SC_FPREGS+152)(a0)) + EX(sdc1 $f21,(SC_FPREGS+168)(a0)) + EX(sdc1 $f23,(SC_FPREGS+184)(a0)) + EX(sdc1 $f25,(SC_FPREGS+200)(a0)) + EX(sdc1 $f27,(SC_FPREGS+216)(a0)) + EX(sdc1 $f29,(SC_FPREGS+232)(a0)) + EX(sdc1 $f31,(SC_FPREGS+248)(a0)) /* Store the 16 even double precision registers */ 1: - sdc1 $f0,(SC_FPREGS+0)(a0) - sdc1 $f2,(SC_FPREGS+16)(a0) - sdc1 $f4,(SC_FPREGS+32)(a0) - sdc1 $f6,(SC_FPREGS+48)(a0) - sdc1 $f8,(SC_FPREGS+64)(a0) - sdc1 $f10,(SC_FPREGS+80)(a0) - sdc1 $f12,(SC_FPREGS+96)(a0) - sdc1 $f14,(SC_FPREGS+112)(a0) - sdc1 $f16,(SC_FPREGS+128)(a0) - sdc1 $f18,(SC_FPREGS+144)(a0) - sdc1 $f20,(SC_FPREGS+160)(a0) - sdc1 $f22,(SC_FPREGS+176)(a0) - sdc1 $f24,(SC_FPREGS+192)(a0) - sdc1 $f26,(SC_FPREGS+208)(a0) - sdc1 $f28,(SC_FPREGS+224)(a0) - sdc1 $f30,(SC_FPREGS+240)(a0) - sw t1,SC_FPC_CSR(a0) + EX(sdc1 $f0,(SC_FPREGS+0)(a0)) + EX(sdc1 $f2,(SC_FPREGS+16)(a0)) + EX(sdc1 $f4,(SC_FPREGS+32)(a0)) + EX(sdc1 $f6,(SC_FPREGS+48)(a0)) + EX(sdc1 $f8,(SC_FPREGS+64)(a0)) + EX(sdc1 $f10,(SC_FPREGS+80)(a0)) + EX(sdc1 $f12,(SC_FPREGS+96)(a0)) + EX(sdc1 $f14,(SC_FPREGS+112)(a0)) + EX(sdc1 $f16,(SC_FPREGS+128)(a0)) + EX(sdc1 $f18,(SC_FPREGS+144)(a0)) + EX(sdc1 $f20,(SC_FPREGS+160)(a0)) + EX(sdc1 $f22,(SC_FPREGS+176)(a0)) + EX(sdc1 $f24,(SC_FPREGS+192)(a0)) + EX(sdc1 $f26,(SC_FPREGS+208)(a0)) + EX(sdc1 $f28,(SC_FPREGS+224)(a0)) + EX(sdc1 $f30,(SC_FPREGS+240)(a0)) + EX(sw t1,SC_FPC_CSR(a0)) cfc1 t0,$0 # implementation/version jr ra .set nomacro - sw t0,SC_FPC_EIR(a0) - .set macro -2: - jr ra - .set nomacro - nop + EX(sw t0,SC_FPC_EIR(a0)) .set macro END(r4k_save_fp_context) @@ -90,56 +88,51 @@ * stack frame which might have been changed by the user. */ LEAF(r4k_restore_fp_context) - mfc0 t1,CP0_STATUS - sll t0,t1,2 - bgez t0,2f - sll t0,t1,5 - + mfc0 t1, CP0_STATUS + sll t0,t1,5 bgez t0,1f - lw t0,SC_FPC_CSR(a0) + EX(lw t0,SC_FPC_CSR(a0)) + /* Restore the 16 odd double precision registers only * when enabled in the cp0 status register. */ - ldc1 $f1,(SC_FPREGS+8)(a0) - ldc1 $f3,(SC_FPREGS+24)(a0) - ldc1 $f5,(SC_FPREGS+40)(a0) - ldc1 $f7,(SC_FPREGS+56)(a0) - ldc1 $f9,(SC_FPREGS+72)(a0) - ldc1 $f11,(SC_FPREGS+88)(a0) - ldc1 $f13,(SC_FPREGS+104)(a0) - ldc1 $f15,(SC_FPREGS+120)(a0) - ldc1 $f17,(SC_FPREGS+136)(a0) - ldc1 $f19,(SC_FPREGS+152)(a0) - ldc1 $f21,(SC_FPREGS+168)(a0) - ldc1 $f23,(SC_FPREGS+184)(a0) - ldc1 $f25,(SC_FPREGS+200)(a0) - ldc1 $f27,(SC_FPREGS+216)(a0) - ldc1 $f29,(SC_FPREGS+232)(a0) - ldc1 $f31,(SC_FPREGS+248)(a0) + EX(ldc1 $f1,(SC_FPREGS+8)(a0)) + EX(ldc1 $f3,(SC_FPREGS+24)(a0)) + EX(ldc1 $f5,(SC_FPREGS+40)(a0)) + EX(ldc1 $f7,(SC_FPREGS+56)(a0)) + EX(ldc1 $f9,(SC_FPREGS+72)(a0)) + EX(ldc1 $f11,(SC_FPREGS+88)(a0)) + EX(ldc1 $f13,(SC_FPREGS+104)(a0)) + EX(ldc1 $f15,(SC_FPREGS+120)(a0)) + EX(ldc1 $f17,(SC_FPREGS+136)(a0)) + EX(ldc1 $f19,(SC_FPREGS+152)(a0)) + EX(ldc1 $f21,(SC_FPREGS+168)(a0)) + EX(ldc1 $f23,(SC_FPREGS+184)(a0)) + EX(ldc1 $f25,(SC_FPREGS+200)(a0)) + EX(ldc1 $f27,(SC_FPREGS+216)(a0)) + EX(ldc1 $f29,(SC_FPREGS+232)(a0)) + EX(ldc1 $f31,(SC_FPREGS+248)(a0)) /* * Restore the 16 even double precision registers * when cp1 was enabled in the cp0 status register. */ -1: ldc1 $f0,(SC_FPREGS+0)(a0) - ldc1 $f2,(SC_FPREGS+16)(a0) - ldc1 $f4,(SC_FPREGS+32)(a0) - ldc1 $f6,(SC_FPREGS+48)(a0) - ldc1 $f8,(SC_FPREGS+64)(a0) - ldc1 $f10,(SC_FPREGS+80)(a0) - ldc1 $f12,(SC_FPREGS+96)(a0) - ldc1 $f14,(SC_FPREGS+112)(a0) - ldc1 $f16,(SC_FPREGS+128)(a0) - ldc1 $f18,(SC_FPREGS+144)(a0) - ldc1 $f20,(SC_FPREGS+160)(a0) - ldc1 $f22,(SC_FPREGS+176)(a0) - ldc1 $f24,(SC_FPREGS+192)(a0) - ldc1 $f26,(SC_FPREGS+208)(a0) - ldc1 $f28,(SC_FPREGS+224)(a0) - ldc1 $f30,(SC_FPREGS+240)(a0) +1: EX(ldc1 $f0,(SC_FPREGS+0)(a0)) + EX(ldc1 $f2,(SC_FPREGS+16)(a0)) + EX(ldc1 $f4,(SC_FPREGS+32)(a0)) + EX(ldc1 $f6,(SC_FPREGS+48)(a0)) + EX(ldc1 $f8,(SC_FPREGS+64)(a0)) + EX(ldc1 $f10,(SC_FPREGS+80)(a0)) + EX(ldc1 $f12,(SC_FPREGS+96)(a0)) + EX(ldc1 $f14,(SC_FPREGS+112)(a0)) + EX(ldc1 $f16,(SC_FPREGS+128)(a0)) + EX(ldc1 $f18,(SC_FPREGS+144)(a0)) + EX(ldc1 $f20,(SC_FPREGS+160)(a0)) + EX(ldc1 $f22,(SC_FPREGS+176)(a0)) + EX(ldc1 $f24,(SC_FPREGS+192)(a0)) + EX(ldc1 $f26,(SC_FPREGS+208)(a0)) + EX(ldc1 $f28,(SC_FPREGS+224)(a0)) + EX(ldc1 $f30,(SC_FPREGS+240)(a0)) jr ra ctc1 t0,fcr31 - -2: jr ra - nop END(r4k_restore_fp_context) diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r4k_misc.S linux/arch/mips/kernel/r4k_misc.S --- v2.1.100/linux/arch/mips/kernel/r4k_misc.S Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/r4k_misc.S Fri May 8 00:13:24 1998 @@ -6,7 +6,7 @@ * Multi-cpu abstraction and reworking: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r4k_misc.S,v 1.3 1997/09/07 04:51:07 ralf Exp $ + * $Id: r4k_misc.S,v 1.4 1998/05/01 01:34:17 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r4k_scall.S linux/arch/mips/kernel/r4k_scall.S --- v2.1.100/linux/arch/mips/kernel/r4k_scall.S Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/r4k_scall.S Wed Dec 31 16:00:00 1969 @@ -1,72 +0,0 @@ -/* $Id: r4k_scall.S,v 1.1.1.1 1997/06/01 03:16:43 ralf Exp $ - * r4k_scall.S: R4xx0 specific code to handle system calls. - * - * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse - * - * Multi-arch abstraction and beautification: - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - .set noreorder - .set mips3 - .align 5 -NESTED(r4k_do_syscalls, 64, sp) - subu sp, 64 - sw ra, 56(sp) - sll a2, a2, PTRLOG - lw t0, dst(a2) - move t2, a1 - jalr t0 - lw t0, PT_R29(a0) # get old user stack pointer -7: - lw t1, 24(t0) # parameter #7 from usp - sw t1, 24(sp) -6: - lw t1, 20(t0) # parameter #6 from usp - sw t1, 20(sp) -5: - lw t1, 16(t0) # parameter #5 from usp - sw t1, 16(sp) -4: - lw a3, PT_R7(a0) # 4 args -3: - lw a2, PT_R6(a0) # 3 args -2: - lw a1, PT_R5(a0) # 2 args -1: - jalr t2 # 1 args - lw a0, PT_R4(a0) - - .set reorder - lw ra, 56(sp) - addiu sp, 64 - jr ra -0: - jalr t2 # 0 args, just pass a0 - nop - lw ra, 56(sp) - addiu sp, 64 - jr ra - nop - END(r4k_do_syscalls) - - .rdata - .align PTRLOG -dst: PTR 0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b - - .section __ex_table,"a" - PTR 7b,bad_stack - PTR 6b,bad_stack - PTR 5b,bad_stack - .previous diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r4k_switch.S linux/arch/mips/kernel/r4k_switch.S --- v2.1.100/linux/arch/mips/kernel/r4k_switch.S Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/kernel/r4k_switch.S Fri May 8 00:13:24 1998 @@ -5,6 +5,8 @@ * * Multi-cpu abstraction and macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: r4k_switch.S,v 1.2 1998/05/01 01:34:19 ralf Exp $ */ #include #include @@ -13,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -25,44 +28,139 @@ .set mips3 .align 5 LEAF(r4xx0_resume) - GET_CURRENT(t0) - mfc0 t1, CP0_STATUS - nop - sw t1, THREAD_STATUS(t0) - ori t2, t1, 0x1f - xori t2, t2, 0x1e - mtc0 t2, CP0_STATUS - CPU_SAVE_NONSCRATCH(t0) - sll t2, t1, 2 # Save floating point state - bgez t2, 2f - sw ra, THREAD_REG31(t0) + mfc0 t1, CP0_STATUS # fp exception boundary + sll t0, t1, 2 + bgez t0, 1f + nop + cfc1 zero, fcr31 +1: sw t1, THREAD_STATUS($28) + CPU_SAVE_NONSCRATCH($28) + sw ra, THREAD_REG31($28) + + /* + * The order of restoring the registers takes care of the race + * updating $28, $29 and kernelsp without disabling ints. + */ + move $28, a0 + CPU_RESTORE_NONSCRATCH($28) + addiu t0, $28, KERNEL_STACK_SIZE-32 + sw t0, kernelsp + lw a3, TASK_MM($28) + lw a2, THREAD_STATUS($28) + lw a3, MM_CONTEXT(a3) + mtc0 a2, CP0_STATUS + andi a3, a3, 0xff + jr ra + mtc0 a3, CP0_ENTRYHI + END(r4xx0_resume) + +/* + * Do lazy fpu context switch. Saves FPU context to the process in a0 + * and loads the new context of the current process. + */ + +#define ST_OFF (KERNEL_STACK_SIZE - 32 - PT_SIZE + PT_STATUS) + +LEAF(r4xx0_lazy_fpu_switch) + mfc0 t0, CP0_STATUS # enable cp1 + li t3, 0x20000000 + or t0, t3 + mtc0 t0, CP0_STATUS + + beqz a0, 2f # Save floating point state + nor t3, zero, t3 + lw t1, ST_OFF(a0) # last thread looses fpu + and t1, t3 + sw t1, ST_OFF(a0) sll t2, t1, 5 bgez t2, 1f - swc1 $f0, (THREAD_FPU + 0x00)(t0) - FPU_SAVE_16ODD(t0) + sdc1 $f0, (THREAD_FPU + 0x00)(a0) + FPU_SAVE_16ODD(a0) 1: - FPU_SAVE_16EVEN(t0, t1) # clobbers t1 + FPU_SAVE_16EVEN(a0, t1) # clobbers t1 2: - lw a3, TASK_MM(a0) - lw a2, THREAD_STATUS(a0) - lw a3, MM_CONTEXT(a3) - ori t1, a2, 1 # restore fpu, pipeline magic - andi a3, a3, 0xff - xori t1, t1, 1 - mtc0 a3, CP0_ENTRYHI - mtc0 t1, CP0_STATUS - sll t0, a2, 2 - bgez t0, 2f - sll t0, a2, 5 + + sll t0, t0, 5 # load new fp state bgez t0, 1f - lwc1 $f0, (THREAD_FPU + 0x00)(a0) - FPU_RESTORE_16ODD(a0) + ldc1 $f0, (THREAD_FPU + 0x00)($28) + FPU_RESTORE_16ODD($28) 1: - FPU_RESTORE_16EVEN(a0, t0) # clobbers t0 -2: - CPU_RESTORE_NONSCRATCH(a0) - lw t0, THREAD_KSP(a0) - sw t0, kernelsp + .set reorder + FPU_RESTORE_16EVEN($28, t0) # clobbers t0 jr ra - mtc0 a2, CP0_STATUS - END(r4xx0_resume) + END(r4xx0_lazy_fpu_switch) + +/* + * Save a thread's fp context. + */ + .set noreorder +LEAF(r4xx0_save_fp) + mfc0 t0, CP0_STATUS + sll t1, t0, 5 + bgez t1, 1f # 16 register mode? + nop + FPU_SAVE_16ODD(a0) +1: + FPU_SAVE_16EVEN(a0, t1) # clobbers t1 + jr ra + sdc1 $f0, (THREAD_FPU + 0x00)(a0) + END(r4xx0_save_fp) + +/* + * Load the FPU with signalling NANS. This bit pattern we're using has + * the property that no matter wether considered as single or as double + * precission represents signaling NANS. + * + * We initialize fcr31 to rounding to nearest, no exceptions. + */ + +#define FPU_DEFAULT 0x00000600 + +LEAF(r4xx0_init_fpu) + mfc0 t0, CP0_STATUS + li t1, 0x20000000 + or t0, t1 + mtc0 t0, CP0_STATUS + sll t0, t0, 5 + + li t1, FPU_DEFAULT + ctc1 t1, fcr31 + + bgez t0, 1f # 16 / 32 register mode? + li t0, -1 + + dmtc1 t0, $f1 + dmtc1 t0, $f3 + dmtc1 t0, $f5 + dmtc1 t0, $f7 + dmtc1 t0, $f9 + dmtc1 t0, $f11 + dmtc1 t0, $f13 + dmtc1 t0, $f15 + dmtc1 t0, $f17 + dmtc1 t0, $f19 + dmtc1 t0, $f21 + dmtc1 t0, $f23 + dmtc1 t0, $f25 + dmtc1 t0, $f27 + dmtc1 t0, $f29 + dmtc1 t0, $f31 + +1: dmtc1 t0, $f0 + dmtc1 t0, $f2 + dmtc1 t0, $f4 + dmtc1 t0, $f6 + dmtc1 t0, $f8 + dmtc1 t0, $f10 + dmtc1 t0, $f12 + dmtc1 t0, $f14 + dmtc1 t0, $f16 + dmtc1 t0, $f18 + dmtc1 t0, $f20 + dmtc1 t0, $f22 + dmtc1 t0, $f24 + dmtc1 t0, $f26 + dmtc1 t0, $f28 + jr ra + dmtc1 t0, $f30 + END(r4xx0_init_fpu) diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r6000_fpu.S linux/arch/mips/kernel/r6000_fpu.S --- v2.1.100/linux/arch/mips/kernel/r6000_fpu.S Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/r6000_fpu.S Fri May 8 00:13:24 1998 @@ -10,7 +10,7 @@ * Multi-arch abstraction and asm macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r6000_fpu.S,v 1.3 1997/12/01 16:56:56 ralf Exp $ + * $Id: r6000_fpu.S,v 1.4 1998/05/01 01:34:20 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/scall_o32.S linux/arch/mips/kernel/scall_o32.S --- v2.1.100/linux/arch/mips/kernel/scall_o32.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/scall_o32.S Fri May 8 00:13:24 1998 @@ -0,0 +1,177 @@ +/* + * arch/mips/kernel/scall_o32.S + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1997, 1998 by Ralf Baechle + * + * $Id: scall_o32.S,v 1.1 1998/05/01 01:34:21 ralf Exp $ + */ +#include +#include +#include +#include +#include +#include +#include + +/* This duplicates the definition from */ +#define PF_TRACESYS 0x00000020 /* tracing system calls */ + +/* This duplicates the definition from */ +#define SIGILL 4 /* Illegal instruction (ANSI). */ + +/* Highest syscall used of any syscall flavour */ +#define MAX_SYSCALL_NO __NR_Linux + __NR_Linux_syscalls + + .align 5 +NESTED(handle_sys, PT_SIZE, sp) + .set noat + SAVE_SOME + STI + .set at + + lw t1, PT_EPC(sp) # skip syscall on return + + sltiu t0, v0, MAX_SYSCALL_NO + 1 # check syscall number + addiu t1, 4 # skip to next instruction + beqz t0, illegal_syscall + sw t1, PT_EPC(sp) + + /* XXX Put both in one cacheline, should save a bit. */ + sll t0, v0, 2 + lw t2, sys_call_table(t0) # syscall routine + lbu t3, sys_narg_table(v0) # number of arguments + beqz t2, illegal_syscall; + + subu t0, t3, 5 # 5 or more arguments? + bgez t0, stackargs + +stack_done: + lw t0, TASK_FLAGS($28) # syscall tracing enabled? + andi t0, PF_TRACESYS + bnez t0, trace_a_syscall + + jalr t2 # Do The Real Thing (TM) + + li t0, -EMAXERRNO - 1 # error? + sltu t0, t0, v0 + sw t0, PT_R7(sp) # set error flag + beqz t0, 1f + + negu v0 # error + sw v0, PT_R0(sp) # set flag for syscall restarting +1: sw v0, PT_R2(sp) # result + +EXPORT(o32_ret_from_sys_call) + lw t0,bh_mask + lw t1,bh_active # unused delay slot + and t0,t1 + bnez t0,o32_handle_bottom_half + +9: lw t0,PT_STATUS(sp) # returning to kernel mode? + andi t1, t0, 0x10 + lw t2, need_resched + beqz t1, o32_return # -> yes + bnez t2, o32_reschedule + lw v0, TASK_SIGPENDING($28) + move a0, zero + beqz v0, o32_return + move a1, sp + SAVE_STATIC + jal do_signal + +o32_return: + RESTORE_SOME + RESTORE_SP + .set mips3 + eret + .set mips0 + +o32_handle_bottom_half: + jal do_bottom_half + b 9b +o32_reschedule: + SAVE_STATIC + jal schedule + b o32_ret_from_sys_call + +/* ------------------------------------------------------------------------ */ + +trace_a_syscall: + SAVE_STATIC + sw t2,PT_R1(sp) + jal syscall_trace + sw t2,PT_R1(sp) + + jalr t2 # Do The Real Thing (TM) + + li t0, -EMAXERRNO - 1 # error? + sltu t0, t0, v0 + sw t0, PT_R7(sp) # set error flag + beqz t0, 1f + + negu v0 # error + sw v0, PT_R0(sp) # set flag for syscall restarting +1: sw v0, PT_R2(sp) # result + + jal syscall_trace + j ret_from_sys_call + +/* ------------------------------------------------------------------------ */ + + /* + * More than four arguments. Try to deal with it by copying the + * stack arguments from the user stack to the kernel stack. + * This Sucks (TM). + */ +stackargs: + lw t0, PT_R29(sp) # get old user stack pointer + subu t3, 4 + sll t1, t3, 2 # stack valid? + + addu t1, t0 # end address + or t0, t1 + bltz t0, bad_stack # -> sp is bad + + lw t0, PT_R29(sp) # get old user stack pointer + la t1, 3f # copy 1 to 2 arguments + sll t3, t3, 3 + subu t1, t3 + jr t1 + + /* Ok, copy the args from the luser stack to the kernel stack */ +1: lw t1, 20(t0) # argument #6 from usp + sw t1, 20(sp) +2: lw t1, 16(t0) # argument #5 from usp + sw t1, 16(sp) + +3: j stack_done # go back + + .section __ex_table,"a" + PTR 1b,bad_stack + PTR 2b,bad_stack + .previous + + /* + * The stackpointer for a call with more than 4 arguments is bad. + */ +bad_stack: + negu v0 # error + sw v0, PT_R0(sp) + sw v0, PT_R2(sp) + li t0, 1 # set error flag + sw t0, PT_R7(sp) + j ret_from_sys_call + + /* + * The system call does not exist in this kernel + */ +illegal_syscall: + li v0, ENOSYS # error + sw v0, PT_R2(sp) + li t0, 1 # set error flag + sw t0, PT_R7(sp) + j ret_from_sys_call diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c --- v2.1.100/linux/arch/mips/kernel/setup.c Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/setup.c Fri May 8 00:13:24 1998 @@ -5,10 +5,11 @@ * Copyright (C) 1995, 1996 Ralf Baechle * Copyright (C) 1996 Stoned Elipot * - * $Id: setup.c,v 1.5 1997/12/06 08:55:42 ralf Exp $ + * $Id: setup.c,v 1.9 1998/05/04 09:17:56 ralf Exp $ */ #include #include +#include #include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -86,6 +88,11 @@ struct drive_info_struct drive_info = DEFAULT_DRIVE_INFO; struct screen_info screen_info = DEFAULT_SCREEN_INFO; +#ifdef CONFIG_BLK_DEV_IDE +extern struct ide_ops no_ide_ops; +struct ide_ops *ide_ops; +#endif + /* * setup informations * @@ -170,25 +177,15 @@ atag = bi_TagFind(tag_vram_base); memcpy(&mips_vram_base, TAGVALPTR(atag), atag->size); + /* Save defaults for configuration dependand routines. */ irq_setup = default_irq_setup; fd_cacheflush = default_fd_cacheflush; +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &no_ide_ops; +#endif switch(mips_machgroup) { -#ifdef CONFIG_MIPS_DECSTATION - case MACH_GROUP_DEC: - decstation_setup(); - break; -#endif -#if defined(CONFIG_MIPS_ARC) - /* - * Perhaps arch/mips/deskstation should be renamed to arch/mips/arc. - * For now CONFIG_MIPS_ARC means DeskStation. -Stoned. - */ - case MACH_GROUP_ARC: - deskstation_setup(); - break; -#endif #ifdef CONFIG_MIPS_JAZZ case MACH_GROUP_JAZZ: jazz_setup(); diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/signal.c linux/arch/mips/kernel/signal.c --- v2.1.100/linux/arch/mips/kernel/signal.c Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/signal.c Fri May 8 00:13:24 1998 @@ -4,7 +4,9 @@ * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1994, 1995, 1996 Ralf Baechle * - * $Id: signal.c,v 1.8 1997/12/01 16:26:34 ralf Exp $ + * $Id: signal.c,v 1.12 1998/05/01 01:34:28 ralf Exp $ + * + * XXX Handle lazy fp context switches correctly. */ #include #include @@ -23,82 +25,189 @@ #include #include -#define _S(nr) (1<<((nr)-1)) +#define DEBUG_SIG 0 -#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, int options, unsigned long *ru); -asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs); +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); extern asmlinkage void (*save_fp_context)(struct sigcontext *sc); extern asmlinkage void (*restore_fp_context)(struct sigcontext *sc); /* * Atomically swap in the new signal mask, and wait for a signal. - * Unlike on Intel we pass a sigset_t *, not sigset_t. */ -asmlinkage int sys_sigsuspend(struct pt_regs *regs) +asmlinkage inline int +sys_sigsuspend(struct pt_regs regs) { - unsigned long mask; - sigset_t *uset, set; + sigset_t *uset, saveset, newset; - uset = (sigset_t *) regs->regs[4]; - if (get_user(set, uset)) + uset = (sigset_t *) regs.regs[4]; + if (copy_from_user(&newset, uset, sizeof(sigset_t))) return -EFAULT; + sigdelsetmask(&newset, ~_BLOCKABLE); spin_lock_irq(¤t->sigmask_lock); - mask = current->blocked; - current->blocked = set & _BLOCKABLE; + saveset = current->blocked; + current->blocked = newset; spin_unlock_irq(¤t->sigmask_lock); - regs->regs[2] = -EINTR; + regs.regs[2] = -EINTR; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(mask, regs)) + if (do_signal(&saveset, ®s)) return -EINTR; } - return -EINTR; } -asmlinkage int sys_sigreturn(struct pt_regs *regs) +asmlinkage int +sys_rt_sigsuspend(struct pt_regs regs) { - struct sigcontext *context; - unsigned long blocked; - long long reg; - int i; + sigset_t *uset, saveset, newset; - context = (struct sigcontext *)(long) regs->regs[29]; - if (!access_ok(VERIFY_READ, context, sizeof(struct sigcontext)) || - (regs->regs[29] & (SZREG - 1))) - goto badframe; + uset = (sigset_t *) regs.regs[4]; + if (copy_from_user(&newset, uset, sizeof(sigset_t))) + return -EFAULT; + sigdelsetmask(&newset, ~_BLOCKABLE); - __get_user(blocked, &context->sc_sigset); - current->blocked = blocked & _BLOCKABLE; - __get_user(regs->cp0_epc, &context->sc_pc); + spin_lock_irq(¤t->sigmask_lock); + saveset = current->blocked; + current->blocked = newset; + spin_unlock_irq(¤t->sigmask_lock); - /* - * Restore all integer registers. - */ - for(i = 31;i >= 0;i--) { - __get_user(reg, &context->sc_regs[i]); - regs->regs[i] = (int) reg; + regs.regs[2] = -EINTR; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal(&saveset, ®s)) + return -EINTR; } +} + +asmlinkage int +sys_sigaction(int sig, const struct sigaction *act, + struct sigaction *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + sigset_t mask; + if (verify_area(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags)) + return -EFAULT; + + __copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t)); + new_ka.ka_restorer = NULL; + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags)) + return -EFAULT; + __copy_to_user(&old_ka.sa.sa_mask, &oact->sa_mask, + sizeof(sigset_t)); + } + + return ret; +} + +/* + * To do: this entire function should be accessed over a function pointer + * such that we can handle stack frames for different ABIs. + */ + +asmlinkage void +restore_sigcontext(struct pt_regs *regs, struct sigcontext *context) +{ + long long reg; + int owned_fp; + + __get_user(regs->cp0_epc, &context->sc_pc); + __get_user(reg, &context->sc_mdhi); regs->hi = (int) reg; __get_user(reg, &context->sc_mdlo); regs->lo = (int) reg; - /* - * FP depends on what FPU in what mode we have. Best done in - * Assembler ... - */ - restore_fp_context(context); +#define restore_gp_reg(i) __get_user(reg, &context->sc_regs[i]); \ + regs->regs[i] = (int) reg; + restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3); + restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6); + restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9); + restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12); + restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15); + restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18); + restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21); + restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24); + restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27); + restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30); + restore_gp_reg(31); +#undef restore_gp_reg + + /* FP depends on what FPU in what mode we have. */ + __get_user(owned_fp, &context->sc_ownedfp); +#if 0 + if (owned_fp) { + restore_fp_context(context); + last_task_used_math = current; + } +#endif +restore_fp_context(context); +} - /* - * Disable syscall checks - */ - regs->orig_reg2 = -1; +/* + * The structure sc describes the stackframe on the userstack. The frames + * are identical for normal and realtime signal stackframes with the + * exception of the additional struct ucontext for rt frames. + */ +struct sigframe { + unsigned long ass[4]; /* argument save space for o32 */ + unsigned int code[4]; /* signal trampoline */ + struct sigcontext scc; +}; + +struct rt_sigframe { + unsigned long ass[4]; + unsigned int code[4]; + struct sigcontext scc; + // struct ucontext uc; +}; + +asmlinkage int sys_sigreturn(struct pt_regs regs) +{ + struct sigcontext *context; + sigset_t blocked; + + context = (struct sigcontext *)(long) regs.regs[29]; + if (!access_ok(VERIFY_READ, context, sizeof(struct sigcontext)) || + (regs.regs[29] & (SZREG - 1))) + goto badframe; + +#if 1 + if (__get_user(blocked.sig[0], &context->sc_sigset[0]) || + __get_user(blocked.sig[1], &context->sc_sigset[1]) || + __get_user(blocked.sig[2], &context->sc_sigset[2]) || + __get_user(blocked.sig[3], &context->sc_sigset[3])) + goto badframe; +#else + if (__copy_from_user(&blocked, &context->sc_sigset, sizeof(blocked))) + goto badframe; +#endif + + sigdelsetmask(&blocked, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = blocked; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + restore_sigcontext(®s, context); /* * Don't let your children do this ... @@ -107,7 +216,7 @@ "move\t$29,%0\n\t" "j\tret_from_sys_call" :/* no outputs */ - :"r" (regs)); + :"r" (®s)); /* Unreached */ badframe: @@ -116,103 +225,113 @@ unlock_kernel(); } +/* same as sys_sigreturn for now */ +asmlinkage int sys_rt_sigreturn(struct pt_regs regs) +{ + return -ENOSYS; +} + +#define scc_offset ((size_t)&((struct sigframe *)0)->scc) + /* - * Set up a signal frame... - * - * This routine is somewhat complicated by the fact that if the kernel may be - * entered by an exception other than a system call; e.g. a bus error or other - * "bad" exception. If this is the case, then *all* the context on the kernel - * stack frame must be saved. - * - * For a large number of exceptions, the stack frame format is the same - * as that which will be created when the process traps back to the kernel - * when finished executing the signal handler. In this case, nothing - * must be done. This information is saved on the user stack and restored - * when the signal handler is returned. - * - * The signal handler will be called with ra pointing to code1 (see below) and - * one parameters in a0 (signum). + * Set up the return code ... * - * usp -> [unused] ; first free word on stack - * arg save space ; 16/32 bytes arg. save space - * code1 (addiu sp,#1-offset) ; pop stackframe - * code2 (li v0,__NR_sigreturn) ; syscall number - * code3 (syscall) ; do sigreturn(2) - * #1| $0, at, v0, v1, a0, a1, a2, a3 ; All integer registers - * | t0, t1, t2, t3, t4, t5, t6, t7 ; $0, k0 and k1 are placeholders - * | s0, s1, s2, s3, s4, s5, s6, s7 - * | k0, k1, t8, t9, gp, sp, fp, ra; - * | epc ; old program counter - * | cause ; CP0 cause register - * | oldmask + * .set noreorder + * addiu sp,0x20 + * li v0,__NR_sigreturn + * syscall + * .set reorder */ +static void inline +setup_trampoline(unsigned int *code) +{ + __put_user(0x27bd0000 + scc_offset , code + 0); + __put_user(0x24020000 + __NR_sigreturn, code + 1); + __put_user(0x0000000c , code + 2); -struct sc { - unsigned long ass[4]; - unsigned int code[4]; - struct sigcontext scc; -}; -#define scc_offset ((size_t)&((struct sc *)0)->scc) + /* + * Flush caches so that the instructions will be correctly executed. + */ + flush_cache_sigtramp((unsigned long) code); +} + +static void inline +setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc, sigset_t *set) +{ + int owned_fp; + + __put_user(regs->cp0_epc, &sc->sc_pc); + __put_user(regs->cp0_status, &sc->sc_status); /* Status register */ + +#define save_gp_reg(i) __put_user(regs->regs[(i)], &sc->sc_regs[(i)]) + __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2); + save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6); + save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10); + save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14); + save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18); + save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22); + save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26); + save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30); + save_gp_reg(31); +#undef save_gp_reg + + __put_user(regs->hi, &sc->sc_mdhi); + __put_user(regs->lo, &sc->sc_mdlo); + __put_user(regs->cp0_cause, &sc->sc_cause); + + owned_fp = (current == last_task_used_math); + __put_user(owned_fp, &sc->sc_ownedfp); + +#if 0 + if (current->used_math) { /* fp is active. */ + set_cp0_status(ST0_CU1, ST0_CU1); + save_fp_context(sc); /* cpu dependant */ + last_task_used_math = NULL; + regs->cp0_status &= ~ST0_CU1; + current->used_math = 0; + } +#endif +set_cp0_status(ST0_CU1, ST0_CU1); +save_fp_context(sc); /* cpu dependant */ -static void setup_frame(struct sigaction * sa, struct pt_regs *regs, - int signr, unsigned long oldmask) + __put_user(set->sig[0], &sc->sc_sigset[0]); + __put_user(set->sig[1], &sc->sc_sigset[1]); + __put_user(set->sig[2], &sc->sc_sigset[2]); + __put_user(set->sig[3], &sc->sc_sigset[3]); +} + +static void inline +setup_frame(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *oldmask) { - struct sc *frame; + struct sigframe *frame; struct sigcontext *sc; - int i; /* Align the stackframe to an adequate boundary for the architecture. */ - frame = (struct sc *) (long) regs->regs[29]; + frame = (struct sigframe *) (long) regs->regs[29]; frame--; - frame = (struct sc *)((unsigned long)frame & ALMASK); + frame = (struct sigframe *)((unsigned long)frame & ALMASK); if (verify_area(VERIFY_WRITE, frame, sizeof (*frame))) goto segv_and_exit; sc = &frame->scc; - /* - * Set up the return code ... - * - * .set noreorder - * addiu sp,0x20 - * li v0,__NR_sigreturn - * syscall - * .set reorder - */ - __put_user(0x27bd0000 + scc_offset, &frame->code[0]); - __put_user(0x24020000 + __NR_sigreturn, &frame->code[1]); - __put_user(0x0000000c, &frame->code[2]); - - /* - * Flush caches so that the instructions will be correctly executed. - */ - flush_cache_sigtramp((unsigned long) frame->code); + setup_trampoline(frame->code); + setup_sigcontext(regs, &frame->scc, oldmask); - /* - * Set up the "normal" sigcontext - */ - __put_user(regs->cp0_epc, &sc->sc_pc); - __put_user(regs->cp0_status, &sc->sc_status); /* Status register */ - for(i = 31;i >= 0;i--) - __put_user(regs->regs[i], &sc->sc_regs[i]); - save_fp_context(sc); - __put_user(regs->hi, &sc->sc_mdhi); - __put_user(regs->lo, &sc->sc_mdlo); - __put_user(regs->cp0_cause, &sc->sc_cause); - __put_user((regs->cp0_status & ST0_CU1) != 0, &sc->sc_ownedfp); - __put_user(oldmask, &sc->sc_sigset); - __put_user(0, &sc->__pad0[0]); - __put_user(0, &sc->__pad0[1]); - __put_user(0, &sc->__pad0[2]); - - regs->regs[4] = signr; /* Arguments for handler */ - regs->regs[5] = 0; /* For now. */ - regs->regs[6] = (long) frame; /* Pointer to sigcontext */ - regs->regs[29] = (unsigned long) frame; /* Stack pointer */ - regs->regs[31] = (unsigned long) frame->code; /* Return address */ - regs->cp0_epc = (unsigned long) sa->sa_handler; /* "return" to the first handler */ - regs->regs[25] = regs->cp0_epc; /* PIC shit... */ - return; + regs->regs[4] = signr; /* arguments */ + regs->regs[5] = 0; /* should be cause */ + regs->regs[6] = (long) frame; /* ptr to sigcontext */ + regs->regs[29] = (unsigned long) frame; /* Stack pointer */ + regs->regs[31] = (unsigned long) frame->code; /* Return address */ + regs->cp0_epc = (unsigned long) ka->sa.sa_handler; /* handler address */ + regs->regs[25] = regs->cp0_epc; /* PIC shit... */ + +#if DEBUG_SIG + printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n", + current->comm, current->pid, frame, regs->cp0_epc, frame->code); +#endif + return; segv_and_exit: lock_kernel(); @@ -220,96 +339,127 @@ unlock_kernel(); } -static inline void handle_signal(unsigned long signr, struct sigaction *sa, - unsigned long oldmask, struct pt_regs * regs) +static void inline +setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *oldmask, siginfo_t *info) { - setup_frame(sa, regs, signr, oldmask); + printk("Aiee: setup_tr_frame wants to be written"); +} - if (sa->sa_flags & SA_ONESHOT) - sa->sa_handler = NULL; - if (!(sa->sa_flags & SA_NOMASK)) { +/* ------------------------------------------------------------------------- */ + +static inline void handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) +{ + if (ka->sa.sa_flags & SA_SIGINFO) + setup_rt_frame(ka, regs, sig, oldset, info); + else + setup_frame(ka, regs, sig, oldset); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sigmask_lock); - current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE; + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked,sig); + recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); } } -static inline void syscall_restart(unsigned long r0, unsigned long or2, - unsigned long or7, struct pt_regs *regs, - struct sigaction *sa) +static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) { - switch(r0) { + switch(regs->regs[0]) { case ERESTARTNOHAND: - no_system_call_restart: - regs->regs[0] = regs->regs[2] = EINTR; + regs->regs[2] = EINTR; break; case ERESTARTSYS: - if(!(sa->sa_flags & SA_RESTART)) - goto no_system_call_restart; + if(!(ka->sa.sa_flags & SA_RESTART)) { + regs->regs[2] = EINTR; + break; + } /* fallthrough */ - case ERESTARTNOINTR: - regs->regs[0] = regs->regs[2] = or2; - regs->regs[7] = or7; + case ERESTARTNOINTR: /* Userland will reload $v0. */ regs->cp0_epc -= 8; } + + regs->regs[0] = 0; /* Don't deal with this again. */ } -extern int do_irix_signal(unsigned long oldmask, struct pt_regs *regs); +extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs); -/* - * Note that 'init' is a special process: it doesn't get signals it doesn't - * want to handle. Thus you cannot kill init even with a SIGKILL even by - * mistake. - * - * Note that we go through the signals twice: once to check the signals that - * the kernel can handle, and then we build all the user-level signal handling - * stack-frames in one go after that. - */ -asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) { - unsigned long mask = ~current->blocked; - unsigned long signr, r0 = regs->regs[0]; - unsigned long r7 = regs->orig_reg7; - struct sigaction * sa; + struct k_sigaction *ka; + siginfo_t info; #ifdef CONFIG_BINFMT_IRIX - if(current->personality != PER_LINUX) - return do_irix_signal(oldmask, regs); + if (current->personality != PER_LINUX) /* XXX */ + return do_irix_signal(oldset, regs); #endif - while ((signr = current->signal & mask)) { - signr = ffz(~signr); - clear_bit(signr, ¤t->signal); - sa = current->sig->action + signr; - signr++; + + if (!oldset) + oldset = ¤t->blocked; + + for (;;) { + unsigned long signr; + + spin_lock_irq(¤t->sigmask_lock); + signr = dequeue_signal(¤t->blocked, &info); + spin_unlock_irq(¤t->sigmask_lock); + + if (!signr) + break; + if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + /* Let the debugger run. */ current->exit_code = signr; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); + + /* We're back. Did the debugger cancel the sig? */ if (!(signr = current->exit_code)) continue; current->exit_code = 0; + + /* The debugger continued. Ignore SIGSTOP. */ if (signr == SIGSTOP) continue; - if (_S(signr) & current->blocked) { - spin_lock_irq(¤t->sigmask_lock); - current->signal |= _S(signr); - spin_unlock_irq(¤t->sigmask_lock); + + /* Update the siginfo structure. Is this good? */ + if (signr != info.si_signo) { + info.si_signo = signr; + info.si_errno = 0; + info.si_code = SI_USER; + info.si_pid = current->p_pptr->pid; + info.si_uid = current->p_pptr->uid; + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(¤t->blocked, signr)) { + send_sig_info(signr, &info, current); continue; } - sa = current->sig->action + signr - 1; } - if (sa->sa_handler == SIG_IGN) { + + ka = ¤t->sig->action[signr-1]; + if (ka->sa.sa_handler == SIG_IGN) { if (signr != SIGCHLD) continue; - /* check for SIGCHLD: it's special */ - while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0) + /* Check for SIGCHLD: it's special. */ + while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) /* nothing */; continue; } - if (sa->sa_handler == SIG_DFL) { + + if (ka->sa.sa_handler == SIG_DFL) { + int exit_code = signr; + + /* Init gets no signals it doesn't want. */ if (current->pid == 1) continue; + switch (signr) { case SIGCONT: case SIGCHLD: case SIGWINCH: continue; @@ -317,72 +467,55 @@ case SIGTSTP: case SIGTTIN: case SIGTTOU: if (is_orphaned_pgrp(current->pgrp)) continue; + /* FALLTHRU */ + case SIGSTOP: - if (current->flags & PF_PTRACED) - continue; current->state = TASK_STOPPED; current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & - SA_NOCLDSTOP)) + if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: - case SIGBUS: lock_kernel(); - if (current->binfmt && current->binfmt->core_dump) { - if (current->binfmt->core_dump(signr, regs)) - signr |= 0x80; - } + if (current->binfmt + && current->binfmt->core_dump + && current->binfmt->core_dump(signr, regs)) + exit_code |= 0x80; unlock_kernel(); - /* fall through */ - default: - spin_lock_irq(¤t->sigmask_lock); - current->signal |= _S(signr & 0x7f); - spin_unlock_irq(¤t->sigmask_lock); + /* FALLTHRU */ + default: + lock_kernel(); + sigaddset(¤t->signal, signr); current->flags |= PF_SIGNALED; - - lock_kernel(); /* 8-( */ - do_exit(signr); - unlock_kernel(); + do_exit(exit_code); + /* NOTREACHED */ } } - /* - * OK, we're invoking a handler - */ - if(r0) - syscall_restart(r0, regs->orig_reg2, - r7, regs, sa); - handle_signal(signr, sa, oldmask, regs); + + if (regs->regs[0]) + syscall_restart(regs, ka); + /* Whee! Actually deliver the signal. */ + handle_signal(signr, ka, &info, oldset, regs); return 1; } + /* * Who's code doesn't conform to the restartable syscall convention * dies here!!! The li instruction, a single machine instruction, * must directly be followed by the syscall instruction. */ - if (r0 && - (regs->regs[2] == ERESTARTNOHAND || - regs->regs[2] == ERESTARTSYS || - regs->regs[2] == ERESTARTNOINTR)) { - regs->regs[0] = regs->regs[2] = regs->orig_reg2; - regs->regs[7] = r7; - regs->cp0_epc -= 8; + if (regs->regs[0]) { + if (regs->regs[2] == ERESTARTNOHAND || + regs->regs[2] == ERESTARTSYS || + regs->regs[2] == ERESTARTNOINTR) { + regs->cp0_epc -= 8; + } } return 0; -} - -/* - * The signal(2) syscall is no longer available in the kernel - * because GNU libc doesn't use it. Maybe I'll add it back to the - * kernel for the binary compatibility stuff. - */ -asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler) -{ - return -ENOSYS; } /* diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c --- v2.1.100/linux/arch/mips/kernel/syscall.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/kernel/syscall.c Fri May 8 00:13:24 1998 @@ -11,7 +11,7 @@ * Don't waste that much memory for empty entries in the syscall * table. * - * $Id: syscall.c,v 1.4 1997/09/18 07:57:30 root Exp $ + * $Id: syscall.c,v 1.11 1998/05/01 01:34:30 ralf Exp $ */ #undef CONF_PRINT_SYSCALLS #undef CONF_DEBUG_IRIX @@ -23,11 +23,14 @@ #include #include #include +#include #include #include #include +#include #include #include +#include #include extern asmlinkage void syscall_trace(void); @@ -37,7 +40,7 @@ extern syscall_t sys_call_table[]; extern unsigned char sys_narg_table[]; -asmlinkage int sys_pipe(struct pt_regs *regs) +asmlinkage int sys_pipe(struct pt_regs regs) { int fd[2]; int error, res; @@ -48,7 +51,7 @@ res = error; goto out; } - regs->regs[3] = fd[1]; + regs.regs[3] = fd[1]; res = fd[0]; out: unlock_kernel(); @@ -59,19 +62,22 @@ int flags, int fd, off_t offset) { struct file * file = NULL; - unsigned long res; + unsigned long error = -EFAULT; lock_kernel(); if (!(flags & MAP_ANONYMOUS)) { - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) - return -EBADF; - } - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - res = do_mmap(file, addr, len, prot, flags, offset); - + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + } + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + error = do_mmap(file, addr, len, prot, flags, offset); + if (file) + fput(file); +out: unlock_kernel(); - return res; + return error; } asmlinkage int sys_idle(void) @@ -105,28 +111,30 @@ return ret; } -asmlinkage int sys_fork(struct pt_regs *regs) +asmlinkage int sys_fork(struct pt_regs regs) { int res; + save_static(®s); lock_kernel(); - res = do_fork(SIGCHLD, regs->regs[29], regs); + res = do_fork(SIGCHLD, regs.regs[29], ®s); unlock_kernel(); return res; } -asmlinkage int sys_clone(struct pt_regs *regs) +asmlinkage int sys_clone(struct pt_regs regs) { unsigned long clone_flags; unsigned long newsp; int res; + save_static(®s); lock_kernel(); - clone_flags = regs->regs[4]; - newsp = regs->regs[5]; + clone_flags = regs.regs[4]; + newsp = regs.regs[5]; if (!newsp) - newsp = regs->regs[29]; - res = do_fork(clone_flags, newsp, regs); + newsp = regs.regs[29]; + res = do_fork(clone_flags, newsp, ®s); unlock_kernel(); return res; } @@ -134,18 +142,18 @@ /* * sys_execve() executes a new program. */ -asmlinkage int sys_execve(struct pt_regs *regs) +asmlinkage int sys_execve(struct pt_regs regs) { int error; char * filename; lock_kernel(); - filename = getname((char *) (long)regs->regs[4]); + filename = getname((char *) (long)regs.regs[4]); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; - error = do_execve(filename, (char **) (long)regs->regs[5], - (char **) (long)regs->regs[6], regs); + error = do_execve(filename, (char **) (long)regs.regs[5], + (char **) (long)regs.regs[6], ®s); putname(filename); out: @@ -193,11 +201,13 @@ /* * Do the indirect syscall syscall. * Don't care about kernel locking; the actual syscall will do it. + * + * XXX This is borken. */ -asmlinkage int sys_syscall(struct pt_regs *regs) +asmlinkage int sys_syscall(struct pt_regs regs) { syscall_t syscall; - unsigned long syscallnr = regs->regs[4]; + unsigned long syscallnr = regs.regs[4]; unsigned long a0, a1, a2, a3, a4, a5, a6; int nargs, errno; @@ -219,7 +229,7 @@ } if(nargs > 3) { - unsigned long usp = regs->regs[29]; + unsigned long usp = regs.regs[29]; unsigned long *sp = (unsigned long *) usp; if(usp & 3) { printk("unaligned usp -EFAULT\n"); @@ -252,9 +262,9 @@ } else { a3 = a4 = a5 = a6 = 0; } - a0 = regs->regs[5]; a1 = regs->regs[6]; a2 = regs->regs[7]; + a0 = regs.regs[5]; a1 = regs.regs[6]; a2 = regs.regs[7]; if(nargs == 0) - a0 = (unsigned long) regs; + a0 = (unsigned long) ®s; return syscall((void *)a0, a1, a2, a3, a4, a5, a6); } @@ -268,6 +278,9 @@ do_exit(SIGSEGV); } +/* + * Build the string table for the builtin "poor man's strace". + */ #ifdef CONF_PRINT_SYSCALLS #define SYS(fun, narg) #fun, static char *sfnames[] = { @@ -281,146 +294,3 @@ #include "irix5sys.h" }; #endif - -/* - * This isn't entirely correct with respect to kernel locking ... - */ -void do_sys(struct pt_regs *regs) -{ - unsigned long syscallnr, usp; - syscall_t syscall; - int errno, narg; - - /* Skip syscall instruction */ - if (delay_slot(regs)) { - /* - * By convention "li v0," is always preceeding - * the syscall instruction. So if we're in a delay slot - * userland is screwed up. - */ - force_sig(SIGILL, current); - return; - } - regs->cp0_epc += 4; - - syscallnr = regs->regs[2]; - if (syscallnr > (__NR_Linux + __NR_Linux_syscalls)) - goto illegal_syscall; - - syscall = sys_call_table[syscallnr]; - if (syscall == NULL) - goto illegal_syscall; - - narg = sys_narg_table[syscallnr]; -#ifdef CONF_PRINT_SYSCALLS - if(syscallnr >= 4000) - printk("do_sys(%s:%d): %s(%08lx,%08lx,%08lx,%08lx)", - current->comm, current->pid, sfnames[syscallnr - __NR_Linux], - regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7], - regs->cp0_epc); -#endif -#if defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX) - if(syscallnr < 2000 && syscallnr >= 1000) { - printk("irix_sys(%s:%d): %s(", current->comm, - current->pid, irix_sys_names[syscallnr - 1000]); - if((narg < 4) && (narg != 0)) { - int i = 0; - - while(i < (narg - 1)) { - printk("%08lx, ", regs->regs[i + 4]); - i++; - } - printk("%08lx) ", regs->regs[i + 4]); - } else if(narg == 0) { - printk("%08lx, %08lx, %08lx, %08lx) ", - regs->regs[4], regs->regs[5], regs->regs[6], - regs->regs[7]); - } else - printk("narg=%d) ", narg); - } -#endif - if (narg > 4) { - /* - * Verify that we can safely get the additional parameters - * from the user stack. Of course I could read the params - * from unaligned addresses ... Consider this a programming - * course caliber .45. - */ - usp = regs->regs[29]; - if (usp & 3) { - printk("unaligned usp\n"); - force_sig(SIGSEGV, current); - regs->regs[2] = EFAULT; - regs->regs[7] = 1; - return; - } - if (!access_ok(VERIFY_READ, (void *) (usp + 16), - (narg - 4) * sizeof(unsigned long))) { - regs->regs[2] = EFAULT; - regs->regs[7] = 1; - return; - } - } - - if ((current->flags & PF_TRACESYS) == 0) - { - errno = do_syscalls(regs, syscall, narg); - if ((errno < 0 && errno > (-ENOIOCTLCMD - 1)) || current->errno) { - goto bad_syscall; - } - regs->regs[2] = errno; - regs->regs[7] = 0; - } - else - { - syscall_trace(); - - errno = do_syscalls(regs, syscall, narg); - if (errno < 0 || current->errno) - { - regs->regs[2] = -errno; - regs->regs[7] = 1; - } - else - { - regs->regs[2] = errno; - regs->regs[7] = 0; - } - - syscall_trace(); - } -#if defined(CONF_PRINT_SYSCALLS) || \ - (defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX)) -#if 0 - printk(" returning: normal\n"); -#else - if(syscallnr >= 4000 && syscallnr < 5000) - printk(" returning: %08lx\n", (unsigned long) errno); -#endif -#endif - return; - -bad_syscall: - regs->regs[0] = regs->regs[2] = -errno; - regs->regs[7] = 1; -#if defined(CONF_PRINT_SYSCALLS) || \ - (defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX)) -#if 0 - printk(" returning: bad_syscall\n"); -#else - if(syscallnr >= 4000 && syscallnr < 5000) - printk(" returning error: %d\n", errno); -#endif -#endif - return; -illegal_syscall: - - regs->regs[2] = ENOSYS; - regs->regs[7] = 1; -#if defined(CONF_PRINT_SYSCALLS) || \ - (defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX)) - if(syscallnr >= 1000 && syscallnr < 2000) - printk(" returning: illegal_syscall\n"); -#endif - return; -} diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/syscalls.h linux/arch/mips/kernel/syscalls.h --- v2.1.100/linux/arch/mips/kernel/syscalls.h Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/kernel/syscalls.h Fri May 8 00:13:24 1998 @@ -7,7 +7,7 @@ * * Copyright (C) 1995, 1996 by Ralf Baechle * - * $Id: syscalls.h,v 1.6 1997/12/06 09:57:39 ralf Exp $ + * $Id: syscalls.h,v 1.13 1998/05/01 01:34:34 ralf Exp $ */ /* @@ -66,7 +66,7 @@ SYS(sys_brk, 1) /* 4045 */ SYS(sys_setgid, 1) SYS(sys_getgid, 0) -SYS(sys_signal, 2) +SYS(sys_ni_syscall, 0) /* was signal(2) */ SYS(sys_geteuid, 0) SYS(sys_getegid, 0) /* 4050 */ SYS(sys_acct, 0) @@ -211,3 +211,13 @@ SYS(sys_setresgid, 3) /* 4190 */ SYS(sys_getresgid, 3) SYS(sys_prctl, 5) +SYS(sys_rt_sigreturn, 0) +SYS(sys_rt_sigaction, 4) +SYS(sys_rt_sigprocmask, 4) /* 4195 */ +SYS(sys_rt_sigpending, 2) +SYS(sys_rt_sigtimedwait, 4) +SYS(sys_rt_sigqueueinfo, 3) +SYS(sys_rt_sigsuspend, 2) +SYS(sys_pread, 4) /* 4200 */ +SYS(sys_pwrite, 4) +SYS(sys_lchown, 3) diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c --- v2.1.100/linux/arch/mips/kernel/sysirix.c Thu May 7 22:51:47 1998 +++ linux/arch/mips/kernel/sysirix.c Fri May 8 00:13:24 1998 @@ -1,7 +1,10 @@ -/* $Id: sysirix.c,v 1.6 1997/12/06 11:29:29 ralf Exp $ +/* * sysirix.c: IRIX system call emulation. * * Copyright (C) 1996 David S. Miller + * Copyright (C) 1997 Miguel de Icaza + * + * $Id: sysirix.c,v 1.9 1998/05/01 01:34:35 ralf Exp $ */ #include @@ -25,11 +28,15 @@ #include #include #include +#include +#include -/* 2,358 lines of complete and utter shit coming up... */ +/* 2,526 lines of complete and utter shit coming up... */ /* The sysmp commands supported thus far. */ -#define MP_PGSIZE 14 /* Return system page size in v1. */ +#define MP_NPROCS 1 /* # processor in complex */ +#define MP_NAPROCS 2 /* # active processors in complex */ +#define MP_PGSIZE 14 /* Return system page size in v1. */ asmlinkage int irix_sysmp(struct pt_regs *regs) { @@ -45,9 +52,13 @@ case MP_PGSIZE: error = PAGE_SIZE; break; - + case MP_NPROCS: + case MP_NAPROCS: + error = 1; + error = NR_CPUS; + break; default: - printk("SYSMP[%s:%d]: Unsupported opcode %d\n", + printk("SYSMP[%s:%ld]: Unsupported opcode %d\n", current->comm, current->pid, (int)cmd); error = -EINVAL; break; @@ -86,7 +97,7 @@ cmd = regs->regs[base + 4]; switch(cmd) { case PR_MAXPROCS: - printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n", + printk("irix_prctl[%s:%ld]: Wants PR_MAXPROCS\n", current->comm, current->pid); error = NR_TASKS; break; @@ -94,7 +105,7 @@ case PR_ISBLOCKED: { struct task_struct *task; - printk("irix_prctl[%s:%d]: Wants PR_ISBLOCKED\n", + printk("irix_prctl[%s:%ld]: Wants PR_ISBLOCKED\n", current->comm, current->pid); task = find_task_by_pid(regs->regs[base + 5]); if(!task) { @@ -109,7 +120,7 @@ case PR_SETSTACKSIZE: { long value = regs->regs[base + 5]; - printk("irix_prctl[%s:%d]: Wants PR_SETSTACKSIZE<%08lx>\n", + printk("irix_prctl[%s:%ld]: Wants PR_SETSTACKSIZE<%08lx>\n", current->comm, current->pid, (unsigned long) value); if(value > RLIM_INFINITY) value = RLIM_INFINITY; @@ -129,25 +140,25 @@ } case PR_GETSTACKSIZE: - printk("irix_prctl[%s:%d]: Wants PR_GETSTACKSIZE\n", + printk("irix_prctl[%s:%ld]: Wants PR_GETSTACKSIZE\n", current->comm, current->pid); error = current->rlim[RLIMIT_STACK].rlim_cur; break; case PR_MAXPPROCS: - printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n", + printk("irix_prctl[%s:%ld]: Wants PR_MAXPROCS\n", current->comm, current->pid); error = 1; break; case PR_UNBLKONEXEC: - printk("irix_prctl[%s:%d]: Wants PR_UNBLKONEXEC\n", + printk("irix_prctl[%s:%ld]: Wants PR_UNBLKONEXEC\n", current->comm, current->pid); error = -EINVAL; break; case PR_SETEXITSIG: - printk("irix_prctl[%s:%d]: Wants PR_SETEXITSIG\n", + printk("irix_prctl[%s:%ld]: Wants PR_SETEXITSIG\n", current->comm, current->pid); /* We can probably play some game where we set the task @@ -158,31 +169,31 @@ break; case PR_RESIDENT: - printk("irix_prctl[%s:%d]: Wants PR_RESIDENT\n", + printk("irix_prctl[%s:%ld]: Wants PR_RESIDENT\n", current->comm, current->pid); error = 0; /* Compatability indeed. */ break; case PR_ATTACHADDR: - printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDR\n", + printk("irix_prctl[%s:%ld]: Wants PR_ATTACHADDR\n", current->comm, current->pid); error = -EINVAL; break; case PR_DETACHADDR: - printk("irix_prctl[%s:%d]: Wants PR_DETACHADDR\n", + printk("irix_prctl[%s:%ld]: Wants PR_DETACHADDR\n", current->comm, current->pid); error = -EINVAL; break; case PR_TERMCHILD: - printk("irix_prctl[%s:%d]: Wants PR_TERMCHILD\n", + printk("irix_prctl[%s:%ld]: Wants PR_TERMCHILD\n", current->comm, current->pid); error = -EINVAL; break; case PR_GETSHMASK: - printk("irix_prctl[%s:%d]: Wants PR_GETSHMASK\n", + printk("irix_prctl[%s:%ld]: Wants PR_GETSHMASK\n", current->comm, current->pid); error = -EINVAL; /* Until I have the sproc() stuff in. */ break; @@ -192,24 +203,24 @@ break; case PR_COREPID: - printk("irix_prctl[%s:%d]: Wants PR_COREPID\n", + printk("irix_prctl[%s:%ld]: Wants PR_COREPID\n", current->comm, current->pid); error = -EINVAL; break; case PR_ATTACHADDRPERM: - printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDRPERM\n", + printk("irix_prctl[%s:%ld]: Wants PR_ATTACHADDRPERM\n", current->comm, current->pid); error = -EINVAL; break; case PR_PTHREADEXIT: - printk("irix_prctl[%s:%d]: Wants PR_PTHREADEXIT\n", + printk("irix_prctl[%s:%ld]: Wants PR_PTHREADEXIT\n", current->comm, current->pid); do_exit(regs->regs[base + 5]); default: - printk("irix_prctl[%s:%d]: Non-existant opcode %d\n", + printk("irix_prctl[%s:%ld]: Non-existant opcode %d\n", current->comm, current->pid, (int)cmd); error = -EINVAL; break; @@ -225,15 +236,25 @@ extern asmlinkage int sys_setpgid(pid_t pid, pid_t pgid); extern void sys_sync(void); extern asmlinkage int sys_getsid(pid_t pid); +extern asmlinkage long sys_write (unsigned int fd, const char *buf, unsigned long count); +extern asmlinkage long sys_lseek (unsigned int fd, off_t offset, unsigned int origin); extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist); extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist); extern int getrusage(struct task_struct *p, int who, struct rusage *ru); +extern char *prom_getenv(char *name); +extern long prom_setenv(char *name, char *value); /* The syssgi commands supported thus far. */ #define SGI_SYSID 1 /* Return unique per-machine identifier. */ +#define SGI_INVENT 5 /* Fetch inventory */ +# define SGI_INV_SIZEOF 1 +# define SGI_INV_READ 2 #define SGI_RDNAME 6 /* Return string name of a process. */ +#define SGI_SETNVRAM 8 /* Set PROM variable. */ +#define SGI_GETNVRAM 9 /* Get PROM variable. */ #define SGI_SETPGID 21 /* Set process group id. */ #define SGI_SYSCONF 22 /* POSIX sysconf garbage. */ +#define SGI_PATHCONF 24 /* POSIX sysconf garbage. */ #define SGI_SETGROUPS 40 /* POSIX sysconf garbage. */ #define SGI_GETGROUPS 41 /* POSIX sysconf garbage. */ #define SGI_RUSAGE 56 /* BSD style rusage(). */ @@ -246,45 +267,81 @@ asmlinkage int irix_syssgi(struct pt_regs *regs) { - unsigned long cmd; - int retval, base = 0; + unsigned long cmd; + int retval, base = 0; - lock_kernel(); - if(regs->regs[2] == 1000) - base = 1; - - cmd = regs->regs[base + 4]; - switch(cmd) { - case SGI_SYSID: { - char *buf = (char *) regs->regs[base + 5]; - - /* XXX Use ethernet addr.... */ - retval = clear_user(buf, 64); - break; - } - - case SGI_RDNAME: { - int pid = (int) regs->regs[base + 5]; - char *buf = (char *) regs->regs[base + 6]; - struct task_struct *p; - - retval = verify_area(VERIFY_WRITE, buf, 16); - if(retval) - break; - for_each_task(p) { - if(p->pid == pid) - goto found0; - } - retval = -ESRCH; - - found0: - copy_to_user(buf, p->comm, 16); - retval = 0; + lock_kernel(); + if(regs->regs[2] == 1000) + base = 1; + + cmd = regs->regs[base + 4]; + switch(cmd) { + case SGI_SYSID: { + char *buf = (char *) regs->regs[base + 5]; + + /* XXX Use ethernet addr.... */ + retval = clear_user(buf, 64); + break; + } +#if 0 + case SGI_RDNAME: { + int pid = (int) regs->regs[base + 5]; + char *buf = (char *) regs->regs[base + 6]; + struct task_struct *p; + + retval = verify_area(VERIFY_WRITE, buf, 16); + if(retval) + break; + for_each_task(p) { + if(p->pid == pid) + goto found0; + } + retval = -ESRCH; + + found0: + /* XXX Need to check sizes. */ + copy_to_user(buf, p->comm, 16); + retval = 0; + break; + } + + case SGI_GETNVRAM: { + char *name = (char *) regs->regs[base+5]; + char *buf = (char *) regs->regs[base+6]; + char *value; + return -EINVAL; /* til I fix it */ + retval = verify_area(VERIFY_WRITE, buf, 128); + if (retval) + break; + value = prom_getenv(name); + if (!value) { + retval = -EINVAL; + break; + } + /* Do I strlen() for the length? */ + copy_to_user(buf, value, 128); + retval = 0; + break; + } + + case SGI_SETNVRAM: { + char *name = (char *) regs->regs[base+5]; + char *value = (char *) regs->regs[base+6]; + return -EINVAL; /* til I fix it */ + retval = prom_setenv(name, value); + /* XXX make sure retval conforms to syssgi(2) */ + printk("[%s:%d] setnvram(\"%s\", \"%s\"): retval %d", + current->comm, current->pid, + name, value, retval); +/* if (retval == PROM_ENOENT) + retval = -ENOENT; */ + break; } - +#endif + case SGI_SETPGID: { #ifdef DEBUG_PROCGRPS - printk("[%s:%d] setpgid(%d, %d) ", + printk("[%s:%ld] setpgid(%d, %d) ", current->comm, current->pid, (int) regs->regs[base + 5], (int)regs->regs[base + 6]); #endif @@ -381,7 +438,7 @@ case SGI_GETSID: #ifdef DEBUG_PROCGRPS - printk("[%s:%d] getsid(%d) ", current->comm, current->pid, + printk("[%s:%ld] getsid(%d) ", current->comm, current->pid, (int) regs->regs[base + 5]); #endif retval = sys_getsid(regs->regs[base + 5]); @@ -428,6 +485,24 @@ break; } + case SGI_INVENT: { + int arg1 = (int) regs->regs [base + 5]; + void *buffer = (void *) regs->regs [base + 6]; + int count = (int) regs->regs [base + 7]; + + switch (arg1){ + case SGI_INV_SIZEOF: + retval = sizeof (inventory_t); + break; + case SGI_INV_READ: + retval = dump_inventory_to_user (buffer, count); + break; + default: + retval = -EINVAL; + } + break; + } + default: printk("irix_syssgi: Unsupported command %d\n", (int)cmd); retval = -EINVAL; @@ -563,7 +638,8 @@ return ret; } -extern int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue); +extern int do_setitimer(int which, struct itimerval *value, + struct itimerval *ovalue); static inline void jiffiestotv(unsigned long jiffies, struct timeval *value) { @@ -604,7 +680,7 @@ it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0; it_new.it_value.tv_sec = seconds; it_new.it_value.tv_usec = 0; - _setitimer(ITIMER_REAL, &it_new, &it_old); + do_setitimer(ITIMER_REAL, &it_new, &it_old); } oldalarm = it_old.it_value.tv_sec; /* ehhh.. We can't return 0 if we have an alarm pending.. */ @@ -634,7 +710,7 @@ int ret; lock_kernel(); - printk("[%s:%d] irix_mount(%p,%p,%08lx,%p,%p,%d)\n", + printk("[%s:%ld] irix_mount(%p,%p,%08lx,%p,%p,%d)\n", current->comm, current->pid, dev_name, dir_name, flags, type, data, datalen); ret = sys_mount(dev_name, dir_name, type, flags, data); @@ -654,8 +730,9 @@ { struct dentry *dentry; struct inode *inode; + mm_segment_t old_fs; struct statfs kbuf; - int error, old_fs, i; + int error, i; /* We don't support this feature yet. */ if(fs_type) { @@ -703,8 +780,9 @@ struct dentry *dentry; struct inode *inode; struct statfs kbuf; + mm_segment_t old_fs; struct file *file; - int error, old_fs, i; + int error, i; lock_kernel(); error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs)); @@ -751,6 +829,7 @@ } error = 0; + dput(dentry); out: unlock_kernel(); return error; @@ -765,7 +844,7 @@ lock_kernel(); #ifdef DEBUG_PROCGRPS - printk("[%s:%d] setpgrp(%d) ", current->comm, current->pid, flags); + printk("[%s:%ld] setpgrp(%d) ", current->comm, current->pid, flags); #endif if(!flags) error = current->pgrp; @@ -845,7 +924,7 @@ asmlinkage unsigned long irix_gethostid(void) { lock_kernel(); - printk("[%s:%d]: irix_gethostid() called...\n", + printk("[%s:%ld]: irix_gethostid() called...\n", current->comm, current->pid); unlock_kernel(); return -EINVAL; @@ -854,7 +933,7 @@ asmlinkage unsigned long irix_sethostid(unsigned long val) { lock_kernel(); - printk("[%s:%d]: irix_sethostid(%08lx) called...\n", + printk("[%s:%ld]: irix_sethostid(%08lx) called...\n", current->comm, current->pid, val); unlock_kernel(); return -EINVAL; @@ -983,8 +1062,9 @@ asmlinkage int irix_lseek64(int fd, int _unused, int offhi, int offlow, int base) { + mm_segment_t old_fs; loff_t junk; - int old_fs, error; + int error; lock_kernel(); old_fs = get_fs(); set_fs(get_ds()); @@ -1026,6 +1106,8 @@ return retval; } +#define IRIX_MAP_AUTOGROW 0x40 + asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot, int flags, int fd, off_t offset) { @@ -1038,7 +1120,19 @@ retval = -EBADF; goto out; } + /* Ok, bad taste hack follows, try to think in something else when reading this */ + if (flags & IRIX_MAP_AUTOGROW){ + unsigned long old_pos; + long max_size = offset + len; + + if (max_size > file->f_dentry->d_inode->i_size){ + old_pos = sys_lseek (fd, max_size - 1, 0); + sys_write (fd, "", 1); + sys_lseek (fd, old_pos, 0); + } + } } + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); retval = do_mmap(file, addr, len, prot, flags, offset); @@ -1051,7 +1145,7 @@ asmlinkage int irix_madvise(unsigned long addr, int len, int behavior) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_madvise(%08lx,%d,%d)\n", + printk("[%s:%ld] Wheee.. irix_madvise(%08lx,%d,%d)\n", current->comm, current->pid, addr, len, behavior); unlock_kernel(); return -EINVAL; @@ -1060,7 +1154,7 @@ asmlinkage int irix_pagelock(char *addr, int len, int op) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_pagelock(%p,%d,%d)\n", + printk("[%s:%ld] Wheee.. irix_pagelock(%p,%d,%d)\n", current->comm, current->pid, addr, len, op); unlock_kernel(); return -EINVAL; @@ -1069,7 +1163,7 @@ asmlinkage int irix_quotactl(struct pt_regs *regs) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_quotactl()\n", + printk("[%s:%ld] Wheee.. irix_quotactl()\n", current->comm, current->pid); unlock_kernel(); return -EINVAL; @@ -1081,7 +1175,7 @@ lock_kernel(); #ifdef DEBUG_PROCGRPS - printk("[%s:%d] BSDsetpgrp(%d, %d) ", current->comm, current->pid, + printk("[%s:%ld] BSDsetpgrp(%d, %d) ", current->comm, current->pid, pid, pgrp); #endif if(!pid) @@ -1104,7 +1198,7 @@ asmlinkage int irix_systeminfo(int cmd, char *buf, int cnt) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_systeminfo(%d,%p,%d)\n", + printk("[%s:%ld] Wheee.. irix_systeminfo(%d,%p,%d)\n", current->comm, current->pid, cmd, buf, cnt); unlock_kernel(); return -EINVAL; @@ -1140,7 +1234,13 @@ #undef DEBUG_XSTAT -static inline int irix_xstat32_xlate(struct stat *kb, struct stat *ubuf) +static inline u32 +linux_to_irix_dev_t (dev_t t) +{ + return MAJOR (t) << 18 | MINOR (t); +} + +static inline int irix_xstat32_xlate(struct stat *kb, void *ubuf) { struct xstat32 { u32 st_dev, st_pad1[3], st_ino, st_mode, st_nlink, st_uid, st_gid; @@ -1151,9 +1251,27 @@ u32 st_blksize, st_blocks; char st_fstype[16]; u32 st_pad4[8]; - } *ub = (struct xstat32 *) ubuf; + } ub; - return copy_to_user(ub, kb, sizeof(*ub)) ? -EFAULT : 0; + ub.st_dev = linux_to_irix_dev_t (kb->st_dev); + ub.st_ino = kb->st_ino; + ub.st_mode = kb->st_mode; + ub.st_nlink = kb->st_nlink; + ub.st_uid = kb->st_uid; + ub.st_gid = kb->st_gid; + ub.st_rdev = linux_to_irix_dev_t (kb->st_rdev); + ub.st_size = kb->st_size; + ub.st_atime0 = kb->st_atime; + ub.st_atime1 = 0; + ub.st_mtime0 = kb->st_mtime; + ub.st_mtime1 = 0; + ub.st_ctime0 = kb->st_ctime; + ub.st_ctime1 = 0; + ub.st_blksize = kb->st_blksize; + ub.st_blocks = kb->st_blocks; + strcpy (ub.st_fstype, "efs"); + + return copy_to_user(ubuf, &ub, sizeof(ub)) ? -EFAULT : 0; } static inline void irix_xstat64_xlate(struct stat *sb) @@ -1173,14 +1291,14 @@ s32 st_pad4[8]; } ks; - ks.st_dev = (u32) sb->st_dev; + ks.st_dev = linux_to_irix_dev_t (sb->st_dev); ks.st_pad1[0] = ks.st_pad1[1] = ks.st_pad1[2] = 0; ks.st_ino = (unsigned long long) sb->st_ino; ks.st_mode = (u32) sb->st_mode; ks.st_nlink = (u32) sb->st_nlink; ks.st_uid = (s32) sb->st_uid; ks.st_gid = (s32) sb->st_gid; - ks.st_rdev = (u32) sb->st_rdev; + ks.st_rdev = linux_to_irix_dev_t (sb->st_rdev); ks.st_pad2[0] = ks.st_pad2[1] = 0; ks.st_size = (long long) sb->st_size; ks.st_pad3 = 0; @@ -1208,13 +1326,13 @@ lock_kernel(); #ifdef DEBUG_XSTAT - printk("[%s:%d] Wheee.. irix_xstat(%d,%s,%p) ", + printk("[%s:%ld] Wheee.. irix_xstat(%d,%s,%p) ", current->comm, current->pid, version, filename, statbuf); #endif switch(version) { case 2: { struct stat kb; - int old_fs; + mm_segment_t old_fs; old_fs = get_fs(); set_fs(get_ds()); retval = sys_newstat(filename, &kb); @@ -1259,13 +1377,13 @@ lock_kernel(); #ifdef DEBUG_XSTAT - printk("[%s:%d] Wheee.. irix_lxstat(%d,%s,%p) ", + printk("[%s:%ld] Wheee.. irix_lxstat(%d,%s,%p) ", current->comm, current->pid, version, filename, statbuf); #endif switch(version) { case 2: { struct stat kb; - int old_fs; + mm_segment_t old_fs; old_fs = get_fs(); set_fs(get_ds()); error = sys_newlstat(filename, &kb); @@ -1310,13 +1428,13 @@ lock_kernel(); #ifdef DEBUG_XSTAT - printk("[%s:%d] Wheee.. irix_fxstat(%d,%d,%p) ", + printk("[%s:%ld] Wheee.. irix_fxstat(%d,%d,%p) ", current->comm, current->pid, version, fd, statbuf); #endif switch(version) { case 2: { struct stat kb; - int old_fs; + mm_segment_t old_fs; old_fs = get_fs(); set_fs(get_ds()); error = sys_newfstat(fd, &kb); @@ -1360,7 +1478,7 @@ int retval; lock_kernel(); - printk("[%s:%d] Wheee.. irix_xmknod(%d,%s,%x,%x)\n", + printk("[%s:%ld] Wheee.. irix_xmknod(%d,%s,%x,%x)\n", current->comm, current->pid, ver, filename, mode, (int) dev); switch(ver) { case 2: @@ -1380,7 +1498,7 @@ asmlinkage int irix_swapctl(int cmd, char *arg) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_swapctl(%d,%p)\n", + printk("[%s:%ld] Wheee.. irix_swapctl(%d,%p)\n", current->comm, current->pid, cmd, arg); unlock_kernel(); return -EINVAL; @@ -1398,11 +1516,12 @@ { struct dentry *dentry; struct inode *inode; + mm_segment_t old_fs; struct statfs kbuf; - int error, old_fs, i; + int error, i; lock_kernel(); - printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n", + printk("[%s:%ld] Wheee.. irix_statvfs(%s,%p)\n", current->comm, current->pid, fname, buf); error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); if(error) @@ -1457,12 +1576,13 @@ { struct dentry *dentry; struct inode *inode; + mm_segment_t old_fs; struct statfs kbuf; struct file *file; - int error, old_fs, i; + int error, i; lock_kernel(); - printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n", + printk("[%s:%ld] Wheee.. irix_fstatvfs(%d,%p)\n", current->comm, current->pid, fd, buf); error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); @@ -1514,6 +1634,7 @@ error = 0; + dput(dentry); out: unlock_kernel(); return error; @@ -1571,11 +1692,11 @@ error = -EDQUOT; if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0)) goto dput_and_out; - error = notify_change(inode, &newattrs); + error = notify_change(dentry, &newattrs); if (error) inode->i_sb->dq_op->transfer(inode, &newattrs, 1); } else - error = notify_change(inode, &newattrs); + error = notify_change(dentry, &newattrs); dput_and_out: dput(dentry); @@ -1612,7 +1733,7 @@ asmlinkage int irix_priocntl(struct pt_regs *regs) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_priocntl()\n", + printk("[%s:%ld] Wheee.. irix_priocntl()\n", current->comm, current->pid); unlock_kernel(); return -EINVAL; @@ -1621,7 +1742,7 @@ asmlinkage int irix_sigqueue(int pid, int sig, int code, int val) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n", + printk("[%s:%ld] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n", current->comm, current->pid, pid, sig, code, val); unlock_kernel(); return -EINVAL; @@ -1667,10 +1788,10 @@ asmlinkage int irix_mmap64(struct pt_regs *regs) { + int len, prot, flags, fd, off1, off2, error, base = 0; unsigned long addr, *sp; - int len, prot, flags, fd, off1, off2, base = 0; - int error; - + struct file *file; + lock_kernel(); if(regs->regs[2] == 1000) base = 1; @@ -1699,6 +1820,26 @@ error = -EINVAL; goto out; } + + if(!(flags & MAP_ANONYMOUS)) { + if(fd >= NR_OPEN || !(file = current->files->fd[fd])) { + error = -EBADF; + goto out; + } + + /* Ok, bad taste hack follows, try to think in something else when reading this */ + if (flags & IRIX_MAP_AUTOGROW){ + unsigned long old_pos; + long max_size = off2 + len; + + if (max_size > file->f_dentry->d_inode->i_size){ + old_pos = sys_lseek (fd, max_size - 1, 0); + sys_write (fd, "", 1); + sys_lseek (fd, old_pos, 0); + } + } + } + error = sys_mmap(addr, (size_t) len, prot, flags, fd, off2); out: @@ -1709,7 +1850,7 @@ asmlinkage int irix_dmi(struct pt_regs *regs) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_dmi()\n", + printk("[%s:%ld] Wheee.. irix_dmi()\n", current->comm, current->pid); unlock_kernel(); return -EINVAL; @@ -1719,7 +1860,7 @@ int off1, int off2) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n", + printk("[%s:%ld] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n", current->comm, current->pid, fd, buf, cnt, off64, off1, off2); unlock_kernel(); return -EINVAL; @@ -1729,7 +1870,7 @@ int off1, int off2) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n", + printk("[%s:%ld] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n", current->comm, current->pid, fd, buf, cnt, off64, off1, off2); unlock_kernel(); return -EINVAL; @@ -1740,7 +1881,7 @@ unsigned long arg4, unsigned long arg5) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_fastpath(%d,%08lx,%08lx,%08lx,%08lx," + printk("[%s:%ld] Wheee.. irix_fastpath(%d,%08lx,%08lx,%08lx,%08lx," "%08lx,%08lx)\n", current->comm, current->pid, cmd, arg0, arg1, arg2, arg3, arg4, arg5); @@ -1763,10 +1904,11 @@ { struct dentry *dentry; struct inode *inode; + mm_segment_t old_fs; struct statfs kbuf; - int error, old_fs, i; + int error, i; - printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n", + printk("[%s:%ld] Wheee.. irix_statvfs(%s,%p)\n", current->comm, current->pid, fname, buf); error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); if(error) @@ -1820,12 +1962,13 @@ { struct dentry *dentry; struct inode *inode; + mm_segment_t old_fs; struct statfs kbuf; struct file *file; - int error, old_fs, i; + int error, i; lock_kernel(); - printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n", + printk("[%s:%ld] Wheee.. irix_fstatvfs(%d,%p)\n", current->comm, current->pid, fd, buf); error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); @@ -1877,6 +2020,7 @@ error = 0; + dput(dentry); out: unlock_kernel(); return error; @@ -1887,7 +2031,7 @@ int error; lock_kernel(); - printk("[%s:%d] irix_getmountid(%s, %p)\n", + printk("[%s:%ld] irix_getmountid(%s, %p)\n", current->comm, current->pid, fname, midbuf); error = verify_area(VERIFY_WRITE, midbuf, (sizeof(unsigned long) * 4)); if(error) @@ -1914,7 +2058,7 @@ unsigned long arg, unsigned long sp, int slen) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n", + printk("[%s:%ld] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n", current->comm, current->pid, entry, mask, arg, sp, slen); unlock_kernel(); return -EINVAL; @@ -1987,7 +2131,7 @@ lock_kernel(); #ifdef DEBUG_GETDENTS - printk("[%s:%d] ngetdents(%d, %p, %d, %p) ", current->comm, + printk("[%s:%ld] ngetdents(%d, %p, %d, %p) ", current->comm, current->pid, fd, dirent, count, eob); #endif error = -EBADF; @@ -2219,41 +2363,41 @@ switch(op) { case 1: /* Reboot */ - printk("[%s:%d] irix_uadmin: Wants to reboot...\n", + printk("[%s:%ld] irix_uadmin: Wants to reboot...\n", current->comm, current->pid); retval = -EINVAL; goto out; case 2: /* Shutdown */ - printk("[%s:%d] irix_uadmin: Wants to shutdown...\n", + printk("[%s:%ld] irix_uadmin: Wants to shutdown...\n", current->comm, current->pid); retval = -EINVAL; goto out; case 4: /* Remount-root */ - printk("[%s:%d] irix_uadmin: Wants to remount root...\n", + printk("[%s:%ld] irix_uadmin: Wants to remount root...\n", current->comm, current->pid); retval = -EINVAL; goto out; case 8: /* Kill all tasks. */ - printk("[%s:%d] irix_uadmin: Wants to kill all tasks...\n", + printk("[%s:%ld] irix_uadmin: Wants to kill all tasks...\n", current->comm, current->pid); retval = -EINVAL; goto out; case 256: /* Set magic mushrooms... */ - printk("[%s:%d] irix_uadmin: Wants to set magic mushroom[%d]...\n", + printk("[%s:%ld] irix_uadmin: Wants to set magic mushroom[%d]...\n", current->comm, current->pid, (int) func); retval = -EINVAL; goto out; default: - printk("[%s:%d] irix_uadmin: Unknown operation [%d]...\n", + printk("[%s:%ld] irix_uadmin: Unknown operation [%d]...\n", current->comm, current->pid, (int) op); retval = -EINVAL; goto out; @@ -2277,20 +2421,20 @@ case 2: /* ustat() */ - printk("[%s:%d] irix_utssys: Wants to do ustat()\n", + printk("[%s:%ld] irix_utssys: Wants to do ustat()\n", current->comm, current->pid); retval = -EINVAL; goto out; case 3: /* fusers() */ - printk("[%s:%d] irix_utssys: Wants to do fusers()\n", + printk("[%s:%ld] irix_utssys: Wants to do fusers()\n", current->comm, current->pid); retval = -EINVAL; goto out; default: - printk("[%s:%d] irix_utssys: Wants to do unknown type[%d]\n", + printk("[%s:%ld] irix_utssys: Wants to do unknown type[%d]\n", current->comm, current->pid, (int) type); retval = -EINVAL; goto out; @@ -2306,16 +2450,20 @@ extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); +#define IRIX_F_ALLOCSP 10 + asmlinkage int irix_fcntl(int fd, int cmd, int arg) { int retval; lock_kernel(); #ifdef DEBUG_FCNTL - printk("[%s:%d] irix_fcntl(%d, %d, %d) ", current->comm, + printk("[%s:%ld] irix_fcntl(%d, %d, %d) ", current->comm, current->pid, fd, cmd, arg); #endif - + if (cmd == IRIX_F_ALLOCSP){ + return 0; + } retval = sys_fcntl(fd, cmd, arg); #ifdef DEBUG_FCNTL printk("%d\n", retval); @@ -2331,26 +2479,26 @@ lock_kernel(); switch(cmd) { case 1: - printk("[%s:%d] irix_ulimit: Wants to get file size limit.\n", + printk("[%s:%ld] irix_ulimit: Wants to get file size limit.\n", current->comm, current->pid); retval = -EINVAL; goto out; case 2: - printk("[%s:%d] irix_ulimit: Wants to set file size limit.\n", + printk("[%s:%ld] irix_ulimit: Wants to set file size limit.\n", current->comm, current->pid); retval = -EINVAL; goto out; case 3: - printk("[%s:%d] irix_ulimit: Wants to get brk limit.\n", + printk("[%s:%ld] irix_ulimit: Wants to get brk limit.\n", current->comm, current->pid); retval = -EINVAL; goto out; case 4: #if 0 - printk("[%s:%d] irix_ulimit: Wants to get fd limit.\n", + printk("[%s:%ld] irix_ulimit: Wants to get fd limit.\n", current->comm, current->pid); retval = -EINVAL; goto out; @@ -2359,13 +2507,13 @@ goto out; case 5: - printk("[%s:%d] irix_ulimit: Wants to get txt offset.\n", + printk("[%s:%ld] irix_ulimit: Wants to get txt offset.\n", current->comm, current->pid); retval = -EINVAL; goto out; default: - printk("[%s:%d] irix_ulimit: Unknown command [%d].\n", + printk("[%s:%ld] irix_ulimit: Unknown command [%d].\n", current->comm, current->pid, cmd); retval = -EINVAL; goto out; @@ -2378,7 +2526,7 @@ asmlinkage int irix_unimp(struct pt_regs *regs) { lock_kernel(); - printk("irix_unimp [%s:%d] v0=%d v1=%d a0=%08lx a1=%08lx a2=%08lx " + printk("irix_unimp [%s:%ld] v0=%d v1=%d a0=%08lx a1=%08lx a2=%08lx " "a3=%08lx\n", current->comm, current->pid, (int) regs->regs[2], (int) regs->regs[3], regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/sysmips.c linux/arch/mips/kernel/sysmips.c --- v2.1.100/linux/arch/mips/kernel/sysmips.c Thu May 7 22:51:47 1998 +++ linux/arch/mips/kernel/sysmips.c Fri May 8 00:13:24 1998 @@ -7,7 +7,7 @@ * * Copyright (C) 1995, 1996, 1997 by Ralf Baechle * - * $Id: sysmips.c,v 1.3 1997/07/18 06:26:02 ralf Exp $ + * $Id: sysmips.c,v 1.7 1998/05/01 01:34:38 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c --- v2.1.100/linux/arch/mips/kernel/time.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/kernel/time.c Fri May 8 00:13:24 1998 @@ -6,7 +6,7 @@ * This file contains the time handling details for PC-style clocks as * found in some MIPS systems. * - * $Id: time.c,v 1.5 1997/11/12 12:12:12 ralf Exp $ + * $Id: time.c,v 1.8 1998/05/01 01:34:39 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c --- v2.1.100/linux/arch/mips/kernel/traps.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/kernel/traps.c Fri May 8 00:13:24 1998 @@ -8,11 +8,12 @@ * Copyright 1994, 1995, 1996, 1997 by Ralf Baechle * Modified for R3000 by Paul M. Antoine, 1995, 1996 * - * $Id: traps.c,v 1.7 1997/12/01 16:33:28 ralf Exp $ + * $Id: traps.c,v 1.10 1998/05/04 09:17:57 ralf Exp $ */ #include #include #include +#include #include #include @@ -27,10 +28,6 @@ #include #include -#ifdef CONFIG_SGI -#include -#endif - #undef CONF_DEBUG_EXCEPTIONS static inline void console_verbose(void) @@ -105,7 +102,7 @@ /* * Dump the stack */ - printk("Process %s (pid: %d, stackpage=%08lx)\nStack: ", + printk("Process %s (pid: %ld, stackpage=%08lx)\nStack: ", current->comm, current->pid, (unsigned long)current); for(i=0;i<5;i++) printk("%08x ", *sp++); @@ -167,18 +164,9 @@ void die_if_kernel(const char * str, struct pt_regs * regs, long err) { - /* - * Just return if in user mode. - * XXX - */ -#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) - if (!((regs)->cp0_status & 0x4)) - return; -#endif -#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) - if (regs->cp0_status & ST0_KSU == KSU_USER) + if (user_mode(regs)) /* Just return if in user mode. */ return; -#endif + console_verbose(); printk("%s: %04lx\n", str, err & 0xffff); show_regs(regs); @@ -196,6 +184,7 @@ void do_ibe(struct pt_regs *regs) { lock_kernel(); +show_regs(regs); while(1); ibe_board_handler(regs); unlock_kernel(); } @@ -203,6 +192,7 @@ void do_dbe(struct pt_regs *regs) { lock_kernel(); +show_regs(regs); while(1); dbe_board_handler(regs); unlock_kernel(); } @@ -240,7 +230,10 @@ } #endif -void do_fpe(struct pt_regs *regs, unsigned int fcr31) +/* + * XXX Delayed fp exceptions when doing a lazy ctx switch XXX + */ +void do_fpe(struct pt_regs *regs, unsigned long fcr31) { #ifdef CONFIG_MIPS_FPE_MODULE if (fpe_handler != NULL) { @@ -252,8 +245,23 @@ #ifdef CONF_DEBUG_EXCEPTIONS show_regs(regs); #endif - printk("Caught floating exception at epc == %08lx, fcr31 == %08x\n", - regs->cp0_epc, fcr31); + if (fcr31 & 0x20000) { + /* Retry instruction with flush to zero ... */ + if (!(fcr31 & (1<<24))) { + printk("Setting flush to zero for %s.\n", + current->comm); + fcr31 &= ~0x20000; + fcr31 |= (1<<24); + __asm__ __volatile__( + "ctc1\t%0,$31" + : /* No outputs */ + : "r" (fcr31)); + goto out; + } + printk("Unimplemented exception at 0x%08lx in %s.\n", + regs->cp0_epc, current->comm); + } + if (compute_return_epc(regs)) goto out; force_sig(SIGFPE, current); @@ -337,7 +345,7 @@ #ifdef CONF_DEBUG_EXCEPTIONS show_regs(regs); #endif - printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n", + printk("[%s:%ld] Illegal instruction at %08lx ra=%08lx\n", current->comm, current->pid, regs->cp0_epc, regs->regs[31]); if (compute_return_epc(regs)) goto out; @@ -350,16 +358,29 @@ { unsigned int cpid; - lock_kernel(); cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; - if (cpid == 1) - { - regs->cp0_status |= ST0_CU1; + if (cpid != 1) + goto bad_cid; + + regs->cp0_status |= ST0_CU1; + if (last_task_used_math == current) goto out; + + if (current->used_math) { /* Using the FPU again. */ + r4xx0_lazy_fpu_switch(last_task_used_math); + } else { /* First time FPU user. */ + + r4xx0_init_fpu(); + current->used_math = 1; } + last_task_used_math = current; + return; + +bad_cid: + lock_kernel(); force_sig(SIGILL, current); -out: unlock_kernel(); +out: } void do_vcei(struct pt_regs *regs) @@ -460,13 +481,6 @@ } } -typedef asmlinkage int (*syscall_t)(void *a0,...); -asmlinkage int (*do_syscalls)(struct pt_regs *regs, syscall_t fun, int narg); -extern asmlinkage int r4k_do_syscalls(struct pt_regs *regs, - syscall_t fun, int narg); -extern asmlinkage int r2300_do_syscalls(struct pt_regs *regs, - syscall_t fun, int narg); - asmlinkage void (*save_fp_context)(struct sigcontext *sc); extern asmlinkage void r4k_save_fp_context(struct sigcontext *sc); extern asmlinkage void r2300_save_fp_context(struct sigcontext *sc); @@ -489,7 +503,6 @@ unsigned long i; if(mips_machtype == MACH_MIPS_MAGNUM_4000 || - mips_machtype == MACH_DESKSTATION_RPC44 || mips_machtype == MACH_SNI_RM200_PCI) EISA_bus = 1; @@ -560,7 +573,6 @@ memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80); memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80); - do_syscalls = r4k_do_syscalls; save_fp_context = r4k_save_fp_context; restore_fp_context = r4k_restore_fp_context; resume = r4xx0_resume; @@ -607,7 +619,6 @@ case CPU_R3000: case CPU_R3000A: memcpy((void *)KSEG0, &except_vec0_r2300, 0x80); - do_syscalls = r2300_do_syscalls; save_fp_context = r2300_save_fp_context; restore_fp_context = r2300_restore_fp_context; resume = r2300_resume; diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/unaligned.c linux/arch/mips/kernel/unaligned.c --- v2.1.100/linux/arch/mips/kernel/unaligned.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/kernel/unaligned.c Fri May 8 00:13:24 1998 @@ -5,7 +5,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996 by Ralf Baechle + * Copyright (C) 1996, 1998 by Ralf Baechle + * + * $Id: unaligned.c,v 1.3 1998/05/04 09:17:59 ralf Exp $ * * This file contains exception handler for address error exception with the * special capability to execute faulting instructions in software. The @@ -34,13 +36,7 @@ * sysmips(MIPS_FIXADE, x); * ... * - * The parameter x is 0 for disabeling software emulation. Set bit 0 for - * enabeling software emulation and bit 1 for enabeling printing debug - * messages into syslog to aid finding address errors in programs. - * - * The logging feature is an addition over RISC/os and IRIX where only the - * values 0 and 1 are acceptable values for x. I'll probably remove this - * hack later on. + * The argument x is 0 for disabling software emulation, enabled otherwise. * * Below a little program to play around with this feature. * @@ -69,12 +65,6 @@ * printf("\n"); * } * - * Until I've written the code to handle branch delay slots it may happen - * that the kernel receives an ades/adel instruction from an insn in a - * branch delay slot but is unable to handle this case. The kernel knows - * this fact and therefore will kill the process. For most code you can - * fix this temporarily by compiling with flags -fno-delayed-branch -Wa,-O0. - * * Coprozessor loads are not supported; I think this case is unimportant * in the practice. * @@ -88,19 +78,15 @@ #include #include +#include #include #include #include #include -#undef CONF_NO_UNALIGNED_KERNEL_ACCESS -#undef CONF_LOG_UNALIGNED_ACCESSES - #define STR(x) __STR(x) #define __STR(x) #x -typedef unsigned long register_t; - /* * User code may only access USEG; kernel code may access the * entire address space. @@ -110,10 +96,12 @@ goto sigbus; static inline void -emulate_load_store_insn(struct pt_regs *regs, unsigned long addr, unsigned long pc) +emulate_load_store_insn(struct pt_regs *regs, + unsigned long addr, + unsigned long pc) { union mips_instruction insn; - register_t value; + unsigned long value, fixup; regs->regs[0] = 0; /* @@ -358,99 +346,70 @@ */ default: /* - * Pheeee... We encountered an yet unknown instruction ... + * Pheeee... We encountered an yet unknown instruction or + * cache coherence problem. Die sucker, die ... */ - force_sig(SIGILL, current); + goto sigill; } return; fault: + /* Did we have an exception handler installed? */ + fixup = search_exception_table(regs->cp0_epc); + if (fixup) { + long new_epc; + new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); + printk(KERN_DEBUG "%s: Forwarding exception at [<%lx>] (%lx)\n", + current->comm, regs->cp0_epc, new_epc); + regs->cp0_epc = new_epc; + return; + } + + lock_kernel(); send_sig(SIGSEGV, current, 1); + unlock_kernel(); return; sigbus: + lock_kernel(); send_sig(SIGBUS, current, 1); + unlock_kernel(); + return; +sigill: + lock_kernel(); + send_sig(SIGILL, current, 1); + unlock_kernel(); return; } unsigned long unaligned_instructions; -static inline void -fix_ade(struct pt_regs *regs, unsigned long pc) +asmlinkage void do_ade(struct pt_regs *regs) { + unsigned long pc; + /* * Did we catch a fault trying to load an instruction? + * This also catches attempts to activate MIPS16 code on + * CPUs which don't support it. */ - if (regs->cp0_badvaddr == pc) { - /* - * Phee... Either the code is severly messed up or the - * process tried to activate some MIPS16 code. - */ - force_sig(SIGBUS, current); - } + if (regs->cp0_badvaddr == regs->cp0_epc) + goto sigbus; + + pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0); + if (compute_return_epc(regs)) + return; + if ((current->tss.mflags & MF_FIXADE) == 0) + goto sigbus; - /* - * Ok, this wasn't a failed instruction load. The CPU was capable of - * reading the instruction and faulted after this. So we don't need - * to verify_area the address of the instrucion. We still don't - * know whether the address used was legal and therefore need to do - * verify_area(). The CPU already did the checking for legal - * instructions for us, so we don't need to do this. - */ emulate_load_store_insn(regs, regs->cp0_badvaddr, pc); unaligned_instructions++; -} - -#define kernel_address(x) ((long)(x) < 0) -asmlinkage void -do_ade(struct pt_regs *regs) -{ - register_t pc = regs->cp0_epc; - register_t badvaddr __attribute__ ((unused)) = regs->cp0_badvaddr; - char adels; + return; +sigbus: lock_kernel(); - adels = (((regs->cp0_cause & CAUSEF_EXCCODE) >> - CAUSEB_EXCCODE) == 4) ? 'l' : 's'; - -#ifdef CONF_NO_UNALIGNED_KERNEL_ACCESS - /* - * In an ideal world there are no unaligned accesses by the kernel. - * So be a bit noisy ... - */ - if (kernel_address(badvaddr) && !user_mode(regs)) { - show_regs(regs); - panic("Caught adel%c exception in kernel mode accessing %08lx.", - adels, badvaddr); - } -#endif /* CONF_NO_UNALIGNED_KERNEL_ACCESS */ - -#ifdef CONF_LOG_UNALIGNED_ACCESSES - if (current->tss.mflags & MF_LOGADE) { - register_t logpc = pc; - if (regs->cp0_cause & CAUSEF_BD) - logpc += 4; - printk(KERN_DEBUG - "Caught adel%c in '%s' at 0x%08lx accessing 0x%08lx.\n", - adels, current->comm, logpc, regs->cp0_badvaddr); - } -#endif /* CONF_LOG_UNALIGNED_ACCESSES */ - - if (compute_return_epc(regs)) - goto out; - if(current->tss.mflags & MF_FIXADE) { - pc += ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0); - fix_ade(regs, pc); - goto out; - } - -#ifdef CONF_DEBUG_EXCEPTIONS - show_regs(regs); -#endif - force_sig(SIGBUS, current); - -out: unlock_kernel(); + return; } diff -u --recursive --new-file v2.1.100/linux/arch/mips/ld.script.big linux/arch/mips/ld.script.big --- v2.1.100/linux/arch/mips/ld.script.big Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/ld.script.big Fri May 8 00:13:24 1998 @@ -37,6 +37,15 @@ } =0 _etext = .; PROVIDE (etext = .); + + /* Startup code */ + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); /* Align double page for init_task_union */ + __init_end = .; + .fini : { *(.fini) } =0 .reginfo : { *(.reginfo) } /* Adjust the address for the data segment. We want to adjust up to @@ -74,6 +83,7 @@ .sdata : { *(.sdata) } _edata = .; PROVIDE (edata = .); + __bss_start = .; _fbss = .; .bss : diff -u --recursive --new-file v2.1.100/linux/arch/mips/ld.script.little linux/arch/mips/ld.script.little --- v2.1.100/linux/arch/mips/ld.script.little Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/ld.script.little Fri May 8 00:13:24 1998 @@ -37,6 +37,15 @@ } =0 _etext = .; PROVIDE (etext = .); + + /* Startup code */ + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); /* Align double page for init_task_union */ + __init_end = .; + .fini : { *(.fini) } =0 .reginfo : { *(.reginfo) } /* Adjust the address for the data segment. We want to adjust up to @@ -74,6 +83,7 @@ .sdata : { *(.sdata) } _edata = .; PROVIDE (edata = .); + __bss_start = .; _fbss = .; .bss : diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile --- v2.1.100/linux/arch/mips/lib/Makefile Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/lib/Makefile Fri May 8 00:13:24 1998 @@ -1,11 +1,7 @@ # # Makefile for MIPS-specific library files.. # -# Many of these routines are just left over debugging trash of ancient -# times when I just make my Tyne beep and so ... -# -# ...and for when I need to get the DECStation to use the boot prom to -# do things... Paul M. Antoine. +# $Id: Makefile,v 1.7 1998/05/04 09:18:03 ralf Exp $ # .S.s: @@ -14,13 +10,12 @@ $(CC) $(CFLAGS) -c $< -o $*.o L_TARGET = lib.a -L_OBJS = beep.o checksum.o copy_user.o csum.o dump_tlb.o memset.o memcpy.o \ - strlen_user.o strncpy_user.o tags.o watch.o +L_OBJS = csum_partial.o csum_partial_copy.o dump_tlb.o ide-std.c ide-no.o \ + memset.o memcpy.o strlen_user.o strncpy_user.o tags.o watch.o -ifdef CONFIG_DECSTATION -L_OBJS += pmaxcon.o pmaxio.o -else +# +# Debug console, works without other support from the kernel +# L_OBJS += tinycon.o -endif include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/checksum.c linux/arch/mips/lib/checksum.c --- v2.1.100/linux/arch/mips/lib/checksum.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/lib/checksum.c Wed Dec 31 16:00:00 1969 @@ -1,131 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * MIPS specific IP/TCP/UDP checksumming routines - * - * Authors: Ralf Baechle, - * Lots of code moved from tcp.c and ip.c; see those files - * for more names. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * $Id: checksum.c,v 1.2 1997/07/29 18:37:35 ralf Exp $ - */ -#include -#include -#include -#include -#include - -static inline unsigned short from32to16(unsigned long x) -{ - /* 32 bits --> 16 bits + carry */ - x = (x & 0xffff) + (x >> 16); - /* 16 bits + carry --> 16 bits including carry */ - x = (x & 0xffff) + (x >> 16); - return x; -} - -static inline unsigned long do_csum(const unsigned char * buff, int len) -{ - int odd, count; - unsigned long result = 0; - - if (len <= 0) - goto out; - odd = 1 & (unsigned long) buff; - if (odd) { - result = be16_to_cpu(*buff); - len--; - buff++; - } - count = len >> 1; /* nr of 16-bit words.. */ - if (count) { - if (2 & (unsigned long) buff) { - result += *(unsigned short *) buff; - count--; - len -= 2; - buff += 2; - } - count >>= 1; /* nr of 32-bit words.. */ - if (count) { - unsigned long carry = 0; - do { - unsigned long w = *(unsigned long *) buff; - count--; - buff += 4; - result += carry; - result += w; - carry = (w > result); - } while (count); - result += carry; - result = (result & 0xffff) + (result >> 16); - } - if (len & 2) { - result += *(unsigned short *) buff; - buff += 2; - } - } - if (len & 1) - result += le16_to_cpu(*buff); - result = from32to16(result); - if (odd) - result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); -out: - return result; -} - -/* - * computes a partial checksum, e.g. for TCP/UDP fragments - */ -unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum) -{ - unsigned long result = do_csum(buff, len); - - /* add in old sum, and carry.. */ - result += sum; - if(sum > result) - result += 1; - return result; -} - -/* - * copy while checksumming, otherwise like csum_partial - */ -unsigned int csum_partial_copy(const char *src, char *dst, - int len, unsigned int sum) -{ - /* - * It's 2:30 am and I don't feel like doing it real ... - * This is lots slower than the real thing (tm) - */ - sum = csum_partial(src, len, sum); - memcpy(dst, src, len); - - return sum; -} - -/* - * Copy from userspace and compute checksum. If we catch an exception - * then zero the rest of the buffer. - */ -unsigned int csum_partial_copy_from_user (const char *src, char *dst, - int len, unsigned int sum, - int *err_ptr) -{ - int *dst_err_ptr=NULL; - int missing; - - missing = copy_from_user(dst, src, len); - if (missing) { - memset(dst + len - missing, 0, missing); - *err_ptr = -EFAULT; - } - - return csum_partial(dst, len, sum); -} diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/copy_user.S linux/arch/mips/lib/copy_user.S --- v2.1.100/linux/arch/mips/lib/copy_user.S Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/lib/copy_user.S Wed Dec 31 16:00:00 1969 @@ -1,201 +0,0 @@ -/* - * arch/mips/lib/copy_user.S - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (c) 1996, 1997 by Ralf Baechle - * - * Less stupid user_copy implementation for 32 bit MIPS CPUs. - * - * $Id: copy_user.S,v 1.2 1997/08/11 04:26:12 ralf Exp $ - */ -#include -#include -#include - -#define BLOCK_SIZE 16 - -#define EX(addr,handler) \ - .section __ex_table,"a"; \ - PTR addr, handler; \ - .previous -#define UEX(addr,handler) \ - EX(addr,handler); \ - EX(addr+4,handler) - - .set noreorder - .set noat - -/* ---------------------------------------------------------------------- */ - -/* - * Bad. We can't fix the alignment for both address parts. - * Align the source address and copy slowly ... - */ -not_even_the_same_alignment: - LONG_SUBU v1,zero,a1 - andi v1,3 - sltu t0,v0,v1 - MOVN(v1,v0,t0) - beqz v1,src_aligned - LONG_ADDU v1,a0 -1: lb $1,(a1) - EX(1b, fault) - LONG_ADDIU a1,1 -2: sb $1,(a0) - EX(2b, fault) - LONG_ADDIU a0,1 - bne a0,v1,1b - LONG_SUBU v0,1 -src_aligned: - -/* - * Ok. We've fixed the alignment of the copy src for this case. - * Now let's copy in the usual BLOCK_SIZE byte blocks using unaligned - * stores. - * XXX Align the destination address. This is better if the __copy_user - * encounters an access fault because we never have to deal with an - * only partially modified destination word. This is required to - * keep the semantics of the result of copy_*_user(). - */ - ori v1,v0,BLOCK_SIZE-1 - xori v1,BLOCK_SIZE-1 - beqz v1,copy_left_over - nop - LONG_SUBU v0,v1 - LONG_ADDU v1,a0 - -1: lw t0,(a1) # Can cause tlb fault - EX(1b, fault) -2: lw t1,4(a1) # Can cause tlb fault - EX(2b, fault) -2: lw t2,8(a1) # Can cause tlb fault - EX(2b, fault) -2: lw t3,12(a1) # Can cause tlb fault - EX(2b, fault) -2: usw t0,(a0) # Can cause tlb faults - UEX(2b, fault) -2: usw t1,4(a0) # Can cause tlb faults - UEX(2b, fault_plus_4) -2: usw t2,8(a0) # Can cause tlb faults - UEX(2b, fault_plus_8) -2: usw t3,12(a0) # Can cause tlb faults - UEX(2b, fault_plus_12) - LONG_ADDIU a0,BLOCK_SIZE - bne a0,v1,1b - LONG_ADDIU a1,BLOCK_SIZE -9: - b copy_left_over # < BLOCK_SIZE bytes left - nop - -/* ---------------------------------------------------------------------- */ - -not_w_aligned: -/* - * Ok, src or destination are not 4-byte aligned. - * Try to fix that. Do at least both addresses have the same alignment? - */ - xor t0,a0,a1 - andi t0,3 - bnez t0,not_even_the_same_alignment - nop # delay slot - -/* - * Ok, we can fix the alignment for both operands and go back to the - * fast path. We have to copy at least one byte, on average 3 bytes - * bytewise. - */ - LONG_SUBU v1,zero,a0 - andi v1,3 - sltu t0,v0,v1 - MOVN(v1,v0,t0) - beqz v1,__copy_user - LONG_ADDU v1,a0 -1: lb $1,(a1) - EX(1b, fault) - LONG_ADDIU a1,1 -2: sb $1,(a0) - EX(2b, fault) - LONG_ADDIU a0,1 - bne a0,v1,1b - LONG_SUBU v0,1 - b align4 - nop - -/* ---------------------------------------------------------------------- */ - -LEAF(__copy_user) - or t1,a0,a1 - andi t1,3 - bnez t1,not_w_aligned # not word alignment - move v0,a2 - -align4: - ori v1,v0,BLOCK_SIZE-1 - xori v1,BLOCK_SIZE-1 - beqz v1,copy_left_over - nop - LONG_SUBU v0,v1 - LONG_ADDU v1,a0 - -1: lw t0,(a1) # Can cause tlb fault - EX(1b, fault) -2: lw t1,4(a1) # Can cause tlb fault - EX(2b, fault) -2: lw t2,8(a1) # Can cause tlb fault - EX(2b, fault) -2: lw t3,12(a1) # Can cause tlb fault - EX(2b, fault) -2: sw t0,(a0) # Can cause tlb fault - EX(2b, fault) -2: sw t1,4(a0) # Can cause tlb fault - EX(2b, fault_plus_4) -2: sw t2,8(a0) # Can cause tlb fault - EX(2b, fault_plus_8) -2: sw t3,12(a0) # Can cause tlb fault - EX(2b, fault_plus_12) - LONG_ADDIU a0,BLOCK_SIZE - bne a0,v1,1b - LONG_ADDIU a1,BLOCK_SIZE -9: - -/* - * XXX Tune me ... - */ -copy_left_over: - beqz v0,3f - nop -1: lb $1,(a1) - EX(1b, fault) - LONG_ADDIU a1,1 -2: sb $1,(a0) - EX(2b, fault) - LONG_SUBU v0,1 - bnez v0,1b - LONG_ADDIU a0,1 -3: - -done: jr ra - nop - - END(__copy_user) - .set at - .set reorder - -/* ---------------------------------------------------------------------- */ - -/* - * Access fault. The number of not copied bytes is in v0. We have to - * correct the number of the not copied bytes in v0 in case of a access - * fault in an unrolled loop, then return. - */ - -fault: jr ra -fault_plus_4: LONG_ADDIU v0,4 - jr ra -fault_plus_8: LONG_ADDIU v0,8 - jr ra -fault_plus_12: LONG_ADDIU v0,12 - jr ra diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/csum_partial.S linux/arch/mips/lib/csum_partial.S --- v2.1.100/linux/arch/mips/lib/csum_partial.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/csum_partial.S Fri May 8 00:13:24 1998 @@ -0,0 +1,242 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998 Ralf Baechle + * + * $Id: csum_partial.S,v 1.1 1998/05/04 09:18:08 ralf Exp $ + */ +#include +#include + +#define ADDC(sum,reg) \ + addu sum, reg; \ + sltu v1, sum, reg; \ + addu sum, v1 + +#define CSUM_BIGCHUNK(src, offset, sum, t0, t1, t2, t3) \ + lw t0, (offset + 0x00)(src); \ + lw t1, (offset + 0x04)(src); \ + lw t2, (offset + 0x08)(src); \ + lw t3, (offset + 0x0c)(src); \ + ADDC(sum, t0); \ + ADDC(sum, t1); \ + ADDC(sum, t2); \ + ADDC(sum, t3); \ + lw t0, (offset + 0x10)(src); \ + lw t1, (offset + 0x14)(src); \ + lw t2, (offset + 0x18)(src); \ + lw t3, (offset + 0x1c)(src); \ + ADDC(sum, t0); \ + ADDC(sum, t1); \ + ADDC(sum, t2); \ + ADDC(sum, t3); \ + +/* + * a0: source address + * a1: length of the area to checksum + * a2: partial checksum + */ + +#define src a0 +#define dest a1 +#define sum v0 + + .text + .set noreorder + +/* unknown src alignment and < 8 bytes to go */ +small_csumcpy: + move a1, t2 + + andi t0, a1, 4 + beqz t0, 1f + andi t0, a1, 2 + + /* Still a full word to go */ + ulw t1, (src) + addiu src, 4 + ADDC(sum, t1) + +1: move t1, zero + beqz t0, 1f + andi t0, a1, 1 + + /* Still a halfword to go */ + ulhu t1, (src) + addiu src, 2 + +1: beqz t0, 1f + sll t1, t1, 16 + + lbu t2, (src) + nop + +#ifdef __MIPSEB__ + sll t2, t2, 8 +#endif + or t1, t2 + +1: ADDC(sum, t1) + + /* fold checksum */ + sll v1, sum, 16 + addu sum, v1 + sltu v1, sum, v1 + srl sum, sum, 16 + addu sum, v1 + + /* odd buffer alignment? */ + beqz t7, 1f + nop + sll v1, sum, 8 + srl sum, sum, 8 + or sum, v1 + andi sum, 0xffff +1: + .set reorder + /* Add the passed partial csum. */ + ADDC(sum, a2) + jr ra + .set noreorder + +/* ------------------------------------------------------------------------- */ + + .align 5 +LEAF(csum_partial) + move sum, zero + move t7, zero + + sltiu t8, a1, 0x8 + bnez t8, small_csumcpy /* < 8 bytes to copy */ + move t2, a1 + + beqz a1, out + andi t7, src, 0x1 /* odd buffer? */ + +hword_align: + beqz t7, word_align + andi t8, src, 0x2 + + lbu t0, (src) + subu a1, a1, 0x1 +#ifdef __MIPSEL__ + sll t0, t0, 8 +#endif + ADDC(sum, t0) + addu src, src, 0x1 + andi t8, src, 0x2 + +word_align: + beqz t8, dword_align + sltiu t8, a1, 56 + + lhu t0, (src) + subu a1, a1, 0x2 + ADDC(sum, t0) + sltiu t8, a1, 56 + addu src, src, 0x2 + +dword_align: + bnez t8, do_end_words + move t8, a1 + + andi t8, src, 0x4 + beqz t8, qword_align + andi t8, src, 0x8 + + lw t0, 0x00(src) + subu a1, a1, 0x4 + ADDC(sum, t0) + addu src, src, 0x4 + andi t8, src, 0x8 + +qword_align: + beqz t8, oword_align + andi t8, src, 0x10 + + lw t0, 0x00(src) + lw t1, 0x04(src) + subu a1, a1, 0x8 + ADDC(sum, t0) + ADDC(sum, t1) + addu src, src, 0x8 + andi t8, src, 0x10 + +oword_align: + beqz t8, begin_movement + srl t8, a1, 0x7 + + lw t3, 0x08(src) + lw t4, 0x0c(src) + lw t0, 0x00(src) + lw t1, 0x04(src) + ADDC(sum, t3) + ADDC(sum, t4) + ADDC(sum, t0) + ADDC(sum, t1) + subu a1, a1, 0x10 + addu src, src, 0x10 + srl t8, a1, 0x7 + +begin_movement: + beqz t8, 1f + andi t2, a1, 0x40 + +move_128bytes: + CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4) + CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4) + CSUM_BIGCHUNK(src, 0x40, sum, t0, t1, t3, t4) + CSUM_BIGCHUNK(src, 0x60, sum, t0, t1, t3, t4) + subu t8, t8, 0x01 + bnez t8, move_128bytes + addu src, src, 0x80 + +1: + beqz t2, 1f + andi t2, a1, 0x20 + +move_64bytes: + CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4) + CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4) + addu src, src, 0x40 + +1: + beqz t2, do_end_words + andi t8, a1, 0x1c + +move_32bytes: + CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4) + andi t8, a1, 0x1c + addu src, src, 0x20 + +do_end_words: + beqz t8, maybe_end_cruft + srl t8, t8, 0x2 + +end_words: + lw t0, (src) + subu t8, t8, 0x1 + ADDC(sum, t0) + bnez t8, end_words + addu src, src, 0x4 + +maybe_end_cruft: + andi t2, a1, 0x3 + +small_memcpy: + j small_csumcpy; move a1, t2 + beqz t2, out + move a1, t2 + +end_bytes: + lb t0, (src) + subu a1, a1, 0x1 + bnez a2, end_bytes + addu src, src, 0x1 + +out: + jr ra + move v0, sum + END(csum_partial) diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/csum_partial_copy.S linux/arch/mips/lib/csum_partial_copy.S --- v2.1.100/linux/arch/mips/lib/csum_partial_copy.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/csum_partial_copy.S Fri May 8 00:13:24 1998 @@ -0,0 +1,518 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998 Ralf Baechle + * + * $Id: csum_partial_copy.S,v 1.1 1998/05/04 09:18:11 ralf Exp $ + * + * Unified implementation of csum_copy_partial and csum_copy_partial_from_user. + */ +#include +#include +#include + +/* + * The fixup routine for csum_partial_copy_from_user depends on copying + * strictly in increasing order. Gas expands ulw/usw macros in the wrong order + * for little endian machines, so we cannot depend on them. + */ +#ifdef __MIPSEB__ +#define ulwL lwl +#define ulwU lwr +#endif +#ifdef __MIPSEL__ +#define ulwL lwr +#define ulwU lwl +#endif + +#define EX(insn,reg,addr,handler) \ +9: insn reg, addr; \ + .section __ex_table,"a"; \ + PTR 9b, handler; \ + .previous + +#define UEX(insn,reg,addr,handler) \ +9: insn ## L reg, addr; \ +10: insn ## U reg, 3 + addr; \ + .section __ex_table,"a"; \ + PTR 9b, handler; \ + PTR 10b, handler; \ + .previous + +#define ADDC(sum,reg) \ + addu sum, reg; \ + sltu v1, sum, reg; \ + addu sum, v1 + +/* ascending order, destination aligned */ +#define CSUM_BIGCHUNK(src, dst, offset, sum, t0, t1, t2, t3) \ + EX(lw, t0, (offset + 0x00)(src), l_fixup); \ + EX(lw, t1, (offset + 0x04)(src), l_fixup); \ + EX(lw, t2, (offset + 0x08)(src), l_fixup); \ + EX(lw, t3, (offset + 0x0c)(src), l_fixup); \ + ADDC(sum, t0); \ + ADDC(sum, t1); \ + ADDC(sum, t2); \ + ADDC(sum, t3); \ + sw t0, (offset + 0x00)(dst); \ + sw t1, (offset + 0x04)(dst); \ + sw t2, (offset + 0x08)(dst); \ + sw t3, (offset + 0x0c)(dst); \ + EX(lw, t0, (offset + 0x10)(src), l_fixup); \ + EX(lw, t1, (offset + 0x14)(src), l_fixup); \ + EX(lw, t2, (offset + 0x18)(src), l_fixup); \ + EX(lw, t3, (offset + 0x1c)(src), l_fixup); \ + ADDC(sum, t0); \ + ADDC(sum, t1); \ + ADDC(sum, t2); \ + ADDC(sum, t3); \ + sw t0, (offset + 0x10)(dst); \ + sw t1, (offset + 0x14)(dst); \ + sw t2, (offset + 0x18)(dst); \ + sw t3, (offset + 0x1c)(dst) + +/* ascending order, destination unaligned */ +#define UCSUM_BIGCHUNK(src, dst, offset, sum, t0, t1, t2, t3) \ + EX(lw, t0, (offset + 0x00)(src), l_fixup); \ + EX(lw, t1, (offset + 0x04)(src), l_fixup); \ + EX(lw, t2, (offset + 0x08)(src), l_fixup); \ + EX(lw, t3, (offset + 0x0c)(src), l_fixup); \ + ADDC(sum, t0); \ + ADDC(sum, t1); \ + ADDC(sum, t2); \ + ADDC(sum, t3); \ + usw t0, (offset + 0x00)(dst); \ + usw t1, (offset + 0x04)(dst); \ + usw t2, (offset + 0x08)(dst); \ + usw t3, (offset + 0x0c)(dst); \ + EX(lw, t0, (offset + 0x00)(src), l_fixup); \ + EX(lw, t1, (offset + 0x04)(src), l_fixup); \ + EX(lw, t2, (offset + 0x08)(src), l_fixup); \ + EX(lw, t3, (offset + 0x0c)(src), l_fixup); \ + ADDC(sum, t0); \ + ADDC(sum, t1); \ + ADDC(sum, t2); \ + ADDC(sum, t3); \ + usw t0, (offset + 0x10)(dst); \ + usw t1, (offset + 0x14)(dst); \ + usw t2, (offset + 0x18)(dst); \ + usw t3, (offset + 0x1c)(dst) + +# +# a0: source address +# a1: destination address +# a2: length of the area to checksum +# a3: partial checksum +# + +#define src a0 +#define dest a1 +#define sum v0 + + .text + .set noreorder + +/* unknown src/dst alignment and < 8 bytes to go */ +small_csumcpy: + move a2, t2 + + andi t0, a2, 4 + beqz t0, 1f + andi t0, a2, 2 + + /* Still a full word to go */ + UEX(ulw, t1, 0(src), l_fixup) + addiu src, 4 + usw t1, 0(dest) + addiu dest, 4 + ADDC(sum, t1) + +1: move t1, zero + beqz t0, 1f + andi t0, a2, 1 + + /* Still a halfword to go */ + ulhu t1, (src) + addiu src, 2 + ush t1, (dest) + addiu dest, 2 + +1: beqz t0, 1f + sll t1, t1, 16 + + lbu t2, (src) + nop + sb t2, (dest) + +#ifdef __MIPSEB__ + sll t2, t2, 8 +#endif + or t1, t2 + +1: ADDC(sum, t1) + + /* fold checksum */ + sll v1, sum, 16 + addu sum, v1 + sltu v1, sum, v1 + srl sum, sum, 16 + addu sum, v1 + + /* odd buffer alignment? */ + beqz t7, 1f + nop + sll v1, sum, 8 + srl sum, sum, 8 + or sum, v1 + andi sum, 0xffff +1: + .set reorder + /* Add the passed partial csum. */ + ADDC(sum, a3) + jr ra + .set noreorder + +/* ------------------------------------------------------------------------- */ + + .align 5 +LEAF(csum_partial_copy_from_user) + addu t5, src, a2 # end address for fixup +EXPORT(csum_partial_copy) + move sum, zero # clear computed sum + move t7, zero # clear odd flag + xor t0, dest, src + andi t0, t0, 0x3 + beqz t0, can_align + sltiu t8, a2, 0x8 + + b memcpy_u_src # bad alignment + move t2, a2 + +can_align: + bnez t8, small_csumcpy # < 8 bytes to copy + move t2, a2 + + beqz a2, out + andi t7, src, 0x1 # odd buffer? + +hword_align: + beqz t7, word_align + andi t8, src, 0x2 + + EX(lbu, t0, (src), l_fixup) + subu a2, a2, 0x1 + EX(sb, t0, (dest), l_fixup) +#ifdef __MIPSEL__ + sll t0, t0, 8 +#endif + ADDC(sum, t0) + addu src, src, 0x1 + addu dest, dest, 0x1 + andi t8, src, 0x2 + +word_align: + beqz t8, dword_align + sltiu t8, a2, 56 + + EX(lhu, t0, (src), l_fixup) + subu a2, a2, 0x2 + sh t0, (dest) + ADDC(sum, t0) + sltiu t8, a2, 56 + addu dest, dest, 0x2 + addu src, src, 0x2 + +dword_align: + bnez t8, do_end_words + move t8, a2 + + andi t8, src, 0x4 + beqz t8, qword_align + andi t8, src, 0x8 + + EX(lw, t0, 0x00(src), l_fixup) + subu a2, a2, 0x4 + ADDC(sum, t0) + sw t0, 0x00(dest) + addu src, src, 0x4 + addu dest, dest, 0x4 + andi t8, src, 0x8 + +qword_align: + beqz t8, oword_align + andi t8, src, 0x10 + + EX(lw, t0, 0x00(src), l_fixup) + EX(lw, t1, 0x04(src), l_fixup) + subu a2, a2, 0x8 + ADDC(sum, t0) + ADDC(sum, t1) + sw t0, 0x00(dest) + addu src, src, 0x8 + sw t1, 0x04(dest) + andi t8, src, 0x10 + addu dest, dest, 0x8 + +oword_align: + beqz t8, begin_movement + srl t8, a2, 0x7 + + EX(lw, t3, 0x08(src), l_fixup) # assumes subblock ordering + EX(lw, t4, 0x0c(src), l_fixup) + EX(lw, t0, 0x00(src), l_fixup) + EX(lw, t1, 0x04(src), l_fixup) + ADDC(sum, t3) + ADDC(sum, t4) + ADDC(sum, t0) + ADDC(sum, t1) + sw t3, 0x08(dest) + subu a2, a2, 0x10 + sw t4, 0x0c(dest) + addu src, src, 0x10 + sw t0, 0x00(dest) + srl t8, a2, 0x7 + addu dest, dest, 0x10 + sw t1, -0x0c(dest) + +begin_movement: + beqz t8, 0f + andi t2, a2, 0x40 + +move_128bytes: + CSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4) + CSUM_BIGCHUNK(src, dest, 0x20, sum, t0, t1, t3, t4) + CSUM_BIGCHUNK(src, dest, 0x40, sum, t0, t1, t3, t4) + CSUM_BIGCHUNK(src, dest, 0x60, sum, t0, t1, t3, t4) + subu t8, t8, 0x01 + addu src, src, 0x80 + bnez t8, move_128bytes + addu dest, dest, 0x80 + +0: + beqz t2, 1f + andi t2, a2, 0x20 + +move_64bytes: + CSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4) + CSUM_BIGCHUNK(src, dest, 0x20, sum, t0, t1, t3, t4) + addu src, src, 0x40 + addu dest, dest, 0x40 + +1: + beqz t2, do_end_words + andi t8, a2, 0x1c + +move_32bytes: + CSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4) + andi t8, a2, 0x1c + addu src, src, 0x20 + addu dest, dest, 0x20 + +do_end_words: + beqz t8, maybe_end_cruft + srl t8, t8, 0x2 + +end_words: + EX(lw, t0, (src), l_fixup) + subu t8, t8, 0x1 + ADDC(sum, t0) + sw t0, (dest) + addu src, src, 0x4 + bnez t8, end_words + addu dest, dest, 0x4 + +maybe_end_cruft: + andi t2, a2, 0x3 + +small_memcpy: + j small_csumcpy; move a2, t2 + beqz t2, out + move a2, t2 + +end_bytes: + EX(lb, t0, (src), l_fixup) + subu a2, a2, 0x1 + sb t0, (dest) + addu src, src, 0x1 + bnez a2, end_bytes + addu dest, dest, 0x1 + +out: + jr ra + move v0, sum + +/* ------------------------------------------------------------------------- */ + +/* Bad, bad. At least try to align the source */ + +memcpy_u_src: + bnez t8, small_memcpy # < 8 bytes? + move t2, a2 + + beqz a2, out + andi t7, src, 0x1 # odd alignment? + +u_hword_align: + beqz t7, u_word_align + andi t8, src, 0x2 + + EX(lbu, t0, (src), l_fixup) + subu a2, a2, 0x1 + sb t0, (dest) +#ifdef __MIPSEL__ + sll t0, t0, 8 +#endif + ADDC(sum, t0) + addu src, src, 0x1 + addu dest, dest, 0x1 + andi t8, src, 0x2 + +u_word_align: + beqz t8, u_dword_align + sltiu t8, a2, 56 + + EX(lhu, t0, (src), l_fixup) + subu a2, a2, 0x2 + ush t0, (dest) + ADDC(sum, t0) + sltiu t8, a2, 56 + addu dest, dest, 0x2 + addu src, src, 0x2 + +u_dword_align: + bnez t8, u_do_end_words + move t8, a2 + + andi t8, src, 0x4 + beqz t8, u_qword_align + andi t8, src, 0x8 + + EX(lw, t0, 0x00(src), l_fixup) + subu a2, a2, 0x4 + ADDC(sum, t0) + usw t0, 0x00(dest) + addu src, src, 0x4 + addu dest, dest, 0x4 + andi t8, src, 0x8 + +u_qword_align: + beqz t8, u_oword_align + andi t8, src, 0x10 + + EX(lw, t0, 0x00(src), l_fixup) + EX(lw, t1, 0x04(src), l_fixup) + subu a2, a2, 0x8 + ADDC(sum, t0) + ADDC(sum, t1) + usw t0, 0x00(dest) + addu src, src, 0x8 + usw t1, 0x04(dest) + andi t8, src, 0x10 + addu dest, dest, 0x8 + +u_oword_align: + beqz t8, u_begin_movement + srl t8, a2, 0x7 + + EX(lw, t3, 0x08(src), l_fixup) + EX(lw, t4, 0x0c(src), l_fixup) + EX(lw, t0, 0x00(src), l_fixup) + EX(lw, t1, 0x04(src), l_fixup) + ADDC(sum, t3) + ADDC(sum, t4) + ADDC(sum, t0) + ADDC(sum, t1) + usw t3, 0x08(dest) + subu a2, a2, 0x10 + usw t4, 0x0c(dest) + addu src, src, 0x10 + usw t0, 0x00(dest) + srl t8, a2, 0x7 + addu dest, dest, 0x10 + usw t1, -0x0c(dest) + +u_begin_movement: + beqz t8, 0f + andi t2, a2, 0x40 + +u_move_128bytes: + UCSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4) + UCSUM_BIGCHUNK(src, dest, 0x20, sum, t0, t1, t3, t4) + UCSUM_BIGCHUNK(src, dest, 0x40, sum, t0, t1, t3, t4) + UCSUM_BIGCHUNK(src, dest, 0x60, sum, t0, t1, t3, t4) + subu t8, t8, 0x01 + addu src, src, 0x80 + bnez t8, u_move_128bytes + addu dest, dest, 0x80 + +0: + beqz t2, 1f + andi t2, a2, 0x20 + +u_move_64bytes: + UCSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4) + UCSUM_BIGCHUNK(src, dest, 0x20, sum, t0, t1, t3, t4) + addu src, src, 0x40 + addu dest, dest, 0x40 + +1: + beqz t2, u_do_end_words + andi t8, a2, 0x1c + +u_move_32bytes: + UCSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4) + andi t8, a2, 0x1c + addu src, src, 0x20 + addu dest, dest, 0x20 + +u_do_end_words: + beqz t8, u_maybe_end_cruft + srl t8, t8, 0x2 + +u_end_words: + EX(lw, t0, 0x00(src), l_fixup) + subu t8, t8, 0x1 + ADDC(sum, t0) + usw t0, 0x00(dest) + addu src, src, 0x4 + bnez t8, u_end_words + addu dest, dest, 0x4 + +u_maybe_end_cruft: + andi t2, a2, 0x3 + +u_cannot_optimize: + j small_csumcpy; move a2, t2 + beqz t2, out + move a2, t2 + +u_end_bytes: + EX(lb, t0, (src), l_fixup) + subu a2, a2, 0x1 + sb t0, (dest) + addu src, src, 0x1 + bnez a2, u_end_bytes + addu dest, dest, 0x1 + + jr ra + move v0, sum + END(csum_partial_copy_from_user) + +l_fixup: + beqz t7, 1f # odd buffer alignment? + nop + sll v1, sum, 8 # swap bytes + srl sum, sum, 8 + or sum, v1 + andi sum, 0xffff +1: ADDC(sum, a3) # Add csum argument. + + lw t0, THREAD_BUADDR($28) # clear the rest of the buffer + nop + subu t1, t0, src # where to start clearing + addu a0, dest, t1 + move a1, zero # zero fill + j __bzero + subu a2, t5, t0 # a2 = bad - srcend bytes to go diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/dump_tlb.c linux/arch/mips/lib/dump_tlb.c --- v2.1.100/linux/arch/mips/lib/dump_tlb.c Sat Aug 16 09:51:07 1997 +++ linux/arch/mips/lib/dump_tlb.c Fri May 8 00:13:24 1998 @@ -20,17 +20,6 @@ "u", "s", "k", "!" }; -static char *cache_map [] = { - "c/nc/wt/nwa,", - "c/nc/wt/wa, ", - "uncached, ", - "c/nc/wb, " - "unknown, ", - "unknown, ", - "unknown, ", - "unknown, " -}; - void dump_tlb(int first, int last) { @@ -69,9 +58,9 @@ c0 = (entrylo0 >> 3) & 7; c1 = (entrylo1 >> 3) & 7; - printk("%s vpn2=%08x " - "[pfn=%06x c=%d d=%d v=%d g=%d]" - "[pfn=%06x c=%d d=%d v=%d g=%d]", + printk("%s vpn2=%08Lx " + "[pfn=%06Lx c=%d d=%d v=%d g=%Ld]" + "[pfn=%06Lx c=%d d=%d v=%d g=%Ld]", region_map [r], (entryhi >> 13) & 0xffffffff, (entrylo0 >> 6) & 0xffffff, c0, (entrylo0 & 4) ? 1 : 0, diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/ide-no.c linux/arch/mips/lib/ide-no.c --- v2.1.100/linux/arch/mips/lib/ide-no.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/ide-no.c Fri May 8 00:13:24 1998 @@ -0,0 +1,73 @@ +/* + * arch/mips/kernel/ide-none.c + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Stub IDE routines to keep Linux from crashing on machine which don't + * have IDE like the Indy. + * + * Copyright (C) 1998 by Ralf Baechle + * + * $Id: ide-no.c,v 1.1 1998/05/04 09:18:13 ralf Exp $ + */ +#include +#include +#include +#include + +static int no_ide_default_irq(ide_ioreg_t base) +{ + return 0; +} + +static ide_ioreg_t no_ide_default_io_base(int index) +{ + return 0; +} + +static void no_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, + int *irq) +{ +} + +static int no_ide_request_irq(unsigned int irq, + void (*handler)(int,void *, struct pt_regs *), + unsigned long flags, const char *device, + void *dev_id) +{ + panic("no_no_ide_request_irq called - shouldn't happen"); +} + +static void no_ide_free_irq(unsigned int irq, void *dev_id) +{ + panic("no_ide_free_irq called - shouldn't happen"); +} + +static int no_ide_check_region(ide_ioreg_t from, unsigned int extent) +{ + panic("no_ide_check_region called - shouldn't happen"); +} + +static void no_ide_request_region(ide_ioreg_t from, unsigned int extent, + const char *name) +{ + panic("no_ide_request_region called - shouldn't happen"); +} + +static void no_ide_release_region(ide_ioreg_t from, unsigned int extent) +{ + panic("no_ide_release_region called - shouldn't happen"); +} + +struct ide_ops no_ide_ops = { + &no_ide_default_irq, + &no_ide_default_io_base, + &no_ide_init_hwif_ports, + &no_ide_request_irq, + &no_ide_free_irq, + &no_ide_check_region, + &no_ide_request_region, + &no_ide_release_region +}; diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/ide-std.c linux/arch/mips/lib/ide-std.c --- v2.1.100/linux/arch/mips/lib/ide-std.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/ide-std.c Fri May 8 00:13:24 1998 @@ -0,0 +1,91 @@ +/* + * include/asm-mips/types.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * IDE routines for typical pc-like standard configurations. + * + * Copyright (C) 1998 by Ralf Baechle + */ +#include +#include +#include + +static int std_ide_default_irq(ide_ioreg_t base) +{ + switch (base) { + case 0x1f0: return 14; + case 0x170: return 15; + case 0x1e8: return 11; + case 0x168: return 10; + default: + return 0; + } +} + +static ide_ioreg_t std_ide_default_io_base(int index) +{ + switch (index) { + case 0: return 0x1f0; + case 1: return 0x170; + case 2: return 0x1e8; + case 3: return 0x168; + default: + return 0; + } +} + +static void std_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, + int *irq) +{ + ide_ioreg_t port = base; + int i = 8; + + while (i--) + *p++ = port++; + *p++ = base + 0x206; + if (irq != NULL) + *irq = 0; +} + +static int std_ide_request_irq(unsigned int irq, + void (*handler)(int,void *, struct pt_regs *), + unsigned long flags, const char *device, + void *dev_id) +{ + return request_irq(irq, handler, flags, device, dev_id); +} + +static void std_ide_free_irq(unsigned int irq, void *dev_id) +{ + free_irq(irq, dev_id); +} + +static int std_ide_check_region(ide_ioreg_t from, unsigned int extent) +{ + return check_region(from, extent); +} + +static void std_ide_request_region(ide_ioreg_t from, unsigned int extent, + const char *name) +{ + request_region(from, extent, name); +} + +static void std_ide_release_region(ide_ioreg_t from, unsigned int extent) +{ + release_region(from, extent); +} + +struct ide_ops std_ide_ops = { + &std_ide_default_irq, + &std_ide_default_io_base, + &std_ide_init_hwif_ports, + &std_ide_request_irq, + &std_ide_free_irq, + &std_ide_check_region, + &std_ide_request_region, + &std_ide_release_region +}; diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/memcpy.S linux/arch/mips/lib/memcpy.S --- v2.1.100/linux/arch/mips/lib/memcpy.S Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/lib/memcpy.S Fri May 8 00:13:24 1998 @@ -1,221 +1,701 @@ -/* memcpy.S: Mips optimized memcpy based upon SparcLinux code. +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. * - * Copyright(C) 1995 Linus Torvalds - * Copyright(C) 1996 David S. Miller - * Copyright(C) 1996 Eddie C. Dost + * $Id: memcpy.S,v 1.2 1998/05/04 09:18:16 ralf Exp $ * - * derived from: - * e-mail between David and Eddie. + * Unified implementation of memcpy, memmove and the __copy_user backend. + * For __rmemcpy and memmove an exception is always a kernel bug, therefore + * they're not protected. In order to keep the exception fixup routine + * simple all memory accesses in __copy_user to src rsp. dst are stricly + * incremental. The fixup routine depends on $at not being changed. */ - #include +#include #include -#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5) \ - lw t0, (offset + 0x18)(src); \ - lw t1, (offset + 0x1c)(src); \ - sw t0, (offset + 0x18)(dst); \ - lw t2, (offset + 0x10)(src); \ - sw t1, (offset + 0x1c)(dst); \ - lw t3, (offset + 0x14)(src); \ - sw t2, (offset + 0x10)(dst); \ - lw t4, (offset + 0x08)(src); \ - sw t3, (offset + 0x14)(dst); \ - lw t5, (offset + 0x0c)(src); \ - sw t4, (offset + 0x08)(dst); \ - lw t0, (offset + 0x00)(src); \ - sw t5, (offset + 0x0c)(dst); \ - lw t1, (offset + 0x04)(src); \ - sw t0, (offset + 0x00)(dst); \ - sw t1, (offset + 0x04)(dst); \ - - /* Alignment cases are: - * 1) (src&0x3)=0x0 (dst&0x3)=0x0 can optimize - * 2) (src&0x3)=0x1 (dst&0x3)=0x1 can optimize - * 3) (src&0x3)=0x2 (dst&0x3)=0x2 can optimize - * 4) (src&0x3)=0x3 (dst&0x3)=0x3 can optimize - * 5) anything else cannot optimize - */ - - /* I hate MIPS register names... AIEEE, it's a SPARC! */ -#define o0 a0 -#define o1 a1 -#define o2 a2 -#define o3 a3 -#define o4 t0 -#define o5 t1 -#define o6 sp -#define o7 ra -#define g0 zero -#define g1 t2 -#define g2 t3 -#define g3 t4 -#define g4 t5 -#define g5 t6 -#define g6 t7 -#define g7 t8 +/* + * The fixup routine for copy_to_user depends on copying strictly in + * increasing order. Gas expands the ulw/usw macros in the wrong order for + * little endian machines, so we cannot depend on them. + */ +#ifdef __MIPSEB__ +#define uswL swl +#define uswU swr +#define ulwL lwl +#define ulwU lwr +#endif +#ifdef __MIPSEL__ +#define uswL swr +#define uswU swl +#define ulwL lwr +#define ulwU lwl +#endif + +#define EX(insn,reg,addr,handler) \ +9: insn reg, addr; \ + .section __ex_table,"a"; \ + PTR 9b, handler; \ + .previous + +#define UEX(insn,reg,addr,handler) \ +9: insn ## L reg, addr; \ +10: insn ## U reg, 3 + addr; \ + .section __ex_table,"a"; \ + PTR 9b, handler; \ + PTR 10b, handler; \ + .previous + +/* ascending order, destination aligned */ +#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ + EX(lw, t0, (offset + 0x00)(src), l_fixup); \ + EX(lw, t1, (offset + 0x04)(src), l_fixup); \ + EX(lw, t2, (offset + 0x08)(src), l_fixup); \ + EX(lw, t3, (offset + 0x0c)(src), l_fixup); \ + EX(sw, t0, (offset + 0x00)(dst), s_fixup); \ + EX(sw, t1, (offset + 0x04)(dst), s_fixup); \ + EX(sw, t2, (offset + 0x08)(dst), s_fixup); \ + EX(sw, t3, (offset + 0x0c)(dst), s_fixup); \ + EX(lw, t0, (offset + 0x10)(src), l_fixup); \ + EX(lw, t1, (offset + 0x14)(src), l_fixup); \ + EX(lw, t2, (offset + 0x18)(src), l_fixup); \ + EX(lw, t3, (offset + 0x1c)(src), l_fixup); \ + EX(sw, t0, (offset + 0x10)(dst), s_fixup); \ + EX(sw, t1, (offset + 0x14)(dst), s_fixup); \ + EX(sw, t2, (offset + 0x18)(dst), s_fixup); \ + EX(sw, t3, (offset + 0x1c)(dst), s_fixup) + +/* ascending order, destination unaligned */ +#define UMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ + EX(lw, t0, (offset + 0x00)(src), l_fixup); \ + EX(lw, t1, (offset + 0x04)(src), l_fixup); \ + EX(lw, t2, (offset + 0x08)(src), l_fixup); \ + EX(lw, t3, (offset + 0x0c)(src), l_fixup); \ + UEX(usw, t0, (offset + 0x00)(dst), s_fixup); \ + UEX(usw, t1, (offset + 0x04)(dst), s_fixup); \ + UEX(usw, t2, (offset + 0x08)(dst), s_fixup); \ + UEX(usw, t3, (offset + 0x0c)(dst), s_fixup); \ + EX(lw, t0, (offset + 0x10)(src), l_fixup); \ + EX(lw, t1, (offset + 0x14)(src), l_fixup); \ + EX(lw, t2, (offset + 0x18)(src), l_fixup); \ + EX(lw, t3, (offset + 0x1c)(src), l_fixup); \ + UEX(usw, t0, (offset + 0x10)(dst), s_fixup); \ + UEX(usw, t1, (offset + 0x14)(dst), s_fixup); \ + UEX(usw, t2, (offset + 0x18)(dst), s_fixup); \ + UEX(usw, t3, (offset + 0x1c)(dst), s_fixup) .text .set noreorder .set noat - .globl bcopy - .globl amemmove - .globl memmove - .globl memcpy - .align 2 -bcopy: - move o3, o0 - move o0, o1 - move o1, o3 - -amemmove: -memmove: -memcpy: /* o0=dst o1=src o2=len */ - xor o4, o0, o1 - andi o4, o4, 0x3 - move g6, o0 - beq o4, g0, can_align - sltiu g7, o2, 0x8 + .align 5 +LEAF(memcpy) /* a0=dst a1=src a2=len */ + move v0, a0 /* return value */ +__memcpy: +EXPORT(__copy_user) + xor t0, a0, a1 + andi t0, t0, 0x3 + move t7, a0 + beqz t0, can_align + sltiu t8, a2, 0x8 - b cannot_optimize - move g1, o2 + b memcpy_u_src # bad alignment + move t2, a2 can_align: - bne g7, g0, cannot_optimize - move g1, o2 + bnez t8, small_memcpy # < 8 bytes to copy + move t2, a2 - beq o2, g0, out - andi g7, o1, 0x1 + beqz a2, out + andi t8, a1, 0x1 hword_align: - beq g7, g0, word_align - andi g7, o1, 0x2 + beqz t8, word_align + andi t8, a1, 0x2 - lbu o4, 0x00(o1) - subu o2, o2, 0x1 - sb o4, 0x00(o0) - addu o1, o1, 0x1 - addu o0, o0, 0x1 - andi g7, o1, 0x2 + EX(lb, t0, (a1), l_fixup) + subu a2, a2, 0x1 + EX(sb, t0, (a0), s_fixup) + addu a1, a1, 0x1 + addu a0, a0, 0x1 + andi t8, a1, 0x2 word_align: - beq g7, g0, dword_align - sltiu g7, o2, 56 + beqz t8, dword_align + sltiu t8, a2, 56 - lhu o4, 0x00(o1) - subu o2, o2, 0x2 - sh o4, 0x00(o0) - sltiu g7, o2, 56 - addu o0, o0, 0x2 - addu o1, o1, 0x2 + EX(lh, t0, (a1), l_fixup) + subu a2, a2, 0x2 + EX(sh, t0, (a0), s_fixup) + sltiu t8, a2, 56 + addu a0, a0, 0x2 + addu a1, a1, 0x2 dword_align: - bne g7, g0, do_end_words - move g7, o2 + bnez t8, do_end_words + move t8, a2 - andi g7, o1, 0x4 - beq g7, zero, qword_align - andi g7, o1, 0x8 - - lw o4, 0x00(o1) - subu o2, o2, 0x4 - sw o4, 0x00(o0) - addu o1, o1, 0x4 - addu o0, o0, 0x4 - andi g7, o1, 0x8 + andi t8, a1, 0x4 + beqz t8, qword_align + andi t8, a1, 0x8 + + EX(lw, t0, 0x00(a1), l_fixup) + subu a2, a2, 0x4 + EX(sw, t0, 0x00(a0), s_fixup) + addu a1, a1, 0x4 + addu a0, a0, 0x4 + andi t8, a1, 0x8 qword_align: - beq g7, g0, oword_align - andi g7, o1, 0x10 + beqz t8, oword_align + andi t8, a1, 0x10 - lw o4, 0x00(o1) - lw o5, 0x04(o1) - subu o2, o2, 0x8 - sw o4, 0x00(o0) - addu o1, o1, 0x8 - sw o5, 0x04(o0) - andi g7, o1, 0x10 - addu o0, o0, 0x8 + EX(lw, t0, 0x00(a1), l_fixup) + EX(lw, t1, 0x04(a1), l_fixup) + subu a2, a2, 0x8 + EX(sw, t0, 0x00(a0), s_fixup) + EX(sw, t1, 0x04(a0), s_fixup) + addu a1, a1, 0x8 + andi t8, a1, 0x10 + addu a0, a0, 0x8 oword_align: - beq g7, g0, begin_movement - srl g7, o2, 0x7 + beqz t8, begin_movement + srl t8, a2, 0x7 - lw g2, 0x08(o1) - lw g3, 0x0c(o1) - lw o4, 0x00(o1) - lw o5, 0x04(o1) - sw g2, 0x08(o0) - subu o2, o2, 0x10 - sw g3, 0x0c(o0) - addu o1, o1, 0x10 - sw o4, 0x00(o0) - srl g7, o2, 0x7 - addu o0, o0, 0x10 - sw o5, -0x0c(o0) + EX(lw, t3, 0x00(a1), l_fixup) + EX(lw, t4, 0x04(a1), l_fixup) + EX(lw, t0, 0x08(a1), l_fixup) + EX(lw, t1, 0x0c(a1), l_fixup) + EX(sw, t3, 0x00(a0), s_fixup) + EX(sw, t4, 0x04(a0), s_fixup) + EX(sw, t0, 0x08(a0), s_fixup) + EX(sw, t1, 0x0c(a0), s_fixup) + subu a2, a2, 0x10 + addu a1, a1, 0x10 + srl t8, a2, 0x7 + addu a0, a0, 0x10 begin_movement: - beq g7, g0, 0f - andi g1, o2, 0x40 + beqz t8, 0f + andi t2, a2, 0x40 move_128bytes: - MOVE_BIGCHUNK(o1, o0, 0x00, o4, o5, g2, g3, g4, g5) - MOVE_BIGCHUNK(o1, o0, 0x20, o4, o5, g2, g3, g4, g5) - MOVE_BIGCHUNK(o1, o0, 0x40, o4, o5, g2, g3, g4, g5) - MOVE_BIGCHUNK(o1, o0, 0x60, o4, o5, g2, g3, g4, g5) - subu g7, g7, 0x01 - addu o1, o1, 0x80 - bne g7, g0, move_128bytes - addu o0, o0, 0x80 + MOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) + MOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4) + MOVE_BIGCHUNK(a1, a0, 0x40, t0, t1, t3, t4) + MOVE_BIGCHUNK(a1, a0, 0x60, t0, t1, t3, t4) + subu t8, t8, 0x01 + addu a1, a1, 0x80 + bnez t8, move_128bytes + addu a0, a0, 0x80 0: - beq g1, g0, 1f - andi g1, o2, 0x20 + beqz t2, 1f + andi t2, a2, 0x20 move_64bytes: - MOVE_BIGCHUNK(o1, o0, 0x00, o4, o5, g2, g3, g4, g5) - MOVE_BIGCHUNK(o1, o0, 0x20, o4, o5, g2, g3, g4, g5) - addu o1, o1, 0x40 - addu o0, o0, 0x40 + MOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) + MOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4) + addu a1, a1, 0x40 + addu a0, a0, 0x40 1: - beq g1, g0, do_end_words - andi g7, o2, 0x1c + beqz t2, do_end_words + andi t8, a2, 0x1c move_32bytes: - MOVE_BIGCHUNK(o1, o0, 0x00, o4, o5, g2, g3, g4, g5) - andi g7, o2, 0x1c - addu o1, o1, 0x20 - addu o0, o0, 0x20 + MOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) + andi t8, a2, 0x1c + addu a1, a1, 0x20 + addu a0, a0, 0x20 do_end_words: - beq g7, g0, maybe_end_cruft - srl g7, g7, 0x2 + beqz t8, maybe_end_cruft + srl t8, t8, 0x2 end_words: - lw o4, 0x00(o1) - subu g7, g7, 0x1 - sw o4, 0x00(o0) - addu o1, o1, 0x4 - bne g7, g0, end_words - addu o0, o0, 0x4 + EX(lw, t0, (a1), l_fixup) + subu t8, t8, 0x1 + EX(sw, t0, (a0), s_fixup) + addu a1, a1, 0x4 + bnez t8, end_words + addu a0, a0, 0x4 maybe_end_cruft: - andi g1, o2, 0x3 + andi t2, a2, 0x3 -cannot_optimize: - beq g1, g0, out - move o2, g1 +small_memcpy: + beqz t2, out + move a2, t2 end_bytes: - lbu o4, 0x00(o1) - subu o2, o2, 0x1 - sb o4, 0x00(o0) - addu o1, o1, 0x1 - bne o2, g0, end_bytes - addu o0, o0, 0x1 - -out: - jr o7 - move v0, g6 + EX(lb, t0, (a1), l_fixup) + subu a2, a2, 0x1 + EX(sb, t0, (a0), s_fixup) + addu a1, a1, 0x1 + bnez a2, end_bytes + addu a0, a0, 0x1 + +out: jr ra + move a2, zero + +/* ------------------------------------------------------------------------- */ + +/* Bad, bad. At least try to align the source */ + +memcpy_u_src: + bnez t8, small_memcpy # < 8 bytes? + move t2, a2 + + addiu t0, a1, 7 # t0: how much to align + ori t0, 7 + xori t0, 7 + subu t0, a1 + + UEX(ulw, t1, 0(a1), l_fixup) # dword alignment + UEX(ulw, t2, 4(a1), l_fixup) + UEX(usw, t1, 0(a0), s_fixup) + UEX(usw, t2, 4(a0), s_fixup) + + addu a1, t0 # src + addu a0, t0 # dst + subu a2, t0 # len + + sltiu t8, a2, 56 + bnez t8, u_do_end_words + andi t8, a2, 0x3c + + andi t8, a1, 8 # now qword aligned? + +u_qword_align: + beqz t8, u_oword_align + andi t8, a1, 0x10 + + EX(lw, t0, 0x00(a1), l_fixup) + EX(lw, t1, 0x04(a1), l_fixup) + subu a2, a2, 0x8 + UEX(usw, t0, 0x00(a0), s_fixup) + UEX(usw, t1, 0x04(a0), s_fixup) + addu a1, a1, 0x8 + andi t8, a1, 0x10 + addu a0, a0, 0x8 + +u_oword_align: + beqz t8, u_begin_movement + srl t8, a2, 0x7 + + EX(lw, t3, 0x08(a1), l_fixup) + EX(lw, t4, 0x0c(a1), l_fixup) + EX(lw, t0, 0x00(a1), l_fixup) + EX(lw, t1, 0x04(a1), l_fixup) + UEX(usw, t3, 0x08(a0), s_fixup) + UEX(usw, t4, 0x0c(a0), s_fixup) + UEX(usw, t0, 0x00(a0), s_fixup) + UEX(usw, t1, 0x04(a0), s_fixup) + subu a2, a2, 0x10 + addu a1, a1, 0x10 + srl t8, a2, 0x7 + addu a0, a0, 0x10 + +u_begin_movement: + beqz t8, 0f + andi t2, a2, 0x40 + +u_move_128bytes: + UMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) + UMOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4) + UMOVE_BIGCHUNK(a1, a0, 0x40, t0, t1, t3, t4) + UMOVE_BIGCHUNK(a1, a0, 0x60, t0, t1, t3, t4) + subu t8, t8, 0x01 + addu a1, a1, 0x80 + bnez t8, u_move_128bytes + addu a0, a0, 0x80 + +0: + beqz t2, 1f + andi t2, a2, 0x20 + +u_move_64bytes: + UMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) + UMOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4) + addu a1, a1, 0x40 + addu a0, a0, 0x40 + +1: + beqz t2, u_do_end_words + andi t8, a2, 0x1c + +u_move_32bytes: + UMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) + andi t8, a2, 0x1c + addu a1, a1, 0x20 + addu a0, a0, 0x20 + +u_do_end_words: + beqz t8, u_maybe_end_cruft + srl t8, t8, 0x2 + +u_end_words: + EX(lw, t0, 0x00(a1), l_fixup) + subu t8, t8, 0x1 + UEX(usw, t0, 0x00(a0), s_fixup) + addu a1, a1, 0x4 + bnez t8, u_end_words + addu a0, a0, 0x4 + +u_maybe_end_cruft: + andi t2, a2, 0x3 + +u_cannot_optimize: + beqz t2, out + move a2, t2 + +u_end_bytes: + EX(lb, t0, (a1), l_fixup) + subu a2, a2, 0x1 + EX(sb, t0, (a0), s_fixup) + addu a1, a1, 0x1 + bnez a2, u_end_bytes + addu a0, a0, 0x1 + + jr ra + move a2, zero + END(memcpy) + +/* descending order, destination aligned */ +#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ + lw t0, (offset + 0x10)(src); \ + lw t1, (offset + 0x14)(src); \ + lw t2, (offset + 0x18)(src); \ + lw t3, (offset + 0x1c)(src); \ + sw t0, (offset + 0x10)(dst); \ + sw t1, (offset + 0x14)(dst); \ + sw t2, (offset + 0x18)(dst); \ + sw t3, (offset + 0x1c)(dst); \ + lw t0, (offset + 0x00)(src); \ + lw t1, (offset + 0x04)(src); \ + lw t2, (offset + 0x08)(src); \ + lw t3, (offset + 0x0c)(src); \ + sw t0, (offset + 0x00)(dst); \ + sw t1, (offset + 0x04)(dst); \ + sw t2, (offset + 0x08)(dst); \ + sw t3, (offset + 0x0c)(dst) + +/* descending order, destination ununaligned */ +#define RUMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ + lw t0, (offset + 0x10)(src); \ + lw t1, (offset + 0x14)(src); \ + lw t2, (offset + 0x18)(src); \ + lw t3, (offset + 0x1c)(src); \ + usw t0, (offset + 0x10)(dst); \ + usw t1, (offset + 0x14)(dst); \ + usw t2, (offset + 0x18)(dst); \ + usw t3, (offset + 0x1c)(dst); \ + lw t0, (offset + 0x00)(src); \ + lw t1, (offset + 0x04)(src); \ + lw t2, (offset + 0x08)(src); \ + lw t3, (offset + 0x0c)(src); \ + usw t0, (offset + 0x00)(dst); \ + usw t1, (offset + 0x04)(dst); \ + usw t2, (offset + 0x08)(dst); \ + usw t3, (offset + 0x0c)(dst) + + .align 5 +LEAF(memmove) + sltu t0, a0, a1 # dst < src -> memcpy + bnez t0, memcpy + addu v0, a0, a2 + sltu t0, v0, a1 # dst + len < src -> non- + bnez t0, __memcpy # overlapping, can use memcpy + move v0, a0 /* return value */ + END(memmove) + +LEAF(__rmemcpy) /* a0=dst a1=src a2=len */ + addu a0, a2 # dst = dst + len + addu a1, a2 # src = src + len + + xor t0, a0, a1 + andi t0, t0, 0x3 + move t7, a0 + beqz t0, r_can_align + sltiu t8, a2, 0x8 + + b r_memcpy_u_src # bad alignment + move t2, a2 + +r_can_align: + bnez t8, r_small_memcpy # < 8 bytes to copy + move t2, a2 + + beqz a2, r_out + andi t8, a1, 0x1 + +r_hword_align: + beqz t8, r_word_align + andi t8, a1, 0x2 + + lb t0, -1(a1) + subu a2, a2, 0x1 + sb t0, -1(a0) + subu a1, a1, 0x1 + subu a0, a0, 0x1 + andi t8, a1, 0x2 + +r_word_align: + beqz t8, r_dword_align + sltiu t8, a2, 56 + + lh t0, -2(a1) + subu a2, a2, 0x2 + sh t0, -2(a0) + sltiu t8, a2, 56 + subu a0, a0, 0x2 + subu a1, a1, 0x2 + +r_dword_align: + bnez t8, r_do_end_words + move t8, a2 + + andi t8, a1, 0x4 + beqz t8, r_qword_align + andi t8, a1, 0x8 + + lw t0, -4(a1) + subu a2, a2, 0x4 + sw t0, -4(a0) + subu a1, a1, 0x4 + subu a0, a0, 0x4 + andi t8, a1, 0x8 + +r_qword_align: + beqz t8, r_oword_align + andi t8, a1, 0x10 + + subu a1, a1, 0x8 + lw t0, 0x04(a1) + lw t1, 0x00(a1) + subu a0, a0, 0x8 + sw t0, 0x04(a0) + sw t1, 0x00(a0) + subu a2, a2, 0x8 + + andi t8, a1, 0x10 + +r_oword_align: + beqz t8, r_begin_movement + srl t8, a2, 0x7 + + subu a1, a1, 0x10 + lw t3, 0x08(a1) # assumes subblock ordering + lw t4, 0x0c(a1) + lw t0, 0x00(a1) + lw t1, 0x04(a1) + subu a0, a0, 0x10 + sw t3, 0x08(a0) + sw t4, 0x0c(a0) + sw t0, 0x00(a0) + sw t1, 0x04(a0) + subu a2, a2, 0x10 + srl t8, a2, 0x7 + +r_begin_movement: + beqz t8, 0f + andi t2, a2, 0x40 + +r_move_128bytes: + RMOVE_BIGCHUNK(a1, a0, -0x80, t0, t1, t3, t4) + RMOVE_BIGCHUNK(a1, a0, -0x60, t0, t1, t3, t4) + RMOVE_BIGCHUNK(a1, a0, -0x40, t0, t1, t3, t4) + RMOVE_BIGCHUNK(a1, a0, -0x20, t0, t1, t3, t4) + subu t8, t8, 0x01 + subu a1, a1, 0x80 + bnez t8, r_move_128bytes + subu a0, a0, 0x80 + +0: + beqz t2, 1f + andi t2, a2, 0x20 + +r_move_64bytes: + subu a1, a1, 0x40 + subu a0, a0, 0x40 + RMOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4) + RMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) + +1: + beqz t2, r_do_end_words + andi t8, a2, 0x1c + +r_move_32bytes: + subu a1, a1, 0x20 + subu a0, a0, 0x20 + RMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) + andi t8, a2, 0x1c + +r_do_end_words: + beqz t8, r_maybe_end_cruft + srl t8, t8, 0x2 + +r_end_words: + lw t0, -4(a1) + subu t8, t8, 0x1 + sw t0, -4(a0) + subu a1, a1, 0x4 + bnez t8, r_end_words + subu a0, a0, 0x4 + +r_maybe_end_cruft: + andi t2, a2, 0x3 + +r_small_memcpy: + beqz t2, r_out + move a2, t2 + +r_end_bytes: + lb t0, -1(a1) + subu a2, a2, 0x1 + sb t0, -1(a0) + subu a1, a1, 0x1 + bnez a2, r_end_bytes + subu a0, a0, 0x1 + +r_out: + jr ra + move a2, zero + +/* ------------------------------------------------------------------------- */ + +/* Bad, bad. At least try to align the source */ + +r_memcpy_u_src: + bnez t8, r_small_memcpy # < 8 bytes? + move t2, a2 + + andi t0, a1, 7 # t0: how much to align + + ulw t1, -8(a1) # dword alignment + ulw t2, -4(a1) + usw t1, -8(a0) + usw t2, -4(a0) + + subu a1, t0 # src + subu a0, t0 # dst + subu a2, t0 # len + + sltiu t8, a2, 56 + bnez t8, ru_do_end_words + andi t8, a2, 0x3c + + andi t8, a1, 8 # now qword aligned? + +ru_qword_align: + beqz t8, ru_oword_align + andi t8, a1, 0x10 + + subu a1, a1, 0x8 + lw t0, 0x00(a1) + lw t1, 0x04(a1) + subu a0, a0, 0x8 + usw t0, 0x00(a0) + usw t1, 0x04(a0) + subu a2, a2, 0x8 + + andi t8, a1, 0x10 + +ru_oword_align: + beqz t8, ru_begin_movement + srl t8, a2, 0x7 + + subu a1, a1, 0x10 + lw t3, 0x08(a1) # assumes subblock ordering + lw t4, 0x0c(a1) + lw t0, 0x00(a1) + lw t1, 0x04(a1) + subu a0, a0, 0x10 + usw t3, 0x08(a0) + usw t4, 0x0c(a0) + usw t0, 0x00(a0) + usw t1, 0x04(a0) + subu a2, a2, 0x10 + + srl t8, a2, 0x7 + +ru_begin_movement: + beqz t8, 0f + andi t2, a2, 0x40 + +ru_move_128bytes: + RUMOVE_BIGCHUNK(a1, a0, -0x80, t0, t1, t3, t4) + RUMOVE_BIGCHUNK(a1, a0, -0x60, t0, t1, t3, t4) + RUMOVE_BIGCHUNK(a1, a0, -0x40, t0, t1, t3, t4) + RUMOVE_BIGCHUNK(a1, a0, -0x20, t0, t1, t3, t4) + subu t8, t8, 0x01 + subu a1, a1, 0x80 + bnez t8, ru_move_128bytes + subu a0, a0, 0x80 + +0: + beqz t2, 1f + andi t2, a2, 0x20 + +ru_move_64bytes: + subu a1, a1, 0x40 + subu a0, a0, 0x40 + RUMOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4) + RUMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) + +1: + beqz t2, ru_do_end_words + andi t8, a2, 0x1c + +ru_move_32bytes: + subu a1, a1, 0x20 + subu a0, a0, 0x20 + RUMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) + andi t8, a2, 0x1c + +ru_do_end_words: + beqz t8, ru_maybe_end_cruft + srl t8, t8, 0x2 + +ru_end_words: + lw t0, -4(a1) + usw t0, -4(a0) + subu t8, t8, 0x1 + subu a1, a1, 0x4 + bnez t8, ru_end_words + subu a0, a0, 0x4 + +ru_maybe_end_cruft: + andi t2, a2, 0x3 + +ru_cannot_optimize: + beqz t2, r_out + move a2, t2 + +ru_end_bytes: + lb t0, -1(a1) + subu a2, a2, 0x1 + sb t0, -1(a0) + subu a1, a1, 0x1 + bnez a2, ru_end_bytes + subu a0, a0, 0x1 + + jr ra + move a2, zero + END(__rmemcpy) + +l_fixup: # clear the rest of the buffer + lw t0, THREAD_BUADDR($28) + nop + subu a2, AT, t0 # a2 bytes to go + addu a0, t0 # compute start address in a1 + subu a0, a1 + j __bzero + move a1, zero + +s_fixup: + jr ra + nop diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/memset.S linux/arch/mips/lib/memset.S --- v2.1.100/linux/arch/mips/lib/memset.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/memset.S Fri May 8 00:13:24 1998 @@ -0,0 +1,141 @@ +/* + * include/asm-mips/types.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998 by Ralf Baechle + * + * $Id: memset.S,v 1.1 1998/05/04 09:18:18 ralf Exp $ + */ +#include +#include +#include + +#define EX(insn,reg,addr,handler) \ +9: insn reg, addr; \ + .section __ex_table,"a"; \ + PTR 9b, handler; \ + .previous + +#define F_FILL64(dst, offset, val, fixup) \ + EX(sw, val, (offset + 0x00)(dst), fixup); \ + EX(sw, val, (offset + 0x04)(dst), fixup); \ + EX(sw, val, (offset + 0x08)(dst), fixup); \ + EX(sw, val, (offset + 0x0c)(dst), fixup); \ + EX(sw, val, (offset + 0x10)(dst), fixup); \ + EX(sw, val, (offset + 0x14)(dst), fixup); \ + EX(sw, val, (offset + 0x18)(dst), fixup); \ + EX(sw, val, (offset + 0x1c)(dst), fixup); \ + EX(sw, val, (offset + 0x20)(dst), fixup); \ + EX(sw, val, (offset + 0x24)(dst), fixup); \ + EX(sw, val, (offset + 0x28)(dst), fixup); \ + EX(sw, val, (offset + 0x2c)(dst), fixup); \ + EX(sw, val, (offset + 0x30)(dst), fixup); \ + EX(sw, val, (offset + 0x34)(dst), fixup); \ + EX(sw, val, (offset + 0x38)(dst), fixup); \ + EX(sw, val, (offset + 0x3c)(dst), fixup) + +/* + * memset(void *s, int c, size_t n) + * + * a0: start of area to clear + * a1: char to fill with + * a2: size of area to clear + */ + .set noreorder + .align 5 +LEAF(memset) + beqz a1, 1f + move v0, a0 /* result */ + + andi a1, 0xff /* spread fillword */ + sll t1, a1, 8 + or a1, t1 + sll t1, a1, 16 + or a1, t1 +1: + +EXPORT(__bzero) + sltiu t0, a2, 4 /* very small region? */ + bnez t0, small_memset + andi t0, a0, 3 /* aligned? */ + + beqz t0, 1f + subu t0, 4 /* alignment in bytes */ + +#ifdef __MIPSEB__ + EX(swl, a1, (a0), first_fixup) /* make word aligned */ +#endif +#ifdef __MIPSEL__ + EX(swr, a1, (a0), first_fixup) /* make word aligned */ +#endif + subu a0, t0 /* word align ptr */ + addu a2, t0 /* correct size */ + +1: ori t1, a2, 0x3f /* # of full blocks */ + xori t1, 0x3f + beqz t1, memset_partial /* no block to fill */ + andi t0, a2, 0x3c + + addu t1, a0 /* end address */ + .set reorder +1: addiu a0, 64 + F_FILL64(a0, -64, a1, fwd_fixup) + bne t1, a0, 1b + .set noreorder + +memset_partial: + la t1, 2f /* where to start */ + subu t1, t0 + jr t1 + addu a0, t0 /* dest ptr */ + + F_FILL64(a0, -64, a1, partial_fixup) /* ... but first do wrds ... */ +2: andi a2, 3 /* 0 <= n <= 3 to go */ + + beqz a2, 1f + addu a0, a2 /* What's left */ +#ifdef __MIPSEB__ + EX(swr, a1, -1(a0), last_fixup) +#endif +#ifdef __MIPSEL__ + EX(swl, a1, -1(a0), last_fixup) +#endif +1: jr ra + move a2, zero + +small_memset: + beqz a2, 2f + addu t1, a0, a2 + +1: addiu a0, 1 /* fill bytewise */ + bne t1, a0, 1b + sb a1, -1(a0) + +2: jr ra /* done */ + move a2, zero + END(memset) + +first_fixup: + jr ra + nop + +fwd_fixup: + lw t0, THREAD_BUADDR($28) + andi a2, 0x3f + addu a2, t1 + jr ra + subu a2, t0 + +partial_fixup: + lw t0, THREAD_BUADDR($28) + andi a2, 3 + addu a2, t1 + jr ra + subu a2, t0 + +last_fixup: + jr ra + andi v1, a2, 3 diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/pmaxcon.c linux/arch/mips/lib/pmaxcon.c --- v2.1.100/linux/arch/mips/lib/pmaxcon.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/lib/pmaxcon.c Wed Dec 31 16:00:00 1969 @@ -1,150 +0,0 @@ -/* ---------------------------------------------------------------------- - * console.c - * - * Copyright (C) 1994 by Waldorf Electronic, - * written by Ralf Baechle and Andreas Busse - * Copyright (C) 1995 Paul M. Antoine (PMAX) - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * ---------------------------------------------------------------------- */ -/* - * FIXME: This file is hacked to be hardwired for the Personal DECStation - * Only thought of as a debugging console output - */ - -#include -#include - -static unsigned int size_x; -static unsigned int size_y; -static unsigned short cursor_x; -static unsigned short cursor_y; -static volatile unsigned short *vram_addr; -static int console_needs_init = 1; - -extern struct bootinfo boot_info; -extern struct screen_info screen_info; - -/* - * Here is the base address of the prom calls - */ -unsigned long pmax_rex_base = 0; - -/* ---------------------------------------------------------------------- - * init_console() - * ---------------------------------------------------------------------- */ - -void init_console(void) -{ - size_x = 80; - size_y = 50; - cursor_x = 0; - cursor_y = 0; - - vram_addr = (unsigned short *)0xe10b8000; - - console_needs_init = 0; -} - -void -set_size_x(unsigned int x) -{ - size_x = x; -} - -void -set_size_y(unsigned int y) -{ - size_y = y; -} - -void -set_vram(unsigned short *vram) -{ - vram_addr = vram; -} - -/* - * FIXME: Temporary hack - changed its name to avoid conflict in - * drivers/char/vga.c that shouldn't be there PMA - */ -void -set_pmax_cursor(unsigned int x, unsigned int y) -{ - cursor_x = x; - cursor_y = y; -} - -void -print_char(unsigned int x, unsigned int y, unsigned char c) -{ - volatile unsigned short *caddr; - -/* caddr = vram_addr + (y * size_x) + x; - *caddr = (*caddr & 0xff00) | 0x0f00 | (unsigned short) c; -*/ - pmax_putch(c); -} - -static void -scroll(void) -{ - volatile unsigned short *caddr; - register int i; -/* - caddr = vram_addr; - for(i=0; i -#include - - .text - .set reorder -/* - * pmax_printf - call the PROM printf() function - */ - .globl pmax_printf -pmax_printf: - lw v0,pmax_rex_base - lw v0,REX_PRINTF(v0) - j v0 - -/* - * pmax_getchar - call the PROM getchar() function - */ - .globl pmax_getch -pmax_getch: - lw v0,pmax_rex_base - lw v0,REX_GETCHAR(v0) - j v0 - -/* - * pmax_putchar - call the PROM putchar() function - */ - .globl pmax_putch -pmax_putch: - lw v0,pmax_rex_base - lw v0,REX_PUTCHAR(v0) - j v0 - -/* - * pmax_halt - call the PROM halt() function - */ - .globl pmax_halt -pmax_halt: - lw v0,pmax_rex_base - lw v0,REX_HALT(v0) - j v0 diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/strlen_user.S linux/arch/mips/lib/strlen_user.S --- v2.1.100/linux/arch/mips/lib/strlen_user.S Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/lib/strlen_user.S Fri May 8 00:13:24 1998 @@ -5,29 +5,44 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 1996 by Ralf Baechle + * Copyright (c) 1996, 1998 by Ralf Baechle + * + * $Id: strlen_user.S,v 1.2 1998/05/04 09:18:20 ralf Exp $ */ #include +#include #include #include +#define EX(insn,reg,addr,handler) \ +9: insn reg, addr; \ + .section __ex_table,"a"; \ + PTR 9b, handler; \ + .previous + /* * Return the size of a string (including the ending 0) * * Return 0 for error */ -LEAF(__strlen_user) - move v0,zero -1: lb t0,(a0) - LONG_ADDIU v0,1 - LONG_ADDIU a0,1 - bnez t0,1b - jr ra - END(__strlen_user) +LEAF(__strlen_user_nocheck_asm) + lw v0, THREAD_CURDS($28) # pointer ok? + subu v0, zero, v0 + and v0, a0 + nor v0, zero, v0 + beqz v0, fault +EXPORT(__strlen_user_asm) + move v0, a0 +1: EX(lb, t0, (v0), fault) + LONG_ADDIU v0, 1 + bnez t0, 1b + LONG_SUBU v0, a0 + jr ra + END(__strlen_user_nocheck_asm) - .section __ex_table,"a" - PTR 1b,fault - .previous + .section __ex_table,"a" + PTR 1b, fault + .previous -fault: move v0,zero - jr ra +fault: move v0, zero + jr ra diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/strncpy_user.S linux/arch/mips/lib/strncpy_user.S --- v2.1.100/linux/arch/mips/lib/strncpy_user.S Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/lib/strncpy_user.S Fri May 8 00:13:24 1998 @@ -6,12 +6,20 @@ * for more details. * * Copyright (c) 1996 by Ralf Baechle + * + * $Id: strncpy_user.S,v 1.2 1998/05/04 09:18:22 ralf Exp $ */ #include - #include +#include #include +#define EX(insn,reg,addr,handler) \ +9: insn reg, addr; \ + .section __ex_table,"a"; \ + PTR 9b, handler; \ + .previous + /* * Returns: -EFAULT if exception before terminator, N if the entire * buffer filled, else strlen. @@ -19,30 +27,37 @@ /* * Ugly special case have to check: we might get passed a user space - * pointer which wraps into the kernel space ... + * pointer which wraps into the kernel space. We don't deal with that. If + * it happens at most some bytes of the exceptions handlers will be copied. */ -LEAF(__strncpy_from_user) - move v0,zero - move v1,a1 - .set noreorder -1: lbu t0,(v1) - LONG_ADDIU v1,1 - beqz t0,2f - sb t0,(a0) # delay slot - LONG_ADDIU v0,1 - bne v0,a2,1b - LONG_ADDIU a0,1 # delay slot - .set reorder -2: LONG_ADDU t0,a1,v0 - xor t0,a1 - bltz t0,fault - jr ra # return n - END(__strncpy_from_user) - -fault: li v0,-EFAULT - jr ra - - .section __ex_table,"a" - PTR 1b,fault - .previous +LEAF(__strncpy_from_user_asm) + lw v0, THREAD_CURDS($28) # pointer ok? + subu v0, zero, v0 + and v0, a1 + nor v0, zero, v0 + beqz v0, fault +EXPORT(__strncpy_from_user_nocheck_asm) + move v0,zero + move v1,a1 + .set noreorder +1: EX(lbu, t0, (v1), fault) + LONG_ADDIU v1,1 + beqz t0,2f + sb t0,(a0) + LONG_ADDIU v0,1 + bne v0,a2,1b + LONG_ADDIU a0,1 + .set reorder +2: LONG_ADDU t0,a1,v0 + xor t0,a1 + bltz t0,fault + jr ra # return n + END(__strncpy_from_user_asm) + +fault: li v0,-EFAULT + jr ra + + .section __ex_table,"a" + PTR 1b,fault + .previous diff -u --recursive --new-file v2.1.100/linux/arch/mips/mm/andes.c linux/arch/mips/mm/andes.c --- v2.1.100/linux/arch/mips/mm/andes.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/mm/andes.c Fri May 8 00:13:24 1998 @@ -1,13 +1,14 @@ -/* $Id: andes.c,v 1.2 1997/12/02 05:51:07 ralf Exp $ +/* * andes.c: MMU and cache operations for the R10000 (ANDES). * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: andes.c,v 1.5 1998/05/04 09:18:26 ralf Exp $ */ - +#include #include #include #include - #include #include #include @@ -85,7 +86,12 @@ /* XXX */ } -void ld_mmu_andes(void) +static int andes_user_mode(struct pt_regs *regs) +{ + return (regs->cp0_status & ST0_KSU) == KSU_USER; +} + +__initfunc(void ld_mmu_andes(void)) { flush_cache_all = andes_flush_cache_all; flush_cache_mm = andes_flush_cache_mm; @@ -100,6 +106,8 @@ flush_tlb_page = andes_flush_tlb_page; add_wired_entry = andes_add_wired_entry; + + user_mode = andes_user_mode; load_pgd = andes_load_pgd; pgd_init = andes_pgd_init; diff -u --recursive --new-file v2.1.100/linux/arch/mips/mm/fault.c linux/arch/mips/mm/fault.c --- v2.1.100/linux/arch/mips/mm/fault.c Sat Aug 16 09:51:07 1997 +++ linux/arch/mips/mm/fault.c Fri May 8 00:13:24 1998 @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -43,6 +44,8 @@ struct mm_struct *mm = tsk->mm; unsigned long fixup; + if (local_irq_count[smp_processor_id()] != 0) + die_if_kernel("page fault from irq handler", regs, writeaccess); lock_kernel(); #if 0 printk("[%s:%d:%08lx:%ld:%08lx]\n", current->comm, current->pid, @@ -85,7 +88,7 @@ if (user_mode(regs)) { tsk->tss.cp0_badvaddr = address; tsk->tss.error_code = writeaccess; -#if 1 +#if 0 printk("do_page_fault() #2: sending SIGSEGV to %s for illegal %s\n" "%08lx (epc == %08lx, ra == %08lx)\n", tsk->comm, @@ -94,9 +97,6 @@ (unsigned long) regs->cp0_epc, (unsigned long) regs->regs[31]); #endif - - current->tss.cp0_badvaddr = address; - current->tss.error_code = writeaccess; force_sig(SIGSEGV, tsk); goto out; } @@ -105,6 +105,8 @@ fixup = search_exception_table(regs->cp0_epc); if (fixup) { long new_epc; + + tsk->tss.cp0_baduaddr = address; new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n", tsk->comm, regs->cp0_epc, new_epc); diff -u --recursive --new-file v2.1.100/linux/arch/mips/mm/init.c linux/arch/mips/mm/init.c --- v2.1.100/linux/arch/mips/mm/init.c Thu Jul 31 13:09:17 1997 +++ linux/arch/mips/mm/init.c Fri May 8 00:13:24 1998 @@ -1,10 +1,14 @@ /* - * arch/mips/mm/init.c + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. * - * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds - * Ported to MIPS by Ralf Baechle + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle + * + * $Id: init.c,v 1.14 1998/05/01 01:34:53 ralf Exp $ */ #include +#include #include #include #include @@ -113,58 +117,12 @@ return (pte_t *)page; } -static inline void -__zeropage(unsigned long page) -{ - unsigned long dummy1, dummy2; - -#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) - /* - * Use 64bit code even for Linux/MIPS 32bit on R4000 - */ - __asm__ __volatile__( - ".set\tnoreorder\n" - ".set\tnoat\n\t" - ".set\tmips3\n" - "1:\tsd\t$0,(%0)\n\t" - "subu\t%1,1\n\t" - "bnez\t%1,1b\n\t" - "addiu\t%0,8\n\t" - ".set\tmips0\n\t" - ".set\tat\n" - ".set\treorder" - :"=r" (dummy1), - "=r" (dummy2) - :"0" (page), - "1" (PAGE_SIZE/8)); -#else /* (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) */ - __asm__ __volatile__( - ".set\tnoreorder\n" - "1:\tsw\t$0,(%0)\n\t" - "subu\t%1,1\n\t" - "bnez\t%1,1b\n\t" - "addiu\t%0,4\n\t" - ".set\treorder" - :"=r" (dummy1), - "=r" (dummy2) - :"0" (page), - "1" (PAGE_SIZE/4)); -#endif -} - -static inline void -zeropage(unsigned long page) -{ - flush_page_to_ram(page); - __zeropage(page); -} - pte_t __bad_page(void) { extern char empty_bad_page[PAGE_SIZE]; unsigned long page = (unsigned long)empty_bad_page; - zeropage(page); + clear_page(page); return pte_mkdirty(mk_pte(page, PAGE_SHARED)); } @@ -198,13 +156,13 @@ extern unsigned long free_area_init(unsigned long, unsigned long); -unsigned long paging_init(unsigned long start_mem, unsigned long end_mem) +__initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)) { pgd_init((unsigned long)swapper_pg_dir); return free_area_init(start_mem, end_mem); } -void mem_init(unsigned long start_mem, unsigned long end_mem) +__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem)) { int codepages = 0; int datapages = 0; @@ -221,7 +179,7 @@ high_memory = (void *)end_mem; /* clear the zero-page */ - memset(empty_zero_page, 0, PAGE_SIZE); + clear_page((unsigned long)empty_zero_page); /* mark usable pages in the mem_map[] */ start_mem = PAGE_ALIGN(start_mem); @@ -229,27 +187,11 @@ for(tmp = MAP_NR(start_mem);tmp < max_mapnr;tmp++) clear_bit(PG_reserved, &mem_map[tmp].flags); - /* - * For rPC44 and RM200 we've reserved some memory too much. Free - * the memory from PAGE_SIZE to PAGE_OFFSET + 0xa0000 again. We - * don't free the lowest page where the exception handlers will - * reside. - */ - if (mips_machgroup == MACH_GROUP_ARC && - mips_machtype == MACH_DESKSTATION_RPC44) - for(tmp = MAP_NR(PAGE_OFFSET + PAGE_SIZE); - tmp < MAP_NR(PAGE_OFFSET + 0xa000); tmp++) - clear_bit(PG_reserved, &mem_map[tmp].flags); - #ifdef CONFIG_SGI prom_fixup_mem_map(start_mem, (unsigned long)high_memory); #endif -#ifdef CONFIG_DESKSTATION_TYNE - deskstation_tyne_dma_init(); -#endif - for (tmp = PAGE_OFFSET; tmp < end_mem; tmp += PAGE_SIZE) { /* * This is only for PC-style DMA. The onboard DMA @@ -284,9 +226,20 @@ return; } +extern char __init_begin, __init_end; + void free_initmem(void) { - /* To be written */ + unsigned long addr; + + addr = (unsigned long)(&__init_begin); + for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { + mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); + atomic_set(&mem_map[MAP_NR(addr)].count, 1); + free_page(addr); + } + printk("Freeing unused kernel memory: %dk freed\n", + (&__init_end - &__init_begin) >> 10); } void si_meminfo(struct sysinfo *val) diff -u --recursive --new-file v2.1.100/linux/arch/mips/mm/loadmmu.c linux/arch/mips/mm/loadmmu.c --- v2.1.100/linux/arch/mips/mm/loadmmu.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/mm/loadmmu.c Fri May 8 00:13:24 1998 @@ -3,9 +3,9 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: loadmmu.c,v 1.4 1997/12/02 05:51:07 ralf Exp $ + * $Id: loadmmu.c,v 1.6 1998/05/01 01:34:54 ralf Exp $ */ - +#include #include #include #include @@ -30,8 +30,8 @@ void (*flush_page_to_ram)(unsigned long page); /* DMA cache operations. */ -void (*flush_cache_pre_dma_out)(unsigned long start, unsigned long size); -void (*flush_cache_post_dma_in)(unsigned long start, unsigned long size); +void (*dma_cache_wback_inv)(unsigned long start, unsigned long size); +void (*dma_cache_inv)(unsigned long start, unsigned long size); /* TLB operations. */ void (*flush_tlb_all)(void); @@ -51,6 +51,8 @@ void (*add_wired_entry)(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask); +int (*user_mode)(struct pt_regs *); + asmlinkage void (*resume)(void *tsk); extern void ld_mmu_r2300(void); @@ -59,7 +61,7 @@ extern void ld_mmu_tfp(void); extern void ld_mmu_andes(void); -void loadmmu(void) +__initfunc(void loadmmu(void)) { switch(mips_cputype) { case CPU_R2000: diff -u --recursive --new-file v2.1.100/linux/arch/mips/mm/r2300.c linux/arch/mips/mm/r2300.c --- v2.1.100/linux/arch/mips/mm/r2300.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/mm/r2300.c Fri May 8 00:13:24 1998 @@ -3,9 +3,9 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r2300.c,v 1.3 1997/12/02 05:51:08 ralf Exp $ + * $Id: r2300.c,v 1.5 1998/05/01 01:34:55 ralf Exp $ */ - +#include #include #include #include @@ -253,7 +253,12 @@ */ } -void ld_mmu_r2300(void) +static int r2300_user_mode(struct pt_regs *regs) +{ + return !(regs->cp0_status & 0x4); +} + +__initfunc(void ld_mmu_r2300(void)) { clear_page = r2300_clear_page; copy_page = r2300_copy_page; @@ -278,5 +283,6 @@ add_wired_entry = r2300_add_wired_entry; + user_mode = r2300_user_mode; flush_tlb_all(); } diff -u --recursive --new-file v2.1.100/linux/arch/mips/mm/r4xx0.c linux/arch/mips/mm/r4xx0.c --- v2.1.100/linux/arch/mips/mm/r4xx0.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/mm/r4xx0.c Fri May 8 00:13:24 1998 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r4xx0.c,v 1.11 1997/12/02 06:33:53 ralf Exp $ + * $Id: r4xx0.c,v 1.11 1998/05/04 09:18:31 ralf Exp $ * * To do: * @@ -11,13 +11,13 @@ * - many of the bug workarounds are not efficient at all, but at * least they are functional ... */ -#include - +#include #include #include #include -#include +#include +#include #include #include #include @@ -45,6 +45,18 @@ #undef DEBUG_CACHE /* + * Dummy cache handling routines for machines without boardcaches + */ +static void no_sc_noop(void) {} + +static struct bcache_ops no_sc_ops = { + (void *)no_sc_noop, (void *)no_sc_noop, + (void *)no_sc_noop, (void *)no_sc_noop +}; + +struct bcache_ops *bcops = &no_sc_ops; + +/* * On processors with QED R4600 style two set assosicative cache * this is the bit which selects the way in the cache for the * indexed cachops. @@ -53,9 +65,19 @@ #define dcache_waybit (dcache_size >> 1) /* - * Zero an entire page. We have three flavours of the routine available. - * One for CPU with 16byte, with 32byte cachelines plus a special version - * with nops which handles the buggy R4600 v1.x. + * Zero an entire page. Basically a simple unrolled loop should do the + * job but we want more performance by saving memory bus bandwidth. We + * have five flavours of the routine available for: + * + * - 16byte cachelines and no second level cache + * - 32byte cachelines second level cache + * - a version which handles the buggy R4600 v1.x + * - a version which handles the buggy R4600 v2.0 + * - Finally a last version without fancy cache games for the SC and MC + * versions of R4000 and R4400. Cache instructions are quite expensive + * and I guess using them for both the primary and the second level cache + * wouldn't be worth the effort. + * This needs to be verified by benchmarking. */ static void r4k_clear_page_d16(unsigned long page) @@ -219,6 +241,32 @@ restore_flags(flags); } +static void r4k_clear_page(unsigned long page) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "daddiu\t$1,%0,%2\n" + "1:\tsd\t$0,(%0)\n\t" + "sd\t$0,8(%0)\n\t" + "sd\t$0,16(%0)\n\t" + "sd\t$0,24(%0)\n\t" + "daddiu\t%0,64\n\t" + "sd\t$0,-32(%0)\n\t" + "sd\t$0,-24(%0)\n\t" + "sd\t$0,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sd\t$0,-8(%0)\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (page) + :"0" (page), + "I" (PAGE_SIZE) + :"$1","memory"); +} + /* * This is still inefficient. We only can do better if we know the @@ -477,6 +525,60 @@ restore_flags(flags); } +static void r4k_copy_page(unsigned long to, unsigned long from) +{ + unsigned long dummy1, dummy2; + unsigned long reg1, reg2, reg3, reg4; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "daddiu\t$1,%0,%8\n" + "1:\tlw\t%2,(%1)\n\t" + "lw\t%3,4(%1)\n\t" + "lw\t%4,8(%1)\n\t" + "lw\t%5,12(%1)\n\t" + "sw\t%2,(%0)\n\t" + "sw\t%3,4(%0)\n\t" + "sw\t%4,8(%0)\n\t" + "sw\t%5,12(%0)\n\t" + "lw\t%2,16(%1)\n\t" + "lw\t%3,20(%1)\n\t" + "lw\t%4,24(%1)\n\t" + "lw\t%5,28(%1)\n\t" + "sw\t%2,16(%0)\n\t" + "sw\t%3,20(%0)\n\t" + "sw\t%4,24(%0)\n\t" + "sw\t%5,28(%0)\n\t" + "daddiu\t%0,64\n\t" + "daddiu\t%1,64\n\t" + "lw\t%2,-32(%1)\n\t" + "lw\t%3,-28(%1)\n\t" + "lw\t%4,-24(%1)\n\t" + "lw\t%5,-20(%1)\n\t" + "sw\t%2,-32(%0)\n\t" + "sw\t%3,-28(%0)\n\t" + "sw\t%4,-24(%0)\n\t" + "sw\t%5,-20(%0)\n\t" + "lw\t%2,-16(%1)\n\t" + "lw\t%3,-12(%1)\n\t" + "lw\t%4,-8(%1)\n\t" + "lw\t%5,-4(%1)\n\t" + "sw\t%2,-16(%0)\n\t" + "sw\t%3,-12(%0)\n\t" + "sw\t%4,-8(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sw\t%5,-4(%0)\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (dummy1), "=r" (dummy2), + "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) + :"0" (to), "1" (from), + "I" (PAGE_SIZE)); +} + /* * If you think for one second that this stuff coming up is a lot * of bulky code eating too many kernel cache lines. Think _again_. @@ -1892,144 +1994,111 @@ * in .pdf format.) */ static void -r4k_flush_cache_pre_dma_out_pc(unsigned long addr, unsigned long size) +r4k_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size) { unsigned long end, a; - unsigned int cmode, flags; - - cmode = read_32bit_cp0_register(CP0_CONFIG) & CONFIG_CM_CMASK; - if (cmode == CONFIG_CM_CACHABLE_WA || - cmode == CONFIG_CM_CACHABLE_NO_WA) { - /* primary dcache is writethrough, therefore memory - is already consistent with the caches. */ - return; - } + unsigned int flags; if (size >= dcache_size) { flush_cache_all(); - return; - } - - /* Workaround for R4600 bug. See comment above. */ - save_and_cli(flags); - *(volatile unsigned long *)KSEG1; + } else { + /* Workaround for R4600 bug. See comment above. */ + save_and_cli(flags); + *(volatile unsigned long *)KSEG1; - a = addr & ~(dc_lsize - 1); - end = (addr + size) & ~(dc_lsize - 1); - while (1) { - flush_dcache_line(a); /* Hit_Writeback_Inv_D */ - if (a == end) break; - a += dc_lsize; + a = addr & ~(dc_lsize - 1); + end = (addr + size) & ~(dc_lsize - 1); + while (1) { + flush_dcache_line(a); /* Hit_Writeback_Inv_D */ + if (a == end) break; + a += dc_lsize; + } + restore_flags(flags); } - restore_flags(flags); + bcops->bc_wback_inv(addr, size); } static void -r4k_flush_cache_pre_dma_out_sc(unsigned long addr, unsigned long size) +r4k_dma_cache_wback_inv_sc(unsigned long addr, unsigned long size) { - unsigned long end; - unsigned long a; + unsigned long end, a; + unsigned int flags; if (size >= scache_size) { flush_cache_all(); - return; + } else { + save_and_cli(flags); + a = addr & ~(dc_lsize - 1); + end = (addr + size) & ~(dc_lsize - 1); + while (1) { + flush_dcache_line(a); /* Hit_Writeback_Inv_D */ + if (a == end) break; + a += dc_lsize; + } + restore_flags(flags); } a = addr & ~(sc_lsize - 1); end = (addr + size) & ~(sc_lsize - 1); while (1) { - flush_scache_line(addr); /* Hit_Writeback_Inv_SD */ - if (addr == end) break; - addr += sc_lsize; + flush_scache_line(a); /* Hit_Writeback_Inv_SD */ + if (a == end) break; + a += sc_lsize; } - r4k_flush_cache_pre_dma_out_pc(addr, size); } static void -r4k_flush_cache_post_dma_in_pc(unsigned long addr, unsigned long size) +r4k_dma_cache_inv_pc(unsigned long addr, unsigned long size) { - unsigned long end; - unsigned long a; + unsigned long end, a; + unsigned int flags; if (size >= dcache_size) { flush_cache_all(); - return; - } - - /* Workaround for R4600 bug. See comment above. */ - *(volatile unsigned long *)KSEG1; + } else { + /* Workaround for R4600 bug. See comment above. */ + save_and_cli(flags); + *(volatile unsigned long *)KSEG1; - a = addr & ~(dc_lsize - 1); - end = (addr + size) & ~(dc_lsize - 1); - while (1) { - invalidate_dcache_line(a); /* Hit_Invalidate_D */ - if (a == end) break; - a += dc_lsize; + a = addr & ~(dc_lsize - 1); + end = (addr + size) & ~(dc_lsize - 1); + while (1) { + flush_dcache_line(a); /* Hit_Writeback_Inv_D */ + if (a == end) break; + a += dc_lsize; + } + restore_flags(flags); } + + bcops->bc_inv(addr, size); } static void -r4k_flush_cache_post_dma_in_sc(unsigned long addr, unsigned long size) +r4k_dma_cache_inv_sc(unsigned long addr, unsigned long size) { - unsigned long end; - unsigned long a; + unsigned long end, a; + unsigned int flags; if (size >= scache_size) { flush_cache_all(); - return; + } else { + save_and_cli(flags); + a = addr & ~(dc_lsize - 1); + end = (addr + size) & ~(dc_lsize - 1); + while (1) { + flush_dcache_line(a); /* Hit_Writeback_Inv_D */ + if (a == end) break; + a += dc_lsize; + } + restore_flags(flags); } a = addr & ~(sc_lsize - 1); end = (addr + size) & ~(sc_lsize - 1); while (1) { - invalidate_scache_line(addr); /* Hit_Invalidate_SD */ - if (addr == end) break; - addr += sc_lsize; - } - r4k_flush_cache_pre_dma_out_pc(addr, size); -} - -static void r4k_flush_page_to_ram_d32i32_r4600(unsigned long page) -{ - page &= PAGE_MASK; - if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) { - unsigned long flags; - -#ifdef DEBUG_CACHE - printk("r4600_cram[%08lx]", page); -#endif - save_and_cli(flags); - blast_dcache32_page(page); -#ifdef CONFIG_SGI - { - unsigned long tmp1, tmp2; - - __asm__ __volatile__(" - .set noreorder - .set mips3 - li %0, 0x1 - dsll %0, 31 - or %0, %0, %2 - lui %1, 0x9000 - dsll32 %1, 0 - or %0, %0, %1 - daddu %1, %0, 0x0fe0 - li %2, 0x80 - mtc0 %2, $12 - nop; nop; nop; nop; -1: sw $0, 0(%0) - bltu %0, %1, 1b - daddu %0, 32 - mtc0 $0, $12 - nop; nop; nop; nop; - .set mips0 - .set reorder" - : "=&r" (tmp1), "=&r" (tmp2), - "=&r" (page) - : "2" (page & 0x0007f000)); - } -#endif /* CONFIG_SGI */ - restore_flags(flags); + flush_scache_line(a); /* Hit_Writeback_Inv_SD */ + if (a == end) break; + a += sc_lsize; } } @@ -2394,173 +2463,31 @@ } /* Detect and size the various r4k caches. */ -static void probe_icache(unsigned long config) +__initfunc(static void probe_icache(unsigned long config)) { - unsigned long tmp; - - tmp = (config >> 9) & 7; - icache_size = (1 << (12 + tmp)); - if((config >> 5) & 1) - ic_lsize = 32; - else - ic_lsize = 16; + icache_size = 1 << (12 + ((config >> 6) & 7)); + ic_lsize = 16 << ((config >> 4) & 1); - printk("Primary ICACHE %dK (linesize %d bytes)\n", - (int)(icache_size >> 10), (int)ic_lsize); + printk("Primary instruction cache %dkb, linesize %d bytes)\n", + icache_size >> 10, ic_lsize); } -static void probe_dcache(unsigned long config) +__initfunc(static void probe_dcache(unsigned long config)) { - unsigned long tmp; + dcache_size = 1 << (12 + ((config >> 6) & 7)); + dc_lsize = 16 << ((config >> 4) & 1); - tmp = (config >> 6) & 7; - dcache_size = (1 << (12 + tmp)); - if((config >> 4) & 1) - dc_lsize = 32; - else - dc_lsize = 16; - - printk("Primary DCACHE %dK (linesize %d bytes)\n", - (int)(dcache_size >> 10), (int)dc_lsize); + printk("Primary data cache %dkb, linesize %d bytes)\n", + dcache_size >> 10, dc_lsize); } -static int probe_scache_eeprom(unsigned long config) -{ -#ifdef CONFIG_SGI - volatile unsigned int *cpu_control; - unsigned short cmd = 0xc220; - unsigned long data = 0; - int i, n; - -#ifdef __MIPSEB__ - cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00034); -#else - cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00030); -#endif -#define DEASSERT(bit) (*(cpu_control) &= (~(bit))) -#define ASSERT(bit) (*(cpu_control) |= (bit)) -#define DELAY for(n = 0; n < 100000; n++) __asm__ __volatile__("") - DEASSERT(SGIMC_EEPROM_PRE); - DEASSERT(SGIMC_EEPROM_SDATAO); - DEASSERT(SGIMC_EEPROM_SECLOCK); - DEASSERT(SGIMC_EEPROM_PRE); - DELAY; - ASSERT(SGIMC_EEPROM_CSEL); ASSERT(SGIMC_EEPROM_SECLOCK); - for(i = 0; i < 11; i++) { - if(cmd & (1<<15)) - ASSERT(SGIMC_EEPROM_SDATAO); - else - DEASSERT(SGIMC_EEPROM_SDATAO); - DEASSERT(SGIMC_EEPROM_SECLOCK); - ASSERT(SGIMC_EEPROM_SECLOCK); - cmd <<= 1; - } - DEASSERT(SGIMC_EEPROM_SDATAO); - for(i = 0; i < (sizeof(unsigned short) * 8); i++) { - unsigned int tmp; - - DEASSERT(SGIMC_EEPROM_SECLOCK); - DELAY; - ASSERT(SGIMC_EEPROM_SECLOCK); - DELAY; - data <<= 1; - tmp = *cpu_control; - if(tmp & SGIMC_EEPROM_SDATAI) - data |= 1; - } - DEASSERT(SGIMC_EEPROM_SECLOCK); - DEASSERT(SGIMC_EEPROM_CSEL); - ASSERT(SGIMC_EEPROM_PRE); - ASSERT(SGIMC_EEPROM_SECLOCK); - data <<= PAGE_SHIFT; - printk("R4600/R5000 SCACHE size %dK ", (int) (data >> 10)); - switch(mips_cputype) { - case CPU_R4600: - case CPU_R4640: - sc_lsize = 32; - break; - - default: - sc_lsize = 128; - break; - } - printk("linesize %d bytes\n", sc_lsize); - scache_size = data; - if(data) { - unsigned long addr, tmp1, tmp2; - - /* Enable r4600/r5000 cache. But flush it first. */ - for(addr = KSEG0; addr < (KSEG0 + dcache_size); - addr += dc_lsize) - flush_dcache_line_indexed(addr); - for(addr = KSEG0; addr < (KSEG0 + icache_size); - addr += ic_lsize) - flush_icache_line_indexed(addr); - for(addr = KSEG0; addr < (KSEG0 + scache_size); - addr += sc_lsize) - flush_scache_line_indexed(addr); - - /* R5000 scache enable is in CP0 config, on R4600 variants - * the scache is enable by the memory mapped cache controller. - */ - if(mips_cputype == CPU_R5000) { - unsigned long config; - - config = read_32bit_cp0_register(CP0_CONFIG); - config |= 0x1000; - write_32bit_cp0_register(CP0_CONFIG, config); - } else { - /* This is really cool... */ - printk("Enabling R4600 SCACHE\n"); - __asm__ __volatile__(" - .set noreorder - .set mips3 - mfc0 %2, $12 - nop; nop; nop; nop; - li %1, 0x80 - mtc0 %1, $12 - nop; nop; nop; nop; - li %0, 0x1 - dsll %0, 31 - lui %1, 0x9000 - dsll32 %1, 0 - or %0, %1, %0 - sb $0, 0(%0) - mtc0 $0, $12 - nop; nop; nop; nop; - mtc0 %2, $12 - nop; nop; nop; nop; - .set mips0 - .set reorder - " : "=r" (tmp1), "=r" (tmp2), "=r" (addr)); - } - - return 1; - } else { - if(mips_cputype == CPU_R5000) - return -1; - else - return 0; - } -#else - /* - * XXX For now we don't panic and assume that existing chipset - * controlled caches are setup correnctly and are completly - * transparent. Works fine for those MIPS machines I know. - * Morituri the salutant ... - */ - return 0; - - panic("Cannot probe SCACHE on this machine."); -#endif -} /* If you even _breathe_ on this function, look at the gcc output * and make sure it does not pop things on and off the stack for * the cache sizing loop that executes in KSEG1 space or else * you will crash and burn badly. You have been warned. */ -static int probe_scache(unsigned long config) +__initfunc(static int probe_scache(unsigned long config)) { extern unsigned long stext; unsigned long flags, addr, begin, end, pow2; @@ -2644,7 +2571,7 @@ return 1; } -static void setup_noscache_funcs(void) +__initfunc(static void setup_noscache_funcs(void)) { unsigned int prid; @@ -2677,18 +2604,16 @@ flush_page_to_ram = r4k_flush_page_to_ram_d32i32; break; } - flush_cache_pre_dma_out = r4k_flush_cache_pre_dma_out_pc; - flush_cache_post_dma_in = r4k_flush_cache_post_dma_in_pc; + dma_cache_wback_inv = r4k_dma_cache_wback_inv_pc; + dma_cache_inv = r4k_dma_cache_inv_pc; } -static void setup_scache_funcs(void) +__initfunc(static void setup_scache_funcs(void)) { switch(sc_lsize) { case 16: switch(dc_lsize) { case 16: - clear_page = r4k_clear_page_d16; - copy_page = r4k_copy_page_d16; flush_cache_all = r4k_flush_cache_all_s16d16i16; flush_cache_mm = r4k_flush_cache_mm_s16d16i16; flush_cache_range = r4k_flush_cache_range_s16d16i16; @@ -2696,8 +2621,6 @@ flush_page_to_ram = r4k_flush_page_to_ram_s16d16i16; break; case 32: - clear_page = r4k_clear_page_d32; - copy_page = r4k_copy_page_d32; flush_cache_all = r4k_flush_cache_all_s16d32i32; flush_cache_mm = r4k_flush_cache_mm_s16d32i32; flush_cache_range = r4k_flush_cache_range_s16d32i32; @@ -2709,8 +2632,6 @@ case 32: switch(dc_lsize) { case 16: - clear_page = r4k_clear_page_d16; - copy_page = r4k_copy_page_d16; flush_cache_all = r4k_flush_cache_all_s32d16i16; flush_cache_mm = r4k_flush_cache_mm_s32d16i16; flush_cache_range = r4k_flush_cache_range_s32d16i16; @@ -2718,8 +2639,6 @@ flush_page_to_ram = r4k_flush_page_to_ram_s32d16i16; break; case 32: - clear_page = r4k_clear_page_d32; - copy_page = r4k_copy_page_d32; flush_cache_all = r4k_flush_cache_all_s32d32i32; flush_cache_mm = r4k_flush_cache_mm_s32d32i32; flush_cache_range = r4k_flush_cache_range_s32d32i32; @@ -2730,8 +2649,6 @@ case 64: switch(dc_lsize) { case 16: - clear_page = r4k_clear_page_d16; - copy_page = r4k_copy_page_d16; flush_cache_all = r4k_flush_cache_all_s64d16i16; flush_cache_mm = r4k_flush_cache_mm_s64d16i16; flush_cache_range = r4k_flush_cache_range_s64d16i16; @@ -2739,8 +2656,6 @@ flush_page_to_ram = r4k_flush_page_to_ram_s64d16i16; break; case 32: - clear_page = r4k_clear_page_d32; - copy_page = r4k_copy_page_d32; flush_cache_all = r4k_flush_cache_all_s64d32i32; flush_cache_mm = r4k_flush_cache_mm_s64d32i32; flush_cache_range = r4k_flush_cache_range_s64d32i32; @@ -2751,8 +2666,6 @@ case 128: switch(dc_lsize) { case 16: - clear_page = r4k_clear_page_d16; - copy_page = r4k_copy_page_d16; flush_cache_all = r4k_flush_cache_all_s128d16i16; flush_cache_mm = r4k_flush_cache_mm_s128d16i16; flush_cache_range = r4k_flush_cache_range_s128d16i16; @@ -2760,8 +2673,6 @@ flush_page_to_ram = r4k_flush_page_to_ram_s128d16i16; break; case 32: - clear_page = r4k_clear_page_d32; - copy_page = r4k_copy_page_d32; flush_cache_all = r4k_flush_cache_all_s128d32i32; flush_cache_mm = r4k_flush_cache_mm_s128d32i32; flush_cache_range = r4k_flush_cache_range_s128d32i32; @@ -2771,77 +2682,57 @@ }; break; } - - /* XXX Do these for Indy style caches also. No need for now ... */ - flush_cache_pre_dma_out = r4k_flush_cache_pre_dma_out_sc; - flush_cache_post_dma_in = r4k_flush_cache_post_dma_in_sc; + clear_page = r4k_clear_page; + copy_page = r4k_copy_page; + dma_cache_wback_inv = r4k_dma_cache_wback_inv_sc; + dma_cache_inv = r4k_dma_cache_inv_sc; } typedef int (*probe_func_t)(unsigned long); -static probe_func_t probe_scache_kseg1; -void ld_mmu_r4xx0(void) +__initfunc(static inline void setup_scache(unsigned int config)) { - unsigned long cfg = read_32bit_cp0_register(CP0_CONFIG); + probe_func_t probe_scache_kseg1; int sc_present = 0; + /* Maybe the cpu knows about a l2 cache? */ + probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache)); + sc_present = probe_scache_kseg1(config); + + if (sc_present) { + setup_scache_funcs(); + return; + } + + setup_noscache_funcs(); +} + +static int r4k_user_mode(struct pt_regs *regs) +{ + return (regs->cp0_status & ST0_KSU) == KSU_USER; +} + + +__initfunc(void ld_mmu_r4xx0(void)) +{ + unsigned long config = read_32bit_cp0_register(CP0_CONFIG); + printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID)); set_cp0_config(CONFIG_CM_CMASK, CONFIG_CM_CACHABLE_NONCOHERENT); -//set_cp0_config(CONFIG_CM_CMASK, CONFIG_CM_CACHABLE_WA); -//set_cp0_config(CONFIG_CM_CMASK, CONFIG_CM_CACHABLE_NO_WA); - probe_icache(cfg); - probe_dcache(cfg); + probe_icache(config); + probe_dcache(config); + setup_scache(config); switch(mips_cputype) { - case CPU_R4000PC: - case CPU_R4000SC: - case CPU_R4000MC: - case CPU_R4400PC: - case CPU_R4400SC: - case CPU_R4400MC: - probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache)); - sc_present = probe_scache_kseg1(cfg); - break; - - case CPU_R4600: - case CPU_R4640: + case CPU_R4600: /* QED style two way caches? */ case CPU_R4700: - case CPU_R5000: /* XXX: We don't handle the true R5000 SCACHE */ + case CPU_R5000: case CPU_NEVADA: - probe_scache_kseg1 = (probe_func_t) - (KSEG1ADDR(&probe_scache_eeprom)); - sc_present = probe_scache_eeprom(cfg); - - /* Try using tags if eeprom gives us bogus data. */ - if(sc_present == -1) { - probe_scache_kseg1 = - (probe_func_t) (KSEG1ADDR(&probe_scache)); - sc_present = probe_scache_kseg1(cfg); - } - break; - }; - - if(sc_present == 1 - && (mips_cputype == CPU_R4000SC - || mips_cputype == CPU_R4000MC - || mips_cputype == CPU_R4400SC - || mips_cputype == CPU_R4400MC)) { - /* Has a true secondary cache. */ - setup_scache_funcs(); - } else { - /* Lacks true secondary cache. */ - setup_noscache_funcs(); - if((mips_cputype != CPU_R5000)) { /* XXX */ - flush_cache_page = - r4k_flush_cache_page_d32i32_r4600; - flush_page_to_ram = - r4k_flush_page_to_ram_d32i32_r4600; - } + flush_cache_page = r4k_flush_cache_page_d32i32_r4600; } - /* XXX Handle true second level cache w/ split I/D */ flush_cache_sigtramp = r4k_flush_cache_sigtramp; if ((read_32bit_cp0_register(CP0_PRID) & 0xfff0) == 0x2020) { flush_cache_sigtramp = r4600v20k_flush_cache_sigtramp; @@ -2859,6 +2750,8 @@ show_regs = r4k_show_regs; add_wired_entry = r4k_add_wired_entry; + + user_mode = r4k_user_mode; flush_cache_all(); write_32bit_cp0_register(CP0_WIRED, 0); diff -u --recursive --new-file v2.1.100/linux/arch/mips/mm/r6000.c linux/arch/mips/mm/r6000.c --- v2.1.100/linux/arch/mips/mm/r6000.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/mm/r6000.c Fri May 8 00:13:24 1998 @@ -1,9 +1,9 @@ -/* $Id: r6000.c,v 1.2 1997/12/02 05:51:08 ralf Exp $ +/* $Id: r6000.c,v 1.4 1998/05/01 01:35:06 ralf Exp $ * r6000.c: MMU and cache routines for the R6000 processors. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) */ - +#include #include #include #include @@ -162,7 +162,12 @@ /* XXX */ } -void ld_mmu_r6000(void) +static int r6000_user_mode(struct pt_regs *regs) +{ + return !(regs->cp0_status & 0x4); +} + +__initfunc(void ld_mmu_r6000(void)) { flush_cache_all = r6000_flush_cache_all; flush_cache_mm = r6000_flush_cache_mm; @@ -183,6 +188,8 @@ show_regs = r6000_show_regs; add_wired_entry = r6000_add_wired_entry; + + user_mode = r6000_user_mode; flush_cache_all(); flush_tlb_all(); diff -u --recursive --new-file v2.1.100/linux/arch/mips/mm/tfp.c linux/arch/mips/mm/tfp.c --- v2.1.100/linux/arch/mips/mm/tfp.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/mm/tfp.c Fri May 8 00:13:24 1998 @@ -1,9 +1,10 @@ -/* $Id: tfp.c,v 1.2 1997/12/02 05:51:09 ralf Exp $ +/* * tfp.c: MMU and cache routines specific to the r8000 (TFP). * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * */ - +#include #include #include #include @@ -85,7 +86,12 @@ /* XXX */ } -void ld_mmu_tfp(void) +static int tfp_user_mode(struct pt_regs *regs) +{ + return (regs->cp0_status & ST0_KSU) == KSU_USER; +} + +__initfunc(void ld_mmu_tfp(void)) { flush_cache_all = tfp_flush_cache_all; flush_cache_mm = tfp_flush_cache_mm; @@ -101,10 +107,11 @@ add_wired_entry = tfp_add_wired_entry; + user_mode = tfp_user_mode; + load_pgd = tfp_load_pgd; pgd_init = tfp_pgd_init; flush_cache_all(); flush_tlb_all(); } - diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/Makefile linux/arch/mips/sgi/kernel/Makefile --- v2.1.100/linux/arch/mips/sgi/kernel/Makefile Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/kernel/Makefile Fri May 8 00:13:25 1998 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ +# $Id: Makefile,v 1.2 1998/05/01 01:35:13 ralf Exp $ # Makefile for the SGI specific kernel interface routines # under Linux. # @@ -13,8 +13,8 @@ .S.o: $(CC) $(CFLAGS) -c $< -o $*.o -OBJS = indy_mc.o indy_hpc.o indy_int.o system.o indy_timer.o indyIRQ.o \ - reset.o setup.o time.o +OBJS = indy_mc.o indy_sc.o indy_hpc.o indy_int.o system.o indy_timer.o \ + indyIRQ.o reset.o setup.o time.o all: sgikern.a diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/indyIRQ.S linux/arch/mips/sgi/kernel/indyIRQ.S --- v2.1.100/linux/arch/mips/sgi/kernel/indyIRQ.S Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/kernel/indyIRQ.S Fri May 8 00:13:25 1998 @@ -1,4 +1,4 @@ -/* $Id: indyIRQ.S,v 1.2 1997/09/20 19:20:14 root Exp $ +/* $Id: indyIRQ.S,v 1.3 1998/05/01 01:35:14 ralf Exp $ * indyIRQ.S: Interrupt exception dispatch code for FullHouse and * Guiness. * @@ -68,7 +68,6 @@ /* Wheee, a timer interrupt. */ move a0, sp - addiu t0, s7, 1 jal indy_timer_interrupt nop # delay slot @@ -117,7 +116,6 @@ */ andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5) beq a0, zero, 1f - addiu t0, s7, 1 /* Must be one of the 8254 timers... */ move a0, sp diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/indy_hpc.c linux/arch/mips/sgi/kernel/indy_hpc.c --- v2.1.100/linux/arch/mips/sgi/kernel/indy_hpc.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/kernel/indy_hpc.c Fri May 8 00:13:25 1998 @@ -1,8 +1,11 @@ -/* $Id: indy_hpc.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ +/* * indy_hpc.c: Routines for generic manipulation of the HPC controllers. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: indy_hpc.c,v 1.2 1998/05/01 01:35:14 ralf Exp $ */ +#include #include #include @@ -38,7 +41,7 @@ hpc3mregs->write2 = write2; } -void sgihpc_init(void) +__initfunc(void sgihpc_init(void)) { unsigned long sid, crev, brev; diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/indy_int.c linux/arch/mips/sgi/kernel/indy_int.c --- v2.1.100/linux/arch/mips/sgi/kernel/indy_int.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/kernel/indy_int.c Fri May 8 00:13:25 1998 @@ -4,10 +4,10 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: indy_int.c,v 1.4 1997/09/20 19:20:15 root Exp $ + * $Id: indy_int.c,v 1.6 1998/05/01 01:35:15 ralf Exp $ */ #include - +#include #include #include #include @@ -55,6 +55,7 @@ extern void rs_kgdb_hook(int); #endif +unsigned int local_bh_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; @@ -230,7 +231,7 @@ if (!action) continue; len += sprintf(buf+len, "%2d: %8d %c %s", - num, kstat.interrupts[num], + num, kstat.irqs[0][num], (action->flags & SA_INTERRUPT) ? '+' : ' ', action->name); for (action=action->next; action; action = action->next) { @@ -245,7 +246,7 @@ if (!action) continue; len += sprintf(buf+len, "%2d: %8d %c %s", - num, kstat.interrupts[num], + num, kstat.irqs[0][num], (action->flags & SA_INTERRUPT) ? '+' : ' ', action->name); for (action=action->next; action; action = action->next) { @@ -274,7 +275,7 @@ cpu = smp_processor_id(); irq_enter(cpu, irq); - kstat.interrupts[irq]++; + kstat.irqs[0][irq]++; printk("Got irq %d, press a key.", irq); prom_getchar(); @@ -416,7 +417,7 @@ printk("Trying to free free IRQ%d\n",irq); } -void init_IRQ(void) +__initfunc(void init_IRQ(void)) { irq_setup(); } @@ -440,7 +441,7 @@ } irq_enter(cpu, irq); - kstat.interrupts[irq + 16]++; + kstat.irqs[0][irq + 16]++; action->handler(irq, action->dev_id, regs); irq_exit(cpu, irq); } @@ -464,7 +465,7 @@ action = local_irq_action[irq]; } irq_enter(cpu, irq); - kstat.interrupts[irq + 24]++; + kstat.irqs[0][irq + 24]++; action->handler(irq, action->dev_id, regs); irq_exit(cpu, irq); } @@ -475,7 +476,7 @@ int irq = 6; irq_enter(cpu, irq); - kstat.interrupts[irq]++; + kstat.irqs[0][irq]++; printk("Got a bus error IRQ, shouldn't happen yet\n"); show_regs(regs); printk("Spinning...\n"); @@ -494,7 +495,7 @@ return 0; } -void sgint_init(void) +__initfunc(void sgint_init(void)) { int i; #ifdef CONFIG_REMOTE_DEBUG diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/indy_mc.c linux/arch/mips/sgi/kernel/indy_mc.c --- v2.1.100/linux/arch/mips/sgi/kernel/indy_mc.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/kernel/indy_mc.c Fri May 8 00:13:25 1998 @@ -1,8 +1,12 @@ -/* $Id: indy_mc.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ +/* * indy_mc.c: Routines for manipulating the INDY memory controller. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: indy_mc.c,v 1.3 1998/05/04 09:18:37 ralf Exp $ */ +#include +#include #include #include @@ -43,7 +47,7 @@ }; } -void sgimc_init(void) +__initfunc(void sgimc_init(void)) { unsigned long tmpreg; diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/indy_sc.c linux/arch/mips/sgi/kernel/indy_sc.c --- v2.1.100/linux/arch/mips/sgi/kernel/indy_sc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/kernel/indy_sc.c Fri May 8 00:13:25 1998 @@ -0,0 +1,227 @@ +/* + * indy_sc.c: Indy cache managment functions. + * + * Copyright (C) 1997 Ralf Baechle (ralf@gnu.org), + * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com). + * + * $Id: indy_sc.c,v 1.4 1998/05/04 09:12:57 ralf Exp $ + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Secondary cache size in bytes, if present. */ +static unsigned long scache_size; + +#undef DEBUG_CACHE + +#define SC_SIZE 0x00080000 +#define SC_LINE 32 +#define CI_MASK (SC_SIZE - SC_LINE) +#define SC_ROUND(n) ((n) + SC_LINE - 1) +#define SC_INDEX(n) ((n) & CI_MASK) + +static inline void indy_sc_wipe(unsigned long first, unsigned long last) +{ + __asm__ __volatile__(" + .set noreorder + .set mips3 + .set noat + li $1, 0x80 # Go 64 bit + mtc0 $1, $12 + + dli $1, 0x9000000080000000 + or %0, $1 # first line to flush + or %1, $1 # last line to flush + .set at + +1: sw $0, 0(%0) + bne %0, %1, 1b + daddu %0, 32 + + mtc0 $0, $12 # Back to 32 bit + nop; nop; nop; nop; + .set mips0 + .set reorder" + : "=r" (first), "=r" (last) + : "0" (first), "1" (last) + : "$1"); +} + +static void indy_sc_wback_invalidate(unsigned long addr, unsigned long size) +{ + unsigned long first_line, last_line; + unsigned int flags; + +#ifdef DEBUG_CACHE + printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size); +#endif + /* Which lines to flush? */ + first_line = SC_INDEX(addr); + last_line = SC_INDEX(SC_ROUND(addr + size)); + + __save_and_cli(flags); + if (first_line <= last_line) { + indy_sc_wipe(first_line, last_line); + goto out; + } + + /* Cache index wrap around. Due to the way the buddy system works + this case should not happen. We're prepared to handle it, + though. */ + indy_sc_wipe(last_line, SC_SIZE); + indy_sc_wipe(0, first_line); +out: + __restore_flags(flags); +} + +static void indy_sc_enable(void) +{ + unsigned long addr, tmp1, tmp2; + + /* This is really cool... */ +#ifdef DEBUG_CACHE + printk("Enabling R4600 SCACHE\n"); +#endif + __asm__ __volatile__(" + .set noreorder + .set mips3 + mfc0 %2, $12 + nop; nop; nop; nop; + li %1, 0x80 + mtc0 %1, $12 + nop; nop; nop; nop; + li %0, 0x1 + dsll %0, 31 + lui %1, 0x9000 + dsll32 %1, 0 + or %0, %1, %0 + sb $0, 0(%0) + mtc0 $0, $12 + nop; nop; nop; nop; + mtc0 %2, $12 + nop; nop; nop; nop; + .set mips0 + .set reorder" + : "=r" (tmp1), "=r" (tmp2), "=r" (addr)); +} + +static void indy_sc_disable(void) +{ + unsigned long tmp1, tmp2, tmp3; + +#ifdef DEBUG_CACHE + printk("Disabling R4600 SCACHE\n"); +#endif + __asm__ __volatile__(" + .set noreorder + .set mips3 + li %0, 0x1 + dsll %0, 31 + lui %1, 0x9000 + dsll32 %1, 0 + or %0, %1, %0 + mfc0 %2, $12 + nop; nop; nop; nop; + li %1, 0x80 + mtc0 %1, $12 + nop; nop; nop; nop; + sh $0, 0(%0) + mtc0 $0, $12 + nop; nop; nop; nop; + mtc0 %2, $12 + nop; nop; nop; nop; + .set mips2 + .set reorder + " : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)); +} + +__initfunc(static inline int indy_sc_probe(void)) +{ + volatile unsigned int *cpu_control; + unsigned short cmd = 0xc220; + unsigned long data = 0; + int i, n; + +#ifdef __MIPSEB__ + cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00034); +#else + cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00030); +#endif +#define DEASSERT(bit) (*(cpu_control) &= (~(bit))) +#define ASSERT(bit) (*(cpu_control) |= (bit)) +#define DELAY for(n = 0; n < 100000; n++) __asm__ __volatile__("") + DEASSERT(SGIMC_EEPROM_PRE); + DEASSERT(SGIMC_EEPROM_SDATAO); + DEASSERT(SGIMC_EEPROM_SECLOCK); + DEASSERT(SGIMC_EEPROM_PRE); + DELAY; + ASSERT(SGIMC_EEPROM_CSEL); ASSERT(SGIMC_EEPROM_SECLOCK); + for(i = 0; i < 11; i++) { + if(cmd & (1<<15)) + ASSERT(SGIMC_EEPROM_SDATAO); + else + DEASSERT(SGIMC_EEPROM_SDATAO); + DEASSERT(SGIMC_EEPROM_SECLOCK); + ASSERT(SGIMC_EEPROM_SECLOCK); + cmd <<= 1; + } + DEASSERT(SGIMC_EEPROM_SDATAO); + for(i = 0; i < (sizeof(unsigned short) * 8); i++) { + unsigned int tmp; + + DEASSERT(SGIMC_EEPROM_SECLOCK); + DELAY; + ASSERT(SGIMC_EEPROM_SECLOCK); + DELAY; + data <<= 1; + tmp = *cpu_control; + if(tmp & SGIMC_EEPROM_SDATAI) + data |= 1; + } + DEASSERT(SGIMC_EEPROM_SECLOCK); + DEASSERT(SGIMC_EEPROM_CSEL); + ASSERT(SGIMC_EEPROM_PRE); + ASSERT(SGIMC_EEPROM_SECLOCK); + + data <<= PAGE_SHIFT; + if (data == 0) + return 0; + + scache_size = data; + + printk("R4600/R5000 SCACHE size %ldK, linesize 32 bytes.\n", + scache_size >> 10); + + return 1; +} + +/* XXX Check with wje if the Indy caches can differenciate between + writeback + invalidate and just invalidate. */ +struct bcache_ops indy_sc_ops = { + indy_sc_enable, + indy_sc_disable, + indy_sc_wback_invalidate, + indy_sc_wback_invalidate +}; + +__initfunc(void indy_sc_init(void)) +{ + if (indy_sc_probe()) { + indy_sc_enable(); + bcops = &indy_sc_ops; + } +} diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/indy_timer.c linux/arch/mips/sgi/kernel/indy_timer.c --- v2.1.100/linux/arch/mips/sgi/kernel/indy_timer.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/kernel/indy_timer.c Fri May 8 00:13:25 1998 @@ -3,10 +3,10 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: indy_timer.c,v 1.3 1997/08/11 04:37:09 ralf Exp $ + * $Id: indy_timer.c,v 1.5 1998/05/01 01:35:17 ralf Exp $ */ - #include +#include #include #include #include @@ -98,15 +98,25 @@ } static long last_rtc_update = 0; +unsigned long missed_heart_beats = 0; void indy_timer_interrupt(struct pt_regs *regs) { + unsigned long count; int irq = 7; /* Ack timer and compute new compare. */ - r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset); + count = read_32bit_cp0_register(CP0_COUNT); + /* This has races. */ + if ((count - r4k_cur) >= r4k_offset) { + /* If this happens to often we'll need to compensate. */ + missed_heart_beats++; + r4k_cur = count + r4k_offset; + } + else + r4k_cur += r4k_offset; ack_r4ktimer(r4k_cur); - kstat.interrupts[irq]++; + kstat.irqs[0][irq]++; do_timer(regs); /* We update the Dallas time of day approx. every 11 minutes, @@ -123,8 +133,8 @@ last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ } -static inline unsigned long dosample(volatile unsigned char *tcwp, - volatile unsigned char *tc2p) +static unsigned long dosample(volatile unsigned char *tcwp, + volatile unsigned char *tc2p) { unsigned long ct0, ct1; unsigned char msb, lsb; @@ -138,16 +148,12 @@ ct0 = read_32bit_cp0_register(CP0_COUNT); /* Latch and spin until top byte of counter2 is zero */ - *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT); - ct1 = read_32bit_cp0_register(CP0_COUNT); - lsb = *tc2p; - msb = *tc2p; - while(msb) { + do { *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT); - ct1 = read_32bit_cp0_register(CP0_COUNT); lsb = *tc2p; msb = *tc2p; - } + ct1 = read_32bit_cp0_register(CP0_COUNT); + } while(msb); /* Stop the counter. */ *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MSWST); @@ -189,7 +195,7 @@ )*60 + sec; /* finally seconds */ } -unsigned long get_indy_time(void) +__initfunc(static unsigned long get_indy_time(void)) { struct indy_clock *clock = INDY_CLOCK_REGS; unsigned int year, mon, day, hour, min, sec; @@ -234,7 +240,7 @@ #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) -void indy_timer_init(void) +__initfunc(void indy_timer_init(void)) { struct sgi_ioc_timers *p; volatile unsigned char *tcwp, *tc2p; @@ -254,11 +260,9 @@ tc2p = &p->tcnt2; printk("calculating r4koff... "); - r4k_offset = dosample(tcwp, tc2p); /* First sample. */ - dosample(tcwp, tc2p); /* Eat one... */ - r4k_offset += dosample(tcwp, tc2p); /* Second sample. */ - r4k_offset = (r4k_offset >> 1); /* Get average. */ - r4k_offset = HZ * r4k_offset; /* Multiply by HZ */ + dosample(tcwp, tc2p); /* First sample. */ + dosample(tcwp, tc2p); /* Eat one. */ + r4k_offset = dosample(tcwp, tc2p); /* Second sample. */ printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); @@ -278,7 +282,7 @@ int irq = 4; irq_enter(cpu, irq); - kstat.interrupts[irq]++; + kstat.irqs[0][irq]++; printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n"); prom_getchar(); prom_imode(); @@ -303,4 +307,3 @@ time_esterror = MAXPHASE; sti(); } - diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/reset.c linux/arch/mips/sgi/kernel/reset.c --- v2.1.100/linux/arch/mips/sgi/kernel/reset.c Thu Jun 26 12:33:38 1997 +++ linux/arch/mips/sgi/kernel/reset.c Fri May 8 00:13:25 1998 @@ -1,25 +1,31 @@ /* - * linux/arch/mips/sgi/kernel/process.c - * * Reset a SGI. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1997, 1998 by Ralf Baechle + * + * $Id: reset.c,v 1.3 1998/05/01 01:35:18 ralf Exp $ */ #include #include #include +#include /* XXX How to pass the reboot command to the firmware??? */ void sgi_machine_restart(char *command) { - for(;;) - prom_imode(); + prom_reboot(); } void sgi_machine_halt(void) { - /* XXX */ + prom_imode(); } void sgi_machine_power_off(void) { - /* XXX */ + prom_powerdown(); } diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/setup.c linux/arch/mips/sgi/kernel/setup.c --- v2.1.100/linux/arch/mips/sgi/kernel/setup.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/kernel/setup.c Fri May 8 00:13:25 1998 @@ -3,12 +3,14 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: setup.c,v 1.5 1997/09/13 02:19:18 ralf Exp $ + * $Id: setup.c,v 1.5 1998/05/01 01:35:19 ralf Exp $ */ +#include #include #include #include +#include #include #include #include @@ -49,7 +51,7 @@ return sgi_kh->command; } -static void sgi_keyboard_setup(void) +__initfunc(static void sgi_keyboard_setup(void)) { kbd_read_input = sgi_read_input; kbd_write_output = sgi_write_output; @@ -57,12 +59,12 @@ kbd_read_status = sgi_read_status; } -static void sgi_irq_setup(void) +__initfunc(static void sgi_irq_setup(void)) { sgint_init(); } -void sgi_setup(void) +__initfunc(void sgi_setup(void)) { char *ctype; @@ -82,6 +84,9 @@ /* Init INDY memory controller. */ sgimc_init(); + + /* Now enable boardcaches, if any. */ + indy_sc_init(); /* ARCS console environment variable is set to "g?" for * graphics console, it is set to "d" for the first serial diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/system.c linux/arch/mips/sgi/kernel/system.c --- v2.1.100/linux/arch/mips/sgi/kernel/system.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/kernel/system.c Fri May 8 00:13:25 1998 @@ -3,8 +3,9 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: system.c,v 1.3 1997/09/13 02:19:18 ralf Exp $ + * $Id: system.c,v 1.4 1998/05/01 01:35:19 ralf Exp $ */ +#include #include #include #include @@ -56,7 +57,7 @@ #define NUM_CPUS 9 /* for now */ -static enum sgi_mach string_to_mach(char *s) +__initfunc(static enum sgi_mach string_to_mach(char *s)) { int i; @@ -71,7 +72,7 @@ return (enum sgi_mach) 0; } -static int string_to_cpu(char *s) +__initfunc(static int string_to_cpu(char *s)) { int i; @@ -90,7 +91,7 @@ * We' call this early before loadmmu(). If we do the other way around * the firmware will crash and burn. */ -void sgi_sysinit(void) +__initfunc(void sgi_sysinit(void)) { pcomponent *p, *toplev, *cpup = 0; int cputype = -1; diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/time.c linux/arch/mips/sgi/kernel/time.c --- v2.1.100/linux/arch/mips/sgi/kernel/time.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/kernel/time.c Fri May 8 00:13:25 1998 @@ -1,13 +1,14 @@ -/* $Id: time.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ +/* $Id: time.c,v 1.2 1998/05/01 01:35:20 ralf Exp $ * time.c: Generic SGI time_init() code, this will dispatch to the * appropriate per-architecture time/counter init code. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) */ +#include extern void indy_timer_init(void); -void time_init(void) +__initfunc(void time_init(void)) { /* XXX assume INDY for now XXX */ indy_timer_init(); diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/Makefile linux/arch/mips/sgi/prom/Makefile --- v2.1.100/linux/arch/mips/sgi/prom/Makefile Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/prom/Makefile Fri May 8 00:13:25 1998 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ +# $Id: Makefile,v 1.2 1998/05/01 01:35:22 ralf Exp $ # Makefile for the SGI arcs prom monitor library routines # under Linux. # diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/cmdline.c linux/arch/mips/sgi/prom/cmdline.c --- v2.1.100/linux/arch/mips/sgi/prom/cmdline.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/prom/cmdline.c Fri May 8 00:13:25 1998 @@ -1,9 +1,11 @@ -/* $Id: cmdline.c,v 1.2 1997/12/02 05:51:09 ralf Exp $ +/* * cmdline.c: Kernel command line creation using ARCS argc/argv. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: cmdline.c,v 1.3 1998/05/01 01:35:22 ralf Exp $ */ - +#include #include #include @@ -14,7 +16,7 @@ extern char arcs_cmdline[CL_SIZE]; -char *prom_getcmdline(void) +__initfunc(char *prom_getcmdline(void)) { return &(arcs_cmdline[0]); } @@ -29,7 +31,7 @@ }; #define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0]))))) -void prom_init_cmdline(void) +__initfunc(void prom_init_cmdline(void)) { char *cp; int actr, i; diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/console.c linux/arch/mips/sgi/prom/console.c --- v2.1.100/linux/arch/mips/sgi/prom/console.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/prom/console.c Fri May 8 00:13:25 1998 @@ -1,12 +1,14 @@ -/* $Id: console.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ +/* * console.c: SGI arcs console code. * * Copyright (C) 1996 David S. Miller (dm@sgi.com) + * + * $Id: console.c,v 1.2 1998/05/01 01:35:23 ralf Exp $ */ - +#include #include -void prom_putchar(char c) +__initfunc(void prom_putchar(char c)) { long cnt; char it = c; @@ -14,7 +16,7 @@ romvec->write(1, &it, 1, &cnt); } -char prom_getchar(void) +__initfunc(char prom_getchar(void)) { long cnt; char c; diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/env.c linux/arch/mips/sgi/prom/env.c --- v2.1.100/linux/arch/mips/sgi/prom/env.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/prom/env.c Fri May 8 00:13:25 1998 @@ -1,20 +1,22 @@ -/* $Id: env.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ +/* * env.c: ARCS environment variable routines. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: env.c,v 1.2 1998/05/01 01:35:24 ralf Exp $ */ - +#include #include #include #include -char *prom_getenv(char *name) +__initfunc(char *prom_getenv(char *name)) { return romvec->get_evar(name); } -long prom_setenv(char *name, char *value) +__initfunc(long prom_setenv(char *name, char *value)) { return romvec->set_evar(name, value); } diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/file.c linux/arch/mips/sgi/prom/file.c --- v2.1.100/linux/arch/mips/sgi/prom/file.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/prom/file.c Fri May 8 00:13:25 1998 @@ -1,58 +1,59 @@ -/* $Id: file.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ +/* * file.c: ARCS firmware interface to files. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: file.c,v 1.2 1998/05/01 01:35:24 ralf Exp $ */ - +#include #include -long prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num, - unsigned long *cnt) +__initfunc(long prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num, unsigned long *cnt)) { return romvec->get_vdirent(fd, ent, num, cnt); } -long prom_open(char *name, enum linux_omode md, unsigned long *fd) +__initfunc(long prom_open(char *name, enum linux_omode md, unsigned long *fd)) { return romvec->open(name, md, fd); } -long prom_close(unsigned long fd) +__initfunc(long prom_close(unsigned long fd)) { return romvec->close(fd); } -long prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt) +__initfunc(long prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt)) { return romvec->read(fd, buf, num, cnt); } -long prom_getrstatus(unsigned long fd) +__initfunc(long prom_getrstatus(unsigned long fd)) { return romvec->get_rstatus(fd); } -long prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt) +__initfunc(long prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt)) { return romvec->write(fd, buf, num, cnt); } -long prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm) +__initfunc(long prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm)) { return romvec->seek(fd, off, sm); } -long prom_mount(char *name, enum linux_mountops op) +__initfunc(long prom_mount(char *name, enum linux_mountops op)) { return romvec->mount(name, op); } -long prom_getfinfo(unsigned long fd, struct linux_finfo *buf) +__initfunc(long prom_getfinfo(unsigned long fd, struct linux_finfo *buf)) { return romvec->get_finfo(fd, buf); } -long prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk) +__initfunc(long prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk)) { return romvec->set_finfo(fd, flags, msk); } diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/init.c linux/arch/mips/sgi/prom/init.c --- v2.1.100/linux/arch/mips/sgi/prom/init.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/prom/init.c Fri May 8 00:13:25 1998 @@ -1,9 +1,11 @@ -/* $Id: init.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ +/* * init.c: PROM library initialisation code. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: init.c,v 1.2 1998/05/01 01:35:25 ralf Exp $ */ - +#include #include #include @@ -19,7 +21,7 @@ extern void prom_testtree(void); -int prom_init(int argc, char **argv, char **envp) +__initfunc(int prom_init(int argc, char **argv, char **envp)) { struct linux_promblock *pb; diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/memory.c linux/arch/mips/sgi/prom/memory.c --- v2.1.100/linux/arch/mips/sgi/prom/memory.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/prom/memory.c Fri May 8 00:13:25 1998 @@ -1,10 +1,12 @@ -/* $Id: memory.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ +/* * memory.c: PROM library functions for acquiring/using memory descriptors * given to us from the ARCS firmware. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: memory.c,v 1.2 1998/05/01 01:35:25 ralf Exp $ */ - +#include #include #include #include @@ -18,7 +20,7 @@ /* #define DEBUG */ -struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr) +__initfunc(struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr)) { return romvec->get_mdesc(curr); } @@ -38,12 +40,12 @@ static struct prom_pmemblock prom_pblocks[PROM_MAX_PMEMBLOCKS]; -struct prom_pmemblock *prom_getpblock_array(void) +__initfunc(struct prom_pmemblock *prom_getpblock_array(void)) { return &prom_pblocks[0]; } -static void prom_setup_memupper(void) +__initfunc(static void prom_setup_memupper(void)) { struct prom_pmemblock *p, *highest; @@ -60,7 +62,7 @@ #endif } -void prom_meminit(void) +__initfunc(void prom_meminit(void)) { struct linux_mdesc *p; int totram; @@ -104,7 +106,7 @@ } /* Called from mem_init() to fixup the mem_map page settings. */ -void prom_fixup_mem_map(unsigned long start, unsigned long end) +__initfunc(void prom_fixup_mem_map(unsigned long start, unsigned long end)) { struct prom_pmemblock *p; int i, nents; diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/misc.c linux/arch/mips/sgi/prom/misc.c --- v2.1.100/linux/arch/mips/sgi/prom/misc.c Thu Jun 26 12:33:38 1997 +++ linux/arch/mips/sgi/prom/misc.c Fri May 8 00:13:25 1998 @@ -2,10 +2,14 @@ * misc.c: Miscellaneous ARCS PROM routines. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: misc.c,v 1.2 1998/05/01 01:35:26 ralf Exp $ */ #include +#include #include +#include #include #include #include @@ -15,91 +19,59 @@ extern void *sgiwd93_host; extern void reset_wd33c93(void *instance); -static inline void shutoff_r4600_cache(void) -{ - unsigned long tmp1, tmp2, tmp3; - - if(mips_cputype != CPU_R4600 && - mips_cputype != CPU_R4640 && - mips_cputype != CPU_R4700) - return; - printk("Disabling R4600 SCACHE\n"); - __asm__ __volatile__(" - .set noreorder - .set mips3 - li %0, 0x1 - dsll %0, 31 - lui %1, 0x9000 - dsll32 %1, 0 - or %0, %1, %0 - mfc0 %2, $12 - nop; nop; nop; nop; - li %1, 0x80 - mtc0 %1, $12 - nop; nop; nop; nop; - sh $0, 0(%0) - mtc0 $0, $12 - nop; nop; nop; nop; - mtc0 %2, $12 - nop; nop; nop; nop; - .set mips2 - .set reorder - " : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)); -} - void prom_halt(void) { - shutoff_r4600_cache(); + bcops->bc_disable(); initialize_kbd(); + cli(); #if CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif - cli(); romvec->halt(); } void prom_powerdown(void) { - shutoff_r4600_cache(); + bcops->bc_disable(); initialize_kbd(); + cli(); #if CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif - cli(); romvec->pdown(); } /* XXX is this a soft reset basically? XXX */ void prom_restart(void) { - shutoff_r4600_cache(); + bcops->bc_disable(); initialize_kbd(); + cli(); #if CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif - cli(); romvec->restart(); } void prom_reboot(void) { - shutoff_r4600_cache(); + bcops->bc_disable(); initialize_kbd(); + cli(); #if CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif - cli(); romvec->reboot(); } void prom_imode(void) { - shutoff_r4600_cache(); + bcops->bc_disable(); initialize_kbd(); + cli(); #if CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif - cli(); romvec->imode(); } @@ -113,7 +85,7 @@ return romvec->get_sysid(); } -void prom_cacheflush(void) +__initfunc(void prom_cacheflush(void)) { romvec->cache_flush(); } diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/printf.c linux/arch/mips/sgi/prom/printf.c --- v2.1.100/linux/arch/mips/sgi/prom/printf.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/prom/printf.c Fri May 8 00:13:25 1998 @@ -1,18 +1,19 @@ -/* $Id: printf.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ +/* * printf.c: Putting things on the screen using SGI arcs * PROM facilities. * * Copyright (C) 1996 David S. Miller (dm@sgi.com) + * + * $Id: printf.c,v 1.2 1998/05/01 01:35:27 ralf Exp $ */ - +#include #include #include static char ppbuf[1024]; -void -prom_printf(char *fmt, ...) +__initfunc(void prom_printf(char *fmt, ...)) { va_list args; char ch, *bptr; diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/salone.c linux/arch/mips/sgi/prom/salone.c --- v2.1.100/linux/arch/mips/sgi/prom/salone.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/prom/salone.c Fri May 8 00:13:25 1998 @@ -1,24 +1,25 @@ -/* $Id: salone.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ +/* * salone.c: Routines to load into memory and execute stand-along * program images using ARCS PROM firmware. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: salone.c,v 1.2 1998/05/01 01:35:27 ralf Exp $ */ - +#include #include -long prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr) +__initfunc(long prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr)) { return romvec->load(name, end, pc, eaddr); } -long prom_invoke(unsigned long pc, unsigned long sp, long argc, - char **argv, char **envp) +__initfunc(long prom_invoke(unsigned long pc, unsigned long sp, long argc, char **argv, char **envp)) { return romvec->invoke(pc, sp, argc, argv, envp); } -long prom_exec(char *name, long argc, char **argv, char **envp) +__initfunc(long prom_exec(char *name, long argc, char **argv, char **envp)) { return romvec->exec(name, argc, argv, envp); } diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/tags.c linux/arch/mips/sgi/prom/tags.c --- v2.1.100/linux/arch/mips/sgi/prom/tags.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/prom/tags.c Fri May 8 00:13:25 1998 @@ -1,10 +1,12 @@ -/* $Id: tags.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ +/* * tags.c: Initialize the arch tags the way the MIPS kernel setup * expects. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: tags.c,v 1.2 1998/05/01 01:35:28 ralf Exp $ */ - +#include #include #include @@ -43,7 +45,7 @@ /* XXX COLOSTOMY BAG!!!! XXX */ }; -void prom_setup_archtags(void) +__initfunc(void prom_setup_archtags(void)) { tag_def *tdp = &taglist_sgi_indy[0]; tag *tp; diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/time.c linux/arch/mips/sgi/prom/time.c --- v2.1.100/linux/arch/mips/sgi/prom/time.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/prom/time.c Fri May 8 00:13:25 1998 @@ -1,17 +1,19 @@ -/* $Id: time.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ +/* * time.c: Extracting time information from ARCS prom. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: time.c,v 1.2 1998/05/01 01:35:29 ralf Exp $ */ - +#include #include -struct linux_tinfo *prom_gettinfo(void) +__initfunc(struct linux_tinfo *prom_gettinfo(void)) { return romvec->get_tinfo(); } -unsigned long prom_getrtime(void) +__initfunc(unsigned long prom_getrtime(void)) { return romvec->get_rtime(); } diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/tree.c linux/arch/mips/sgi/prom/tree.c --- v2.1.100/linux/arch/mips/sgi/prom/tree.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sgi/prom/tree.c Fri May 8 00:13:25 1998 @@ -1,48 +1,50 @@ -/* $Id: tree.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ +/* * tree.c: PROM component device tree code. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: tree.c,v 1.2 1998/05/01 01:35:30 ralf Exp $ */ - +#include #include #define DEBUG_PROM_TREE -pcomponent *prom_getsibling(pcomponent *this) +__initfunc(pcomponent *prom_getsibling(pcomponent *this)) { if(this == PROM_NULL_COMPONENT) return PROM_NULL_COMPONENT; return romvec->next_component(this); } -pcomponent *prom_getchild(pcomponent *this) +__initfunc(pcomponent *prom_getchild(pcomponent *this)) { return romvec->child_component(this); } -pcomponent *prom_getparent(pcomponent *child) +__initfunc(pcomponent *prom_getparent(pcomponent *child)) { if(child == PROM_NULL_COMPONENT) return PROM_NULL_COMPONENT; return romvec->parent_component(child); } -long prom_getcdata(void *buffer, pcomponent *this) +__initfunc(long prom_getcdata(void *buffer, pcomponent *this)) { return romvec->component_data(buffer, this); } -pcomponent *prom_childadd(pcomponent *this, pcomponent *tmp, void *data) +__initfunc(pcomponent *prom_childadd(pcomponent *this, pcomponent *tmp, void *data)) { return romvec->child_add(this, tmp, data); } -long prom_delcomponent(pcomponent *this) +__initfunc(long prom_delcomponent(pcomponent *this)) { return romvec->comp_del(this); } -pcomponent *prom_componentbypath(char *path) +__initfunc(pcomponent *prom_componentbypath(char *path)) { return romvec->component_by_path(path); } @@ -72,7 +74,7 @@ "input", "output" }; -static void dump_component(pcomponent *p) +__initfunc(static void dump_component(pcomponent *p)) { prom_printf("[%p]:class<%s>type<%s>flags<%s>ver<%d>rev<%d>", p, classes[p->class], types[p->type], @@ -81,7 +83,7 @@ p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname); } -static void traverse(pcomponent *p, int op) +__initfunc(static void traverse(pcomponent *p, int op)) { dump_component(p); if(prom_getchild(p)) @@ -90,7 +92,7 @@ traverse(prom_getsibling(p), 1); } -void prom_testtree(void) +__initfunc(void prom_testtree(void)) { pcomponent *p; diff -u --recursive --new-file v2.1.100/linux/arch/mips/sni/Makefile linux/arch/mips/sni/Makefile --- v2.1.100/linux/arch/mips/sni/Makefile Thu Jun 26 12:33:38 1997 +++ linux/arch/mips/sni/Makefile Fri May 8 00:13:25 1998 @@ -5,6 +5,8 @@ # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # +# $Id: Makefile,v 1.2 1998/05/01 01:35:32 ralf Exp $ +# .S.s: $(CPP) $(CFLAGS) $< -o $*.s @@ -13,7 +15,7 @@ all: sni.o O_TARGET := sni.o -O_OBJS := hw-access.o int-handler.o io.o pci.o reset.o setup.o +O_OBJS := hw-access.o int-handler.o io.o pci.o pcimt_scache.o reset.o setup.o int-handler.o: int-handler.S diff -u --recursive --new-file v2.1.100/linux/arch/mips/sni/hw-access.c linux/arch/mips/sni/hw-access.c --- v2.1.100/linux/arch/mips/sni/hw-access.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sni/hw-access.c Fri May 8 00:13:25 1998 @@ -5,11 +5,12 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 1997 by Ralf Baechle + * Copyright (C) 1996, 1997, 1998 by Ralf Baechle * - * $Id: hw-access.c,v 1.3 1997/07/29 17:46:46 ralf Exp $ + * $Id: hw-access.c,v 1.4 1998/05/01 01:35:32 ralf Exp $ */ #include +#include #include #include #include @@ -182,7 +183,7 @@ return inb(KBD_STATUS_REG); } -void sni_rm200_keyboard_setup(void) +__initfunc(void sni_rm200_keyboard_setup(void)) { kbd_read_input = sni_read_input; kbd_write_output = sni_write_output; diff -u --recursive --new-file v2.1.100/linux/arch/mips/sni/int-handler.S linux/arch/mips/sni/int-handler.S --- v2.1.100/linux/arch/mips/sni/int-handler.S Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sni/int-handler.S Fri May 8 00:13:25 1998 @@ -3,7 +3,7 @@ * * Copyright (C) 1994 - 1997 by Ralf Baechle * - * $Id: int-handler.S,v 1.3 1997/12/01 16:39:24 ralf Exp $ + * $Id: int-handler.S,v 1.3 1998/05/01 01:35:33 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.1.100/linux/arch/mips/sni/io.c linux/arch/mips/sni/io.c --- v2.1.100/linux/arch/mips/sni/io.c Thu Jun 26 12:33:38 1997 +++ linux/arch/mips/sni/io.c Fri May 8 00:13:25 1998 @@ -4,6 +4,8 @@ * for more details. * * Low level I/O functions for SNI. + * + * $Id: io.c,v 1.2 1998/05/01 01:35:34 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.1.100/linux/arch/mips/sni/pci.c linux/arch/mips/sni/pci.c --- v2.1.100/linux/arch/mips/sni/pci.c Mon Apr 6 17:40:59 1998 +++ linux/arch/mips/sni/pci.c Fri May 8 00:13:25 1998 @@ -4,9 +4,11 @@ * for more details. * * SNI specific PCI support for RM200/RM300. + * + * $Id: pci.c,v 1.4 1998/05/01 01:35:34 ralf Exp $ */ #include -#include +#include #include #include #include @@ -15,13 +17,14 @@ #ifdef CONFIG_PCI -extern inline u32 mkaddr(unsigned char bus, unsigned char dev_fn, - unsigned char where) -{ - return ((bus & 0xff) << 0x10) | - ((dev_fn & 0xff) << 0x08) | - (where & 0xfc); -} +#define mkaddr(bus, dev_fn, where) \ +do { \ + if (bus == 0 && dev_fn >= PCI_DEVFN(8, 0)) \ + return -1; \ + *(volatile u32 *)PCIMT_CONFIG_ADDRESS = ((bus & 0xff) << 0x10) | \ + ((dev_fn & 0xff) << 0x08) | \ + (where & 0xfc); \ +} while(0); static unsigned long sni_rm200_pcibios_fixup (unsigned long memory_start, unsigned long memory_end) @@ -31,6 +34,9 @@ * Take care of RM300 revision D boards for where the network * slot became an ordinary PCI slot. */ + pcibios_write_config_byte(0, PCI_DEVFN(1, 0), PCI_INTERRUPT_LINE, + PCIMT_IRQ_SCSI); + return memory_start; } @@ -45,7 +51,7 @@ { u32 res; - *(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where); + mkaddr(bus, dev_fn, where); res = *(volatile u32 *)PCIMT_CONFIG_DATA; res = (le32_to_cpu(res) >> ((where & 3) << 3)) & 0xff; *val = res; @@ -62,7 +68,7 @@ if (where & 1) return PCIBIOS_BAD_REGISTER_NUMBER; - *(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where); + mkaddr(bus, dev_fn, where); res = *(volatile u32 *)PCIMT_CONFIG_DATA; res = (le32_to_cpu(res) >> ((where & 3) << 3)) & 0xffff; *val = res; @@ -77,9 +83,9 @@ { u32 res; - if (where & 3) + if (where & 3) return PCIBIOS_BAD_REGISTER_NUMBER; - *(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where); + mkaddr(bus, dev_fn, where); res = *(volatile u32 *)PCIMT_CONFIG_DATA; res = le32_to_cpu(res); *val = res; @@ -92,7 +98,9 @@ unsigned char where, unsigned char val) { - /* To do */ + mkaddr(bus, dev_fn, where); + *(volatile u8 *)(PCIMT_CONFIG_DATA + (where & 3)) = val; + return PCIBIOS_SUCCESSFUL; } @@ -101,7 +109,11 @@ unsigned char where, unsigned short val) { - /* To do */ + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + mkaddr(bus, dev_fn, where); + *(volatile u16 *)(PCIMT_CONFIG_DATA + (where & 3)) = le16_to_cpu(val); + return PCIBIOS_SUCCESSFUL; } @@ -112,7 +124,7 @@ { if (where & 3) return PCIBIOS_BAD_REGISTER_NUMBER; - *(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where); + mkaddr(bus, dev_fn, where); *(volatile u32 *)PCIMT_CONFIG_DATA = le32_to_cpu(val); return PCIBIOS_SUCCESSFUL; diff -u --recursive --new-file v2.1.100/linux/arch/mips/sni/pcimt_scache.c linux/arch/mips/sni/pcimt_scache.c --- v2.1.100/linux/arch/mips/sni/pcimt_scache.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sni/pcimt_scache.c Fri May 8 00:13:25 1998 @@ -0,0 +1,34 @@ +/* + * arch/mips/sni/pcimt_scache.c + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1997 by Ralf Baechle + * + * $Id: pcimt_scache.c,v 1.1 1998/03/04 08:47:29 ralf Exp $ + */ +#include +#include +#include + +__initfunc(void sni_pcimt_sc_init(void)) +{ + unsigned int cacheconf, sc_size; + + cacheconf = *(volatile unsigned int *)PCIMT_CACHECONF; + if ((cacheconf & 7) == 0) { + printk("No second level cache detected\n"); + printk("WARNING: not activating second level cache, " + "tell ralf@gnu.org\n"); + return; + } + if ((cacheconf & 7) >= 6) { + printk("Invalid second level cache size detected\n"); + return; + } + + sc_size = 128 << (cacheconf & 7); + printk("%dkb second level cache detected.\n", sc_size); +} diff -u --recursive --new-file v2.1.100/linux/arch/mips/sni/setup.c linux/arch/mips/sni/setup.c --- v2.1.100/linux/arch/mips/sni/setup.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sni/setup.c Fri May 8 00:13:25 1998 @@ -1,5 +1,5 @@ /* - * Setup pointers to hardware dependand routines. + * Setup pointers to hardware dependant routines. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -7,17 +7,21 @@ * * Copyright (C) 1996, 1997 by Ralf Baechle * - * $Id: setup.c,v 1.5 1997/12/01 16:19:12 ralf Exp $ + * $Id: setup.c,v 1.5 1998/05/04 09:18:42 ralf Exp $ */ #include +#include +#include #include #include #include #include #include #include +#include #include #include +#include #include #include #include @@ -45,6 +49,8 @@ extern void sni_machine_halt(void); extern void sni_machine_power_off(void); +extern struct ide_ops std_ide_ops; + __initfunc(static void sni_irq_setup(void)) { set_except_vector(0, sni_rm200_pci_handle_int); @@ -94,32 +100,8 @@ asic = (csmsr & 0x08) ? asic : !asic; p += sprintf(p, ", ASIC PCI Rev %s", asic ? "1.0" : "1.1"); printk("%s.\n", boardtype); - - cacheconf = *(volatile unsigned int *)PCIMT_CACHECONF; - switch(cacheconf & 7) { - case 0: - printk("Secondary cache disabled\n"); - break; - case 1: - printk("256kb secondary cache\n"); - break; - case 2: - printk("512kb secondary cache\n"); - break; - case 3: - printk("1mb secondary cache\n"); - break; - case 4: - printk("2mb secondary cache\n"); - break; - case 5: - printk("4mb secondary cache\n"); - break; - default: - panic("invalid secondary cache size\n"); - } } - + __initfunc(void sni_rm200_pci_setup(void)) { tag *atag; @@ -149,6 +131,7 @@ } sni_pcimt_detect(); + sni_pcimt_sc_init(); irq_setup = sni_irq_setup; fd_cacheflush = sni_fd_cacheflush; // Will go away @@ -183,4 +166,7 @@ */ request_region(0xcfc,0x04,"PCI config data"); pci_ops = &sni_pci_ops; +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &std_ide_ops; +#endif } diff -u --recursive --new-file v2.1.100/linux/arch/mips/tools/Makefile linux/arch/mips/tools/Makefile --- v2.1.100/linux/arch/mips/tools/Makefile Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/tools/Makefile Fri May 8 00:13:25 1998 @@ -3,7 +3,7 @@ # Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) # Copyright (C) 1997 Ralf Baechle (ralf@gnu.ai.mit.edu) # -# $Id: Makefile,v 1.2 1997/09/23 06:23:49 ralf Exp $ +# $Id: Makefile,v 1.3 1998/05/01 01:35:37 ralf Exp $ # TARGET := $(TOPDIR)/include/asm-$(ARCH)/offset.h diff -u --recursive --new-file v2.1.100/linux/arch/mips/tools/offset.c linux/arch/mips/tools/offset.c --- v2.1.100/linux/arch/mips/tools/offset.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/tools/offset.c Fri May 8 00:13:25 1998 @@ -4,7 +4,7 @@ * Copyright (C) 1996 David S. Miller * Made portable by Ralf Baechle * - * $Id: offset.c,v 1.3 1997/07/29 18:57:11 ralf Exp $ + * $Id: offset.c,v 1.6 1998/05/04 09:18:45 ralf Exp $ */ #include @@ -65,8 +65,6 @@ offset("#define PT_R31 ", struct pt_regs, regs[31]); offset("#define PT_LO ", struct pt_regs, lo); offset("#define PT_HI ", struct pt_regs, hi); - offset("#define PT_OR2 ", struct pt_regs, orig_reg2); - offset("#define PT_OR7 ", struct pt_regs, orig_reg7); offset("#define PT_EPC ", struct pt_regs, cp0_epc); offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr); offset("#define PT_STATUS ", struct pt_regs, cp0_status); @@ -81,9 +79,8 @@ offset("#define TASK_STATE ", struct task_struct, state); offset("#define TASK_COUNTER ", struct task_struct, counter); offset("#define TASK_PRIORITY ", struct task_struct, priority); - offset("#define TASK_SIGNAL ", struct task_struct, signal); - offset("#define TASK_BLOCKED ", struct task_struct, blocked); offset("#define TASK_FLAGS ", struct task_struct, flags); + offset("#define TASK_SIGPENDING ", struct task_struct, sigpending); offset("#define TASK_MM ", struct task_struct, mm); linefeed; } @@ -99,16 +96,15 @@ offset("#define THREAD_REG21 ", struct task_struct, tss.reg21); offset("#define THREAD_REG22 ", struct task_struct, tss.reg22); offset("#define THREAD_REG23 ", struct task_struct, tss.reg23); - offset("#define THREAD_REG28 ", struct task_struct, tss.reg28); offset("#define THREAD_REG29 ", struct task_struct, tss.reg29); offset("#define THREAD_REG30 ", struct task_struct, tss.reg30); offset("#define THREAD_REG31 ", struct task_struct, tss.reg31); offset("#define THREAD_STATUS ", struct task_struct, tss.cp0_status); offset("#define THREAD_FPU ", struct task_struct, tss.fpu); offset("#define THREAD_BVADDR ", struct task_struct, tss.cp0_badvaddr); + offset("#define THREAD_BUADDR ", struct task_struct, tss.cp0_baduaddr); offset("#define THREAD_ECODE ", struct task_struct, tss.error_code); offset("#define THREAD_TRAPNO ", struct task_struct, tss.trap_no); - offset("#define THREAD_KSP ", struct task_struct, tss.ksp); offset("#define THREAD_PGDIR ", struct task_struct, tss.pg_dir); offset("#define THREAD_MFLAGS ", struct task_struct, tss.mflags); offset("#define THREAD_CURDS ", struct task_struct, tss.current_ds); diff -u --recursive --new-file v2.1.100/linux/arch/ppc/8xx_io/commproc.c linux/arch/ppc/8xx_io/commproc.c --- v2.1.100/linux/arch/ppc/8xx_io/commproc.c Sat Apr 25 18:13:10 1998 +++ linux/arch/ppc/8xx_io/commproc.c Fri May 8 00:18:13 1998 @@ -85,7 +85,6 @@ */ dp_alloc_base = CPM_DATAONLY_BASE; dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE; - /* Set the host page for allocation. */ host_buffer = host_page_addr; /* Host virtual page address */ @@ -104,7 +103,6 @@ (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) | ((CPM_INTERRUPT/2) << 13) | CICR_HP_MASK; ((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cimr = 0; - /* Set our interrupt handler with the core CPU. */ if (request_irq(CPM_INTERRUPT, cpm_interrupt, 0, "cpm", NULL) != 0) @@ -113,7 +111,6 @@ /* Install our own error handler. */ cpm_install_handler(CPMVEC_ERROR, cpm_error_interrupt, NULL); - ((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN; } diff -u --recursive --new-file v2.1.100/linux/arch/ppc/8xx_io/enet.c linux/arch/ppc/8xx_io/enet.c --- v2.1.100/linux/arch/ppc/8xx_io/enet.c Sat Apr 25 18:13:10 1998 +++ linux/arch/ppc/8xx_io/enet.c Fri May 8 00:18:13 1998 @@ -30,10 +30,8 @@ #include #include #include -#include #include -#include - +#include #include #include #include @@ -41,8 +39,9 @@ #include #include #include +#include +#include #include "commproc.h" -#include /* * Theory of Operation @@ -151,762 +150,766 @@ /* GET THIS FROM THE VPD!!!! */ -static ushort my_enet_addr[] = { 0x0800, 0x3e26, 0x1559 }; +/*static ushort my_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };*/ -/* Initialize the CPM Ethernet on SCC1. If EPPC-Bug loaded us, or performed - * some other network I/O, a whole bunch of this has already been set up. - * It is no big deal if we do it again, we just have to disable the - * transmit and receive to make sure we don't catch the CPM with some - * inconsistent control information. - */ -__initfunc(int cpm_enet_init(void)) +static int +cpm_enet_open(struct device *dev) { - struct device *dev; - struct cpm_enet_private *cep; - int i, j; - unsigned char *eap; - unsigned long mem_addr; - pte_t *pte; - volatile cbd_t *bdp; - volatile cpm8xx_t *cp; - volatile scc_t *sccp; - volatile scc_enet_t *ep; - volatile immap_t *immap; - cp = cpmp; /* Get pointer to Communication Processor */ + /* I should reset the ring buffers here, but I don't yet know + * a simple way to do that. + */ - immap = (immap_t *)MBX_IMAP_ADDR; /* and to internal registers */ + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; - /* Allocate some private information. - */ - cep = (struct cpm_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL); - memset(cep, 0, sizeof(*cep)); + return 0; /* Always succeed */ +} - /* Create an Ethernet device instance. - */ - dev = init_etherdev(0, 0); +static int +cpm_enet_start_xmit(struct sk_buff *skb, struct device *dev) +{ + struct cpm_enet_private *cep = (struct cpm_enet_private *)dev->priv; + volatile cbd_t *bdp; + unsigned long flags; - /* Get pointer to SCC1 area in parameter RAM. - */ - ep = (scc_enet_t *)(&cp->cp_dparam[PROFF_SCC1]); + /* Transmitter timeout, serious problems. */ + if (dev->tbusy) { + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < 20) + return 1; + printk("%s: transmit timed out.\n", dev->name); + cep->stats.tx_errors++; +#ifndef final_version + { + int i; + cbd_t *bdp; + printk(" Ring data dump: cur_tx %x%s cur_rx %x.\n", + cep->cur_tx, cep->tx_full ? " (full)" : "", + cep->cur_rx); + bdp = cep->tx_bd_base; + for (i = 0 ; i < TX_RING_SIZE; i++) + printk("%04x %04x %08x\n", + bdp->cbd_sc, + bdp->cbd_datlen, + bdp->cbd_bufaddr); + bdp = cep->rx_bd_base; + for (i = 0 ; i < RX_RING_SIZE; i++) + printk("%04x %04x %08x\n", + bdp->cbd_sc, + bdp->cbd_datlen, + bdp->cbd_bufaddr); + } +#endif - /* And another to the SCC register area. - */ - sccp = (volatile scc_t *)(&cp->cp_scc[0]); - cep->sccp = (scc_t *)sccp; /* Keep the pointer handy */ + dev->tbusy=0; + dev->trans_start = jiffies; - /* Disable receive and transmit in case EPPC-Bug started it. - */ - sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); + return 0; + } - /* Cookbook style from the MPC860 manual..... - * Not all of this is necessary if EPPC-Bug has initialized - * the network. + /* Block a timer-based transmit from overlapping. This could better be + done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ + if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { + printk("%s: Transmitter access conflict.\n", dev->name); + return 1; + } + + if (test_and_set_bit(0, (void*)&cep->lock) != 0) { + printk("%s: tx queue lock!.\n", dev->name); + /* don't clear dev->tbusy flag. */ + return 1; + } + + /* Fill in a Tx ring entry */ + bdp = cep->cur_tx; + +#ifndef final_version + if (bdp->cbd_sc & BD_ENET_TX_READY) { + /* Ooops. All transmit buffers are full. Bail out. + * This should not happen, since dev->tbusy should be set. + */ + printk("%s: tx queue full!.\n", dev->name); + cep->lock = 0; + return 1; + } +#endif + + /* Clear all of the status flags. */ + bdp->cbd_sc &= ~BD_ENET_TX_STATS; - /* Configure port A pins for Txd and Rxd. + /* If the frame is short, tell CPM to pad it. */ - immap->im_ioport.iop_papar |= (PA_ENET_RXD | PA_ENET_TXD); - immap->im_ioport.iop_padir &= ~(PA_ENET_RXD | PA_ENET_TXD); - immap->im_ioport.iop_paodr &= ~PA_ENET_TXD; + if (skb->len <= ETH_ZLEN) + bdp->cbd_sc |= BD_ENET_TX_PAD; + else + bdp->cbd_sc &= ~BD_ENET_TX_PAD; - /* Configure port C pins to enable CLSN and RENA. + /* Set buffer length and buffer pointer. */ - immap->im_ioport.iop_pcpar &= ~(PC_ENET_CLSN | PC_ENET_RENA); - immap->im_ioport.iop_pcdir &= ~(PC_ENET_CLSN | PC_ENET_RENA); - immap->im_ioport.iop_pcso |= (PC_ENET_CLSN | PC_ENET_RENA); + bdp->cbd_datlen = skb->len; + bdp->cbd_bufaddr = __pa(skb->data); - /* Configure port A for TCLK and RCLK. + /* Save skb pointer. */ - immap->im_ioport.iop_papar |= (PA_ENET_TCLK | PA_ENET_RCLK); - immap->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK); - - /* Configure Serial Interface clock routing. - * First, clear all SCC1 bits to zero, then set the ones we want. - */ - cp->cp_sicr &= ~SICR_ENET_MASK; - cp->cp_sicr |= SICR_ENET_CLKRT; + cep->tx_skbuff[cep->skb_cur] = skb; - /* Manual says set SDDR, but I can't find anything with that - * name. I think it is a misprint, and should be SDCR. This - * has already been set by the communication processor initialization. + cep->stats.tx_bytes += skb->len; + cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK; + + /* Push the data cache so the CPM does not get stale memory + * data. */ + /*flush_dcache_range(skb->data, skb->data + skb->len);*/ - /* Allocate space for the buffer descriptors in the DP ram. - * These are relative offsets in the DP ram address space. - * Initialize base addresses for the buffer descriptors. + /* Send it on its way. Tell CPM its ready, interrupt when done, + * its the last BD of the frame, and to put the CRC on the end. */ - i = mbx_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE); - ep->sen_genscc.scc_rbase = i; - cep->rx_bd_base = (cbd_t *)&cp->cp_dpmem[i]; - - i = mbx_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE); - ep->sen_genscc.scc_tbase = i; - cep->tx_bd_base = (cbd_t *)&cp->cp_dpmem[i]; - - cep->dirty_tx = cep->cur_tx = cep->tx_bd_base; - cep->cur_rx = cep->rx_bd_base; + bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC); - /* Issue init Rx BD command for SCC1. - * Manual says to perform an Init Rx parameters here. We have - * to perform both Rx and Tx because the SCC may have been - * already running. - * In addition, we have to do it later because we don't yet have - * all of the BD control/status set properly. - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_INIT_RX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); - */ + dev->trans_start = jiffies; - /* Initialize function code registers for big-endian. + /* If this was the last BD in the ring, start at the beginning again. */ - ep->sen_genscc.scc_rfcr = SCC_EB; - ep->sen_genscc.scc_tfcr = SCC_EB; + if (bdp->cbd_sc & BD_ENET_TX_WRAP) + bdp = cep->tx_bd_base; + else + bdp++; - /* Set maximum bytes per receive buffer. - * This appears to be an Ethernet frame size, not the buffer - * fragment size. It must be a multiple of four. - */ - ep->sen_genscc.scc_mrblr = PKT_MAXBLR_SIZE; + save_flags(flags); + cli(); + cep->lock = 0; + if (bdp->cbd_sc & BD_ENET_TX_READY) + cep->tx_full = 1; + else + dev->tbusy=0; + restore_flags(flags); - /* Set CRC preset and mask. - */ - ep->sen_cpres = 0xffffffff; - ep->sen_cmask = 0xdebb20e3; + cep->cur_tx = (cbd_t *)bdp; - ep->sen_crcec = 0; /* CRC Error counter */ - ep->sen_alec = 0; /* alignment error counter */ - ep->sen_disfc = 0; /* discard frame counter */ + return 0; +} - ep->sen_pads = 0x8888; /* Tx short frame pad character */ - ep->sen_retlim = 15; /* Retry limit threshold */ +/* The interrupt handler. + * This is called from the CPM handler, not the MPC core interrupt. + */ +static void +cpm_enet_interrupt(void *dev_id) +{ + struct device *dev = dev_id; + struct cpm_enet_private *cep; + volatile cbd_t *bdp; + ushort int_events; + int must_restart; - ep->sen_maxflr = PKT_MAXBUF_SIZE; /* maximum frame length register */ - ep->sen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register */ + cep = (struct cpm_enet_private *)dev->priv; + if (dev->interrupt) + printk("%s: Re-entering the interrupt handler.\n", dev->name); - ep->sen_maxd1 = PKT_MAXBUF_SIZE; /* maximum DMA1 length */ - ep->sen_maxd2 = PKT_MAXBUF_SIZE; /* maximum DMA2 length */ + dev->interrupt = 1; - /* Clear hash tables. + /* Get the interrupt events that caused us to be here. */ - ep->sen_gaddr1 = 0; - ep->sen_gaddr2 = 0; - ep->sen_gaddr3 = 0; - ep->sen_gaddr4 = 0; - ep->sen_iaddr1 = 0; - ep->sen_iaddr2 = 0; - ep->sen_iaddr3 = 0; - ep->sen_iaddr4 = 0; + int_events = cep->sccp->scc_scce; + must_restart = 0; - /* Set Ethernet station address. This must come from the - * Vital Product Data (VPD) EEPROM.....as soon as I get the - * I2C interface working..... - * - * Since we performed a diskless boot, the Ethernet controller - * has been initialized and we copy the address out into our - * own structure. - */ -#ifdef notdef - ep->sen_paddrh = my_enet_addr[0]; - ep->sen_paddrm = my_enet_addr[1]; - ep->sen_paddrl = my_enet_addr[2]; -#else - eap = (unsigned char *)&(ep->sen_paddrh); - for (i=5; i>=0; i--) - dev->dev_addr[i] = *eap++; -#endif - - ep->sen_pper = 0; /* 'cause the book says so */ - ep->sen_taddrl = 0; /* temp address (LSB) */ - ep->sen_taddrm = 0; - ep->sen_taddrh = 0; /* temp address (MSB) */ + /* Handle receive event in its own function. + */ + if (int_events & SCCE_ENET_RXF) + cpm_enet_rx(dev_id); - /* Now allocate the host memory pages and initialize the - * buffer descriptors. + /* Check for a transmit error. The manual is a little unclear + * about this, so the debug code until I get it figured out. It + * appears that if TXE is set, then TXB is not set. However, + * if carrier sense is lost during frame transmission, the TXE + * bit is set, "and continues the buffer transmission normally." + * I don't know if "normally" implies TXB is set when the buffer + * descriptor is closed.....trial and error :-). */ - bdp = cep->tx_bd_base; - for (i=0; icbd_sc = 0; - bdp->cbd_bufaddr = 0; - bdp++; - } + bdp = cep->dirty_tx; +#ifndef final_version + printk("CPM ENET xmit error %x\n", bdp->cbd_sc); + if (bdp->cbd_sc & BD_ENET_TX_READY) + printk("HEY! Enet xmit interrupt and TX_READY.\n"); +#endif + if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */ + cep->stats.tx_heartbeat_errors++; + if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */ + cep->stats.tx_window_errors++; + if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */ + cep->stats.tx_aborted_errors++; + if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */ + cep->stats.tx_fifo_errors++; + if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */ + cep->stats.tx_carrier_errors++; - /* Set the last buffer to wrap. - */ - bdp--; - bdp->cbd_sc |= BD_SC_WRAP; + cep->stats.tx_errors++; - bdp = cep->rx_bd_base; - for (i=0; icbd_sc & + (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) + must_restart = 1; + } - /* Allocate a page. - */ - mem_addr = __get_free_page(GFP_KERNEL); + /* Transmit OK, or non-fatal error. Update the buffer descriptors. + */ + if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) { + cep->stats.tx_packets++; + bdp = cep->dirty_tx; +#ifndef final_version + if (bdp->cbd_sc & BD_ENET_TX_READY) + printk("HEY! Enet xmit interrupt and TX_READY.\n"); +#endif + /* Deferred means some collisions occurred during transmit, + * but we eventually sent the packet OK. + */ + if (bdp->cbd_sc & BD_ENET_TX_DEF) + cep->stats.collisions++; - /* Make it uncached. + /* Free the sk buffer associated with this last transmit. */ - pte = va_to_pte(&init_task, mem_addr); - pte_val(*pte) |= _PAGE_NO_CACHE; - flush_tlb_page(current->mm->mmap, mem_addr); + dev_kfree_skb(cep->tx_skbuff[cep->skb_dirty]/*, FREE_WRITE*/); + cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK; - /* Initialize the BD for every fragment in the page. + /* Update pointer to next buffer descriptor to be transmitted. */ - for (j=0; jcbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR; - bdp->cbd_bufaddr = __pa(mem_addr); - mem_addr += CPM_ENET_RX_FRSIZE; + if (bdp->cbd_sc & BD_ENET_TX_WRAP) + bdp = cep->tx_bd_base; + else bdp++; + + /* I don't know if we can be held off from processing these + * interrupts for more than one frame time. I really hope + * not. In such a case, we would now want to check the + * currently available BD (cur_tx) and determine if any + * buffers between the dirty_tx and cur_tx have also been + * sent. We would want to process anything in between that + * does not have BD_ENET_TX_READY set. + */ + + /* Since we have freed up a buffer, the ring is no longer + * full. + */ + if (cep->tx_full && dev->tbusy) { + cep->tx_full = 0; + dev->tbusy = 0; + mark_bh(NET_BH); } + + cep->dirty_tx = (cbd_t *)bdp; } - /* Set the last buffer to wrap. - */ - bdp--; - bdp->cbd_sc |= BD_SC_WRAP; + if (must_restart) { + volatile cpm8xx_t *cp; - /* Let's re-initialize the channel now. We have to do it later - * than the manual describes because we have just now finished - * the BD initialization. + /* Some transmit errors cause the transmitter to shut + * down. We now issue a restart transmit. Since the + * errors close the BD and update the pointers, the restart + * _should_ pick up without having to reset any of our + * pointers either. + */ + cp = cpmp; + cp->cp_cpcr = + mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_RESTART_TX) | CPM_CR_FLG; + while (cp->cp_cpcr & CPM_CR_FLG); + } + + /* Check for receive busy, i.e. packets coming but no place to + * put them. This "can't happen" because the receive interrupt + * is tossing previous frames. */ - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_INIT_TRX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); + if (int_events & SCCE_ENET_BSY) { + cep->stats.rx_dropped++; + printk("CPM ENET: BSY can't happen.\n"); + } - cep->skb_cur = cep->skb_dirty = 0; + /* Write the SCC event register with the events we have handled + * to clear them. Maybe we should do this sooner? + */ + cep->sccp->scc_scce = int_events; - sccp->scc_scce = 0xffff; /* Clear any pending events */ + dev->interrupt = 0; - /* Enable interrupts for transmit error, complete frame - * received, and any transmit buffer we have also set the - * interrupt flag. - */ - sccp->scc_sccm = (SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB); + return; +} - /* Install our interrupt handler. - */ - cpm_install_handler(CPMVEC_SCC1, cpm_enet_interrupt, dev); +/* During a receive, the cur_rx points to the current incoming buffer. + * When we update through the ring, if the next incoming buffer has + * not been given to the system, we just set the empty indicator, + * effectively tossing the packet. + */ +static int +cpm_enet_rx(struct device *dev) +{ + struct cpm_enet_private *cep; + volatile cbd_t *bdp; + struct sk_buff *skb; + ushort pkt_len; - /* Set GSMR_H to enable all normal operating modes. - * Set GSMR_L to enable Ethernet to MC68160. + cep = (struct cpm_enet_private *)dev->priv; + + /* First, grab all of the stats for the incoming packet. + * These get messed up if we get called due to a busy condition. */ - sccp->scc_gsmrh = 0; - sccp->scc_gsmrl = (SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 | SCC_GSMRL_MODE_ENET); + bdp = cep->cur_rx; - /* Set sync/delimiters. +for (;;) { + if (bdp->cbd_sc & BD_ENET_RX_EMPTY) + break; + +#ifndef final_version + /* Since we have allocated space to hold a complete frame, both + * the first and last indicators should be set. + */ + if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) != + (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) + printk("CPM ENET: rcv is not first+last\n"); +#endif + + /* Frame too long or too short. */ - sccp->scc_dsr = 0xd555; + if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH)) + cep->stats.rx_length_errors++; + if (bdp->cbd_sc & BD_ENET_RX_NO) /* Frame alignment */ + cep->stats.rx_frame_errors++; + if (bdp->cbd_sc & BD_ENET_RX_CR) /* CRC Error */ + cep->stats.rx_crc_errors++; + if (bdp->cbd_sc & BD_ENET_RX_OV) /* FIFO overrun */ + cep->stats.rx_crc_errors++; - /* Set processing mode. Use Ethernet CRC, catch broadcast, and - * start frame search 22 bit times after RENA. + /* Report late collisions as a frame error. + * On this error, the BD is closed, but we don't know what we + * have in the buffer. So, just drop this frame on the floor. */ - sccp->scc_pmsr = (SCC_PMSR_ENCRC | SCC_PMSR_BRO | SCC_PMSR_NIB22); + if (bdp->cbd_sc & BD_ENET_RX_CL) { + cep->stats.rx_frame_errors++; + } + else { - /* It is now OK to enable the Ethernet transmitter. - */ - immap->im_ioport.iop_pcpar |= PC_ENET_TENA; - immap->im_ioport.iop_pcdir &= ~PC_ENET_TENA; + /* Process the incoming frame. + */ + cep->stats.rx_packets++; + pkt_len = bdp->cbd_datlen; + cep->stats.rx_bytes += pkt_len; - dev->base_addr = (unsigned long)ep; - dev->priv = cep; - dev->name = "CPM_ENET"; + /* This does 16 byte alignment, much more than we need. + */ + skb = dev_alloc_skb(pkt_len); - /* The CPM Ethernet specific entries in the device structure. */ - dev->open = cpm_enet_open; - dev->hard_start_xmit = cpm_enet_start_xmit; - dev->stop = cpm_enet_close; - dev->get_stats = cpm_enet_get_stats; - dev->set_multicast_list = set_multicast_list; + if (skb == NULL) { + printk("%s: Memory squeeze, dropping packet.\n", dev->name); + cep->stats.rx_dropped++; + } + else { + skb->dev = dev; + skb_put(skb,pkt_len); /* Make room */ + eth_copy_and_sum(skb, + (unsigned char *)__va(bdp->cbd_bufaddr), + pkt_len, 0); + skb->protocol=eth_type_trans(skb,dev); + netif_rx(skb); + } + } - /* And last, enable the transmit and receive processing. + /* Clear the status flags for this buffer. */ - sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); + bdp->cbd_sc &= ~BD_ENET_RX_STATS; - printk("CPM ENET Version 0.1, "); - for (i=0; i<5; i++) - printk("%02x:", dev->dev_addr[i]); - printk("%02x\n", dev->dev_addr[5]); + /* Mark the buffer empty. + */ + bdp->cbd_sc |= BD_ENET_RX_EMPTY; + + /* Update BD pointer to next entry. + */ + if (bdp->cbd_sc & BD_ENET_RX_WRAP) + bdp = cep->rx_bd_base; + else + bdp++; + + } + cep->cur_rx = (cbd_t *)bdp; return 0; } static int -cpm_enet_open(struct device *dev) +cpm_enet_close(struct device *dev) { + /* Don't know what to do yet. + */ - /* I should reset the ring buffers here, but I don't yet know - * a simple way to do that. - */ - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - - return 0; /* Always succeed */ + return 0; } -static int -cpm_enet_start_xmit(struct sk_buff *skb, struct device *dev) +static struct net_device_stats *cpm_enet_get_stats(struct device *dev) { struct cpm_enet_private *cep = (struct cpm_enet_private *)dev->priv; - volatile cbd_t *bdp; - unsigned long flags; - /* Transmitter timeout, serious problems. */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 20) - return 1; - printk("%s: transmit timed out.\n", dev->name); - cep->stats.tx_errors++; -#ifndef final_version - { - int i; - cbd_t *bdp; - printk(" Ring data dump: cur_tx %x%s cur_rx %x.\n", - cep->cur_tx, cep->tx_full ? " (full)" : "", - cep->cur_rx); - bdp = cep->tx_bd_base; - for (i = 0 ; i < TX_RING_SIZE; i++) - printk("%04x %04x %08x\n", - bdp->cbd_sc, - bdp->cbd_datlen, - bdp->cbd_bufaddr); - bdp = cep->rx_bd_base; - for (i = 0 ; i < RX_RING_SIZE; i++) - printk("%04x %04x %08x\n", - bdp->cbd_sc, - bdp->cbd_datlen, - bdp->cbd_bufaddr); - } -#endif - - dev->tbusy=0; - dev->trans_start = jiffies; - - return 0; - } - - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - printk("%s: Transmitter access conflict.\n", dev->name); - return 1; - } - - if (test_and_set_bit(0, (void*)&cep->lock) != 0) { - printk("%s: tx queue lock!.\n", dev->name); - /* don't clear dev->tbusy flag. */ - return 1; - } - - /* Fill in a Tx ring entry */ - bdp = cep->cur_tx; - -#ifndef final_version - if (bdp->cbd_sc & BD_ENET_TX_READY) { - /* Ooops. All transmit buffers are full. Bail out. - * This should not happen, since dev->tbusy should be set. - */ - printk("%s: tx queue full!.\n", dev->name); - cep->lock = 0; - return 1; - } -#endif - - /* Clear all of the status flags. - */ - bdp->cbd_sc &= ~BD_ENET_TX_STATS; + return &cep->stats; +} - /* If the frame is short, tell CPM to pad it. - */ - if (skb->len <= ETH_ZLEN) - bdp->cbd_sc |= BD_ENET_TX_PAD; - else - bdp->cbd_sc &= ~BD_ENET_TX_PAD; +/* Set or clear the multicast filter for this adaptor. + * Skeleton taken from sunlance driver. + * The CPM Ethernet implementation allows Multicast as well as individual + * MAC address filtering. Some of the drivers check to make sure it is + * a group multicast address, and discard those that are not. I guess I + * will do the same for now, but just remove the test if you want + * individual filtering as well (do the upper net layers want or support + * this kind of feature?). + */ - /* Set buffer length and buffer pointer. - */ - bdp->cbd_datlen = skb->len; - bdp->cbd_bufaddr = __pa(skb->data); +static void set_multicast_list(struct device *dev) +{ + struct cpm_enet_private *cep; + struct dev_mc_list *dmi; + u_char *mcptr, *tdptr; + volatile scc_enet_t *ep; + int i, j; + cep = (struct cpm_enet_private *)dev->priv; - /* Save skb pointer. + /* Get pointer to SCC1 area in parameter RAM. */ - cep->tx_skbuff[cep->skb_cur] = skb; + ep = (scc_enet_t *)dev->base_addr; - cep->stats.tx_bytes += skb->len; - cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK; - - /* Push the data cache so the CPM does not get stale memory - * data. - */ - /*flush_dcache_range(skb->data, skb->data + skb->len);*/ + if (dev->flags&IFF_PROMISC) { + + /* Log any net taps. */ + printk("%s: Promiscuous mode enabled.\n", dev->name); + cep->sccp->scc_pmsr |= SCC_PMSR_PRO; + } else { - /* Send it on its way. Tell CPM its ready, interrupt when done, - * its the last BD of the frame, and to put the CRC on the end. - */ - bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC); + cep->sccp->scc_pmsr &= ~SCC_PMSR_PRO; - dev->trans_start = jiffies; + if (dev->flags & IFF_ALLMULTI) { + /* Catch all multicast addresses, so set the + * filter to all 1's. + */ + ep->sen_gaddr1 = 0xffff; + ep->sen_gaddr2 = 0xffff; + ep->sen_gaddr3 = 0xffff; + ep->sen_gaddr4 = 0xffff; + } + else { + /* Clear filter and add the addresses in the list. + */ + ep->sen_gaddr1 = 0; + ep->sen_gaddr2 = 0; + ep->sen_gaddr3 = 0; + ep->sen_gaddr4 = 0; - /* If this was the last BD in the ring, start at the beginning again. - */ - if (bdp->cbd_sc & BD_ENET_TX_WRAP) - bdp = cep->tx_bd_base; - else - bdp++; + dmi = dev->mc_list; - save_flags(flags); - cli(); - cep->lock = 0; - if (bdp->cbd_sc & BD_ENET_TX_READY) - cep->tx_full = 1; - else - dev->tbusy=0; - restore_flags(flags); + for (i=0; imc_count; i++) { + + /* Only support group multicast for now. + */ + if (!(dmi->dmi_addr[0] & 1)) + continue; - cep->cur_tx = (cbd_t *)bdp; + /* The address in dmi_addr is LSB first, + * and taddr is MSB first. We have to + * copy bytes MSB first from dmi_addr. + */ + mcptr = (u_char *)dmi->dmi_addr + 5; + tdptr = (u_char *)&ep->sen_taddrh; + for (j=0; j<6; j++) + *tdptr++ = *mcptr--; - return 0; + /* Ask CPM to run CRC and set bit in + * filter mask. + */ + cpmp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_SET_GADDR) | CPM_CR_FLG; + /* this delay is necessary here -- Cort */ + udelay(10); + while (cpmp->cp_cpcr & CPM_CR_FLG); + } + } + } } -/* The interrupt handler. - * This is called from the CPM handler, not the MPC core interrupt. +/* Initialize the CPM Ethernet on SCC1. If EPPC-Bug loaded us, or performed + * some other network I/O, a whole bunch of this has already been set up. + * It is no big deal if we do it again, we just have to disable the + * transmit and receive to make sure we don't catch the CPM with some + * inconsistent control information. */ -static void -cpm_enet_interrupt(void *dev_id) +__initfunc(int cpm_enet_init(void)) { - struct device *dev = dev_id; - struct cpm_enet_private *cep; - volatile cbd_t *bdp; - ushort int_events; - int must_restart; + struct device *dev; + struct cpm_enet_private *cep; + int i, j; + unsigned char *eap; + unsigned long mem_addr; + pte_t *pte; + volatile cbd_t *bdp; + volatile cpm8xx_t *cp; + volatile scc_t *sccp; + volatile scc_enet_t *ep; + volatile immap_t *immap; - cep = (struct cpm_enet_private *)dev->priv; - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); + cp = cpmp; /* Get pointer to Communication Processor */ - dev->interrupt = 1; + immap = (immap_t *)MBX_IMAP_ADDR; /* and to internal registers */ - /* Get the interrupt events that caused us to be here. + /* Allocate some private information. */ - int_events = cep->sccp->scc_scce; - must_restart = 0; + cep = (struct cpm_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL); + /*memset(cep, 0, sizeof(*cep));*/ + __clear_user(cep,sizeof(*cep)); - /* Handle receive event in its own function. + /* Create an Ethernet device instance. */ - if (int_events & SCCE_ENET_RXF) - cpm_enet_rx(dev_id); + dev = init_etherdev(0, 0); - /* Check for a transmit error. The manual is a little unclear - * about this, so the debug code until I get it figured out. It - * appears that if TXE is set, then TXB is not set. However, - * if carrier sense is lost during frame transmission, the TXE - * bit is set, "and continues the buffer transmission normally." - * I don't know if "normally" implies TXB is set when the buffer - * descriptor is closed.....trial and error :-). - */ - if (int_events & SCCE_ENET_TXE) { + /* Get pointer to SCC1 area in parameter RAM. + */ + ep = (scc_enet_t *)(&cp->cp_dparam[PROFF_SCC1]); - /* Transmission errors. - */ - bdp = cep->dirty_tx; -#ifndef final_version - printk("CPM ENET xmit error %x\n", bdp->cbd_sc); - if (bdp->cbd_sc & BD_ENET_TX_READY) - printk("HEY! Enet xmit interrupt and TX_READY.\n"); -#endif - if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */ - cep->stats.tx_heartbeat_errors++; - if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */ - cep->stats.tx_window_errors++; - if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */ - cep->stats.tx_aborted_errors++; - if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */ - cep->stats.tx_fifo_errors++; - if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */ - cep->stats.tx_carrier_errors++; + /* And another to the SCC register area. + */ + sccp = (volatile scc_t *)(&cp->cp_scc[0]); + cep->sccp = (scc_t *)sccp; /* Keep the pointer handy */ - cep->stats.tx_errors++; + /* Disable receive and transmit in case EPPC-Bug started it. + */ + sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); - /* No heartbeat or Lost carrier are not really bad errors. - * The others require a restart transmit command. - */ - if (bdp->cbd_sc & - (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) - must_restart = 1; - } + /* Cookbook style from the MPC860 manual..... + * Not all of this is necessary if EPPC-Bug has initialized + * the network. + */ - /* Transmit OK, or non-fatal error. Update the buffer descriptors. + /* Configure port A pins for Txd and Rxd. */ - if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) { - cep->stats.tx_packets++; - bdp = cep->dirty_tx; -#ifndef final_version - if (bdp->cbd_sc & BD_ENET_TX_READY) - printk("HEY! Enet xmit interrupt and TX_READY.\n"); -#endif - /* Deferred means some collisions occurred during transmit, - * but we eventually sent the packet OK. - */ - if (bdp->cbd_sc & BD_ENET_TX_DEF) - cep->stats.collisions++; + immap->im_ioport.iop_papar |= (PA_ENET_RXD | PA_ENET_TXD); + immap->im_ioport.iop_padir &= ~(PA_ENET_RXD | PA_ENET_TXD); + immap->im_ioport.iop_paodr &= ~PA_ENET_TXD; - /* Free the sk buffer associated with this last transmit. - */ - dev_kfree_skb(cep->tx_skbuff[cep->skb_dirty]/*, FREE_WRITE*/); - cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK; + /* Configure port C pins to enable CLSN and RENA. + */ + immap->im_ioport.iop_pcpar &= ~(PC_ENET_CLSN | PC_ENET_RENA); + immap->im_ioport.iop_pcdir &= ~(PC_ENET_CLSN | PC_ENET_RENA); + immap->im_ioport.iop_pcso |= (PC_ENET_CLSN | PC_ENET_RENA); - /* Update pointer to next buffer descriptor to be transmitted. - */ - if (bdp->cbd_sc & BD_ENET_TX_WRAP) - bdp = cep->tx_bd_base; - else - bdp++; + /* Configure port A for TCLK and RCLK. + */ + immap->im_ioport.iop_papar |= (PA_ENET_TCLK | PA_ENET_RCLK); + immap->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK); - /* I don't know if we can be held off from processing these - * interrupts for more than one frame time. I really hope - * not. In such a case, we would now want to check the - * currently available BD (cur_tx) and determine if any - * buffers between the dirty_tx and cur_tx have also been - * sent. We would want to process anything in between that - * does not have BD_ENET_TX_READY set. - */ + /* Configure Serial Interface clock routing. + * First, clear all SCC1 bits to zero, then set the ones we want. + */ + cp->cp_sicr &= ~SICR_ENET_MASK; + cp->cp_sicr |= SICR_ENET_CLKRT; - /* Since we have freed up a buffer, the ring is no longer - * full. - */ - if (cep->tx_full && dev->tbusy) { - cep->tx_full = 0; - dev->tbusy = 0; - mark_bh(NET_BH); - } + /* Manual says set SDDR, but I can't find anything with that + * name. I think it is a misprint, and should be SDCR. This + * has already been set by the communication processor initialization. + */ - cep->dirty_tx = (cbd_t *)bdp; - } + /* Allocate space for the buffer descriptors in the DP ram. + * These are relative offsets in the DP ram address space. + * Initialize base addresses for the buffer descriptors. + */ + i = mbx_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE); + ep->sen_genscc.scc_rbase = i; + cep->rx_bd_base = (cbd_t *)&cp->cp_dpmem[i]; - if (must_restart) { - volatile cpm8xx_t *cp; + i = mbx_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE); + ep->sen_genscc.scc_tbase = i; + cep->tx_bd_base = (cbd_t *)&cp->cp_dpmem[i]; - /* Some transmit errors cause the transmitter to shut - * down. We now issue a restart transmit. Since the - * errors close the BD and update the pointers, the restart - * _should_ pick up without having to reset any of our - * pointers either. - */ - cp = cpmp; - cp->cp_cpcr = - mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_RESTART_TX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); - } + cep->dirty_tx = cep->cur_tx = cep->tx_bd_base; + cep->cur_rx = cep->rx_bd_base; - /* Check for receive busy, i.e. packets coming but no place to - * put them. This "can't happen" because the receive interrupt - * is tossing previous frames. + /* Issue init Rx BD command for SCC1. + * Manual says to perform an Init Rx parameters here. We have + * to perform both Rx and Tx because the SCC may have been + * already running. + * In addition, we have to do it later because we don't yet have + * all of the BD control/status set properly. + cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_INIT_RX) | CPM_CR_FLG; + while (cp->cp_cpcr & CPM_CR_FLG); */ - if (int_events & SCCE_ENET_BSY) { - cep->stats.rx_dropped++; - printk("CPM ENET: BSY can't happen.\n"); - } - /* Write the SCC event register with the events we have handled - * to clear them. Maybe we should do this sooner? + /* Initialize function code registers for big-endian. + */ + ep->sen_genscc.scc_rfcr = SCC_EB; + ep->sen_genscc.scc_tfcr = SCC_EB; + + /* Set maximum bytes per receive buffer. + * This appears to be an Ethernet frame size, not the buffer + * fragment size. It must be a multiple of four. */ - cep->sccp->scc_scce = int_events; + ep->sen_genscc.scc_mrblr = PKT_MAXBLR_SIZE; - dev->interrupt = 0; + /* Set CRC preset and mask. + */ + ep->sen_cpres = 0xffffffff; + ep->sen_cmask = 0xdebb20e3; - return; -} + ep->sen_crcec = 0; /* CRC Error counter */ + ep->sen_alec = 0; /* alignment error counter */ + ep->sen_disfc = 0; /* discard frame counter */ -/* During a receive, the cur_rx points to the current incoming buffer. - * When we update through the ring, if the next incoming buffer has - * not been given to the system, we just set the empty indicator, - * effectively tossing the packet. - */ -static int -cpm_enet_rx(struct device *dev) -{ - struct cpm_enet_private *cep; - volatile cbd_t *bdp; - struct sk_buff *skb; - ushort pkt_len; + ep->sen_pads = 0x8888; /* Tx short frame pad character */ + ep->sen_retlim = 15; /* Retry limit threshold */ - cep = (struct cpm_enet_private *)dev->priv; + ep->sen_maxflr = PKT_MAXBUF_SIZE; /* maximum frame length register */ + ep->sen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register */ + + ep->sen_maxd1 = PKT_MAXBUF_SIZE; /* maximum DMA1 length */ + ep->sen_maxd2 = PKT_MAXBUF_SIZE; /* maximum DMA2 length */ - /* First, grab all of the stats for the incoming packet. - * These get messed up if we get called due to a busy condition. - */ - bdp = cep->cur_rx; + /* Clear hash tables. + */ + ep->sen_gaddr1 = 0; + ep->sen_gaddr2 = 0; + ep->sen_gaddr3 = 0; + ep->sen_gaddr4 = 0; + ep->sen_iaddr1 = 0; + ep->sen_iaddr2 = 0; + ep->sen_iaddr3 = 0; + ep->sen_iaddr4 = 0; -for (;;) { - if (bdp->cbd_sc & BD_ENET_RX_EMPTY) - break; - -#ifndef final_version - /* Since we have allocated space to hold a complete frame, both - * the first and last indicators should be set. + /* Set Ethernet station address. This must come from the + * Vital Product Data (VPD) EEPROM.....as soon as I get the + * I2C interface working..... + * + * Since we performed a diskless boot, the Ethernet controller + * has been initialized and we copy the address out into our + * own structure. */ - if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) != - (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) - printk("CPM ENET: rcv is not first+last\n"); +#ifdef notdef + ep->sen_paddrh = my_enet_addr[0]; + ep->sen_paddrm = my_enet_addr[1]; + ep->sen_paddrl = my_enet_addr[2]; +#else + eap = (unsigned char *)&(ep->sen_paddrh); + for (i=5; i>=0; i--) + dev->dev_addr[i] = *eap++; #endif - /* Frame too long or too short. - */ - if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH)) - cep->stats.rx_length_errors++; - if (bdp->cbd_sc & BD_ENET_RX_NO) /* Frame alignment */ - cep->stats.rx_frame_errors++; - if (bdp->cbd_sc & BD_ENET_RX_CR) /* CRC Error */ - cep->stats.rx_crc_errors++; - if (bdp->cbd_sc & BD_ENET_RX_OV) /* FIFO overrun */ - cep->stats.rx_crc_errors++; + ep->sen_pper = 0; /* 'cause the book says so */ + ep->sen_taddrl = 0; /* temp address (LSB) */ + ep->sen_taddrm = 0; + ep->sen_taddrh = 0; /* temp address (MSB) */ - /* Report late collisions as a frame error. - * On this error, the BD is closed, but we don't know what we - * have in the buffer. So, just drop this frame on the floor. + /* Now allocate the host memory pages and initialize the + * buffer descriptors. */ - if (bdp->cbd_sc & BD_ENET_RX_CL) { - cep->stats.rx_frame_errors++; - } - else { - - /* Process the incoming frame. - */ - cep->stats.rx_packets++; - pkt_len = bdp->cbd_datlen; - cep->stats.rx_bytes += pkt_len; + bdp = cep->tx_bd_base; + for (i=0; iname); - cep->stats.rx_dropped++; - } - else { - skb->dev = dev; - skb_put(skb,pkt_len); /* Make room */ - eth_copy_and_sum(skb, - (unsigned char *)__va(bdp->cbd_bufaddr), - pkt_len, 0); - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - } + bdp->cbd_sc = 0; + bdp->cbd_bufaddr = 0; + bdp++; } - /* Clear the status flags for this buffer. + /* Set the last buffer to wrap. */ - bdp->cbd_sc &= ~BD_ENET_RX_STATS; + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; - /* Mark the buffer empty. - */ - bdp->cbd_sc |= BD_ENET_RX_EMPTY; + bdp = cep->rx_bd_base; + for (i=0; icbd_sc & BD_ENET_RX_WRAP) - bdp = cep->rx_bd_base; - else - bdp++; + /* Allocate a page. + */ + mem_addr = __get_free_page(GFP_KERNEL); - } - cep->cur_rx = (cbd_t *)bdp; + /* Make it uncached. + */ + pte = va_to_pte(&init_task, mem_addr); + pte_val(*pte) |= _PAGE_NO_CACHE; + flush_tlb_page(current->mm->mmap, mem_addr); - return 0; -} + /* Initialize the BD for every fragment in the page. + */ + for (j=0; jcbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR; + bdp->cbd_bufaddr = __pa(mem_addr); + mem_addr += CPM_ENET_RX_FRSIZE; + bdp++; + } + } -static int -cpm_enet_close(struct device *dev) -{ - /* Don't know what to do yet. + /* Set the last buffer to wrap. */ + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; - return 0; -} + /* Let's re-initialize the channel now. We have to do it later + * than the manual describes because we have just now finished + * the BD initialization. + */ + cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_INIT_TRX) | CPM_CR_FLG; + while (cp->cp_cpcr & CPM_CR_FLG); -static struct net_device_stats *cpm_enet_get_stats(struct device *dev) -{ - struct cpm_enet_private *cep = (struct cpm_enet_private *)dev->priv; + cep->skb_cur = cep->skb_dirty = 0; - return &cep->stats; -} + sccp->scc_scce = 0xffff; /* Clear any pending events */ -/* Set or clear the multicast filter for this adaptor. - * Skeleton taken from sunlance driver. - * The CPM Ethernet implementation allows Multicast as well as individual - * MAC address filtering. Some of the drivers check to make sure it is - * a group multicast address, and discard those that are not. I guess I - * will do the same for now, but just remove the test if you want - * individual filtering as well (do the upper net layers want or support - * this kind of feature?). - */ + /* Enable interrupts for transmit error, complete frame + * received, and any transmit buffer we have also set the + * interrupt flag. + */ + sccp->scc_sccm = (SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB); -static void set_multicast_list(struct device *dev) -{ - struct cpm_enet_private *cep; - struct dev_mc_list *dmi; - u_char *mcptr, *tdptr; - volatile scc_enet_t *ep; - int i, j; + /* Install our interrupt handler. + */ + cpm_install_handler(CPMVEC_SCC1, cpm_enet_interrupt, dev); - cep = (struct cpm_enet_private *)dev->priv; + /* Set GSMR_H to enable all normal operating modes. + * Set GSMR_L to enable Ethernet to MC68160. + */ + sccp->scc_gsmrh = 0; + sccp->scc_gsmrl = (SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 | SCC_GSMRL_MODE_ENET); - /* Get pointer to SCC1 area in parameter RAM. + /* Set sync/delimiters. */ - ep = (scc_enet_t *)dev->base_addr; + sccp->scc_dsr = 0xd555; - if (dev->flags&IFF_PROMISC) { - /* Log any net taps. */ - printk("%s: Promiscuous mode enabled.\n", dev->name); - cep->sccp->scc_pmsr |= SCC_PMSR_PRO; - } else { + /* Set processing mode. Use Ethernet CRC, catch broadcast, and + * start frame search 22 bit times after RENA. + */ + sccp->scc_pmsr = (SCC_PMSR_ENCRC | SCC_PMSR_BRO | SCC_PMSR_NIB22); - cep->sccp->scc_pmsr &= ~SCC_PMSR_PRO; + /* It is now OK to enable the Ethernet transmitter. + */ + immap->im_ioport.iop_pcpar |= PC_ENET_TENA; + immap->im_ioport.iop_pcdir &= ~PC_ENET_TENA; - if (dev->flags & IFF_ALLMULTI) { - /* Catch all multicast addresses, so set the - * filter to all 1's. - */ - ep->sen_gaddr1 = 0xffff; - ep->sen_gaddr2 = 0xffff; - ep->sen_gaddr3 = 0xffff; - ep->sen_gaddr4 = 0xffff; - } - else { - /* Clear filter and add the addresses in the list. - */ - ep->sen_gaddr1 = 0; - ep->sen_gaddr2 = 0; - ep->sen_gaddr3 = 0; - ep->sen_gaddr4 = 0; + dev->base_addr = (unsigned long)ep; + dev->priv = cep; + dev->name = "CPM_ENET"; - dmi = dev->mc_list; + /* The CPM Ethernet specific entries in the device structure. */ + dev->open = cpm_enet_open; + dev->hard_start_xmit = cpm_enet_start_xmit; + dev->stop = cpm_enet_close; + dev->get_stats = cpm_enet_get_stats; + dev->set_multicast_list = set_multicast_list; - for (i=0; imc_count; i++) { - - /* Only support group multicast for now. - */ - if (!(dmi->dmi_addr[0] & 1)) - continue; + /* And last, enable the transmit and receive processing. + */ + sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); - /* The address in dmi_addr is LSB first, - * and taddr is MSB first. We have to - * copy bytes MSB first from dmi_addr. - */ - mcptr = (u_char *)dmi->dmi_addr + 5; - tdptr = (u_char *)&ep->sen_taddrh; - for (j=0; j<6; j++) - *tdptr++ = *mcptr--; + printk("CPM ENET Version 0.1, "); + for (i=0; i<5; i++) + printk("%02x:", dev->dev_addr[i]); + printk("%02x\n", dev->dev_addr[5]); - /* Ask CPM to run CRC and set bit in - * filter mask. - */ - cpmp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_SET_GADDR) | CPM_CR_FLG; - while (cpmp->cp_cpcr & CPM_CR_FLG); - } - } - } + return 0; } + diff -u --recursive --new-file v2.1.100/linux/arch/ppc/8xx_io/uart.c linux/arch/ppc/8xx_io/uart.c --- v2.1.100/linux/arch/ppc/8xx_io/uart.c Thu Apr 23 20:21:28 1998 +++ linux/arch/ppc/8xx_io/uart.c Fri May 8 00:18:13 1998 @@ -59,6 +59,7 @@ static struct tty_driver serial_driver, callout_driver; static int serial_refcount; +static int serial_console_setup(struct console *co, char *options); /* * Serial driver configuration section. Here are the various options: @@ -277,7 +278,7 @@ { struct tty_struct *tty = info->tty; unsigned char ch, *cp; - int ignored = 0; + /*int ignored = 0;*/ int i; ushort status; struct async_icount *icount; @@ -594,10 +595,10 @@ tty_hangup(tty); } -static void rs_8xx_timer(void) +/*static void rs_8xx_timer(void) { printk("rs_8xx_timer\n"); -} +}*/ static int startup(ser_info_t *info) @@ -1607,7 +1608,7 @@ { ser_info_t *info = (ser_info_t *)tty->driver_data; unsigned long orig_jiffies, char_time; - int lsr; + /*int lsr;*/ volatile cbd_t *bdp; if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent")) @@ -1645,7 +1646,7 @@ printk("lsr = %d (jiff=%lu)...", lsr, jiffies); #endif current->state = TASK_INTERRUPTIBLE; -/* current->counter = 0; /* make us low-priority */ +/* current->counter = 0; make us low-priority */ current->timeout = jiffies + char_time; schedule(); if (signal_pending(current)) @@ -2030,6 +2031,185 @@ printk(KERN_INFO "%s version %s\n", serial_name, serial_version); } + +/* + * The serial console driver used during boot. Note that these names + * clash with those found in "serial.c", so we currently can't support + * the 16xxx uarts and these at the same time. I will fix this to become + * an indirect function call from tty_io.c (or something). + */ + +#ifdef CONFIG_SERIAL_CONSOLE + +/* + * Print a string to the serial port trying not to disturb any possible + * real use of the port... + */ +static void serial_console_write(struct console *c, const char *s, + unsigned count) +{ + struct serial_state *ser; + ser_info_t *info; + unsigned i; + volatile cbd_t *bdp, *bdbase; + volatile smc_uart_t *up; + volatile u_char *cp; + + ser = rs_table + c->index; + + /* If the port has been initialized for general use, we have + * to use the buffer descriptors allocated there. Otherwise, + * we simply use the single buffer allocated. + */ + if ((info = (ser_info_t *)ser->info) != NULL) { + bdp = info->tx_cur; + bdbase = info->tx_bd_base; + } + else { + /* Pointer to UART in parameter ram. + */ + up = (smc_uart_t *)&cpmp->cp_dparam[ser->port]; + + /* Get the address of the host memory buffer. + */ + bdp = bdbase = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase]; + } + + /* + * We need to gracefully shut down the transmitter, disable + * interrupts, then send our bytes out. + */ + + /* + * Now, do each character. This is not as bad as it looks + * since this is a holding FIFO and not a transmitting FIFO. + * We could add the complexity of filling the entire transmit + * buffer, but we would just wait longer between accesses...... + */ + for (i = 0; i < count; i++, s++) { + /* Wait for transmitter fifo to empty. + * Ready indicates output is ready, and xmt is doing + * that, not that it is ready for us to send. + */ + while (bdp->cbd_sc & BD_SC_READY); + /* Send the character out. */ + cp = __va(bdp->cbd_bufaddr); + *cp = *s; + + bdp->cbd_datlen = 1; + bdp->cbd_sc |= BD_SC_READY; + + if (bdp->cbd_sc & BD_SC_WRAP) + bdp = bdbase; + else + bdp++; + + /* if a LF, also do CR... */ + if (*s == 10) { + while (bdp->cbd_sc & BD_SC_READY); + cp = __va(bdp->cbd_bufaddr); + *cp = 13; + bdp->cbd_datlen = 1; + bdp->cbd_sc |= BD_SC_READY; + + if (bdp->cbd_sc & BD_SC_WRAP) { + bdp = bdbase; + } + else { + bdp++; + } + } + } + + /* + * Finally, Wait for transmitter & holding register to empty + * and restore the IER + */ + while (bdp->cbd_sc & BD_SC_READY); + + if (info) + info->tx_cur = (cbd_t *)bdp; +} + +/* + * Receive character from the serial port. This only works well + * before the port is initialize for real use. + */ +static int serial_console_wait_key(struct console *co) +{ + struct serial_state *ser; + u_char c, *cp; + ser_info_t *info; + volatile cbd_t *bdp; + volatile smc_uart_t *up; + + ser = rs_table + co->index; + + /* Pointer to UART in parameter ram. + */ + up = (smc_uart_t *)&cpmp->cp_dparam[ser->port]; + + /* Get the address of the host memory buffer. + * If the port has been initialized for general use, we must + * use information from the port structure. + */ + if ((info = (ser_info_t *)ser->info)) + bdp = info->rx_cur; + else + bdp = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; + + /* + * We need to gracefully shut down the receiver, disable + * interrupts, then read the input. + */ + while (bdp->cbd_sc & BD_SC_EMPTY); /* Wait for a character */ + cp = __va(bdp->cbd_bufaddr); + + if (info) { + if (bdp->cbd_sc & BD_SC_WRAP) { + bdp = info->rx_bd_base; + } + else { + bdp++; + } + info->rx_cur = (cbd_t *)bdp; + } + + c = *cp; + return((int)c); +} + +static kdev_t serial_console_device(struct console *c) +{ + return MKDEV(TTYAUX_MAJOR, 64 + c->index); +} + + +static struct console sercons = { + "ttyS", + serial_console_write, + NULL, + serial_console_device, + serial_console_wait_key, + NULL, + serial_console_setup, + CON_PRINTBUFFER, + CONFIG_SERIAL_CONSOLE_PORT, + 0, + NULL +}; + +/* + * Register console. + */ +__initfunc (long console_8xx_init(long kmem_start, long kmem_end)) +{ + register_console(&sercons); + return kmem_start; +} + +#endif + /* * The serial driver boot-time initialization code! */ @@ -2055,7 +2235,8 @@ /* Initialize the tty_driver structure */ - memset(&serial_driver, 0, sizeof(struct tty_driver)); + /*memset(&serial_driver, 0, sizeof(struct tty_driver));*/ + __clear_user(&serial_driver,sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; serial_driver.driver_name = "serial"; serial_driver.name = "ttyS"; @@ -2147,7 +2328,8 @@ #endif info = kmalloc(sizeof(ser_info_t), GFP_KERNEL); if (info) { - memset(info, 0, sizeof(ser_info_t)); + /*memset(info, 0, sizeof(ser_info_t));*/ + __clear_user(info,sizeof(ser_info_t)); info->magic = SERIAL_MAGIC; info->flags = state->flags; info->tqueue.routine = do_softint; @@ -2267,159 +2449,6 @@ return 0; } -/* - * The serial console driver used during boot. Note that these names - * clash with those found in "serial.c", so we currently can't support - * the 16xxx uarts and these at the same time. I will fix this to become - * an indirect function call from tty_io.c (or something). - */ - -#ifdef CONFIG_SERIAL_CONSOLE - -/* - * Print a string to the serial port trying not to disturb any possible - * real use of the port... - */ -static void serial_console_write(struct console *c, const char *s, - unsigned count) -{ - struct serial_state *ser; - ser_info_t *info; - unsigned i; - volatile cbd_t *bdp, *bdbase; - volatile smc_uart_t *up; - volatile u_char *cp; - - ser = rs_table + c->index; - - /* If the port has been initialized for general use, we have - * to use the buffer descriptors allocated there. Otherwise, - * we simply use the single buffer allocated. - */ - if ((info = (ser_info_t *)ser->info) != NULL) { - bdp = info->tx_cur; - bdbase = info->tx_bd_base; - } - else { - /* Pointer to UART in parameter ram. - */ - up = (smc_uart_t *)&cpmp->cp_dparam[ser->port]; - - /* Get the address of the host memory buffer. - */ - bdp = bdbase = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase]; - } - - /* - * We need to gracefully shut down the transmitter, disable - * interrupts, then send our bytes out. - */ - - /* - * Now, do each character. This is not as bad as it looks - * since this is a holding FIFO and not a transmitting FIFO. - * We could add the complexity of filling the entire transmit - * buffer, but we would just wait longer between accesses...... - */ - for (i = 0; i < count; i++, s++) { - - /* Wait for transmitter fifo to empty. - * Ready indicates output is ready, and xmt is doing - * that, not that it is ready for us to send. - */ - while (bdp->cbd_sc & BD_SC_READY); - - /* Send the character out. */ - cp = __va(bdp->cbd_bufaddr); - *cp = *s; - bdp->cbd_datlen = 1; - bdp->cbd_sc |= BD_SC_READY; - - if (bdp->cbd_sc & BD_SC_WRAP) - bdp = bdbase; - else - bdp++; - - /* if a LF, also do CR... */ - if (*s == 10) { - while (bdp->cbd_sc & BD_SC_READY); - cp = __va(bdp->cbd_bufaddr); - *cp = 13; - bdp->cbd_datlen = 1; - bdp->cbd_sc |= BD_SC_READY; - - if (bdp->cbd_sc & BD_SC_WRAP) { - bdp = bdbase; - } - else { - bdp++; - } - } - } - - /* - * Finally, Wait for transmitter & holding register to empty - * and restore the IER - */ - while (bdp->cbd_sc & BD_SC_READY); - - if (info) - info->tx_cur = (cbd_t *)bdp; -} - -/* - * Receive character from the serial port. This only works well - * before the port is initialize for real use. - */ -static int serial_console_wait_key(struct console *co) -{ - struct serial_state *ser; - u_char c, *cp; - ser_info_t *info; - volatile cbd_t *bdp; - volatile smc_uart_t *up; - - ser = rs_table + co->index; - - /* Pointer to UART in parameter ram. - */ - up = (smc_uart_t *)&cpmp->cp_dparam[ser->port]; - - /* Get the address of the host memory buffer. - * If the port has been initialized for general use, we must - * use information from the port structure. - */ - if ((info = ser->info)) - bdp = info->rx_cur; - else - bdp = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; - - /* - * We need to gracefully shut down the receiver, disable - * interrupts, then read the input. - */ - while (bdp->cbd_sc & BD_SC_EMPTY); /* Wait for a character */ - cp = __va(bdp->cbd_bufaddr); - - if (info) { - if (bdp->cbd_sc & BD_SC_WRAP) { - bdp = info->rx_bd_base; - } - else { - bdp++; - } - info->rx_cur = (cbd_t *)bdp; - } - - c = *cp; - return((int)c); -} - -static kdev_t serial_console_device(struct console *c) -{ - return MKDEV(TTYAUX_MAJOR, 64 + c->index); -} - /* This must always be called before the rs_8xx_init() function, otherwise * it blows away the port control information. */ @@ -2431,7 +2460,6 @@ volatile cpm8xx_t *cp; volatile smc_t *sp; volatile smc_uart_t *up; - co->cflag = CREAD|CLOCAL|B9600|CS8; ser = rs_table + co->index; @@ -2441,7 +2469,6 @@ /* Right now, assume we are using SMCs. */ sp = &cp->cp_smc[ser->smc_scc_num]; - /* When we get here, the CPM has been reset, so we need * to configure the port. * We need to allocate a transmit and receive buffer descriptor @@ -2486,8 +2513,12 @@ /* Send the CPM an initialize command. */ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC1, CPM_CR_INIT_TRX) | CPM_CR_FLG; + /* + * delay for a bit - this is necessary on my board! + * -- Cort + */ + printk(""); while (cp->cp_cpcr & CPM_CR_FLG); - /* Set UART mode, 8 bit, no parity, one stop. * Enable receive and transmit. */ @@ -2496,35 +2527,10 @@ /* Set up the baud rate generator. */ mbx_cpm_setbrg(ser->smc_scc_num, 9600); - + /* And finally, enable Rx and Tx. */ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; return 0; } - -static struct console sercons = { - "ttyS", - serial_console_write, - NULL, - serial_console_device, - serial_console_wait_key, - NULL, - serial_console_setup, - CON_PRINTBUFFER, - CONFIG_SERIAL_CONSOLE_PORT, - 0, - NULL -}; - -/* - * Register console. - */ -__initfunc (long console_8xx_init(long kmem_start, long kmem_end)) -{ - register_console(&sercons); - return kmem_start; -} - -#endif diff -u --recursive --new-file v2.1.100/linux/arch/ppc/Makefile linux/arch/ppc/Makefile --- v2.1.100/linux/arch/ppc/Makefile Thu Apr 23 20:21:28 1998 +++ linux/arch/ppc/Makefile Fri May 8 00:09:20 1998 @@ -95,6 +95,8 @@ @$(MAKEBOOT) clean @$(MAKECHRPBOOT) clean +archmrproper: + archdep: $(MAKEBOOT) fastdep $(MAKECHRPBOOT) fastdep diff -u --recursive --new-file v2.1.100/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile --- v2.1.100/linux/arch/ppc/boot/Makefile Thu Apr 23 20:21:28 1998 +++ linux/arch/ppc/boot/Makefile Fri May 8 00:18:13 1998 @@ -69,9 +69,25 @@ --add-section=image=../coffboot/vmlinux.gz \ zvmlinux.initrd.tmp $@ rm zvmlinux.initrd.tmp - -else -zvmlinux.initrd: +endif +ifeq ($(CONFIG_MBX),y) +zvmlinux.initrd: zvmlinux + $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS) + $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ + --add-section=initrd=ramdisk.image.gz \ + --add-section=image=../coffboot/vmlinux.gz \ + zvmlinux.initrd.tmp zvmlinux.initrd + $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset zvmlinux.initrd initrd` \ + -DINITRD_SIZE=`sh size zvmlinux.initrd initrd` \ + -DZIMAGE_OFFSET=`sh offset zvmlinux.initrd image` \ + -DZIMAGE_SIZE=`sh size zvmlinux.initrd image` \ + -DKERNELBASE=$(KERNELBASE) -c -o misc.o misc.c + $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS) + $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ + --add-section=initrd=ramdisk.image.gz \ + --add-section=image=../coffboot/vmlinux.gz \ + zvmlinux.initrd.tmp $@ + rm zvmlinux.initrd.tmp endif zImage: zvmlinux mkprep diff -u --recursive --new-file v2.1.100/linux/arch/ppc/boot/head.S linux/arch/ppc/boot/head.S --- v2.1.100/linux/arch/ppc/boot/head.S Sat Apr 25 18:13:10 1998 +++ linux/arch/ppc/boot/head.S Fri May 8 00:18:13 1998 @@ -43,6 +43,28 @@ ori r4,r4,MSR_EE andc r3,r3,r4 mtmsr r3 +/* check if we need to relocate ourselves to the link addr or were we + loaded there to begin with -- Cort */ + lis r4,start@h + ori r4,r4,start@l + mflr r3 + subi r3,r3,4 /* we get the nip, not the ip of the branch */ + mr r8,r3 + cmp 0,r3,r4 + bne 1010f +/* compute size of whole image in words. this should be moved to + * start_ldr() -- Cort + */ + lis r4,start@h + ori r4,r4,start@l + lis r5,end@h + ori r5,r5,end@l + addi r5,r5,3 /* round up */ + sub r5,r5,r4 + srwi r5,r5,2 + mr r7,r5 + b start_ldr +1010: /* Copy relocation code down to location 0x0100 (where we hope it's safe!) */ mflr r3 addi r5,r3,start_ldr-start_ @@ -115,13 +137,18 @@ andc r1,r1,r2 /* Run loader */ #ifdef CONFIG_MBX + mr r21, r11 bl serial_init /* Init MBX serial port */ -#define ILAP_ADDRESS 0xfa000020 - lis r8, ILAP_ADDRESS@h - lwz r8, ILAP_ADDRESS@l(r8) + mr r11, r21 + lis r8,start@h + ori r8,r8,start@l li r9,end@h ori r9,r9,end@l sub r7,r8,r9 + srwi r7,r7,2 +#define ILAP_ADDRESS 0xfa000020 + lis r8, ILAP_ADDRESS@h + lwz r8, ILAP_ADDRESS@l(r8) addis r8, r8, 1 /* Add 64K */ #endif mr r3,r8 /* Load point */ diff -u --recursive --new-file v2.1.100/linux/arch/ppc/boot/misc.c linux/arch/ppc/boot/misc.c --- v2.1.100/linux/arch/ppc/boot/misc.c Thu Apr 23 20:21:28 1998 +++ linux/arch/ppc/boot/misc.c Fri May 8 00:18:13 1998 @@ -11,22 +11,34 @@ #include "asm/residual.h" #include #include +#include #ifdef CONFIG_MBX #include bd_t hold_board_info; #endif -/* this is where the INITRD gets moved to for safe keeping */ -#define INITRD_DESTINATION /*0x00f00000*/ 0x01800000 -#ifdef CONFIG_8xx -char *avail_ram = (char *) 0x00200000; -char *end_avail = (char *) 0x00400000; -#else /* CONFIG_8xx */ -/* this will do for now - Cort */ -char *avail_ram = (char *) 0x00800000; /* start with 8M */ -/* assume 15M max since this is where we copy the initrd to -- Cort */ -char *end_avail = (char *) INITRD_DESTINATION; -#endif /* CONFIG_8xx */ +/* + * MBX: loads at: 0x00200000 + * board data at: end of ram + * PREP: + * powerstack 1: + * network load at: configurable - should set to link addr-0x400 + * exec. addr set to link addr + * such as load: 0x005ffc00 exec 0x00600000 + * hd/floppy/tape load at: + * powerstack 2: + * loads at: 0x00400000 + * IBM 830 (carolina): + * loads at: ??? + * + * Please send me load/board info and such data for hardware not + * listed here so I can keep track since things are getting tricky + * with the different load addrs with different firmware. This will + * help to avoid breaking the load/boot process. + * -- Cort + */ +char *avail_ram; +char *end_avail; char cmd_line[256]; RESIDUAL hold_residual; @@ -313,24 +325,35 @@ orig_y = 24; -#ifndef CONFIG_8xx +#ifndef CONFIG_MBX vga_init(0xC0000000); /* copy the residual data */ if (residual) memcpy(&hold_residual,residual,sizeof(RESIDUAL)); -#endif /* CONFIG_8xx */ -#ifdef CONFIG_MBX +#else /* CONFIG_MBX */ /* copy board data */ if (residual) _bcopy((char *)residual, (char *)&hold_board_info, sizeof(hold_board_info)); -#endif /* CONFIG_8xx */ +#endif /* CONFIG_MBX */ + + /* MBX/prep put the board/residual data at the end of memory */ + if ( residual ) + end_avail = (char *)PAGE_ALIGN((unsigned long)residual); + /* prep netboot looses the residual */ + else + end_avail = (char *)0x00800000; puts("loaded at: "); puthex(load_addr); puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n"); - puts("relocated to: "); puthex((unsigned long)&start); - puts(" "); puthex((unsigned long)((unsigned long)&start + (4*num_words))); puts("\n"); + if ( (unsigned long)load_addr != (unsigned long)&start ) + { + puts("relocated to: "); puthex((unsigned long)&start); + puts(" "); + puthex((unsigned long)((unsigned long)&start + (4*num_words))); + puts("\n"); + } if ( residual ) { @@ -357,6 +380,8 @@ puts("\n"); } + /* we have to subtract 0x10000 here to correct for objdump including the + size of the elf header which we strip -- Cort */ zimage_start = (char *)(load_addr - 0x10000 + ZIMAGE_OFFSET); zimage_size = ZIMAGE_SIZE; puts("zimage at: "); puthex((unsigned long)zimage_start); @@ -367,20 +392,45 @@ else initrd_start = 0; initrd_end = INITRD_SIZE + initrd_start; - + + /* + * setup avail_ram - this is the first part of ram usable + * by the uncompress code. -- Cort + */ + avail_ram = (char *)PAGE_ALIGN((unsigned long)zimage_start+zimage_size); + if ( (load_addr+(num_words*4)) > (unsigned long) avail_ram ) + avail_ram = (char *)(load_addr+(num_words*4)); + if ( ((unsigned long)&start+(num_words*4)) > (unsigned long) avail_ram ) + avail_ram = (char *)((unsigned long)&start+(num_words*4)); + /* relocate initrd */ if ( initrd_start ) { puts("initrd at: "); puthex(initrd_start); puts(" "); puthex(initrd_end); puts("\n"); - - memcpy ((void *)INITRD_DESTINATION,(void *)initrd_start, + /* + * Memory is really tight on the MBX (we can assume 4M) + * so put the initrd at the TOP of ram, and set end_avail + * to right after that. + * + * I should do something like this for prep, too and keep + * a variable end_of_DRAM to keep track of what we think the + * max ram is. + * -- Cort + */ + memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE), + (void *)initrd_start, INITRD_SIZE ); - initrd_end = INITRD_DESTINATION + INITRD_SIZE; - initrd_start = INITRD_DESTINATION; - puts("Moved initrd to: "); puthex(initrd_start); + initrd_start = PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE); + initrd_end = initrd_start + INITRD_SIZE; + end_avail = (char *)initrd_start; + puts("relocated to: "); puthex(initrd_start); puts(" "); puthex(initrd_end); puts("\n"); } + + puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" "); + puthex((unsigned long)end_avail); puts("\n"); + #ifndef CONFIG_MBX CRT_tstc(); /* Forces keyboard to be initialized */ #endif @@ -417,13 +467,14 @@ puts("Uncompressing Linux..."); - /* these _bcopy() calls are here so I can add breakpoints to the boot for mbx -- Cort */ - /*_bcopy( (char *)0x100,(char *)&sanity, 0x2000-0x100);*/ gunzip(0, 0x400000, zimage_start, &zimage_size); - /*_bcopy( (char *)&sanity,(char *)0x100,0x2000-0x100);*/ puts("done.\n"); puts("Now booting the kernel\n"); +#ifndef CONFIG_MBX return (unsigned long)&hold_residual; +#else + return (unsigned long)&hold_board_info; +#endif } void puthex(unsigned long val) diff -u --recursive --new-file v2.1.100/linux/arch/ppc/chrp_defconfig linux/arch/ppc/chrp_defconfig --- v2.1.100/linux/arch/ppc/chrp_defconfig Thu Apr 23 20:21:28 1998 +++ linux/arch/ppc/chrp_defconfig Fri May 8 00:18:13 1998 @@ -226,7 +226,6 @@ # CD-ROM drivers (not for SCSI or IDE/ATAPI drives) # # CONFIG_CD_NO_IDESCSI is not set -CONFIG_CDROM=y # # Filesystems diff -u --recursive --new-file v2.1.100/linux/arch/ppc/common_defconfig linux/arch/ppc/common_defconfig --- v2.1.100/linux/arch/ppc/common_defconfig Thu Apr 23 20:21:28 1998 +++ linux/arch/ppc/common_defconfig Fri May 8 00:18:13 1998 @@ -219,7 +219,6 @@ # CD-ROM drivers (not for SCSI or IDE/ATAPI drives) # # CONFIG_CD_NO_IDESCSI is not set -CONFIG_CDROM=y # # Filesystems diff -u --recursive --new-file v2.1.100/linux/arch/ppc/config.in linux/arch/ppc/config.in --- v2.1.100/linux/arch/ppc/config.in Sat May 2 14:19:52 1998 +++ linux/arch/ppc/config.in Fri May 8 00:18:13 1998 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.47 1998/04/10 10:19:04 geert Exp $ +# $Id: config.in,v 1.53 1998/05/02 12:06:12 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -28,6 +28,10 @@ MBX CONFIG_MBX" PReP endmenu +if [ "$CONFIG_MBX" = "y" ];then + define_bool CONFIG_SERIAL_CONSOLE y +fi + if [ "$CONFIG_ALL_PPC" != "y" ]; then define_bool CONFIG_MACH_SPECIFIC y fi @@ -84,8 +88,6 @@ else define_bool CONFIG_PMAC_CONSOLE y fi - define_bool CONFIG_MAC_KEYBOARD y - define_bool CONFIG_MAC_FLOPPY y else # if compiling specifically for prep or chrp, or supporting all arch's if [ "$CONFIG_ABSTRACT_CONSOLE" = "y" ]; then @@ -95,9 +97,10 @@ else bool 'Support for PowerMac console' CONFIG_PMAC_CONSOLE fi - bool 'Support for PowerMac keyboard' CONFIG_MAC_KEYBOARD - bool 'Support for PowerMac floppy' CONFIG_MAC_FLOPPY fi +bool 'Support for PowerMac keyboard' CONFIG_MAC_KEYBOARD +bool 'Support for PowerMac floppy' CONFIG_MAC_FLOPPY +bool 'Support for PowerMac serial ports' CONFIG_MAC_SERIAL if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool 'Support for PowerMac mouse (EXPERIMENTAL)' CONFIG_MACMOUSE fi @@ -122,7 +125,7 @@ source drivers/pnp/Config.in source drivers/block/Config.in -source drivers.new/Config.in +#source drivers.new/Config.in if [ "$CONFIG_NET" = "y" ]; then source net/Config.in @@ -179,11 +182,12 @@ source drivers/char/Config.in -mainmenu_option next_comment -comment 'Sound' - -tristate 'Sound card support' CONFIG_SOUND -if [ "$CONFIG_SOUND" != "n" ]; then - source drivers/sound/Config.in -fi -endmenu +#mainmenu_option next_comment +#comment 'Sound' +# +#tristate 'Sound card support' CONFIG_SOUND +#if [ "$CONFIG_SOUND" != "n" ]; then +# source drivers/sound/Config.in +#fi +# +#endmenu diff -u --recursive --new-file v2.1.100/linux/arch/ppc/defconfig linux/arch/ppc/defconfig --- v2.1.100/linux/arch/ppc/defconfig Thu Apr 23 20:21:28 1998 +++ linux/arch/ppc/defconfig Fri May 8 00:18:13 1998 @@ -1,42 +1,54 @@ # -# Automatically generated by make menuconfig: don't edit +# Automatically generated make config: don't edit # # # Platform support # CONFIG_PPC=y -# CONFIG_6xx is not set -CONFIG_8xx=y -# CONFIG_PMAC is not set +CONFIG_6xx=y +# CONFIG_8xx is not set +CONFIG_PMAC=y # CONFIG_PREP is not set # CONFIG_CHRP is not set # CONFIG_ALL_PPC is not set -CONFIG_MBX=y +# CONFIG_APUS is not set +# CONFIG_MBX is not set CONFIG_MACH_SPECIFIC=y # # General setup # -# CONFIG_EXPERIMENTAL is not set -# CONFIG_MODULES is not set +CONFIG_EXPERIMENTAL=y +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y CONFIG_PCI=y CONFIG_PCI_OLD_PROC=y CONFIG_NET=y -# CONFIG_SYSCTL is not set +CONFIG_SYSCTL=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y -# CONFIG_BINFMT_MISC is not set +CONFIG_BINFMT_MISC=m # CONFIG_BINFMT_JAVA is not set # CONFIG_PARPORT is not set -# CONFIG_PMAC_CONSOLE is not set -# CONFIG_MAC_KEYBOARD is not set -# CONFIG_MAC_FLOPPY is not set -# CONFIG_PROC_DEVICETREE is not set +# CONFIG_ABSTRACT_CONSOLE is not set +CONFIG_PMAC_CONSOLE=y +CONFIG_MAC_KEYBOARD=y +CONFIG_MAC_FLOPPY=y +CONFIG_MAC_SERIAL=y +CONFIG_MACMOUSE=y +CONFIG_PROC_DEVICETREE=y +# CONFIG_KGDB is not set # CONFIG_XMON is not set -CONFIG_VGA_CONSOLE=y +CONFIG_CONTROL_VIDEO=y +CONFIG_PLATINUM_VIDEO=y +CONFIG_VALKYRIE_VIDEO=y +CONFIG_ATY_VIDEO=y +CONFIG_IMSTT_VIDEO=y +CONFIG_CHIPS_VIDEO=y # # Plug and Play support @@ -47,8 +59,25 @@ # Floppy, IDE, and other block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_IDE is not set -# CONFIG_BLK_DEV_HD_ONLY is not set +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_RZ1000 is not set +# CONFIG_BLK_DEV_IDEPCI is not set +# CONFIG_IDE_CHIPSETS is not set + +# +# Additional Block Devices +# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set @@ -60,41 +89,112 @@ # CONFIG_BLK_DEV_HD is not set # -# NEW devices (io_request, all ALPHA and dangerous) -# -# CONFIG_IO_REQUEST is not set - -# # Networking options # # CONFIG_PACKET is not set # CONFIG_NETLINK is not set # CONFIG_FIREWALL is not set -# CONFIG_NET_ALIAS is not set +CONFIG_NET_ALIAS=y # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set +CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set +# CONFIG_IP_PNP is not set # CONFIG_IP_ACCT is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set -# CONFIG_IP_ALIAS is not set +# CONFIG_IP_MROUTE is not set +CONFIG_IP_ALIAS=y # CONFIG_SYN_COOKIES is not set -# CONFIG_INET_RARP is not set + +# +# (it is safe to leave these untouched) +# +CONFIG_INET_RARP=y CONFIG_IP_NOSR=y -# CONFIG_SKB_LARGE is not set +CONFIG_SKB_LARGE=y +# CONFIG_IPV6 is not set + +# +# +# # CONFIG_IPX is not set -# CONFIG_ATALK is not set +CONFIG_ATALK=m +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set +# CONFIG_CPU_IS_SLOW is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_PROFILE is not set # # SCSI support # -# CONFIG_SCSI is not set +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +CONFIG_SCSI_AIC7XXX=m +# CONFIG_OVERRIDE_CMDS is not set +CONFIG_AIC7XXX_PROC_STATS=y +CONFIG_AIC7XXX_RESET_DELAY=15 +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA_DMA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_NCR53C8XX is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_SEAGATE is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_SCSI_DEBUG is not set +CONFIG_SCSI_MESH=y +CONFIG_SCSI_MESH_SYNC_RATE=5 +CONFIG_SCSI_MAC53C94=y # # Network device support @@ -104,22 +204,42 @@ # CONFIG_DUMMY is not set # CONFIG_EQUALIZER is not set CONFIG_NET_ETHERNET=y +CONFIG_MACE=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_RTL8139 is not set +# CONFIG_YELLOWFIN is not set # CONFIG_NET_ISA is not set -# CONFIG_NET_EISA is not set +CONFIG_NET_EISA=y +# CONFIG_PCNET32 is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +CONFIG_DE4X5=m +CONFIG_DEC_ELCP=m +# CONFIG_DGRS is not set +# CONFIG_EEXPRESS_PRO100 is not set +# CONFIG_ES3210 is not set +# CONFIG_EPIC100 is not set +# CONFIG_TLAN is not set +# CONFIG_ZNET is not set # CONFIG_NET_POCKET is not set # CONFIG_FDDI is not set # CONFIG_DLCI is not set -# CONFIG_PPP is not set +# CONFIG_LTPC is not set +# CONFIG_COPS is not set +# CONFIG_IPDDP is not set +CONFIG_PPP=m + +# +# CCP compressors for PPP are only built as modules. +# # CONFIG_SLIP is not set # CONFIG_NET_RADIO is not set # CONFIG_TR is not set -# CONFIG_WAN_DRIVERS is not set -# CONFIG_LAPBETHER is not set -# CONFIG_X25_ASY is not set +# CONFIG_SHAPER is not set # # Amateur Radio support @@ -135,7 +255,6 @@ # CD-ROM drivers (not for SCSI or IDE/ATAPI drives) # # CONFIG_CD_NO_IDESCSI is not set -# CONFIG_CDROM is not set # # Filesystems @@ -143,15 +262,15 @@ # CONFIG_QUOTA is not set # CONFIG_MINIX_FS is not set CONFIG_EXT2_FS=y -# CONFIG_ISO9660_FS is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m # CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_PROC_FS is not set +CONFIG_VFAT_FS=m +CONFIG_PROC_FS=y CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -# CONFIG_NFSD is not set +CONFIG_NFSD=y CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_CODA_FS is not set @@ -160,28 +279,62 @@ # CONFIG_NTFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set +CONFIG_HFS_FS=m # CONFIG_ROMFS_FS is not set -# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS_FS=y # CONFIG_UFS_FS is not set -# CONFIG_MAC_PARTITION is not set -# CONFIG_NLS is not set +# CONFIG_ADFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_MAC_PARTITION=y +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_KOI8_R is not set # # Character devices # -# CONFIG_VT is not set -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +# CONFIG_SOFTCURSOR is not set +# CONFIG_SERIAL is not set # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_MOUSE is not set +# CONFIG_UMISC is not set # CONFIG_QIC02_TAPE is not set # CONFIG_APM is not set # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set # CONFIG_VIDEO_DEV is not set -# CONFIG_NVRAM is not set +CONFIG_NVRAM=y # CONFIG_JOYSTICK is not set # CONFIG_MISC_RADIO is not set @@ -189,8 +342,3 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set - -# -# Sound -# -# CONFIG_SOUND is not set diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile --- v2.1.100/linux/arch/ppc/kernel/Makefile Thu Apr 23 20:21:28 1998 +++ linux/arch/ppc/kernel/Makefile Fri May 8 00:18:14 1998 @@ -15,7 +15,11 @@ O_OBJS := traps.o irq.o idle.o time.o process.o signal.o syscalls.o misc.o \ - bitops.o ppc_htab.o setup.o ptrace.o align.o + bitops.o setup.o ptrace.o align.o + +ifndef CONFIG_8xx +O_OBJS += ppc_htab.o +endif ifdef CONFIG_PCI O_OBJS += pci.o diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c --- v2.1.100/linux/arch/ppc/kernel/chrp_setup.c Thu Apr 23 20:21:28 1998 +++ linux/arch/ppc/kernel/chrp_setup.c Fri May 8 00:18:14 1998 @@ -85,7 +85,7 @@ { } -void chrp_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq) +__initfunc(void chrp_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)) { int i; @@ -221,7 +221,7 @@ ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */ -#ifdef CONFIG_BLK_DEV_RAM +#ifdef CONFIG_BLK_DEV_INITRD /* initrd_start and size are setup by boot/head.S and kernel/head.S */ if ( initrd_start ) { diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/chrp_time.c linux/arch/ppc/kernel/chrp_time.c --- v2.1.100/linux/arch/ppc/kernel/chrp_time.c Thu Apr 23 20:21:28 1998 +++ linux/arch/ppc/kernel/chrp_time.c Fri May 8 00:18:14 1998 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,7 @@ static int nvram_as0 = NVRAM_AS0; static int nvram_data = NVRAM_DATA; -void chrp_time_init(void) +__initfunc(void chrp_time_init(void)) { struct device_node *rtcs; int base; @@ -150,7 +151,7 @@ } -void chrp_calibrate_decr(void) +__initfunc(void chrp_calibrate_decr(void)) { struct device_node *cpu; int freq, *fp, divisor; diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/find_name.c linux/arch/ppc/kernel/find_name.c --- v2.1.100/linux/arch/ppc/kernel/find_name.c Mon Jan 12 15:18:13 1998 +++ linux/arch/ppc/kernel/find_name.c Fri May 8 00:18:14 1998 @@ -1,16 +1,16 @@ #include #include #include +#include /* * Finds a given address in the System.map and prints it out * with its neighbors. -- Cort */ -void main(int argc, char **argv) +int main(int argc, char **argv) { unsigned long addr, cmp, i; FILE *f; - char *ptr; char s[256], last[256]; if ( argc < 2 ) @@ -21,7 +21,7 @@ for ( i = 1 ; argv[i] ; i++ ) { - sscanf( argv[i], "%0x", &addr ); + sscanf( argv[i], "%0lx", &addr ); /* adjust if addr is relative to kernelbase */ if ( addr < PAGE_OFFSET ) addr += PAGE_OFFSET; @@ -35,7 +35,7 @@ while ( !feof(f) ) { fgets(s, 255 , f); - sscanf( s, "%0x", &cmp ); + sscanf( s, "%0lx", &cmp ); if ( addr < cmp ) break; strcpy( last, s); @@ -44,4 +44,5 @@ printf( "%s", last); } fclose(f); + return 0; } diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S --- v2.1.100/linux/arch/ppc/kernel/head.S Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/kernel/head.S Fri May 8 00:18:14 1998 @@ -325,7 +325,7 @@ ori r8, r8, MD_SVALID /* Make it valid */ mtspr MD_TWC, r8 lis r8, 0xfa000000@h /* Create paddr for TLB */ - ori r8, r8, MI_BOOTINIT + ori r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */ mtspr MD_RPN, r8 #endif @@ -338,19 +338,17 @@ mtspr DC_CST, r8 lis r8, IDC_ENABLE@h mtspr IC_CST, r8 -#ifdef notdef +#if 0 mtspr DC_CST, r8 #else /* I still have a bug somewhere because the Ethernet driver * does not want to work with copyback enabled. For now, * at least enable write through. */ -#if 0 lis r8, DC_SFWT@h mtspr DC_CST, r8 lis r8, IDC_ENABLE@h mtspr DC_CST, r8 -#endif #endif /* We now have the lower 8 Meg mapped into TLB entries, and the caches @@ -689,11 +687,11 @@ STD_EXCEPTION(0x1000, SoftEmu, SoftwareEmulation) #endif -#ifndef CONFIG_8xx /* * Handle TLB miss for DATA Load operation on 603/603e */ . = 0x1100 +#ifndef CONFIG_8xx DataLoadTLBMiss: #ifdef NO_RELOAD_HTAB /* @@ -1558,11 +1556,12 @@ bl set_mbx_memory #endif bl MMU_init - /* * Go back to running unmapped so we can load up new values * for SDR1 (hash table pointer) and the segment registers * and change to using our exception vectors. + * On the 8xx, all we have to do is invalidate the TLB to clear + * the old 8M byte TLB mappings and load the page table base register. */ #ifndef CONFIG_8xx lis r6,_SDR1@ha @@ -1586,7 +1585,6 @@ rfi /* Load up the kernel context */ 2: - SYNC /* Force all PTE updates to finish */ tlbia /* Clear all TLB entries */ #ifndef CONFIG_8xx @@ -1610,7 +1608,6 @@ LOAD_BAT(2,32,r3,r4,r5) LOAD_BAT(3,48,r3,r4,r5) #endif /* CONFIG_8xx */ - /* Set up for using our exception vectors */ /* ptr to phys current tss */ tophys(r4,r2,r4) @@ -1618,7 +1615,6 @@ mtspr SPRG3,r4 li r3,0 mtspr SPRG2,r3 /* 0 => r1 has kernel sp */ - /* Now turn on the MMU for real! */ li r4,MSR_KERNEL lis r3,start_kernel@h @@ -1893,11 +1889,12 @@ * page directory loaded into the MMU base register, and set the * ASID compare register with the new "context". */ - mtspr M_CASID, r5 /* Update context */ - lwz r5,MM-TSS(r4) /* Get virtual address of mm */ - lwz r5,PGD(r5) /* get new->mm->pgd */ - tophys(r5, r5, 0) /* convert to phys addr */ - mtspr M_TWB, r5 /* Update MMU base address */ + lwz r3,MM-TSS(r4) /* Get virtual address of mm */ + lwz r3,PGD(r3) /* get new->mm->pgd */ + addis r3,r3,-KERNELBASE@h /* convert to phys addr */ + mtspr M_TWB, r3 /* Update MMU base address */ + mtspr M_CASID, r5 /* Update context */ + tlbia #endif SYNC @@ -2262,18 +2259,6 @@ rfi /* return to caller */ #endif /* CONFIG_8xx */ -#ifdef CONFIG_8xx -/* This is called during an exec when new page tables are created. - * It maps to the SET_PAGE_DIR macro. I guess I should make it an - * inline function. - */ -_GLOBAL(set_page_dir) - addis r3,r3,-KERNELBASE@h /* convert to phys addr */ - mtspr M_TWB, r3 /* Update MMU base address */ - blr -#endif - - #ifdef __SMP__ /* * Secondary processor begins executing here. diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c --- v2.1.100/linux/arch/ppc/kernel/idle.c Sat Apr 25 18:13:10 1998 +++ linux/arch/ppc/kernel/idle.c Fri May 8 00:18:14 1998 @@ -1,5 +1,5 @@ /* - * $Id: idle.c,v 1.35 1998/04/07 20:24:23 cort Exp $ + * $Id: idle.c,v 1.37 1998/04/26 06:59:12 cort Exp $ * * Idle daemon for PowerPC. Idle daemon will handle any action * that needs to be taken when the system becomes idle. @@ -319,19 +319,18 @@ case 6: /* 603e */ case 7: /* 603ev */ case 8: /* 750 */ - break; + save_flags(msr); + cli(); + if (!need_resched) { + asm("mfspr %0,1008" : "=r" (hid0) :); + hid0 &= ~(HID0_NAP | HID0_SLEEP | HID0_DOZE); + hid0 |= powersave_mode | HID0_DPM; + asm("mtspr 1008,%0" : : "r" (hid0)); + msr |= MSR_POW; + } + restore_flags(msr); default: return; } - save_flags(msr); - cli(); - if (!need_resched) { - asm("mfspr %0,1008" : "=r" (hid0) :); - hid0 &= ~(HID0_NAP | HID0_SLEEP | HID0_DOZE); - hid0 |= powersave_mode | HID0_DPM; - asm("mtspr 1008,%0" : : "r" (hid0)); - msr |= MSR_POW; - } - restore_flags(msr); } diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c --- v2.1.100/linux/arch/ppc/kernel/irq.c Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/kernel/irq.c Fri May 8 00:18:14 1998 @@ -327,6 +327,9 @@ else len += sprintf(buf+len, " OpenPIC "); break; + case _MACH_mbx: + len += sprintf(buf+len, " MPC8xx "); + break; } len += sprintf(buf+len, " %s",action->name); diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/mbx_setup.c linux/arch/ppc/kernel/mbx_setup.c --- v2.1.100/linux/arch/ppc/kernel/mbx_setup.c Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/kernel/mbx_setup.c Fri May 8 00:18:14 1998 @@ -72,53 +72,19 @@ #endif } -int -mbx_get_cpuinfo(char *buffer) -{ - int pvr = _get_PVR(); - int len; - char *model; - bd_t *bp; - extern RESIDUAL res; - - /* I know the MPC860 is 0x50. I don't have the book handy - * to check the others. - */ - if ((pvr>>16) == 0x50) - model = "MPC860"; - else - model = "unknown"; - -#ifdef __SMP__ -#define CD(X) (cpu_data[n].X) -#else -#define CD(X) (X) -#define CPUN 0 -#endif - bp = (bd_t *)&res; - - len = sprintf(buffer,"processor\t: %d\n" - "cpu\t\t: %s\n" - "revision\t: %d.%d\n" - "clock\t\t: %d MHz\n" - "bus clock\t: %d MHz\n", - CPUN, - model, - MAJOR(pvr), MINOR(pvr), - bp->bi_intfreq / 1000000, - bp->bi_busfreq / 1000000 - ); - - return len; -} - __initfunc(void mbx_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)) { int cpm_page; - + extern char cmd_line[]; + cpm_page = *memory_start_p; *memory_start_p += PAGE_SIZE; + + sprintf(cmd_line, +"%s root=/dev/nfs nfsroot=/sys/mbxroot", + cmd_line); + printk("Boot arguments: %s\n", cmd_line); /* Reset the Communication Processor Module. */ @@ -128,7 +94,7 @@ ROOT_DEV = to_kdev_t(0x0301); /* hda1 */ #endif -#ifdef CONFIG_BLK_DEV_RAM +#ifdef CONFIG_BLK_DEV_INITRD #if 0 ROOT_DEV = to_kdev_t(0x0200); /* floppy */ rd_prompt = 1; diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S --- v2.1.100/linux/arch/ppc/kernel/misc.S Sat Apr 25 18:13:10 1998 +++ linux/arch/ppc/kernel/misc.S Fri May 8 00:18:14 1998 @@ -436,8 +436,8 @@ .long sys_time .long sys_mknod .long sys_chmod /* 15 */ - .long sys_chown - .long /*sys_break*/ sys_ni_syscall + .long sys_lchown + .long sys_ni_syscall .long sys_stat .long sys_lseek .long sys_getpid /* 20 */ @@ -590,9 +590,19 @@ .long sys_poll .long sys_nfsservctl .long sys_setresgid - .long sys_getresgid /* 170 */ + .long sys_getresgid /* 170 */ .long sys_prctl + .long sys_rt_sigreturn + .long sys_rt_sigaction + .long sys_rt_sigprocmask + .long sys_rt_sigpending /* 175 */ + .long sys_rt_sigtimedwait + .long sys_rt_sigqueueinfo + .long sys_rt_sigsuspend + .long sys_pread + .long sys_pwrite /* 180 */ + .long sys_chown + .long sys_getcwd .long sys_xstat .long sys_xmknod - .space (NR_syscalls-173)*4 - + .space (NR_syscalls-185)*4 diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/openpic.c linux/arch/ppc/kernel/openpic.c --- v2.1.100/linux/arch/ppc/kernel/openpic.c Mon Jan 12 15:18:13 1998 +++ linux/arch/ppc/kernel/openpic.c Fri May 8 00:18:14 1998 @@ -264,7 +264,7 @@ openpic_set_spurious(OPENPIC_VEC_SPURIOUS); if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT, - "OpenPIC cascade", NULL)) + "82c59 cascade", NULL)) printk("Unable to get OpenPIC IRQ 0 for cascade\n"); openpic_set_priority(0, 0); openpic_disable_8259_pass_through(); diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c --- v2.1.100/linux/arch/ppc/kernel/pci.c Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/kernel/pci.c Fri May 8 00:18:14 1998 @@ -1,5 +1,5 @@ /* - * $Id: pci.c,v 1.24 1998/02/19 21:29:49 cort Exp $ + * $Id: pci.c,v 1.27 1998/04/24 02:46:47 cort Exp $ * Common pmac/prep/chrp pci routines. -- Cort */ @@ -88,6 +88,19 @@ extern int prep_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int val); +extern int mbx_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char *val); +extern int mbx_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short *val); +extern int mbx_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int *val); +extern int mbx_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char val); +extern int mbx_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short val); +extern int mbx_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int val); + int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char *val) { @@ -124,15 +137,14 @@ return 1; } -__initfunc(unsigned long - pcibios_init(unsigned long mem_start,unsigned long mem_end)) +__initfunc(void pcibios_init(void)) { - return mem_start; } __initfunc(void setup_pci_ptrs(void)) { +#ifndef CONFIG_MBX switch (_machine) { case _MACH_prep: ptr_pcibios_read_config_byte = prep_pcibios_read_config_byte; @@ -158,12 +170,20 @@ ptr_pcibios_write_config_word = chrp_pcibios_write_config_word; ptr_pcibios_write_config_dword = chrp_pcibios_write_config_dword; break; + default: + printk("setup_pci_ptrs(): unknown machine type!\n"); } +#else /* CONFIG_MBX */ + ptr_pcibios_read_config_byte = mbx_pcibios_read_config_byte; + ptr_pcibios_read_config_word = mbx_pcibios_read_config_word; + ptr_pcibios_read_config_dword = mbx_pcibios_read_config_dword; + ptr_pcibios_write_config_byte = mbx_pcibios_write_config_byte; + ptr_pcibios_write_config_word = mbx_pcibios_write_config_word; + ptr_pcibios_write_config_dword = mbx_pcibios_write_config_dword; +#endif /* CONFIG_MBX */ } -__initfunc(unsigned long - pcibios_fixup(unsigned long mem_start, unsigned long mem_end)) - +__initfunc(void pcibios_fixup(void)) { extern route_pci_interrupts(void); struct pci_dev *dev; @@ -223,7 +243,6 @@ } break; } - return mem_start; } __initfunc(char *pcibios_setup(char *str)) diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c --- v2.1.100/linux/arch/ppc/kernel/pmac_pci.c Sat Apr 25 18:13:10 1998 +++ linux/arch/ppc/kernel/pmac_pci.c Fri May 8 00:18:14 1998 @@ -39,114 +39,7 @@ #define BANDIT_MAGIC 0x50 #define BANDIT_COHERENT 0x40 -/* - * For a bandit bridge, turn on cache coherency if necessary. - * N.B. we can't use pcibios_*_config_* here because bridges[] - * is not initialized yet. - */ -static void init_bandit(struct bridge_data *bp) -{ - unsigned int vendev, magic; - int rev; - - /* read the word at offset 0 in config space for device 11 */ - out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID); - udelay(2); - vendev = in_le32((volatile unsigned int *)bp->cfg_data); - if (vendev != (BANDIT_DEVID << 16) + APPLE_VENDID) { - printk(KERN_WARNING "bandit isn't? (%x)\n", vendev); - return; - } - - /* read the revision id */ - out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID); - udelay(2); - rev = in_8(bp->cfg_data); - if (rev != BANDIT_REVID) - printk(KERN_WARNING "Unknown revision %d for bandit at %p\n", - rev, bp->io_base); - - /* read the word at offset 0x50 */ - out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC); - udelay(2); - magic = in_le32((volatile unsigned int *)bp->cfg_data); - if ((magic & BANDIT_COHERENT) != 0) - return; - magic |= BANDIT_COHERENT; - udelay(2); - out_le32((volatile unsigned int *)bp->cfg_data, magic); - printk(KERN_INFO "Cache coherency enabled for bandit/PSX at %p\n", - bp->io_base); -} - -unsigned long pmac_find_bridges(unsigned long mem_start, unsigned long mem_end) -{ - int bus; - struct bridge_data *bridge; - - bridge_list = 0; - max_bus = 0; - add_bridges(find_devices("bandit"), &mem_start); - add_bridges(find_devices("chaos"), &mem_start); - bridges = (struct bridge_data **) mem_start; - mem_start += (max_bus + 1) * sizeof(struct bridge_data *); - memset(bridges, 0, (max_bus + 1) * sizeof(struct bridge_data *)); - for (bridge = bridge_list; bridge != NULL; bridge = bridge->next) - for (bus = bridge->bus_number; bus <= bridge->max_bus; ++bus) - bridges[bus] = bridge; - - return mem_start; -} - -static void add_bridges(struct device_node *dev, unsigned long *mem_ptr) -{ - int *bus_range; - int len; - struct bridge_data *bp; - struct reg_property *addr; - - for (; dev != NULL; dev = dev->next) { - addr = (struct reg_property *) get_property(dev, "reg", &len); - if (addr == NULL || len < sizeof(*addr)) { - printk(KERN_WARNING "Can't use %s: no address\n", - dev->full_name); - continue; - } - bus_range = (int *) get_property(dev, "bus-range", &len); - if (bus_range == NULL || len < 2 * sizeof(int)) { - printk(KERN_WARNING "Can't get bus-range for %s\n", - dev->full_name); - continue; - } - if (bus_range[1] == bus_range[0]) - printk(KERN_INFO "PCI bus %d", bus_range[0]); - else - printk(KERN_INFO "PCI buses %d..%d", bus_range[0], - bus_range[1]); - printk(" controlled by %s at %x\n", dev->name, addr->address); - bp = (struct bridge_data *) *mem_ptr; - *mem_ptr += sizeof(struct bridge_data); - bp->cfg_addr = (volatile unsigned int *) - ioremap(addr->address + 0x800000, 0x1000); - bp->cfg_data = (volatile unsigned char *) - ioremap(addr->address + 0xc00000, 0x1000); - bp->io_base = (void *) ioremap(addr->address, 0x10000); -#ifdef CONFIG_PMAC - if (isa_io_base == 0) - isa_io_base = (unsigned long) bp->io_base; -#endif - bp->bus_number = bus_range[0]; - bp->max_bus = bus_range[1]; - bp->next = bridge_list; - bp->node = dev; - bridge_list = bp; - if (bp->max_bus > max_bus) - max_bus = bp->max_bus; - - if (strcmp(dev->name, "bandit") == 0) - init_bandit(bp); - } -} +__pmac void *pci_io_base(unsigned int bus) { @@ -303,3 +196,113 @@ out_le32((volatile unsigned int *)bp->cfg_data, val); return PCIBIOS_SUCCESSFUL; } + +/* + * For a bandit bridge, turn on cache coherency if necessary. + * N.B. we can't use pcibios_*_config_* here because bridges[] + * is not initialized yet. + */ +__initfunc(static void init_bandit(struct bridge_data *bp)) +{ + unsigned int vendev, magic; + int rev; + + /* read the word at offset 0 in config space for device 11 */ + out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID); + udelay(2); + vendev = in_le32((volatile unsigned int *)bp->cfg_data); + if (vendev != (BANDIT_DEVID << 16) + APPLE_VENDID) { + printk(KERN_WARNING "bandit isn't? (%x)\n", vendev); + return; + } + + /* read the revision id */ + out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID); + udelay(2); + rev = in_8(bp->cfg_data); + if (rev != BANDIT_REVID) + printk(KERN_WARNING "Unknown revision %d for bandit at %p\n", + rev, bp->io_base); + + /* read the word at offset 0x50 */ + out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC); + udelay(2); + magic = in_le32((volatile unsigned int *)bp->cfg_data); + if ((magic & BANDIT_COHERENT) != 0) + return; + magic |= BANDIT_COHERENT; + udelay(2); + out_le32((volatile unsigned int *)bp->cfg_data, magic); + printk(KERN_INFO "Cache coherency enabled for bandit/PSX at %p\n", + bp->io_base); +} + +__initfunc(unsigned long pmac_find_bridges(unsigned long mem_start, unsigned long mem_end)) +{ + int bus; + struct bridge_data *bridge; + + bridge_list = 0; + max_bus = 0; + add_bridges(find_devices("bandit"), &mem_start); + add_bridges(find_devices("chaos"), &mem_start); + bridges = (struct bridge_data **) mem_start; + mem_start += (max_bus + 1) * sizeof(struct bridge_data *); + memset(bridges, 0, (max_bus + 1) * sizeof(struct bridge_data *)); + for (bridge = bridge_list; bridge != NULL; bridge = bridge->next) + for (bus = bridge->bus_number; bus <= bridge->max_bus; ++bus) + bridges[bus] = bridge; + + return mem_start; +} + +__initfunc(static void add_bridges(struct device_node *dev, unsigned long *mem_ptr)) +{ + int *bus_range; + int len; + struct bridge_data *bp; + struct reg_property *addr; + + for (; dev != NULL; dev = dev->next) { + addr = (struct reg_property *) get_property(dev, "reg", &len); + if (addr == NULL || len < sizeof(*addr)) { + printk(KERN_WARNING "Can't use %s: no address\n", + dev->full_name); + continue; + } + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s\n", + dev->full_name); + continue; + } + if (bus_range[1] == bus_range[0]) + printk(KERN_INFO "PCI bus %d", bus_range[0]); + else + printk(KERN_INFO "PCI buses %d..%d", bus_range[0], + bus_range[1]); + printk(" controlled by %s at %x\n", dev->name, addr->address); + bp = (struct bridge_data *) *mem_ptr; + *mem_ptr += sizeof(struct bridge_data); + bp->cfg_addr = (volatile unsigned int *) + ioremap(addr->address + 0x800000, 0x1000); + bp->cfg_data = (volatile unsigned char *) + ioremap(addr->address + 0xc00000, 0x1000); + bp->io_base = (void *) ioremap(addr->address, 0x10000); +#ifdef CONFIG_PMAC + if (isa_io_base == 0) + isa_io_base = (unsigned long) bp->io_base; +#endif + bp->bus_number = bus_range[0]; + bp->max_bus = bus_range[1]; + bp->next = bridge_list; + bp->node = dev; + bridge_list = bp; + if (bp->max_bus > max_bus) + max_bus = bp->max_bus; + + if (strcmp(dev->name, "bandit") == 0) + init_bandit(bp); + } +} + diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c --- v2.1.100/linux/arch/ppc/kernel/pmac_setup.c Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/kernel/pmac_setup.c Fri May 8 00:18:14 1998 @@ -22,6 +22,7 @@ */ #include +#include #include #include #include @@ -47,6 +48,8 @@ #include #include #include +#include +#include #include #include #include @@ -58,10 +61,44 @@ #define DEFAULT_ROOT_DEVICE 0x0801 /* sda1 - slightly silly choice */ +extern void zs_kgdb_hook(int tty_num); static void ohare_init(void); -void -pmac_setup_arch(unsigned long *memory_start_p, unsigned long *memory_end_p) +__pmac + +int +pmac_get_cpuinfo(char *buffer) +{ + int len; + /* should find motherboard type here as well */ + len = sprintf(buffer,"machine\t\t: PowerMac\n"); + return len; +} + +#ifdef CONFIG_SCSI +/* Find the device number for the disk (if any) at target tgt + on host adaptor host. + XXX this really really should be in drivers/scsi/sd.c. */ +#include +#include "../../../drivers/scsi/scsi.h" +#include "../../../drivers/scsi/sd.h" +#include "../../../drivers/scsi/hosts.h" + +kdev_t sd_find_target(void *host, int tgt) +{ + Scsi_Disk *dp; + int i; + + for (dp = rscsi_disks, i = 0; i < sd_template.dev_max; ++i, ++dp) + if (dp->device != NULL && dp->device->host == host + && dp->device->id == tgt) + return MKDEV(SCSI_DISK_MAJOR, i << 4); + return 0; +} +#endif + +__initfunc(void +pmac_setup_arch(unsigned long *memory_start_p, unsigned long *memory_end_p)) { struct device_node *cpu; int *fp; @@ -94,6 +131,13 @@ ohare_init(); +#ifdef CONFIG_KGDB + zs_kgdb_hook(0); +#endif + + find_via_cuda(); + find_via_pmu(); + #ifdef CONFIG_FB /* Frame buffer device based console */ conswitchp = &fb_con; @@ -102,7 +146,7 @@ static volatile u32 *feature_addr; -static void ohare_init(void) +__initfunc(static void ohare_init(void)) { struct device_node *np; @@ -134,28 +178,20 @@ int boot_part; kdev_t boot_dev; -unsigned long -powermac_init(unsigned long mem_start, unsigned long mem_end) +__initfunc(void powermac_init(void)) { -#ifdef CONFIG_KGDB - extern void zs_kgdb_hook(int tty_num); - zs_kgdb_hook(0); -#endif adb_init(); pmac_nvram_init(); if (_machine == _MACH_Pmac) { - pmac_read_rtc_time(); media_bay_init(); } #ifdef CONFIG_PMAC_CONSOLE pmac_find_display(); #endif - - return mem_start; } -void -note_scsi_host(struct device_node *node, void *host) +__initfunc(void +note_scsi_host(struct device_node *node, void *host)) { int l; char *p; @@ -183,29 +219,7 @@ } } -#ifdef CONFIG_SCSI -/* Find the device number for the disk (if any) at target tgt - on host adaptor host. - XXX this really really should be in drivers/scsi/sd.c. */ -#include -#include "../../../drivers/scsi/scsi.h" -#include "../../../drivers/scsi/sd.h" -#include "../../../drivers/scsi/hosts.h" - -kdev_t sd_find_target(void *host, int tgt) -{ - Scsi_Disk *dp; - int i; - - for (dp = rscsi_disks, i = 0; i < sd_template.dev_max; ++i, ++dp) - if (dp->device != NULL && dp->device->host == host - && dp->device->id == tgt) - return MKDEV(SCSI_DISK_MAJOR, i << 4); - return 0; -} -#endif - -void find_boot_device(void) +__initfunc(void find_boot_device(void)) { kdev_t dev; @@ -223,7 +237,7 @@ /* XXX should cope with booting from IDE also */ } -void note_bootable_part(kdev_t dev, int part) +__initfunc(void note_bootable_part(kdev_t dev, int part)) { static int found_boot = 0; @@ -243,7 +257,7 @@ ide_ioreg_t pmac_ide_regbase[MAX_HWIFS]; int pmac_ide_irq[MAX_HWIFS]; -void pmac_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq) +__initfunc(void pmac_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)) { int i; @@ -268,7 +282,7 @@ } } -void pmac_ide_probe(void) +__initfunc(void pmac_ide_probe(void)) { struct device_node *np; int i; @@ -325,11 +339,3 @@ } #endif /* CONFIG_BLK_DEV_IDE */ -int -pmac_get_cpuinfo(char *buffer) -{ - int len; - /* should find motherboard type here as well */ - len = sprintf(buffer,"machine\t\t: PowerMac\n"); - return len; -} diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/pmac_support.c linux/arch/ppc/kernel/pmac_support.c --- v2.1.100/linux/arch/ppc/kernel/pmac_support.c Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/kernel/pmac_support.c Fri May 8 00:18:15 1998 @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,9 @@ static int nvram_mult; #define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */ + + +__pmac void pmac_nvram_init(void) { diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/pmac_time.c linux/arch/ppc/kernel/pmac_time.c --- v2.1.100/linux/arch/ppc/kernel/pmac_time.c Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/kernel/pmac_time.c Fri May 8 00:18:15 1998 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -47,11 +48,49 @@ /* Bits in IFR and IER */ #define T1_INT 0x40 /* Timer 1 interrupt */ +__pmac + +unsigned long pmac_get_rtc_time(void) +{ + struct adb_request req; + + /* Get the time from the RTC */ + switch (adb_hardware) { + case ADB_VIACUDA: + if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) + return 0; + while (!req.complete) + cuda_poll(); + if (req.reply_len != 7) + printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", + req.reply_len); + return (req.reply[3] << 24) + (req.reply[4] << 16) + + (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET; + case ADB_VIAPMU: + if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) + return 0; + while (!req.complete) + pmu_poll(); + if (req.reply_len != 5) + printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", + req.reply_len); + return (req.reply[1] << 24) + (req.reply[2] << 16) + + (req.reply[3] << 8) + req.reply[4] - RTC_OFFSET; + default: + return 0; + } +} + +int pmac_set_rtc_time(unsigned long nowtime) +{ + return 0; +} + /* * Calibrate the decrementer register using VIA timer 1. * This is used both on powermacs and CHRP machines. */ -int via_calibrate_decr(void) +__initfunc(int via_calibrate_decr(void)) { struct device_node *vias; volatile unsigned char *via; @@ -100,7 +139,7 @@ * This was taken from the pmac time_init() when merging the prep/pmac * time functions. */ -void pmac_calibrate_decr(void) +__initfunc(void pmac_calibrate_decr(void)) { struct device_node *cpu; int freq, *fp, divisor; @@ -127,51 +166,3 @@ count_period_den = freq / 1000000; } -unsigned long -pmac_get_rtc_time(void) -{ - struct adb_request req; - - /* Get the time from the RTC */ - switch (adb_hardware) { - case ADB_VIACUDA: - if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) - return 0; - while (!req.complete) - cuda_poll(); - if (req.reply_len != 7) - printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", - req.reply_len); - return (req.reply[3] << 24) + (req.reply[4] << 16) - + (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET; - case ADB_VIAPMU: - if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) - return 0; - while (!req.complete) - pmu_poll(); - if (req.reply_len != 5) - printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", - req.reply_len); - return (req.reply[1] << 24) + (req.reply[2] << 16) - + (req.reply[3] << 8) + req.reply[4] - RTC_OFFSET; - default: - return 0; - } -} - -int pmac_set_rtc_time(unsigned long nowtime) -{ - return 0; -} - -/* - * We can't do this in time_init, because via_cuda_init hasn't - * been called at that stage. - */ -void -pmac_read_rtc_time(void) -{ - xtime.tv_sec = pmac_get_rtc_time(); - xtime.tv_usec = 0; - last_rtc_update = xtime.tv_sec; -} diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c --- v2.1.100/linux/arch/ppc/kernel/ppc_htab.c Sat Apr 25 18:13:10 1998 +++ linux/arch/ppc/kernel/ppc_htab.c Fri May 8 00:18:15 1998 @@ -1,5 +1,5 @@ /* - * $Id: ppc_htab.c,v 1.17 1998/03/14 07:52:49 cort Exp $ + * $Id: ppc_htab.c,v 1.18 1998/04/24 12:29:39 davem Exp $ * * PowerPC hash table management proc entry. Will show information * about the current hash table and will allow changes to it. diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c --- v2.1.100/linux/arch/ppc/kernel/prep_setup.c Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/kernel/prep_setup.c Fri May 8 00:18:21 1998 @@ -62,7 +62,7 @@ extern int rd_image_start; /* starting block # of image */ #endif -void prep_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq) +__initfunc(void prep_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)) { ide_ioreg_t port = base; int i = 8; @@ -188,7 +188,7 @@ break; } -#ifdef CONFIG_BLK_DEV_RAM +#ifdef CONFIG_BLK_DEV_INITRD /* initrd_start and size are setup by boot/head.S and kernel/head.S */ if ( initrd_start ) { diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/prep_time.c linux/arch/ppc/kernel/prep_time.c --- v2.1.100/linux/arch/ppc/kernel/prep_time.c Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/kernel/prep_time.c Fri May 8 00:18:23 1998 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -173,67 +174,3 @@ year += 100; return mktime(year, mon, day, hour, min, sec); } - -#if 0 -void time_init(void) -{ - void (*irq_handler)(int, void *,struct pt_regs *); - - xtime.tv_sec = prep_get_rtc_time(); - xtime.tv_usec = 0; - - prep_calibrate_decr(); - - /* If we have the CPU hardware time counters, use them */ - irq_handler = timer_interrupt; - if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL) != 0) - panic("Could not allocate timer IRQ!"); -} - -/* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "do_timer()" routine every clocktick - */ -static inline void timer_interrupt(int irq, void *dev, struct pt_regs * regs) -{ - prep_calibrate_decr_handler(irq,dev,regs); - do_timer(regs); - - /* update the hw clock if: - * the time is marked out of sync (TIME_ERROR) - * or ~11 minutes have expired since the last update -- Cort - * If we have an externally synchronized Linux clock, then update - * CMOS clock accordingly every ~11 minutes. prep_set_rtc_mmss() has to be - * called as close as possible to 500 ms before the new second starts. - */ - if ( time_state == TIME_BAD || - xtime.tv_sec > last_rtc_update + 660 ) - /*if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 && - xtime.tv_usec > 500000 - (tick >> 1) && - xtime.tv_usec < 500000 + (tick >> 1))*/ - if (prep_set_rtc_time(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ - - -#ifdef CONFIG_HEARTBEAT - /* use hard disk LED as a heartbeat instead -- much more useful - for debugging -- Cort */ - switch(kstat_irqs(0) % 101) - { - /* act like an actual heart beat -- ie thump-thump-pause... */ - case 0: - case 20: - outb(1,IBM_HDD_LED); - break; - case 7: - case 27: - outb(0,IBM_HDD_LED); - break; - case 100: - break; - } -#endif -} -#endif diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c --- v2.1.100/linux/arch/ppc/kernel/prom.c Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/kernel/prom.c Fri May 8 00:18:23 1998 @@ -122,6 +122,8 @@ #define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long)) +__pmac + static void prom_exit() { diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c --- v2.1.100/linux/arch/ppc/kernel/ptrace.c Thu May 7 22:51:47 1998 +++ linux/arch/ppc/kernel/ptrace.c Fri May 8 00:18:23 1998 @@ -430,11 +430,11 @@ } if (addr >= PT_FPR0 && addr < PT_FPR0 + 64) { #ifndef __SMP__ - if (child->tss.regs->msr & MSR_FP ) - smp_giveup_fpu(child); -#else if (last_task_used_math == child) giveup_fpu(); +#else + if (child->tss.regs->msr & MSR_FP ) + smp_giveup_fpu(child); #endif ((long *)child->tss.fpr)[addr - PT_FPR0] = data; ret = 0; diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c --- v2.1.100/linux/arch/ppc/kernel/setup.c Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/kernel/setup.c Fri May 8 00:18:23 1998 @@ -1,5 +1,5 @@ /* - * $Id: setup.c,v 1.68 1998/04/07 08:20:33 geert Exp $ + * $Id: setup.c,v 1.77 1998/05/04 07:24:38 geert Exp $ * Common prep/pmac/chrp boot and setup code. */ @@ -73,11 +73,11 @@ /* * I really need to add multiple-console support... -- Cort */ -int pmac_display_supported(char *name) +__initfunc(int pmac_display_supported(char *name)) { return 0; } -void pmac_find_display(void) +__initfunc(void pmac_find_display(void)) { } #endif @@ -103,6 +103,7 @@ /* cmd is ignored for now... */ void machine_restart(char *cmd) { +#ifndef CONFIG_MBX struct adb_request req; unsigned long flags; unsigned long i = 10000; @@ -176,10 +177,15 @@ for(;;); break; } +#else /* CONFIG_MBX */ + extern void MBX_gorom(void); + MBX_gorom(); +#endif /* CONFIG_MBX */ } void machine_power_off(void) { +#ifndef CONFIG_MBX struct adb_request req; #if 0 int err; @@ -222,8 +228,10 @@ #endif #endif } - for (;;) - ; + for (;;); +#else /* CONFIG_MBX */ + machine_restart(NULL); +#endif /* CONFIG_MBX */ } void machine_halt(void) @@ -244,6 +252,7 @@ #ifdef CONFIG_BLK_DEV_IDE void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq) { +#ifndef CONFIG_MBX switch (_machine) { case _MACH_Pmac: pmac_ide_init_hwif_ports(p,base,irq); @@ -255,11 +264,13 @@ prep_ide_init_hwif_ports(p,base,irq); break; } +#endif } #endif unsigned long cpu_temp(void) { +#if 0 unsigned long i, temp, thrm1, dir; int sanity; @@ -318,8 +329,9 @@ } asm("mtspr 1020, %0\n\t" "mtspr 1022, %0\n\t" ::"r" (0) ); +#endif #endif - return temp; + return 0; } int get_cpuinfo(char *buffer) @@ -390,13 +402,18 @@ case 10: len += sprintf(len+buffer, "604ev5 (MachV)\n"); break; + case 50: + len += sprintf(len+buffer, "821\n"); + case 80: + len += sprintf(len+buffer, "860\n"); + break; default: len += sprintf(len+buffer, "unknown (%lu)\n", GET_PVR>>16); break; } - - + +#ifndef CONFIG_MBX /* * Assume here that all clock rates are the same in a * smp system. -- Cort @@ -426,7 +443,20 @@ res.VitalProductData.ProcessorHz); else len += sprintf(len+buffer, "???\n"); - } + } +#else /* CONFIG_MBX */ + { + bd_t *bp; + extern RESIDUAL res; + + bp = (bd_t *)&res; + + len += sprintf(len+buffer,"clock\t\t: %dMHz\n" + "bus clock\t: %dMHz\n", + bp->bi_intfreq /*/ 1000000*/, + bp->bi_busfreq /*/ 1000000*/); + } +#endif /* CONFIG_MBX */ len += sprintf(len+buffer, "revision\t: %ld.%ld\n", (GET_PVR & 0xff00) >> 8, GET_PVR & 0xff); @@ -460,6 +490,7 @@ ((zeropage_calls)?zeropage_calls:1)); } +#ifndef CONFIG_MBX switch (_machine) { case _MACH_Pmac: @@ -477,6 +508,7 @@ break; #endif } +#endif /* ndef CONFIG_MBX */ return len; } @@ -488,8 +520,8 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7)) { - extern setup_pci_ptrs(void); -#ifndef CONFIG_MBX8xx + extern void setup_pci_ptrs(void); +#ifndef CONFIG_MBX #ifdef CONFIG_APUS if ( r3 == 0x61707573 ) @@ -513,7 +545,7 @@ return 0; } -#endif +#endif /* CONFIG_APUS */ #ifndef CONFIG_MACH_SPECIFIC /* prep boot loader tells us if we're prep or not */ @@ -621,14 +653,14 @@ } else /* assume motorola if no residual (netboot?) */ _prep_type = _PREP_Motorola; -#ifdef CONFIG_BLK_DEV_RAM +#ifdef CONFIG_BLK_DEV_INITRD /* take care of initrd if we have one */ if ( r4 ) { initrd_start = r4 + KERNELBASE; initrd_end = r5 + KERNELBASE; } -#endif /* CONFIG_BLK_DEV_RAM */ +#endif /* CONFIG_BLK_DEV_INITRD */ /* take care of cmd line */ if ( r6 ) { @@ -637,14 +669,14 @@ } break; case _MACH_chrp: -#ifdef CONFIG_BLK_DEV_RAM +#ifdef CONFIG_BLK_DEV_INITRD /* take care of initrd if we have one */ if ( r3 ) { initrd_start = r3 + KERNELBASE; initrd_end = r3+ r4 + KERNELBASE; } -#endif /* CONFIG_BLK_DEV_RAM */ +#endif /* CONFIG_BLK_DEV_INITRD */ #if !defined(CONFIG_MACH_SPECIFIC) isa_io_base = CHRP_ISA_IO_BASE; isa_mem_base = CHRP_ISA_MEM_BASE; @@ -657,22 +689,21 @@ default: printk("Unknown machine type in identify_machine!\n"); } -#else /* CONFIG_MBX8xx */ - extern setup_pci_ptrs(void); +#else /* CONFIG_MBX */ if ( r3 ) memcpy( (void *)&res,(void *)(r3+KERNELBASE), sizeof(bd_t) ); setup_pci_ptrs(); -#ifdef CONFIG_BLK_DEV_RAM +#ifdef CONFIG_BLK_DEV_INITRD /* take care of initrd if we have one */ if ( r4 ) { initrd_start = r4 + KERNELBASE; initrd_end = r5 + KERNELBASE; } -#endif /* CONFIG_BLK_DEV_RAM */ +#endif /* CONFIG_BLK_DEV_INITRD */ /* take care of cmd line */ if ( r6 ) { @@ -682,7 +713,6 @@ } #endif /* CONFIG_MBX */ - return 0; } @@ -693,6 +723,7 @@ extern void chrp_setup_arch(unsigned long *, unsigned long *); extern void prep_setup_arch(unsigned long *, unsigned long *); extern void apus_setup_arch(char **, unsigned long *, unsigned long *); + extern void mbx_setup_arch(unsigned long *, unsigned long *); extern int panic_timeout; extern char _etext[], _edata[]; extern char *klimit; @@ -718,7 +749,9 @@ *memory_start_p = find_available_memory(); *memory_end_p = (unsigned long) end_of_DRAM; - +#ifdef CONFIG_MBX + mbx_setup_arch(memory_start_p,memory_end_p); +#else /* CONFIG_MBX */ switch (_machine) { case _MACH_Pmac: pmac_setup_arch(memory_start_p, memory_end_p); @@ -738,4 +771,5 @@ default: printk("Unknown machine %d in setup_arch()\n", _machine); } +#endif /* CONFIG_MBX */ } diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/signal.c linux/arch/ppc/kernel/signal.c --- v2.1.100/linux/arch/ppc/kernel/signal.c Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/kernel/signal.c Fri May 8 00:18:23 1998 @@ -118,6 +118,14 @@ } } + +asmlinkage int sys_rt_sigreturn(unsigned long __unused) +{ + printk("sys_rt_sigreturn(): %s/%d not yet implemented.\n", + current->comm,current->pid); + do_exit(SIGSEGV); +} + int sys_sigaction(int sig, const struct old_sigaction *act, struct old_sigaction *oact) diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c --- v2.1.100/linux/arch/ppc/kernel/smp.c Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/kernel/smp.c Fri May 8 00:18:23 1998 @@ -1,5 +1,5 @@ /* - * $Id: smp.c,v 1.22 1998/04/10 01:53:34 cort Exp $ + * $Id: smp.c,v 1.24 1998/04/27 09:02:37 cort Exp $ * * Smp support for ppc. * @@ -7,7 +7,6 @@ * deal of code from the sparc and intel versions. */ - #include #include #include @@ -18,6 +17,7 @@ #include #define __KERNEL_SYSCALLS__ #include +#include #include #include @@ -53,7 +53,123 @@ extern int cpu_idle(void *unused); -void smp_boot_cpus(void) +void smp_local_timer_interrupt(struct pt_regs * regs) +{ + int cpu = smp_processor_id(); + extern void update_one_process(struct task_struct *,unsigned long, + unsigned long,unsigned long,int); + + if (!--prof_counter[cpu]) { + int user=0,system=0; + struct task_struct * p = current; + + /* + * After doing the above, we need to make like + * a normal interrupt - otherwise timer interrupts + * ignore the global interrupt lock, which is the + * WrongThing (tm) to do. + */ + + if (user_mode(regs)) + user=1; + else + system=1; + + if (p->pid) { + update_one_process(p, 1, user, system, cpu); + + p->counter -= 1; + if (p->counter < 0) { + p->counter = 0; + need_resched = 1; + } + if (p->priority < DEF_PRIORITY) { + kstat.cpu_nice += user; + kstat.per_cpu_nice[cpu] += user; + } else { + kstat.cpu_user += user; + kstat.per_cpu_user[cpu] += user; + } + + kstat.cpu_system += system; + kstat.per_cpu_system[cpu] += system; + + } + prof_counter[cpu]=prof_multiplier[cpu]; + } +} + +/* + * Dirty hack to get smp message passing working. + * Right now it only works for stop cpu's but will be setup + * later for more general message passing. + * + * As it is now, if we're sending two message as the same time + * we have race conditions. I avoided doing locks here since + * all that works right now is the stop cpu message. + * + * -- Cort + */ +int smp_message[NR_CPUS]; +void smp_message_recv(void) +{ + int msg = smp_message[smp_processor_id()]; + + printk("SMP %d: smp_message_recv() msg %x\n", smp_processor_id(),msg); + + /* make sure msg is for us */ + if ( msg == -1 ) return; +printk("recv after msg check\n"); + switch( msg ) + { + case MSG_STOP_CPU: + __cli(); + while (1) ; + break; + case 0xf0f0: /* syncing time bases - just return */ + break; + default: + printk("SMP %d: smp_message_recv(): unknown msg %d\n", + smp_processor_id(), msg); + break; + } + /* reset message */ + smp_message[smp_processor_id()] = -1; +} + +spinlock_t mesg_pass_lock = SPIN_LOCK_UNLOCKED; +void smp_message_pass(int target, int msg, unsigned long data, int wait) +{ + printk("SMP %d: sending smp message\n", current->processor); + + spin_lock(&mesg_pass_lock); + if ( _machine != _MACH_Pmac ) + return; + +#define OTHER (~smp_processor_id() & 1) + + switch( target ) + { + case MSG_ALL: + smp_message[smp_processor_id()] = msg; + /* fall through */ + case MSG_ALL_BUT_SELF: + smp_message[OTHER] = msg; + break; + default: + smp_message[target] = msg; + break; + } + /* interrupt secondary processor */ + /**(volatile unsigned long *)(0xf80000c0) = 0xffffffff; + eieio();*/ + *(volatile unsigned long *)(0xf80000c0) = 0; + /* interrupt primary */ + /**(volatile unsigned long *)(0xf3019000);*/ + spin_unlock(&mesg_pass_lock); +} + +__initfunc(void smp_boot_cpus(void)) { extern unsigned long secondary_entry[]; extern struct task_struct *current_set[NR_CPUS]; @@ -118,10 +234,10 @@ __cpu_logical_map[i] = 1; printk("Processor 1 found.\n"); -#if 0 /* this sync's the decr's */ +#if 0 /* this sync's the decr's, but we don't want this now -- Cort */ set_dec(decrementer_count); #endif - /* interrupt secondary to sync the time bases */ + /* interrupt secondary to start decr's again */ smp_message_pass(1,0xf0f0, 0, 0); /* interrupt secondary to begin executing code */ /**(volatile unsigned long *)(0xf80000c0) = 0L; @@ -132,7 +248,7 @@ } } -void smp_commence(void) +__initfunc(void smp_commence(void)) { printk("SMP %d: smp_commence()\n",current->processor); /* @@ -144,19 +260,19 @@ } /* intel needs this */ -void initialize_secondary(void) +__initfunc(void initialize_secondary(void)) { } /* Activate a secondary processor. */ -int start_secondary(void *unused) +__initfunc(int start_secondary(void *unused)) { printk("SMP %d: start_secondary()\n",current->processor); smp_callin(); return cpu_idle(NULL); } -void smp_callin(void) +__initfunc(void smp_callin(void)) { printk("SMP %d: smp_callin()\n",current->processor); smp_store_cpu_info(1); @@ -174,128 +290,12 @@ __sti(); } -void smp_setup(char *str, int *ints) +__initfunc(void smp_setup(char *str, int *ints)) { printk("SMP %d: smp_setup()\n",current->processor); } -void smp_local_timer_interrupt(struct pt_regs * regs) -{ - int cpu = smp_processor_id(); - extern void update_one_process(struct task_struct *,unsigned long, - unsigned long,unsigned long,int); - - if (!--prof_counter[cpu]) { - int user=0,system=0; - struct task_struct * p = current; - - /* - * After doing the above, we need to make like - * a normal interrupt - otherwise timer interrupts - * ignore the global interrupt lock, which is the - * WrongThing (tm) to do. - */ - - if (user_mode(regs)) - user=1; - else - system=1; - - if (p->pid) { - update_one_process(p, 1, user, system, cpu); - - p->counter -= 1; - if (p->counter < 0) { - p->counter = 0; - need_resched = 1; - } - if (p->priority < DEF_PRIORITY) { - kstat.cpu_nice += user; - kstat.per_cpu_nice[cpu] += user; - } else { - kstat.cpu_user += user; - kstat.per_cpu_user[cpu] += user; - } - - kstat.cpu_system += system; - kstat.per_cpu_system[cpu] += system; - - } - prof_counter[cpu]=prof_multiplier[cpu]; - } -} - -/* - * Dirty hack to get smp message passing working. - * Right now it only works for stop cpu's but will be setup - * later for more general message passing. - * - * As it is now, if we're sending two message as the same time - * we have race conditions. I avoided doing locks here since - * all that works right now is the stop cpu message. - * - * -- Cort - */ -int smp_message[NR_CPUS]; -void smp_message_recv(void) -{ - int msg = smp_message[smp_processor_id()]; - - printk("SMP %d: smp_message_recv() msg %x\n", smp_processor_id(),msg); - - /* make sure msg is for us */ - if ( msg == -1 ) return; -printk("recv after msg check\n"); - switch( msg ) - { - case MSG_STOP_CPU: - __cli(); - while (1) ; - break; - case 0xf0f0: /* syncing time bases - just return */ - break; - default: - printk("SMP %d: smp_message_recv(): unknown msg %d\n", - smp_processor_id(), msg); - break; - } - /* reset message */ - smp_message[smp_processor_id()] = -1; -} - -spinlock_t mesg_pass_lock = SPIN_LOCK_UNLOCKED; -void smp_message_pass(int target, int msg, unsigned long data, int wait) -{ - printk("SMP %d: sending smp message\n", current->processor); - - spin_lock(&mesg_pass_lock); - if ( _machine != _MACH_Pmac ) - return; - -#define OTHER (~smp_processor_id() & 1) - - switch( target ) - { - case MSG_ALL: - smp_message[smp_processor_id()] = msg; - /* fall through */ - case MSG_ALL_BUT_SELF: - smp_message[OTHER] = msg; - break; - default: - smp_message[target] = msg; - break; - } - /* interrupt secondary processor */ - /**(volatile unsigned long *)(0xf80000c0) = 0xffffffff; - eieio();*/ - *(volatile unsigned long *)(0xf80000c0) = 0; - /* interrupt primary */ - /**(volatile unsigned long *)(0xf3019000);*/ - spin_unlock(&mesg_pass_lock); -} - -int setup_profiling_timer(unsigned int multiplier) +__initfunc(int setup_profiling_timer(unsigned int multiplier)) { return 0; } @@ -307,4 +307,3 @@ c->loops_per_sec = loops_per_sec; c->pvr = _get_PVR(); } - diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/softemu8xx.c linux/arch/ppc/kernel/softemu8xx.c --- v2.1.100/linux/arch/ppc/kernel/softemu8xx.c Sat Apr 25 18:13:10 1998 +++ linux/arch/ppc/kernel/softemu8xx.c Fri May 8 00:18:23 1998 @@ -63,34 +63,57 @@ ea = (uint *)(regs->gpr[idxreg] + disp); ip = (uint *)¤t->tss.fpr[flreg]; - if (inst == LFD) { + switch ( inst ) + { + case LFD: if (copy_from_user(ip, ea, sizeof(double))) retval = EFAULT; - } - else if (inst == LFDU) { - + break; + + case LFDU: if (copy_from_user(ip, ea, sizeof(double))) retval = EFAULT; else regs->gpr[idxreg] = (uint)ea; - } - else if (inst == STFD) { - + break; + case STFD: if (copy_to_user(ea, ip, sizeof(double))) retval = EFAULT; - } - else if (inst == STFDU) { + break; + case STFDU: if (copy_to_user(ea, ip, sizeof(double))) retval = EFAULT; else regs->gpr[idxreg] = (uint)ea; - } - else { + break; + default: retval = 1; + printk("Bad emulation %s/%d\n" + " NIP: %08x instruction: %08x opcode: %x " + "A: %x B: %x C: %x code: %x rc: %x\n", + current->comm,current->pid, + regs->nip, + instword,inst, + (instword>>16)&0x1f, + (instword>>11)&0x1f, + (instword>>6)&0x1f, + (instword>>1)&0x1f, + instword&1); + { + int pa; + print_8xx_pte(current->mm,regs->nip); + pa = get_8xx_pte(current->mm,regs->nip) & PAGE_MASK; + pa |= (regs->nip & ~PAGE_MASK); + pa = __va(pa); + printk("Kernel VA for NIP %x ", pa); + print_8xx_pte(current->mm,pa); + } + } if (retval == 0) regs->nip += 4; return(retval); } + diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c --- v2.1.100/linux/arch/ppc/kernel/time.c Sat Apr 25 18:13:10 1998 +++ linux/arch/ppc/kernel/time.c Fri May 8 00:18:23 1998 @@ -1,5 +1,5 @@ /* - * $Id: time.c,v 1.28 1998/04/07 18:49:49 cort Exp $ + * $Id: time.c,v 1.32 1998/04/24 12:29:38 davem Exp $ * Common time routines among all ppc machines. * * Written by Cort Dougan (cort@cs.nmt.edu) to merge @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -76,7 +77,6 @@ * this hack should leave for a better solution -- Cort */ unsigned dcache_locked = unlock_dcache(); -if ( smp_processor_id() ) printk("SMP 1: timer intr\n"); hardirq_enter(cpu); while ((dval = get_dec()) < 0) { @@ -116,6 +116,7 @@ */ void timebase_interrupt(int irq, void * dev, struct pt_regs * regs) { + printk("timebase_interrupt()\n"); } /* The RTC on the MPC8xx is an internal register. @@ -168,8 +169,7 @@ } -void -time_init(void) +__initfunc(void time_init(void)) { #ifndef CONFIG_MBX if ((_get_PVR() >> 16) == 1) { @@ -181,8 +181,7 @@ switch (_machine) { case _MACH_Pmac: - /* can't call pmac_get_rtc_time() yet, - because via-cuda isn't initialized yet. */ + xtime.tv_sec = pmac_get_rtc_time(); if ( (_get_PVR() >> 16) != 1 && (!smp_processor_id()) ) pmac_calibrate_decr(); if ( !smp_processor_id() ) @@ -212,8 +211,7 @@ #endif } xtime.tv_usec = 0; - set_dec(decrementer_count); -#else +#else /* CONFIG_MBX */ mbx_calibrate_decr(); set_rtc_time = mbx_set_rtc_time; @@ -249,7 +247,7 @@ xtime.tv_usec = 0; #endif /* CONFIG_MBX */ - + set_dec(decrementer_count); /* mark the rtc/on-chip timer as in sync * so we don't update right away */ @@ -265,7 +263,7 @@ */ int calibrate_done = 0; volatile int *done_ptr = &calibrate_done; -void prep_calibrate_decr(void) +__initfunc(void prep_calibrate_decr(void)) { unsigned long flags; @@ -308,7 +306,7 @@ free_irq( 0, NULL); } -void prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs * regs) +__initfunc(void prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs * regs)) { unsigned long freq, divisor; static unsigned long t1 = 0, t2 = 0; @@ -337,8 +335,9 @@ * sixteen, or external oscillator divided by four. Currently, we only * support the MBX, which is system clock divided by sixteen. */ -void mbx_calibrate_decr(void) +__initfunc(void mbx_calibrate_decr(void)) { + bd_t *binfo = (bd_t *)&res; int freq, fp, divisor; if ((((immap_t *)MBX_IMAP_ADDR)->im_clkrst.car_sccr & 0x02000000) == 0) @@ -348,7 +347,7 @@ * as MHz. The value 'fp' is the number of decrementer ticks * per second. */ - /*fp = (mbx_board_info.bi_intfreq * 1000000) / 16;*/ + fp = (binfo->bi_intfreq * 1000000) / 16; freq = fp*60; /* try to make freq/1e6 an integer */ divisor = 60; printk("time_init: decrementer frequency = %d/%d\n", freq, divisor); @@ -432,3 +431,6 @@ /* Days are what is left over (+1) from all that. */ tm->tm_mday = day + 1; } + + + diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c --- v2.1.100/linux/arch/ppc/kernel/traps.c Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/kernel/traps.c Fri May 8 00:18:23 1998 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -69,11 +70,6 @@ */ void -trap_init(void) -{ -} - -void _exception(int signr, struct pt_regs *regs) { if (!user_mode(regs)) @@ -93,6 +89,11 @@ { if ( !user_mode(regs) ) { +#ifdef CONFIG_MBX + /* the mbx pci read routines can cause machine checks -- Cort */ + bad_page_fault(regs,regs->dar); + return; +#endif /* CONFIG_MBX */ #if defined(CONFIG_XMON) || defined(CONFIG_KGDB) if (debugger_fault_handler) { debugger_fault_handler(regs); @@ -230,32 +231,28 @@ } #ifdef CONFIG_8xx - void SoftwareEmulation(struct pt_regs *regs) { int errcode; extern int Soft_emulate_8xx (struct pt_regs *regs); + extern void print_8xx_pte(struct mm_struct *, unsigned long); - if (user_mode(regs)) { -#if 0 - printk("(user mode)\n"); - _exception(SIGTRAP, regs); -#else - if (errcode = Soft_emulate_8xx(regs)) { -printk("Software Emulation 0x%x: 0x%x ", - regs->nip, *((uint *)regs->nip)); -print_8xx_pte(current->mm, regs->nip); + if (user_mode(regs)) + { + if ((errcode = Soft_emulate_8xx(regs))) { +printk("Software Emulation %s/%d NIP: %lx *NIP: 0x%x code: %x", + current->comm,current->pid, + regs->nip, *((uint *)regs->nip), errcode); +/*print_8xx_pte(current->mm, regs->nip);*/ if (errcode == EFAULT) _exception(SIGBUS, regs); else _exception(SIGILL, regs); } -#endif } else { - printk("(kernel mode)\n"); - panic("Kernel Mode Software Emulation"); + panic("Kernel Mode Software FPU Emulation"); } } #endif @@ -265,4 +262,8 @@ { printk("TAU trap at PC: %lx, SR: %lx, vector=%lx\n", regs->nip, regs->msr, regs->trap); +} + +__initfunc(void trap_init(void)) +{ } diff -u --recursive --new-file v2.1.100/linux/arch/ppc/lib/string.S linux/arch/ppc/lib/string.S --- v2.1.100/linux/arch/ppc/lib/string.S Mon Jan 12 15:18:13 1998 +++ linux/arch/ppc/lib/string.S Fri May 8 00:18:23 1998 @@ -274,6 +274,8 @@ .long 17b,99b .text +#undef CLEAR_USE_DCBZ 1 +#undef CLEAR_NO_CACHE 1 .globl __clear_user __clear_user: addi r6,r3,-4 @@ -281,17 +283,34 @@ li r5,0 cmplwi 0,r4,4 blt 7f + /* clear a single word */ 11: stwu r5,4(r6) beqlr +#if defined(CLEAR_NO_CACHE) && defined (CONFIG_6xx) + /* + * no reason to turn off the cache for a single word + * or a few bytes -- Cort + */ + mfspr r7,HID0 + ori r8,r7,HID0_DLOCK + mtspr HID0,r8 +#endif /* CLEAR_NO_CACHE */ + /* clear word sized chunks */ andi. r0,r6,3 add r4,r0,r4 subf r6,r0,r6 - rlwinm r0,r4,32-2,2,31 + /*rlwinm r0,r4,32-2,2,31*/ + srwi r0,r4,2 mtctr r0 bdz 6f 1: stwu r5,4(r6) bdnz 1b 6: andi. r4,r4,3 +#if defined(CLEAR_NO_CACHE) && defined (CONFIG_6xx) + /* restore the original state of HID0 in case cache was off -- Cort */ + mtspr HID0,r7 +#endif /* CLEAR_NO_CACHE */ + /* clear byte sized chunks */ 7: cmpwi 0,r4,0 beqlr mtctr r4 @@ -305,6 +324,9 @@ .align 2 .long 11b,99b .long 1b,99b +#ifdef CLEAR_USE_DCBZ + /*.long 66b,99b*/ +#endif .long 8b,99b .text diff -u --recursive --new-file v2.1.100/linux/arch/ppc/mbx_defconfig linux/arch/ppc/mbx_defconfig --- v2.1.100/linux/arch/ppc/mbx_defconfig Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/mbx_defconfig Fri May 8 00:18:23 1998 @@ -12,7 +12,9 @@ # CONFIG_PREP is not set # CONFIG_CHRP is not set # CONFIG_ALL_PPC is not set +# CONFIG_APUS is not set CONFIG_MBX=y +CONFIG_SERIAL_CONSOLE=y CONFIG_MACH_SPECIFIC=y # @@ -34,7 +36,9 @@ # CONFIG_PMAC_CONSOLE is not set # CONFIG_MAC_KEYBOARD is not set # CONFIG_MAC_FLOPPY is not set +# CONFIG_MAC_SERIAL is not set # CONFIG_PROC_DEVICETREE is not set +# CONFIG_KGDB is not set # CONFIG_XMON is not set CONFIG_VGA_CONSOLE=y @@ -52,19 +56,13 @@ # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_XD is not set CONFIG_PARIDE_PARPORT=y # CONFIG_PARIDE is not set # CONFIG_BLK_DEV_HD is not set # -# NEW devices (io_request, all ALPHA and dangerous) -# -# CONFIG_IO_REQUEST is not set - -# # Networking options # # CONFIG_PACKET is not set @@ -142,13 +140,13 @@ # # CONFIG_QUOTA is not set # CONFIG_MINIX_FS is not set -CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS is not set # CONFIG_ISO9660_FS is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set -# CONFIG_PROC_FS is not set +CONFIG_PROC_FS=y CONFIG_NFS_FS=y CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set @@ -171,8 +169,7 @@ # Character devices # # CONFIG_VT is not set -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL is not set # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_MOUSE is not set @@ -189,8 +186,3 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set - -# -# Sound -# -# CONFIG_SOUND is not set diff -u --recursive --new-file v2.1.100/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c --- v2.1.100/linux/arch/ppc/mm/fault.c Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/mm/fault.c Fri May 8 00:18:23 1998 @@ -62,13 +62,13 @@ struct vm_area_struct * vma; struct mm_struct *mm = current->mm; - /*printk("address: %08lx code: %08lx %s%s%s%s%s%s\n", - address,error_code, + /*printk("address: %08lx nip:%08lx code: %08lx %s%s%s%s%s%s\n", + address,regs->nip,error_code, (error_code&0x40000000)?"604 tlb&htab miss ":"", (error_code&0x20000000)?"603 tlbmiss ":"", (error_code&0x02000000)?"write ":"", (error_code&0x08000000)?"prot ":"", - (error_code&0x95700000)?"I/O ":"", + (error_code&0x80000000)?"I/O ":"", (regs->trap == 0x400)?"instr":"data" );*/ @@ -161,32 +161,6 @@ bad_page_fault(struct pt_regs *regs, unsigned long address) { unsigned long fixup; -#if 0 - extern unsigned long video_mem_base; - extern unsigned long video_mem_term; - - /* - * Remap video IO areas for buggy X servers. - * The S3 server wants direct access to video memory - * at 0x8000 0000 and 0xc000 0000 on prep systems, but - * we don't allow that AND we remap the io areas so it's not - * even there! - * So, for this task only give a virtual=physical mapping of the - * video mem. - * -- Cort - */ - if ( is_prep && user_mode(regs) ) - { - printk("%s/%d: fault on %x\n", - current->comm,current->pid,address); - printk("mapping: %x -> %x\n", - address&PAGE_MASK, address&PAGE_MASK); - map_page(current,address&PAGE_MASK,address&PAGE_MASK, - _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE|_PAGE_NO_CACHE|_PAGE_WRITETHRU); - return; - } -#endif - if (user_mode(regs)) { force_sig(SIGSEGV, current); return; @@ -209,6 +183,7 @@ regs->nip,regs->link,address,current->comm,current->pid); } +#ifdef CONFIG_8xx /* * I need a va to pte function for the MPC8xx so I can set the cache * attributes on individual pages used by the Communication Processor @@ -286,6 +261,17 @@ if (pte) { printk(" (0x%08lx)->(0x%08lx)->0x%08lx\n", (long)pgd, (long)pte, (long)pte_val(*pte)); +#define pp ((long)pte_val(*pte)) + printk(" RPN: %05x PP: %x SPS: %x SH: %x " + "CI: %x v: %x\n", + pp>>12, /* rpn */ + (pp>>10)&3, /* pp */ + (pp>>3)&1, /* small */ + (pp>>2)&1, /* shared */ + (pp>>1)&1, /* cache inhibit */ + pp&1 /* valid */ + ); +#undef pp } else { printk("no pte\n"); @@ -320,6 +306,7 @@ } return(retval); } +#endif /* CONFIG_8xx */ #if 0 /* diff -u --recursive --new-file v2.1.100/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c --- v2.1.100/linux/arch/ppc/mm/init.c Thu May 7 22:51:47 1998 +++ linux/arch/ppc/mm/init.c Fri May 8 00:18:23 1998 @@ -1,5 +1,5 @@ /* - * arch/ppc/mm/init.c + * $Id: init.c,v 1.94 1998/05/06 02:07:36 paulus Exp $ * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) @@ -33,30 +33,25 @@ #include #include #include +#include +#ifdef CONFIG_BLK_DEV_INITRD +#include /* for initrd_* */ +#endif + #include #include #include #include #include #include -#ifdef CONFIG_BLK_DEV_INITRD -#include /* for initrd_* */ -#endif +#include #ifdef CONFIG_8xx #include #endif #ifdef CONFIG_MBX #include #endif - -#ifndef CONFIG_8xx -unsigned long _SDR1; -PTE *Hash, *Hash_end; -unsigned long Hash_size, Hash_mask; -#endif /* CONFIG_8xx */ - -/* ifdef APUS specific stuff until the merge is completed. -jskov */ -#ifdef CONFIG_APUS +#ifdef CONFIG_APUS /* ifdef APUS specific stuff until the merge is completed. -jskov */ #include #include #endif @@ -69,67 +64,60 @@ extern char _start[], _end[]; extern char etext[], _stext[]; extern char __init_begin, __init_end; +extern char __prep_begin, __prep_end; +extern char __pmac_begin, __pmac_end; +extern char __openfirmware_begin, __openfirmware_end; extern RESIDUAL res; char *klimit = _end; struct device_node *memory_node; unsigned long ioremap_base; unsigned long ioremap_bot; +unsigned long avail_start; #ifndef __SMP__ struct pgtable_cache_struct quicklists; #endif -#ifndef CONFIG_8xx -static void hash_init(void); -#endif /* CONFIG_8xx */ -static void mapin_ram(void); +void MMU_init(void); static void *MMU_get_page(void); +unsigned long *prep_find_end_of_memory(void); +unsigned long *pmac_find_end_of_memory(void); +extern unsigned long *find_end_of_memory(void); +static void mapin_ram(void); void map_page(struct task_struct *, unsigned long va, unsigned long pa, int flags); extern void die_if_kernel(char *,struct pt_regs *,long); extern void show_net_buffers(void); -extern unsigned long *find_end_of_memory(void); extern struct task_struct *current_set[NR_CPUS]; +#ifndef CONFIG_8xx +unsigned long _SDR1; +PTE *Hash, *Hash_end; +unsigned long Hash_size, Hash_mask; +static void hash_init(void); +union ubat { /* BAT register values to be loaded */ + BAT bat; + P601_BAT bat_601; + u32 word[2]; +} BATS[4][2]; /* 4 pairs of IBAT, DBAT */ + +struct batrange { /* stores address ranges mapped by BATs */ + unsigned long start; + unsigned long limit; + unsigned long phys; +} bat_addrs[4]; +#endif /* CONFIG_8xx */ #ifdef CONFIG_MBX -/* This is a big hack that may not yet work correctly. - * The MBX8xx boards have a single DIMM socket for additional memory. - * Although it appears you can set magical locations in the serial - * EEPROM to get EPPC-Bug to configure this memory, there are no tools - * (i.e. commands) to make this easy. If you screw up, you will most - * likely end up with a board that will not boot until you find a - * way to program the EEPROM correctly. I decided to simply program - * the memory controller here to add the additional memory. - * The reason this may not work correctly is that depending upon the - * on-board and DIMM memory size, there may be holes in the physical - * address space. This is the case for me, I have a 4 MB local memory - * and a 32 MB DIMM. - * The DIMM is 64 bits wide, and we see it as two banks of 32 bit - * memory. The holes are caused by the requirement to map the - * memory on a natural alignment, that is a 16 MB bank must begin on - * a 16 MB boundary. The DIMM_SIZE below represents the size of the - * bank, which is the total size divided by two. - * Although I may not have all of this working, the intention is to - * mark all of the page maps in the "hole" as reserved, and adjust - * num_physpages accordingly. In the current implementation, this - * seems to work, but there are some assumptions about contiguous - * memory. The correct solution is to modify the memory allocators - * to know about holes, but that will have to wait for another day. - * - * define DIMM_8xx to enable this feature. - * define DIMM_SIZE to reflect the bank size (DIMM size divided by two). - */ -/*#define DIMM_8xx 1 */ -#define DIMM_SIZE (16 * 1024 * 1024) +void set_mbx_memory(void); #endif /* CONFIG_MBX */ /* * this tells the system to map all of ram with the segregs * (i.e. page tables) instead of the bats. + * -- Cort */ #undef MAP_RAM_WITH_SEGREGS 1 - -/* optimization for 603 to load the tlb directly from the linux table */ +/* optimization for 603 to load the tlb directly from the linux table -- Cort */ #define NO_RELOAD_HTAB 1 /* change in kernel/head.S too! */ void __bad_pte(pmd_t *pmd) @@ -177,7 +165,8 @@ pte_t * __bad_pagetable(void) { - memset((void *)empty_bad_page_table, 0, PAGE_SIZE); + /*memset((void *)empty_bad_page_table, 0, PAGE_SIZE);*/ + __clear_user((void *)empty_bad_page_table, PAGE_SIZE); return (pte_t *) empty_bad_page_table; } @@ -185,10 +174,355 @@ pte_t __bad_page(void) { - memset((void *)empty_bad_page, 0, PAGE_SIZE); + /*memset((void *)empty_bad_page, 0, PAGE_SIZE);*/ + __clear_user((void *)empty_bad_page, PAGE_SIZE); return pte_mkdirty(mk_pte(empty_bad_page, PAGE_SHARED)); } +void show_mem(void) +{ + int i,free = 0,total = 0,reserved = 0; + int shared = 0, cached = 0; + struct task_struct *p; + + printk("Mem-info:\n"); + show_free_areas(); + printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); + i = max_mapnr; + while (i-- > 0) { + total++; + if (PageReserved(mem_map+i)) + reserved++; + else if (PageSwapCache(mem_map+i)) + cached++; + else if (!atomic_read(&mem_map[i].count)) + free++; + else + shared += atomic_read(&mem_map[i].count) - 1; + } + printk("%d pages of RAM\n",total); + printk("%d free pages\n",free); + printk("%d reserved pages\n",reserved); + printk("%d pages shared\n",shared); + printk("%d pages swap cached\n",cached); + printk("%d pages in page table cache\n",(int)pgtable_cache_size); + show_buffers(); +#ifdef CONFIG_NET + show_net_buffers(); +#endif + printk("%-8s %3s %3s %8s %8s %8s %9s %8s", "Process", "Pid", "Cnt", + "Ctx", "Ctx<<4", "Last Sys", "pc", "task"); +#ifdef __SMP__ + printk(" %3s", "CPU"); +#endif /* __SMP__ */ + printk("\n"); + for_each_task(p) + { + printk("%-8.8s %3d %3d %8ld %8ld %8ld %c%08lx %08lx ", + p->comm,p->pid, + p->mm->count,p->mm->context, + p->mm->context<<4, p->tss.last_syscall, + user_mode(p->tss.regs) ? 'u' : 'k', p->tss.regs->nip, + (ulong)p); + { + int iscur = 0; +#ifdef __SMP__ + printk("%3d ", p->processor); + if ( (p->processor != NO_PROC_ID) && + (p == current_set[p->processor]) ) + +#else + if ( p == current ) +#endif /* __SMP__ */ + { + iscur = 1; + printk("current"); + } + if ( p == last_task_used_math ) + { + if ( iscur ) + printk(","); + printk("last math"); + } + printk("\n"); + } + } +} + +void si_meminfo(struct sysinfo *val) +{ + int i; + + i = max_mapnr; + val->totalram = 0; + val->sharedram = 0; + val->freeram = nr_free_pages << PAGE_SHIFT; + val->bufferram = buffermem; + while (i-- > 0) { + if (PageReserved(mem_map+i)) + continue; + val->totalram++; + if (!atomic_read(&mem_map[i].count)) + continue; + val->sharedram += atomic_read(&mem_map[i].count) - 1; + } + val->totalram <<= PAGE_SHIFT; + val->sharedram <<= PAGE_SHIFT; + return; +} + +void * +ioremap(unsigned long addr, unsigned long size) +{ + return __ioremap(addr, size, _PAGE_NO_CACHE); +} + +void * +__ioremap(unsigned long addr, unsigned long size, unsigned long flags) +{ + unsigned long p, v, i; + + /* + * Choose an address to map it to. + * Once the vmalloc system is running, we use it. + * Before then, we map addresses >= ioremap_base + * virt == phys; for addresses below this we use + * space going down from ioremap_base (ioremap_bot + * records where we're up to). + * + * We should also look out for a frame buffer and + * map it with a free BAT register, if there is one. + */ + p = addr & PAGE_MASK; + size = PAGE_ALIGN(addr + size) - p; + if (size == 0) + return NULL; + + if (mem_init_done) { + struct vm_struct *area; + area = get_vm_area(size); + if (area == 0) + return NULL; + v = VMALLOC_VMADDR(area->addr); + } else { + if (p >= ioremap_base) + v = p; + else + v = (ioremap_bot -= size); + } + + flags |= pgprot_val(PAGE_KERNEL); + if (flags & (_PAGE_NO_CACHE | _PAGE_WRITETHRU)) + flags |= _PAGE_GUARDED; + for (i = 0; i < size; i += PAGE_SIZE) + map_page(&init_task, v+i, p+i, flags); + + return (void *) (v + (addr & ~PAGE_MASK)); +} + +void iounmap(void *addr) +{ + /* XXX todo */ +} + +unsigned long iopa(unsigned long addr) +{ + unsigned long idx; + pmd_t *pd; + pte_t *pg; +#ifndef CONFIG_8xx + int b; +#endif + idx = addr & ~PAGE_MASK; + addr = addr & PAGE_MASK; + +#ifndef CONFIG_8xx + /* Check the BATs */ + for (b = 0; b < 4; ++b) + if (addr >= bat_addrs[b].start && addr <= bat_addrs[b].limit) +#ifndef CONFIG_APUS + return bat_addrs[b].phys | idx; +#else + /* Do a more precise remapping of virtual address */ + /* --Carsten */ + return (bat_addrs[b].phys - bat_addrs[b].start + addr) | idx; +#endif /* CONFIG_APUS */ +#endif /* CONFIG_8xx */ + /* Do we have a page table? */ + if (init_task.mm->pgd == NULL) + return 0; + + /* Use upper 10 bits of addr to index the first level map */ + pd = (pmd_t *) (init_task.mm->pgd + (addr >> PGDIR_SHIFT)); + if (pmd_none(*pd)) + return 0; + + /* Use middle 10 bits of addr to index the second-level map */ + pg = pte_offset(pd, addr); + return (pte_val(*pg) & PAGE_MASK) | idx; +} + +void +map_page(struct task_struct *tsk, unsigned long va, + unsigned long pa, int flags) +{ + pmd_t *pd; + pte_t *pg; +#ifndef CONFIG_8xx + int b; +#endif + if (tsk->mm->pgd == NULL) { + /* Allocate upper level page map */ + tsk->mm->pgd = (pgd_t *) MMU_get_page(); + } + /* Use upper 10 bits of VA to index the first level map */ + pd = (pmd_t *) (tsk->mm->pgd + (va >> PGDIR_SHIFT)); + if (pmd_none(*pd)) { +#ifndef CONFIG_8xx + /* + * Need to allocate second-level table, but first + * check whether this address is already mapped by + * the BATs; if so, don't bother allocating the page. + */ + for (b = 0; b < 4; ++b) { + if (va >= bat_addrs[b].start + && va <= bat_addrs[b].limit) { + /* XXX should check the phys address matches */ + return; + } + } +#endif /* CONFIG_8xx */ + pg = (pte_t *) MMU_get_page(); + pmd_val(*pd) = (unsigned long) pg; + } + /* Use middle 10 bits of VA to index the second-level map */ + pg = pte_offset(pd, va); + set_pte(pg, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags))); +#ifndef CONFIG_8xx + flush_hash_page(0, va); +#endif +} + +/* + * TLB flushing: + * + * - flush_tlb_all() flushes all processes TLBs + * - flush_tlb_mm(mm) flushes the specified mm context TLB's + * - flush_tlb_page(vma, vmaddr) flushes one page + * - flush_tlb_range(mm, start, end) flushes a range of pages + * + * since the hardware hash table functions as an extension of the + * tlb as far as the linux tables are concerned, flush it too. + * -- Cort + */ + +/* + * Flush all tlb/hash table entries (except perhaps for those + * mapping RAM starting at PAGE_OFFSET, since they never change). + */ +void +local_flush_tlb_all(void) +{ +#ifndef CONFIG_8xx + __clear_user(Hash, Hash_size); + /*memset(Hash, 0, Hash_size);*/ + _tlbia(); +#else + asm volatile ("tlbia" : : ); +#endif +} + +/* + * Flush all the (user) entries for the address space described + * by mm. We can't rely on mm->mmap describing all the entries + * that might be in the hash table. + */ +void +local_flush_tlb_mm(struct mm_struct *mm) +{ +#ifndef CONFIG_8xx + mm->context = NO_CONTEXT; + if (mm == current->mm) + activate_context(current); +#else + asm volatile ("tlbia" : : ); +#endif +} + +void +local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) +{ +#ifndef CONFIG_8xx + if (vmaddr < TASK_SIZE) + flush_hash_page(vma->vm_mm->context, vmaddr); + else + flush_hash_page(0, vmaddr); +#else + asm volatile ("tlbia" : : ); +#endif +} + + +/* + * for each page addr in the range, call MMU_invalidate_page() + * if the range is very large and the hash table is small it might be + * faster to do a search of the hash table and just invalidate pages + * that are in the range but that's for study later. + * -- Cort + */ +void +local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) +{ +#ifndef CONFIG_8xx + start &= PAGE_MASK; + + if (end - start > 20 * PAGE_SIZE) + { + flush_tlb_mm(mm); + return; + } + + for (; start < end && start < TASK_SIZE; start += PAGE_SIZE) + { + flush_hash_page(mm->context, start); + } +#else + asm volatile ("tlbia" : : ); +#endif +} + +/* + * The context counter has overflowed. + * We set mm->context to NO_CONTEXT for all mm's in the system. + * We assume we can get to all mm's by looking as tsk->mm for + * all tasks in the system. + */ +void +mmu_context_overflow(void) +{ +#ifndef CONFIG_8xx + struct task_struct *tsk; + + printk(KERN_DEBUG "mmu_context_overflow\n"); + read_lock(&tasklist_lock); + for_each_task(tsk) { + if (tsk->mm) + tsk->mm->context = NO_CONTEXT; + } + read_unlock(&tasklist_lock); + flush_hash_segments(0x10, 0xffffff); + next_mmu_context = 0; + /* make sure current always has a context */ + current->mm->context = MUNGE_CONTEXT(++next_mmu_context); + set_context(current->mm->context); +#else + /* We set the value to -1 because it is pre-incremented before + * before use. + */ + next_mmu_context = -1; +#endif +} + /* * The following stuff defines a data structure for representing * areas of memory as an array of (address, length) pairs, and @@ -211,8 +545,8 @@ /* * Scan a region for a piece of a given size with the required alignment. */ -void * -find_mem_piece(unsigned size, unsigned align) +__initfunc(void * +find_mem_piece(unsigned size, unsigned align)) { int i; unsigned a, e; @@ -235,9 +569,9 @@ /* * Remove some memory from an array of pieces */ -static void +__initfunc(static void remove_mem_piece(struct mem_pieces *mp, unsigned start, unsigned size, - int must_exist) + int must_exist)) { int i, j; unsigned end, rs, re; @@ -291,8 +625,7 @@ } } -static void -print_mem_pieces(struct mem_pieces *mp) +__initfunc(static void print_mem_pieces(struct mem_pieces *mp)) { int i; @@ -311,8 +644,7 @@ static void coalesce_mem_pieces(struct mem_pieces *); static void append_mem_piece(struct mem_pieces *, unsigned, unsigned); -static void -sort_mem_pieces(struct mem_pieces *mp) +__initfunc(static void sort_mem_pieces(struct mem_pieces *mp)) { unsigned long a, s; int i, j; @@ -330,8 +662,7 @@ } } -static void -coalesce_mem_pieces(struct mem_pieces *mp) +__initfunc(static void coalesce_mem_pieces(struct mem_pieces *mp)) { unsigned long a, e; int i, j, d; @@ -353,8 +684,8 @@ /* * Add some memory to an array of pieces */ -static void -append_mem_piece(struct mem_pieces *mp, unsigned start, unsigned size) +__initfunc(static void + append_mem_piece(struct mem_pieces *mp, unsigned start, unsigned size)) { struct reg_property *rp; @@ -369,8 +700,7 @@ * Read in a property describing some pieces of memory. */ -static void -get_mem_prop(char *name, struct mem_pieces *mp) +__initfunc(static void get_mem_prop(char *name, struct mem_pieces *mp)) { struct reg_property *rp; int s; @@ -389,423 +719,16 @@ coalesce_mem_pieces(mp); } -/* - * On systems with Open Firmware, collect information about - * physical RAM and which pieces are already in use. - * At this point, we have (at least) the first 8MB mapped with a BAT. - * Our text, data, bss use something over 1MB, starting at 0. - * Open Firmware may be using 1MB at the 4MB point. - */ -unsigned long *pmac_find_end_of_memory(void) -{ - unsigned long a, total; - unsigned long kstart, ksize; - int i; - - memory_node = find_devices("memory"); - if (memory_node == NULL) { - printk(KERN_ERR "can't find memory node\n"); - abort(); - } - - /* - * Find out where physical memory is, and check that it - * starts at 0 and is contiguous. It seems that RAM is - * always physically contiguous on Power Macintoshes, - * because MacOS can't cope if it isn't. - * - * Supporting discontiguous physical memory isn't hard, - * it just makes the virtual <-> physical mapping functions - * more complicated (or else you end up wasting space - * in mem_map). - */ - get_mem_prop("reg", &phys_mem); - if (phys_mem.n_regions == 0) - panic("No RAM??"); - a = phys_mem.regions[0].address; - if (a != 0) - panic("RAM doesn't start at physical address 0"); - total = phys_mem.regions[0].size; - if (phys_mem.n_regions > 1) { - printk("RAM starting at 0x%x is not contiguous\n", - phys_mem.regions[1].address); - printk("Using RAM from 0 to 0x%lx\n", total-1); - phys_mem.n_regions = 1; - } - - /* record which bits the prom is using */ - get_mem_prop("available", &phys_avail); - prom_mem = phys_mem; - for (i = 0; i < phys_avail.n_regions; ++i) - remove_mem_piece(&prom_mem, phys_avail.regions[i].address, - phys_avail.regions[i].size, 1); - - /* - * phys_avail records memory we can use now. - * prom_mem records memory allocated by the prom that we - * don't want to use now, but we'll reclaim later. - * Make sure the kernel text/data/bss is in neither. - */ - kstart = __pa(_stext); /* should be 0 */ - ksize = PAGE_ALIGN(klimit - _stext); - remove_mem_piece(&phys_avail, kstart, ksize, 0); - remove_mem_piece(&prom_mem, kstart, ksize, 0); - remove_mem_piece(&phys_avail, 0, 0x4000, 0); - remove_mem_piece(&prom_mem, 0, 0x4000, 0); - - return __va(total); -} -#endif /* CONFIG_8xx */ - -#ifdef CONFIG_APUS -#define HARDWARE_MAPPED_SIZE (512*1024) -unsigned long *apus_find_end_of_memory(void) -{ - unsigned long kstart, ksize; - - /* Add the chunk that ADOS does not see. Removed again below. */ - m68k_memory[0].size += HARDWARE_MAPPED_SIZE; - - append_mem_piece(&phys_mem, m68k_memory[0].addr, m68k_memory[0].size); - - phys_avail = phys_mem; - kstart = __pa(_stext); - ksize = PAGE_ALIGN(klimit - _stext); - remove_mem_piece(&phys_avail, kstart, ksize, 1); - - /* Remove the upper HARDWARE_MAPPED_SIZE bytes where the address - * range 0xfff00000-0xfffx0000 is mapped to. - * We do it this way to ensure that the memory registered in the - * system has a power-of-two size. - */ - remove_mem_piece(&phys_avail, - (m68k_memory[0].addr + m68k_memory[0].size - - HARDWARE_MAPPED_SIZE), - HARDWARE_MAPPED_SIZE, 1); - - /* FIXME:APUS: Only handles one block of memory! Problem is - * that the VTOP/PTOV code in head.S would be a mess if it had - * to handle more than one block. - */ - return __va(m68k_memory[0].addr + m68k_memory[0].size); -} -#endif - -/* - * Find some memory for setup_arch to return. - * We use the last chunk of available memory as the area - * that setup_arch returns, making sure that there are at - * least 32 pages unused before this for MMU_get_page to use. - */ -unsigned long avail_start; - -unsigned long find_available_memory(void) -{ - int i; - unsigned long a, free; - unsigned long start, end; - - free = 0; - if (_machine == _MACH_mbx) { - /* Return the first, not the last region, because we - * may not yet have properly initialized the additonal - * memory DIMM. - */ - a = PAGE_ALIGN(phys_avail.regions[0].address); - avail_start = (unsigned long) __va(a); - return avail_start; - } - - for (i = 0; i < phys_avail.n_regions - 1; ++i) { - start = phys_avail.regions[i].address; - end = start + phys_avail.regions[i].size; - free += (end & PAGE_MASK) - PAGE_ALIGN(start); - } - a = PAGE_ALIGN(phys_avail.regions[i].address); - if (free < 32 * PAGE_SIZE) - a += 32 * PAGE_SIZE - free; - avail_start = (unsigned long) __va(a); - return avail_start; -} - -void show_mem(void) -{ - int i,free = 0,total = 0,reserved = 0; - int shared = 0, cached = 0; - struct task_struct *p; - - printk("Mem-info:\n"); - show_free_areas(); - printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); - i = max_mapnr; - while (i-- > 0) { - total++; - if (PageReserved(mem_map+i)) - reserved++; - else if (PageSwapCache(mem_map+i)) - cached++; - else if (!atomic_read(&mem_map[i].count)) - free++; - else - shared += atomic_read(&mem_map[i].count) - 1; - } - printk("%d pages of RAM\n",total); - printk("%d free pages\n",free); - printk("%d reserved pages\n",reserved); - printk("%d pages shared\n",shared); - printk("%d pages swap cached\n",cached); - printk("%d pages in page table cache\n",(int)pgtable_cache_size); - show_buffers(); -#ifdef CONFIG_NET - show_net_buffers(); -#endif - printk("%-8s %3s %3s %8s %8s %8s %9s %8s", "Process", "Pid", "Cnt", - "Ctx", "Ctx<<4", "Last Sys", "pc", "task"); -#ifdef __SMP__ - printk(" %3s", "CPU"); -#endif /* __SMP__ */ - printk("\n"); - for_each_task(p) - { - printk("%-8.8s %3d %3d %8ld %8ld %8ld %c%08lx %08lx ", - p->comm,p->pid, - p->mm->count,p->mm->context, - p->mm->context<<4, p->tss.last_syscall, - user_mode(p->tss.regs) ? 'u' : 'k', p->tss.regs->nip, - (ulong)p); - { - int iscur = 0; -#ifdef __SMP__ - printk("%3d ", p->processor); - if ( (p->processor != NO_PROC_ID) && - (p == current_set[p->processor]) ) - -#else - if ( p == current ) -#endif /* __SMP__ */ - { - iscur = 1; - printk("current"); - } - if ( p == last_task_used_math ) - { - if ( iscur ) - printk(","); - printk("last math"); - } - printk("\n"); - } - } -} - -extern unsigned long free_area_init(unsigned long, unsigned long); - -/* - * paging_init() sets up the page tables - in fact we've already done this. - */ -unsigned long paging_init(unsigned long start_mem, unsigned long end_mem) -{ - /* - * Grab some memory for bad_page and bad_pagetable to use. - */ - empty_bad_page = PAGE_ALIGN(start_mem); - empty_bad_page_table = empty_bad_page + PAGE_SIZE; - start_mem = empty_bad_page + 2 * PAGE_SIZE; - - /* note: free_area_init uses its second argument - to size the mem_map array. */ - start_mem = free_area_init(start_mem, end_mem); - return start_mem; -} - -void mem_init(unsigned long start_mem, unsigned long end_mem) -{ - unsigned long addr; - int i; - unsigned long a, lim; - int codepages = 0; - int datapages = 0; - int initpages = 0; - extern unsigned int rtas_data, rtas_size; - - end_mem &= PAGE_MASK; - high_memory = (void *) end_mem; - max_mapnr = MAP_NR(high_memory); - num_physpages = max_mapnr; /* RAM is assumed contiguous */ - - /* mark usable pages in the mem_map[] */ - start_mem = PAGE_ALIGN(start_mem); - -#ifndef CONFIG_8xx - remove_mem_piece(&phys_avail, __pa(avail_start), - start_mem - avail_start, 1); - - for (addr = PAGE_OFFSET; addr < end_mem; addr += PAGE_SIZE) - set_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags); - - for (i = 0; i < phys_avail.n_regions; ++i) { - a = (unsigned long) __va(phys_avail.regions[i].address); - lim = a + phys_avail.regions[i].size; - a = PAGE_ALIGN(a); - for (; a < lim; a += PAGE_SIZE) - clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); - } - phys_avail.n_regions = 0; - - /* free the prom's memory - no-op on prep */ - for (i = 0; i < prom_mem.n_regions; ++i) { - a = (unsigned long) __va(prom_mem.regions[i].address); - lim = a + prom_mem.regions[i].size; - a = PAGE_ALIGN(a); - for (; a < lim; a += PAGE_SIZE) - clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); - } - prom_trashed = 1; -#else /* CONFIG_8xx */ - /* When we get here, all of the page maps have been set up and - * Linux thinks we have contiguous memory. Since the MBX can - * have memory holes, we need to compensate for that here. - * The memory holes are currently pages marked reserved (all - * pages right now are marked reserved). - * All of the memory allocated by the kernel up to this point - * had to come from region 0. - */ - - /* First, unreserve all memory from the page following start_mem - * to the end of region 0. - */ - for (addr = start_mem + PAGE_SIZE ; - addr < (ulong) __va(phys_mem.regions[0].size); - addr += PAGE_SIZE) { - clear_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags); - } - - /* Now add any additional regions to the system. - */ - for (i = 1; i < phys_avail.n_regions; ++i) { - a = (unsigned long) __va(phys_avail.regions[i].address); - lim = a + phys_avail.regions[i].size; - a = PAGE_ALIGN(a); - for (; a < lim; a += PAGE_SIZE) - clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); - } - phys_avail.n_regions = 0; /* Nothing available, kernel owns */ - /* Count up the size of the holes. We look for the space - * between the end of one region and the start of the next. - */ - lim = 0; - for (i = 0; i < phys_mem.n_regions-1; ++i) { - a = (unsigned long) phys_mem.regions[i].address; - a += phys_mem.regions[i].size; - lim += phys_mem.regions[i+1].address - a; - } - - /* It appears that num_physpages is only used for quota checking, - * when pages are locked down. We subtract the size of the holes - * from it now. - */ - num_physpages -= lim/PAGE_SIZE; -#endif /* CONFIG_8xx */ - - for (addr = PAGE_OFFSET; addr < end_mem; addr += PAGE_SIZE) { - if (PageReserved(mem_map + MAP_NR(addr))) { - if (addr < (ulong) etext) - codepages++; - else if (addr >= (unsigned long)&__init_begin - && addr < (unsigned long)&__init_end) - initpages++; - else if (addr < (ulong) start_mem) - datapages++; - continue; - } - atomic_set(&mem_map[MAP_NR(addr)].count, 1); -#ifdef CONFIG_BLK_DEV_INITRD - if (!initrd_start || - addr < (initrd_start & PAGE_MASK) || addr >= initrd_end) -#endif /* CONFIG_BLK_DEV_INITRD */ -#ifndef CONFIG_8xx - if ( !rtas_data || - addr < (rtas_data & PAGE_MASK) || - addr >= (rtas_data+rtas_size)) #endif /* CONFIG_8xx */ - free_page(addr); - } - - printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08x,%08lx]\n", - (unsigned long) nr_free_pages << (PAGE_SHIFT-10), - codepages << (PAGE_SHIFT-10), - datapages << (PAGE_SHIFT-10), - initpages << (PAGE_SHIFT-10), - PAGE_OFFSET, end_mem); - mem_init_done = 1; -} - -/* - * Unfortunately, we can't put initialization functions in their - * own section and free that at this point, because gas gets some - * relocations wrong if we do. :-( But this code is here for when - * gas gets fixed. - */ -void free_initmem(void) -{ - unsigned long a; - unsigned long num_freed_pages = 0; - - a = (unsigned long)(&__init_begin); - for (; a < (unsigned long)(&__init_end); a += PAGE_SIZE) { - clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); - atomic_set(&mem_map[MAP_NR(a)].count, 1); - free_page(a); - num_freed_pages++; - } - - printk ("Freeing unused kernel memory: %ldk freed\n", - (num_freed_pages * PAGE_SIZE) >> 10); -} - -void si_meminfo(struct sysinfo *val) -{ - int i; - - i = max_mapnr; - val->totalram = 0; - val->sharedram = 0; - val->freeram = nr_free_pages << PAGE_SHIFT; - val->bufferram = buffermem; - while (i-- > 0) { - if (PageReserved(mem_map+i)) - continue; - val->totalram++; - if (!atomic_read(&mem_map[i].count)) - continue; - val->sharedram += atomic_read(&mem_map[i].count) - 1; - } - val->totalram <<= PAGE_SHIFT; - val->sharedram <<= PAGE_SHIFT; - return; -} #ifndef CONFIG_8xx -union ubat { /* BAT register values to be loaded */ - BAT bat; - P601_BAT bat_601; - u32 word[2]; -} BATS[4][2]; /* 4 pairs of IBAT, DBAT */ - -struct batrange { /* stores address ranges mapped by BATs */ - unsigned long start; - unsigned long limit; - unsigned long phys; -} bat_addrs[4]; - /* * Set up one of the I/D BAT (block address translation) register pairs. * The parameters are not checked; in particular size must be a power * of 2 between 128k and 256M. */ -void -setbat(int index, unsigned long virt, unsigned long phys, - unsigned int size, int flags) +__initfunc(void setbat(int index, unsigned long virt, unsigned long phys, + unsigned int size, int flags)) { unsigned int bl; int wimgxpp; @@ -853,37 +776,6 @@ #define RAM_PAGE (_PAGE_RW) #endif -/* - * This finds the amount of physical ram and does necessary - * setup for prep. This is pretty architecture specific so - * this will likely stay seperate from the pmac. - * -- Cort - */ -unsigned long *prep_find_end_of_memory(void) -{ - unsigned long kstart, ksize; - unsigned long total; - total = res.TotalMemory; - - if (total == 0 ) - { - /* - * I need a way to probe the amount of memory if the residual - * data doesn't contain it. -- Cort - */ - printk("Ramsize from residual data was 0 -- Probing for value\n"); - total = 0x02000000; - printk("Ramsize default to be %ldM\n", total>>20); - } - append_mem_piece(&phys_mem, 0, total); - phys_avail = phys_mem; - kstart = __pa(_stext); /* should be 0 */ - ksize = PAGE_ALIGN(klimit - _stext); - remove_mem_piece(&phys_avail, kstart, ksize, 0); - remove_mem_piece(&phys_avail, 0, 0x4000, 0); - - return (__va(total)); -} #endif /* CONFIG_8xx */ /* @@ -891,7 +783,7 @@ */ #define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED) -static void mapin_ram() +__initfunc(static void mapin_ram(void)) { int i; unsigned long v, p, s, f; @@ -957,87 +849,64 @@ } } -#ifndef CONFIG_8xx -/* - * Initialize the hash table and patch the instructions in head.S. - */ -static void hash_init(void) +__initfunc(static void *MMU_get_page(void)) { - int Hash_bits; - unsigned long h, ramsize; + void *p; - extern unsigned int hash_page_patch_A[], hash_page_patch_B[], - hash_page_patch_C[], hash_page_patch_D[]; + if (mem_init_done) { + p = (void *) __get_free_page(GFP_KERNEL); + if (p == 0) + panic("couldn't get a page in MMU_get_page"); + } else { + p = find_mem_piece(PAGE_SIZE, PAGE_SIZE); + } + /*memset(p, 0, PAGE_SIZE);*/ + __clear_user(p, PAGE_SIZE); + return p; +} - /* - * Allow 64k of hash table for every 16MB of memory, - * up to a maximum of 2MB. - */ - ramsize = (ulong)end_of_DRAM - KERNELBASE; - for (h = 64<<10; h < ramsize / 256 && h < 2<<20; h *= 2) - ; - Hash_size = h; - Hash_mask = (h >> 6) - 1; - -#ifdef NO_RELOAD_HTAB - /* shrink the htab since we don't use it on 603's -- Cort */ - switch (_get_PVR()>>16) { - case 3: /* 603 */ - case 6: /* 603e */ - case 7: /* 603ev */ - Hash_size = 0; - Hash_mask = 0; - break; - default: - /* on 601/4 let things be */ - break; - } -#endif /* NO_RELOAD_HTAB */ - - /* Find some memory for the hash table. */ - if ( Hash_size ) - Hash = find_mem_piece(Hash_size, Hash_size); - else - Hash = 0; +__initfunc(void free_initmem(void)) +{ + unsigned long a; + unsigned long num_freed_pages = 0, num_prep_pages = 0, + num_pmac_pages = 0; - printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", - ramsize >> 20, Hash_size >> 10, Hash); - if ( Hash_size ) - { - memset(Hash, 0, Hash_size); - Hash_end = (PTE *) ((unsigned long)Hash + Hash_size); +#define FREESEC(START,END,CNT) do { \ + a = (unsigned long)(&START); \ + for (; a < (unsigned long)(&END); a += PAGE_SIZE) { \ + clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); \ + atomic_set(&mem_map[MAP_NR(a)].count, 1); \ + free_page(a); \ + CNT++; \ + } \ +} while (0) - /* - * Patch up the instructions in head.S:hash_page - */ - Hash_bits = ffz(~Hash_size) - 6; - hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff) - | (__pa(Hash) >> 16); - hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0) - | ((26 - Hash_bits) << 6); - if (Hash_bits > 16) - Hash_bits = 16; - hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0) - | ((26 - Hash_bits) << 6); - hash_page_patch_B[0] = (hash_page_patch_B[0] & ~0xffff) - | (Hash_mask >> 10); - hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff) - | (Hash_mask >> 10); - hash_page_patch_D[0] = (hash_page_patch_D[0] & ~0xffff) - | (Hash_mask >> 10); - /* - * Ensure that the locations we've patched have been written - * out from the data cache and invalidated in the instruction - * cache, on those machines with split caches. - */ - flush_icache_range((unsigned long) hash_page_patch_A, - (unsigned long) (hash_page_patch_D + 1)); + FREESEC(__init_begin,__init_end,num_freed_pages); + switch (_machine) + { + case _MACH_Pmac: + case _MACH_chrp: + FREESEC(__prep_begin,__prep_end,num_prep_pages); + break; + case _MACH_prep: + FREESEC(__pmac_begin,__pmac_end,num_pmac_pages); + FREESEC(__openfirmware_begin,__openfirmware_end,num_pmac_pages); + break; + case _MACH_mbx: + FREESEC(__pmac_begin,__pmac_end,num_pmac_pages); + FREESEC(__openfirmware_begin,__openfirmware_end,num_pmac_pages); + FREESEC(__prep_begin,__prep_end,num_prep_pages); + break; } - else - Hash_end = 0; - + + printk ("Freeing unused kernel memory: %ldk init", + (num_freed_pages * PAGE_SIZE) >> 10); + if ( num_prep_pages ) + printk(" %ldk prep",(num_prep_pages*PAGE_SIZE)>>10); + if ( num_pmac_pages ) + printk(" %ldk pmac",(num_pmac_pages*PAGE_SIZE)>>10); + printk("\n"); } -#endif /* CONFIG_8xx */ /* * Do very early mm setup such as finding the size of memory @@ -1046,8 +915,7 @@ * still be merged. * -- Cort */ -void -MMU_init(void) +__initfunc(void MMU_init(void)) { #ifndef CONFIG_8xx if (have_of) diff -u --recursive --new-file v2.1.100/linux/arch/ppc/pmac_defconfig linux/arch/ppc/pmac_defconfig --- v2.1.100/linux/arch/ppc/pmac_defconfig Thu Apr 23 20:21:29 1998 +++ linux/arch/ppc/pmac_defconfig Fri May 8 00:18:23 1998 @@ -6,13 +6,15 @@ # Platform support # CONFIG_PPC=y -CONFIG_NATIVE=y -CONFIG_PPC6XX=y -# CONFIG_PPC8XX is not set -CONFIG_MACH_SPECIFIC=y +CONFIG_6xx=y +# CONFIG_8xx is not set CONFIG_PMAC=y # CONFIG_PREP is not set # CONFIG_CHRP is not set +# CONFIG_ALL_PPC is not set +# CONFIG_APUS is not set +# CONFIG_MBX is not set +CONFIG_MACH_SPECIFIC=y # # General setup @@ -20,7 +22,7 @@ CONFIG_EXPERIMENTAL=y CONFIG_MODULES=y # CONFIG_MODVERSIONS is not set -CONFIG_KERNELD=y +CONFIG_KMOD=y CONFIG_PCI=y CONFIG_PCI_OLD_PROC=y CONFIG_NET=y @@ -31,12 +33,15 @@ CONFIG_KERNEL_ELF=y CONFIG_BINFMT_MISC=m # CONFIG_BINFMT_JAVA is not set +# CONFIG_PARPORT is not set # CONFIG_ABSTRACT_CONSOLE is not set CONFIG_PMAC_CONSOLE=y CONFIG_MAC_KEYBOARD=y CONFIG_MAC_FLOPPY=y +CONFIG_MAC_SERIAL=y CONFIG_MACMOUSE=y CONFIG_PROC_DEVICETREE=y +# CONFIG_KGDB is not set # CONFIG_XMON is not set CONFIG_CONTROL_VIDEO=y CONFIG_PLATINUM_VIDEO=y @@ -73,22 +78,17 @@ # # Additional Block Devices # -CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_INITRD=y # CONFIG_BLK_DEV_XD is not set -CONFIG_PARIDE_PARPORT=m +CONFIG_PARIDE_PARPORT=y # CONFIG_PARIDE is not set # CONFIG_BLK_DEV_HD is not set # -# NEW devices (io_request, all ALPHA and dangerous) -# -# CONFIG_IO_REQUEST is not set - -# # Networking options # # CONFIG_PACKET is not set @@ -102,7 +102,6 @@ # CONFIG_IP_ADVANCED_ROUTER is not set # CONFIG_IP_PNP is not set # CONFIG_IP_ACCT is not set -# CONFIG_IP_MASQUERADE is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set @@ -122,11 +121,12 @@ # # # CONFIG_IPX is not set -# CONFIG_ATALK is not set +CONFIG_ATALK=m # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_BRIDGE is not set # CONFIG_LLC is not set +# CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_FASTROUTE is not set # CONFIG_NET_HW_FLOWCONTROL is not set @@ -146,7 +146,7 @@ CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SG is not set # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs @@ -163,9 +163,7 @@ # CONFIG_SCSI_AHA1542 is not set # CONFIG_SCSI_AHA1740 is not set CONFIG_SCSI_AIC7XXX=m -# CONFIG_AIC7XXX_TAGGED_QUEUEING is not set # CONFIG_OVERRIDE_CMDS is not set -# CONFIG_AIC7XXX_PAGE_ENABLE is not set CONFIG_AIC7XXX_PROC_STATS=y CONFIG_AIC7XXX_RESET_DELAY=15 # CONFIG_SCSI_ADVANSYS is not set @@ -182,7 +180,6 @@ # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_NCR53C8XX is not set -# CONFIG_SCSI_PPA is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set @@ -194,8 +191,9 @@ # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_SCSI_DEBUG is not set CONFIG_SCSI_MESH=y -CONFIG_SCSI_MESH_SYNC_RATE=10 +CONFIG_SCSI_MESH_SYNC_RATE=5 CONFIG_SCSI_MAC53C94=y # @@ -223,13 +221,16 @@ CONFIG_DEC_ELCP=m # CONFIG_DGRS is not set # CONFIG_EEXPRESS_PRO100 is not set -# CONFIG_TLAN is not set # CONFIG_ES3210 is not set +# CONFIG_EPIC100 is not set +# CONFIG_TLAN is not set # CONFIG_ZNET is not set # CONFIG_NET_POCKET is not set # CONFIG_FDDI is not set # CONFIG_DLCI is not set -# CONFIG_PLIP is not set +# CONFIG_LTPC is not set +# CONFIG_COPS is not set +# CONFIG_IPDDP is not set CONFIG_PPP=m # @@ -254,7 +255,6 @@ # CD-ROM drivers (not for SCSI or IDE/ATAPI drives) # # CONFIG_CD_NO_IDESCSI is not set -CONFIG_CDROM=y # # Filesystems @@ -284,13 +284,14 @@ CONFIG_AUTOFS_FS=y # CONFIG_UFS_FS is not set # CONFIG_ADFS_FS is not set +CONFIG_DEVPTS_FS=y CONFIG_MAC_PARTITION=y CONFIG_NLS=y # # Native Language Support # -# CONFIG_NLS_CODEPAGE_437 is not set +CONFIG_NLS_CODEPAGE_437=y # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set # CONFIG_NLS_CODEPAGE_850 is not set @@ -323,11 +324,9 @@ CONFIG_VT=y CONFIG_VT_CONSOLE=y # CONFIG_SOFTCURSOR is not set -CONFIG_SERIAL=y -# CONFIG_SERIAL_CONSOLE is not set +# CONFIG_SERIAL is not set # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_PRINTER is not set # CONFIG_MOUSE is not set # CONFIG_UMISC is not set # CONFIG_QIC02_TAPE is not set @@ -343,8 +342,3 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set - -# -# Sound -# -# CONFIG_SOUND is not set diff -u --recursive --new-file v2.1.100/linux/arch/ppc/prep_defconfig linux/arch/ppc/prep_defconfig --- v2.1.100/linux/arch/ppc/prep_defconfig Sat May 2 14:19:52 1998 +++ linux/arch/ppc/prep_defconfig Fri May 8 00:18:23 1998 @@ -23,7 +23,6 @@ CONFIG_MODVERSIONS=y CONFIG_KERNELD=y CONFIG_PCI=y -# CONFIG_PCI_QUIRKS is not set # CONFIG_PCI_OPTIMIZE is not set CONFIG_PCI_OLD_PROC=y CONFIG_NET=y @@ -221,7 +220,6 @@ # CD-ROM drivers (not for SCSI or IDE/ATAPI drives) # # CONFIG_CD_NO_IDESCSI is not set -CONFIG_CDROM=y # # Filesystems diff -u --recursive --new-file v2.1.100/linux/arch/ppc/vmlinux.lds linux/arch/ppc/vmlinux.lds --- v2.1.100/linux/arch/ppc/vmlinux.lds Thu Sep 4 12:54:48 1997 +++ linux/arch/ppc/vmlinux.lds Fri May 8 00:18:23 1998 @@ -71,6 +71,27 @@ . = ALIGN(4096); __init_end = .; + . = ALIGN(4096); + __pmac_begin = .; + .text.pmac : { *(.text.pmac) } + .data.pmac : { *(.data.pmac) } + . = ALIGN(4096); + __pmac_end = .; + + . = ALIGN(4096); + __prep_begin = .; + .text.prep : { *(.text.prep) } + .data.prep : { *(.data.prep) } + . = ALIGN(4096); + __prep_end = .; + + . = ALIGN(4096); + __openfirmware_begin = .; + .text.openfirmware : { *(.text.openfirmware) } + .data.openfirmware : { *(.data.openfirmware) } + . = ALIGN(4096); + __openfirmware_end = .; + __bss_start = .; .bss : { diff -u --recursive --new-file v2.1.100/linux/arch/sparc/Makefile linux/arch/sparc/Makefile --- v2.1.100/linux/arch/sparc/Makefile Thu Apr 23 20:21:30 1998 +++ linux/arch/sparc/Makefile Fri May 8 00:09:20 1998 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.34 1998/04/06 16:09:34 jj Exp $ +# $Id: Makefile,v 1.35 1998/04/18 03:40:53 davem Exp $ # sparc/Makefile # # Makefile for the architecture dependent flags and dependencies on the @@ -45,6 +45,8 @@ archclean: -$(MAKE) -C arch/sparc/boot archclean + +archmrproper: -$(MAKE) -C arch/sparc/math-emu cleansymlinks archdep: diff -u --recursive --new-file v2.1.100/linux/arch/sparc/config.in linux/arch/sparc/config.in --- v2.1.100/linux/arch/sparc/config.in Thu Apr 23 20:21:30 1998 +++ linux/arch/sparc/config.in Fri May 8 00:11:28 1998 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.54 1998/03/27 06:59:39 davem Exp $ +# $Id: config.in,v 1.55 1998/04/12 06:20:22 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # diff -u --recursive --new-file v2.1.100/linux/arch/sparc/defconfig linux/arch/sparc/defconfig --- v2.1.100/linux/arch/sparc/defconfig Thu Apr 23 20:21:30 1998 +++ linux/arch/sparc/defconfig Fri May 8 00:11:28 1998 @@ -138,16 +138,14 @@ # # CONFIG_IPX=m - -# -# IPX options -# # CONFIG_IPX_INTERN is not set +# CONFIG_SPX is not set CONFIG_ATALK=m CONFIG_X25=m # CONFIG_LAPB is not set # CONFIG_BRIDGE is not set # CONFIG_LLC is not set +# CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_FASTROUTE is not set # CONFIG_NET_HW_FLOWCONTROL is not set @@ -155,11 +153,12 @@ CONFIG_NET_SCHED=y CONFIG_NET_SCH_CBQ=m CONFIG_NET_SCH_CSZ=m +CONFIG_NET_SCH_PRIO=y CONFIG_NET_SCH_RED=m CONFIG_NET_SCH_SFQ=m +# CONFIG_NET_SCH_TEQL is not set CONFIG_NET_SCH_TBF=y -CONFIG_NET_SCH_PFIFO=y -CONFIG_NET_SCH_PRIO=y +# CONFIG_NET_QOS is not set # CONFIG_NET_PROFILE is not set # @@ -226,7 +225,6 @@ CONFIG_HAPPYMEAL=m CONFIG_SUNQE=m CONFIG_MYRI_SBUS=m -CONFIG_CDROM=y # # Filesystems @@ -268,6 +266,7 @@ CONFIG_SMD_DISKLABEL=y # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_ADFS_FS is not set +CONFIG_DEVPTS_FS=y # CONFIG_MAC_PARTITION is not set CONFIG_NLS=y diff -u --recursive --new-file v2.1.100/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S --- v2.1.100/linux/arch/sparc/kernel/head.S Thu Apr 23 20:21:30 1998 +++ linux/arch/sparc/kernel/head.S Fri May 8 00:11:28 1998 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.90 1998/03/24 18:12:05 jj Exp $ +/* $Id: head.S,v 1.91 1998/04/24 13:40:48 jj Exp $ * head.S: The initial boot code for the Sparc port of Linux. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -403,7 +403,7 @@ BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff) #endif - .align 4096 + .align PAGE_SIZE /* This was the only reasonable way I could think of to properly align * these page-table data structures. diff -u --recursive --new-file v2.1.100/linux/arch/sparc/kernel/sun4d_irq.c linux/arch/sparc/kernel/sun4d_irq.c --- v2.1.100/linux/arch/sparc/kernel/sun4d_irq.c Thu Apr 23 20:21:30 1998 +++ linux/arch/sparc/kernel/sun4d_irq.c Fri May 8 00:11:28 1998 @@ -1,4 +1,4 @@ -/* $Id: sun4d_irq.c,v 1.12 1998/03/19 15:36:36 jj Exp $ +/* $Id: sun4d_irq.c,v 1.13 1998/04/15 14:58:33 jj Exp $ * arch/sparc/kernel/sun4d_irq.c: * SS1000/SC2000 interrupt handling. * @@ -495,7 +495,7 @@ #endif } -__initfunc(unsigned long sun4d_init_sbi_irq(unsigned long memory_start)) +__initfunc(void sun4d_init_sbi_irq(void)) { struct linux_sbus *sbus; unsigned mask; @@ -503,9 +503,7 @@ nsbi = 0; for_each_sbus(sbus) nsbi++; - memory_start = ((memory_start + 7) & ~7); - sbus_actions = (struct sbus_action *)memory_start; - memory_start += (nsbi * 8 * 4 * sizeof(struct sbus_action)); + sbus_actions = (struct sbus_action *)kmalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC); memset (sbus_actions, 0, (nsbi * 8 * 4 * sizeof(struct sbus_action))); for_each_sbus(sbus) { #ifdef __SMP__ @@ -521,7 +519,6 @@ release_sbi(sbus->devid, mask); } } - return memory_start; } __initfunc(void sun4d_init_IRQ(void)) diff -u --recursive --new-file v2.1.100/linux/arch/sparc/kernel/systbls.S linux/arch/sparc/kernel/systbls.S --- v2.1.100/linux/arch/sparc/kernel/systbls.S Thu Apr 23 20:21:30 1998 +++ linux/arch/sparc/kernel/systbls.S Fri May 8 00:11:28 1998 @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.71 1998/03/24 06:25:06 ecd Exp $ +/* $Id: systbls.S,v 1.72 1998/04/14 13:49:46 jj Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -63,7 +63,7 @@ .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_gettimeofday), C_LABEL(sys_getrusage) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_readv) + .long C_LABEL(sys_nis_syscall), C_LABEL(sys_getcwd), C_LABEL(sys_readv) .long C_LABEL(sys_writev), C_LABEL(sys_settimeofday), C_LABEL(sys_fchown) .long C_LABEL(sys_fchmod), C_LABEL(sys_nis_syscall), C_LABEL(sys_setreuid) .long C_LABEL(sys_setregid), C_LABEL(sys_rename), C_LABEL(sys_truncate) diff -u --recursive --new-file v2.1.100/linux/arch/sparc/math-emu/fnegs.c linux/arch/sparc/math-emu/fnegs.c --- v2.1.100/linux/arch/sparc/math-emu/fnegs.c Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc/math-emu/fnegs.c Fri May 8 00:11:28 1998 @@ -4,4 +4,3 @@ rd[0] = rs2[0] ^ 0x80000000UL; return 1; } - diff -u --recursive --new-file v2.1.100/linux/arch/sparc/mm/fault.c linux/arch/sparc/mm/fault.c --- v2.1.100/linux/arch/sparc/mm/fault.c Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc/mm/fault.c Fri May 8 00:11:28 1998 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.93 1998/03/25 10:43:16 jj Exp $ +/* $Id: fault.c,v 1.94 1998/05/01 16:00:27 jj Exp $ * fault.c: Page fault handlers for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -248,9 +248,11 @@ extern const unsigned __csum_partial_copy_start[]; extern const unsigned __csum_partial_copy_end[]; +#ifdef DEBUG_EXCEPTIONS printk("Exception: PC<%08lx> faddr<%08lx>\n", regs->pc, address); printk("EX_TABLE: insn<%08lx> fixup<%08x> g2<%08lx>\n", regs->pc, fixup, g2); +#endif if ((regs->pc >= (unsigned long)__memset_start && regs->pc < (unsigned long)__memset_end) || (regs->pc >= (unsigned long)__csum_partial_copy_start && diff -u --recursive --new-file v2.1.100/linux/arch/sparc/mm/io-unit.c linux/arch/sparc/mm/io-unit.c --- v2.1.100/linux/arch/sparc/mm/io-unit.c Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc/mm/io-unit.c Fri May 8 00:11:28 1998 @@ -1,4 +1,4 @@ -/* $Id: io-unit.c,v 1.10 1998/03/03 12:31:14 jj Exp $ +/* $Id: io-unit.c,v 1.11 1998/04/13 07:26:37 davem Exp $ * io-unit.c: IO-UNIT specific routines for memory management. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -23,22 +23,17 @@ #define IOD(x) do { } while (0) #endif -#define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1)) - #define IOPERM (IOUPTE_CACHE | IOUPTE_WRITE | IOUPTE_VALID) #define MKIOPTE(phys) __iopte((((phys)>>4) & IOUPTE_PAGE) | IOPERM) -__initfunc(unsigned long -iounit_init(int sbi_node, int io_node, unsigned long memory_start, - unsigned long memory_end, struct linux_sbus *sbus)) +__initfunc(void +iounit_init(int sbi_node, int io_node, struct linux_sbus *sbus)) { iopte_t *xpt, *xptend; struct iounit_struct *iounit; struct linux_prom_registers iommu_promregs[PROMREG_MAX]; - memory_start = LONG_ALIGN(memory_start); - iounit = (struct iounit_struct *)memory_start; - memory_start = LONG_ALIGN(memory_start + sizeof(struct iounit_struct)); + iounit = kmalloc(sizeof(struct iounit_struct), GFP_ATOMIC); memset(iounit, 0, sizeof(*iounit)); iounit->limit[0] = IOUNIT_BMAP1_START; @@ -62,8 +57,6 @@ for (xptend = iounit->page_table + (16 * PAGE_SIZE) / sizeof(iopte_t); xpt < xptend;) *xpt++ = 0; - - return memory_start; } /* One has to hold iounit->lock to call this */ diff -u --recursive --new-file v2.1.100/linux/arch/sparc/mm/iommu.c linux/arch/sparc/mm/iommu.c --- v2.1.100/linux/arch/sparc/mm/iommu.c Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc/mm/iommu.c Fri May 8 00:11:28 1998 @@ -1,4 +1,4 @@ -/* $Id: iommu.c,v 1.7 1998/02/22 10:32:26 ecd Exp $ +/* $Id: iommu.c,v 1.9 1998/04/15 14:58:37 jj Exp $ * iommu.c: IOMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -26,14 +27,12 @@ extern void viking_flush_page(unsigned long page); extern void viking_mxcc_flush_page(unsigned long page); -#define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1)) - #define IOPERM (IOPTE_CACHE | IOPTE_WRITE | IOPTE_VALID) #define MKIOPTE(phys) (((((phys)>>4) & IOPTE_PAGE) | IOPERM) & ~IOPTE_WAZ) -static inline void iommu_map_dvma_pages_for_iommu(struct iommu_struct *iommu, - unsigned long kern_end) +static inline void iommu_map_dvma_pages_for_iommu(struct iommu_struct *iommu) { + unsigned long kern_end = (unsigned long) high_memory; unsigned long first = page_offset; unsigned long last = kern_end; iopte_t *iopte = iommu->page_table; @@ -45,18 +44,17 @@ } } -__initfunc(unsigned long -iommu_init(int iommund, unsigned long memory_start, - unsigned long memory_end, struct linux_sbus *sbus)) +__initfunc(void +iommu_init(int iommund, struct linux_sbus *sbus)) { unsigned int impl, vers, ptsize; unsigned long tmp; struct iommu_struct *iommu; struct linux_prom_registers iommu_promregs[PROMREG_MAX]; + int i, j, k, l, m; + struct iommu_alloc { unsigned long addr; int next; } *ia; - memory_start = LONG_ALIGN(memory_start); - iommu = (struct iommu_struct *) memory_start; - memory_start += sizeof(struct iommu_struct); + iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC); prom_getproperty(iommund, "reg", (void *) iommu_promregs, sizeof(iommu_promregs)); iommu->regs = (struct iommu_regs *) @@ -98,16 +96,68 @@ ptsize = iommu->end - iommu->start + 1; ptsize = (ptsize >> PAGE_SHIFT) * sizeof(iopte_t); - /* Stupid alignment constraints give me a headache. */ - memory_start = PAGE_ALIGN(memory_start); - memory_start = (((memory_start) + (ptsize - 1)) & ~(ptsize - 1)); - iommu->lowest = iommu->page_table = (iopte_t *) memory_start; - memory_start += ptsize; + /* Stupid alignment constraints give me a headache. + We want to get very large aligned memory area, larger than + maximum what get_free_pages gives us (128K): we need + 256K or 512K or 1M or 2M aligned to its size. */ + ia = (struct iommu_alloc *) kmalloc (sizeof(struct iommu_alloc) * 128, GFP_ATOMIC); + for (i = 0; i < 128; i++) { + ia[i].addr = 0; + ia[i].next = -1; + } + k = 0; + for (i = 0; i < 128; i++) { + ia[i].addr = __get_free_pages(GFP_DMA, 5); + if (ia[i].addr <= ia[k].addr) { + if (i) { + ia[i].next = k; + k = i; + } + } else { + for (m = k, l = ia[k].next; l != -1; m = l, l = ia[l].next) + if (ia[i].addr <= ia[l].addr) { + ia[i].next = l; + ia[m].next = i; + } + if (l == -1) + ia[m].next = i; + } + for (m = -1, j = 0, l = k; l != -1; l = ia[l].next) { + if (!(ia[l].addr & (ptsize - 1))) { + tmp = ia[l].addr; + m = l; + j = 128 * 1024; + } else if (m != -1) { + if (ia[l].addr != tmp + j) + m = -1; + else { + j += 128 * 1024; + if (j == ptsize) { + break; + } + } + } + } + if (l != -1) + break; + } + if (i == 128) { + prom_printf("Could not allocate iopte of size 0x%08x\n", ptsize); + prom_halt(); + } + for (l = m, j = 0; j < ptsize; j += 128 * 1024, l = ia[l].next) + ia[l].addr = 0; + for (l = k; l != -1; l = ia[l].next) + if (ia[l].addr) + free_pages(ia[l].addr, 5); + kfree (ia); + iommu->lowest = iommu->page_table = (iopte_t *)tmp; + /* Initialize new table. */ flush_cache_all(); memset(iommu->page_table, 0, ptsize); - iommu_map_dvma_pages_for_iommu(iommu, memory_end); + iommu_map_dvma_pages_for_iommu(iommu); if(viking_mxcc_present) { unsigned long start = (unsigned long) iommu->page_table; unsigned long end = (start + ptsize); @@ -130,7 +180,6 @@ sbus->iommu = iommu; printk("IOMMU: impl %d vers %d page table at %p of size %d bytes\n", impl, vers, iommu->page_table, ptsize); - return memory_start; } static __u32 iommu_get_scsi_one_noflush(char *vaddr, unsigned long len, struct linux_sbus *sbus) diff -u --recursive --new-file v2.1.100/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c --- v2.1.100/linux/arch/sparc/mm/srmmu.c Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc/mm/srmmu.c Fri May 8 00:11:28 1998 @@ -1,4 +1,4 @@ -/* $Id: srmmu.c,v 1.170 1998/03/09 14:04:01 jj Exp $ +/* $Id: srmmu.c,v 1.171 1998/04/24 15:03:35 jj Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -512,7 +512,7 @@ pgd_cache_size--; } spin_unlock(&pgd_spinlock); - return (pte_t *)ret; + return (pgd_t *)ret; } static inline pgd_t *srmmu_get_pgd_slow(void) diff -u --recursive --new-file v2.1.100/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c --- v2.1.100/linux/arch/sparc/mm/sun4c.c Sat May 2 14:19:52 1998 +++ linux/arch/sparc/mm/sun4c.c Fri May 8 00:11:28 1998 @@ -1,4 +1,4 @@ -/* $Id: sun4c.c,v 1.163 1998/03/11 04:08:21 tdyas Exp $ +/* $Id: sun4c.c,v 1.164 1998/05/02 12:06:19 davem Exp $ * sun4c.c: Doing in software what should be done in hardware. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/Makefile linux/arch/sparc64/Makefile --- v2.1.100/linux/arch/sparc64/Makefile Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc64/Makefile Fri May 8 00:09:20 1998 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.25 1998/04/06 16:10:31 jj Exp $ +# $Id: Makefile,v 1.26 1998/04/18 03:40:54 davem Exp $ # sparc64/Makefile # # Makefile for the architecture dependent flags and dependencies on the @@ -56,6 +56,8 @@ archclean: rm -f $(TOPDIR)/vmlinux.aout + +archmrproper: archdep: diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.1.100/linux/arch/sparc64/config.in Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc64/config.in Fri May 8 00:11:28 1998 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.44 1998/04/06 16:10:35 jj Exp $ +# $Id: config.in,v 1.46 1998/05/05 17:17:21 jj Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -46,6 +46,7 @@ define_bool CONFIG_SUN_IO y define_bool CONFIG_PCI y source drivers/sbus/char/Config.in + source drivers/sbus/audio/Config.in fi tristate 'Openprom tree appears in /proc/openprom (EXPERIMENTAL)' CONFIG_SUN_OPENPROMFS diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.1.100/linux/arch/sparc64/defconfig Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc64/defconfig Fri May 8 00:11:28 1998 @@ -55,6 +55,13 @@ CONFIG_OBP_FLASH=m # CONFIG_SUN_BPP is not set # CONFIG_SUN_VIDEOPIX is not set + +# +# Linux/SPARC audio subsystem (EXPERIMENTAL) +# +# CONFIG_SPARCAUDIO is not set +# CONFIG_SPARCAUDIO_AMD7930 is not set +# CONFIG_SPARCAUDIO_CS4231 is not set CONFIG_SUN_OPENPROMFS=m CONFIG_PCI_OLD_PROC=y CONFIG_NET=y @@ -132,16 +139,14 @@ # # CONFIG_IPX=m - -# -# IPX options -# # CONFIG_IPX_INTERN is not set +# CONFIG_SPX is not set CONFIG_ATALK=m # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_BRIDGE is not set # CONFIG_LLC is not set +# CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_FASTROUTE is not set # CONFIG_NET_HW_FLOWCONTROL is not set @@ -149,11 +154,12 @@ CONFIG_NET_SCHED=y CONFIG_NET_SCH_CBQ=y CONFIG_NET_SCH_CSZ=y +CONFIG_NET_SCH_PRIO=y CONFIG_NET_SCH_RED=y CONFIG_NET_SCH_SFQ=y +# CONFIG_NET_SCH_TEQL is not set CONFIG_NET_SCH_TBF=y -CONFIG_NET_SCH_PFIFO=y -CONFIG_NET_SCH_PRIO=y +# CONFIG_NET_QOS is not set # CONFIG_NET_PROFILE is not set # @@ -269,6 +275,7 @@ CONFIG_SMD_DISKLABEL=y CONFIG_SOLARIS_X86_PARTITION=y # CONFIG_ADFS_FS is not set +CONFIG_DEVPTS_FS=y # CONFIG_MAC_PARTITION is not set CONFIG_NLS=y diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c --- v2.1.100/linux/arch/sparc64/kernel/ebus.c Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc64/kernel/ebus.c Fri May 8 00:11:28 1998 @@ -1,4 +1,4 @@ -/* $Id: ebus.c,v 1.23 1998/03/29 16:27:24 ecd Exp $ +/* $Id: ebus.c,v 1.26 1998/04/21 06:34:02 ecd Exp $ * ebus.c: PCI to EBus bridge device. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,7 @@ extern void prom_ebus_ranges_init(struct linux_ebus *); extern void prom_ebus_intmap_init(struct linux_ebus *); -extern unsigned long pci_console_init(unsigned long memory_start); +extern void pci_console_init(void); #ifdef CONFIG_SUN_OPENPROMIO extern int openprom_init(void); @@ -48,19 +49,9 @@ extern int envctrl_init(void); #endif -extern unsigned int psycho_irq_build(struct linux_pbm_info *pbm, - unsigned int full_ino); - -static inline unsigned long -ebus_alloc(unsigned long *memory_start, size_t size) +static inline unsigned long ebus_alloc(size_t size) { - unsigned long mem; - - *memory_start = (*memory_start + 7) & ~(7); - mem = *memory_start; - *memory_start += size; - memset((void *)mem, 0, size); - return mem; + return (unsigned long)kmalloc(size, GFP_ATOMIC); } __initfunc(void ebus_intmap_match(struct linux_ebus *ebus, @@ -117,11 +108,27 @@ len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); if ((len == -1) || (len == 0)) { dev->num_irqs = 0; + /* + * Oh, well, some PROMs don't export interrupts + * property to children of EBus devices... + * + * Be smart about PS/2 keyboard and mouse. + */ + if (!strcmp(dev->parent->prom_name, "8042")) { + if (!strcmp(dev->prom_name, "kb_ps2")) { + dev->num_irqs = 1; + dev->irqs[0] = dev->parent->irqs[0]; + } else { + dev->num_irqs = 1; + dev->irqs[0] = dev->parent->irqs[1]; + } + } } else { dev->num_irqs = len / sizeof(irqs[0]); for (i = 0; i < dev->num_irqs; i++) { ebus_intmap_match(dev->bus, preg, &irqs[i]); - dev->irqs[i] = psycho_irq_build(dev->bus->parent, irqs[i]); + dev->irqs[i] = psycho_irq_build(dev->bus->parent, + dev->bus->self, irqs[i]); } } @@ -139,9 +146,7 @@ #endif } -__initfunc(unsigned long fill_ebus_device(int node, - struct linux_ebus_device *dev, - unsigned long memory_start)) +__initfunc(void fill_ebus_device(int node, struct linux_ebus_device *dev)) { struct linux_prom_registers regs[PROMREG_MAX]; struct linux_ebus_child *child; @@ -176,7 +181,8 @@ dev->num_irqs = len / sizeof(irqs[0]); for (i = 0; i < dev->num_irqs; i++) { ebus_intmap_match(dev->bus, ®s[0], &irqs[i]); - dev->irqs[i] = psycho_irq_build(dev->bus->parent, irqs[i]); + dev->irqs[i] = psycho_irq_build(dev->bus->parent, + dev->bus->self, irqs[i]); } } @@ -194,7 +200,7 @@ #endif if ((node = prom_getchild(node))) { dev->children = (struct linux_ebus_child *) - ebus_alloc(&memory_start, sizeof(struct linux_ebus_child)); + ebus_alloc(sizeof(struct linux_ebus_child)); child = dev->children; child->next = 0; @@ -204,7 +210,7 @@ while ((node = prom_getsibling(node))) { child->next = (struct linux_ebus_child *) - ebus_alloc(&memory_start, sizeof(struct linux_ebus_child)); + ebus_alloc(sizeof(struct linux_ebus_child)); child = child->next; child->next = 0; @@ -213,15 +219,12 @@ fill_ebus_child(node, ®s[0], child); } } - - return memory_start; } extern void sun4u_start_timers(void); extern void clock_probe(void); -__initfunc(unsigned long ebus_init(unsigned long memory_start, - unsigned long memory_end)) +__initfunc(void ebus_init(void)) { struct linux_prom_pci_registers regs[PROMREG_MAX]; struct linux_pbm_info *pbm; @@ -237,7 +240,7 @@ int num_ebus = 0; if (!pci_present()) - return memory_start; + return; pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, 0); if (!pdev) { @@ -245,14 +248,14 @@ #ifdef PROM_DEBUG dprintf("ebus: No EBus's found.\n"); #endif - return memory_start; + return; } cookie = pdev->sysdata; ebusnd = cookie->prom_node; ebus_chain = ebus = (struct linux_ebus *) - ebus_alloc(&memory_start, sizeof(struct linux_ebus)); + ebus_alloc(sizeof(struct linux_ebus)); ebus->next = 0; while (ebusnd) { @@ -323,24 +326,23 @@ goto next_ebus; ebus->devices = (struct linux_ebus_device *) - ebus_alloc(&memory_start, - sizeof(struct linux_ebus_device)); + ebus_alloc(sizeof(struct linux_ebus_device)); dev = ebus->devices; dev->next = 0; dev->children = 0; dev->bus = ebus; - memory_start = fill_ebus_device(nd, dev, memory_start); + fill_ebus_device(nd, dev); while ((nd = prom_getsibling(nd))) { dev->next = (struct linux_ebus_device *) - ebus_alloc(&memory_start, sizeof(struct linux_ebus_device)); + ebus_alloc(sizeof(struct linux_ebus_device)); dev = dev->next; dev->next = 0; dev->children = 0; dev->bus = ebus; - memory_start = fill_ebus_device(nd, dev, memory_start); + fill_ebus_device(nd, dev); } next_ebus: @@ -353,13 +355,13 @@ ebusnd = cookie->prom_node; ebus->next = (struct linux_ebus *) - ebus_alloc(&memory_start, sizeof(struct linux_ebus)); + ebus_alloc(sizeof(struct linux_ebus)); ebus = ebus->next; ebus->next = 0; ++num_ebus; } - memory_start = pci_console_init(memory_start); + pci_console_init(); #ifdef CONFIG_SUN_OPENPROMIO openprom_init(); @@ -381,5 +383,4 @@ #endif sun4u_start_timers(); clock_probe(); - return memory_start; } diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S --- v2.1.100/linux/arch/sparc64/kernel/entry.S Mon Jan 12 15:15:44 1998 +++ linux/arch/sparc64/kernel/entry.S Fri May 8 00:11:29 1998 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.76 1998/01/05 17:00:13 jj Exp $ +/* $Id: entry.S,v 1.78 1998/05/01 20:36:24 davem Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -58,8 +58,7 @@ mov 1, %o2 .align 32 sparc64_dtlb_refbit_catch: - srlx %g5, 9, %g4 - and %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4 + and %g5, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4 cmp %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9) be,a,pt %xcc, 2f mov 1, %g4 @@ -85,8 +84,7 @@ clr %l6 .align 32 sparc64_itlb_refbit_catch: - srlx %g5, 9, %g4 - and %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4 + and %g5, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4 cmp %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9) be,a,pt %xcc, 3f mov 1, %g4 @@ -666,7 +664,7 @@ ba,pt %xcc, rtrap clr %l6 - /* This is how fork() was meant to be done, 12 instruction entry. + /* This is how fork() was meant to be done, 8 instruction entry. * * I questioned the following code briefly, let me clear things * up so you must not reason on it like I did. @@ -695,7 +693,8 @@ sys_fork: sys_vfork: mov SIGCHLD, %o0 clr %o1 -sys_clone: mov %o7, %l5 +sys_clone: flushw + mov %o7, %l5 add %sp, STACK_BIAS + REGWIN_SZ, %o2 movrz %o1, %fp, %o1 call do_fork diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c --- v2.1.100/linux/arch/sparc64/kernel/ioctl32.c Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc64/kernel/ioctl32.c Fri May 8 00:11:29 1998 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.35 1998/04/10 02:01:46 davem Exp $ +/* $Id: ioctl32.c,v 1.37 1998/05/06 05:34:13 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include /* Ugly hack. */ @@ -66,6 +68,22 @@ return err; } +static int rw_long(unsigned int fd, unsigned int cmd, u32 arg) +{ + mm_segment_t old_fs = get_fs(); + int err; + unsigned long val; + + if(get_user(val, (u32 *)A(arg))) + return -EFAULT; + set_fs (KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&val); + set_fs (old_fs); + if (!err && put_user(val, (u32 *)A(arg))) + return -EFAULT; + return err; +} + struct timeval32 { int tv_sec; int tv_usec; @@ -1059,6 +1077,57 @@ return 0; } +struct loop_info32 { + int lo_number; /* ioctl r/o */ + __kernel_dev_t32 lo_device; /* ioctl r/o */ + unsigned int lo_inode; /* ioctl r/o */ + __kernel_dev_t32 lo_rdevice; /* ioctl r/o */ + int lo_offset; + int lo_encrypt_type; + int lo_encrypt_key_size; /* ioctl w/o */ + int lo_flags; /* ioctl r/o */ + char lo_name[LO_NAME_SIZE]; + unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ + unsigned int lo_init[2]; + char reserved[4]; +}; + +static int loop_status(unsigned int fd, unsigned int cmd, u32 arg) +{ + mm_segment_t old_fs = get_fs(); + struct loop_info l; + int err = 0; + + switch(cmd) { + case LOOP_SET_STATUS: + if ((get_user(l.lo_number, &((struct loop_info32 *)A(arg))->lo_number) || + __get_user(l.lo_device, &((struct loop_info32 *)A(arg))->lo_device) || + __get_user(l.lo_inode, &((struct loop_info32 *)A(arg))->lo_inode) || + __get_user(l.lo_rdevice, &((struct loop_info32 *)A(arg))->lo_rdevice) || + __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)A(arg))->lo_offset, + 8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset))) + return -EFAULT; + set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long)&l); + set_fs (old_fs); + break; + case LOOP_GET_STATUS: + set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long)&l); + set_fs (old_fs); + if (!err && + (put_user(l.lo_number, &((struct loop_info32 *)A(arg))->lo_number) || + __put_user(l.lo_device, &((struct loop_info32 *)A(arg))->lo_device) || + __put_user(l.lo_inode, &((struct loop_info32 *)A(arg))->lo_inode) || + __put_user(l.lo_rdevice, &((struct loop_info32 *)A(arg))->lo_rdevice) || + __copy_to_user((char *)&((struct loop_info32 *)A(arg))->lo_offset, + (char *)&l.lo_offset, (unsigned long)l.lo_init - (unsigned long)&l.lo_offset))) + err = -EFAULT; + break; + } + return err; +} + asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg) { struct file * filp; @@ -1185,6 +1254,15 @@ case CDROMREADALL: error = cdrom_ioctl_trans(fd, cmd, arg); goto out; + + case LOOP_SET_STATUS: + case LOOP_GET_STATUS: + error = loop_status(fd, cmd, arg); + goto out; + + case AUTOFS_IOC_SETTIMEOUT: + error = rw_long(fd, cmd, arg); + goto out; /* List here exlicitly which ioctl's are known to have * compatable types passed or none at all... @@ -1455,6 +1533,17 @@ case CDROM_DRIVE_STATUS: case CDROM_DISC_STATUS: case CDROM_CHANGER_NSLOTS: + + /* Big L */ + case LOOP_SET_FD: + case LOOP_CLR_FD: + + /* AUTOFS */ + case AUTOFS_IOC_READY: + case AUTOFS_IOC_FAIL: + case AUTOFS_IOC_CATATONIC: + case AUTOFS_IOC_PROTOVER: + case AUTOFS_IOC_EXPIRE: error = sys_ioctl (fd, cmd, (unsigned long)arg); goto out; diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c --- v2.1.100/linux/arch/sparc64/kernel/irq.c Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc64/kernel/irq.c Fri May 8 00:11:29 1998 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.52 1998/03/19 00:22:54 ecd Exp $ +/* $Id: irq.c,v 1.53 1998/04/20 07:14:58 ecd Exp $ * irq.c: UltraSparc IRQ handling/init/registry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -36,6 +36,7 @@ /* Internal flag, should not be visible elsewhere at all. */ #define SA_IMAP_MASKED 0x100 +#define SA_DMA_SYNC 0x200 #ifdef __SMP__ void distribute_irqs(void); @@ -543,6 +544,8 @@ #ifdef CONFIG_PCI if(PCI_IRQ_P(irq)) { pci_irq_frobnicate(&cpu_irq, &ivindex_fixup, &imap, &iclr, irq); + if (irq & PCI_IRQ_DMA_SYNC) + irqflags |= SA_DMA_SYNC; } else #endif if(irqflags & SA_DCOOKIE) { diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c --- v2.1.100/linux/arch/sparc64/kernel/process.c Thu Apr 23 20:21:32 1998 +++ linux/arch/sparc64/kernel/process.c Fri May 8 00:11:29 1998 @@ -1,9 +1,9 @@ -/* $Id: process.c,v 1.52 1998/03/29 12:57:53 ecd Exp $ +/* $Id: process.c,v 1.54 1998/04/28 08:23:28 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1997, 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) + * Copyright (C) 1997, 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ /* @@ -43,6 +43,45 @@ #ifndef __SMP__ +extern int pgt_cache_water[2]; + +static inline void ultra_check_pgt_cache(void) +{ + struct page *page, *page2; + + if(pgtable_cache_size > pgt_cache_water[0]) { + do { + if(pmd_quicklist) + free_pmd_slow(get_pmd_fast()); + if(pte_quicklist) + free_pte_slow(get_pte_fast()); + } while(pgtable_cache_size > pgt_cache_water[1]); + } + if (pgd_cache_size > pgt_cache_water[0] / 4) { + for (page2 = NULL, page = (struct page *)pgd_quicklist; page;) { + if ((unsigned long)page->pprev_hash == 3) { + if (page2) + page2->next_hash = page->next_hash; + else + (struct page *)pgd_quicklist = page->next_hash; + page->next_hash = NULL; + page->pprev_hash = NULL; + pgd_cache_size -= 2; + free_page(PAGE_OFFSET + (page->map_nr << PAGE_SHIFT)); + if (page2) + page = page2->next_hash; + else + page = (struct page *)pgd_quicklist; + if (pgd_cache_size <= pgt_cache_water[1] / 4) + break; + continue; + } + page2 = page; + page = page->next_hash; + } + } +} + /* * the idle loop on a Sparc... ;) */ @@ -55,7 +94,7 @@ current->priority = -100; current->counter = -100; for (;;) { - check_pgt_cache(); + ultra_check_pgt_cache(); run_task_queue(&tq_scheduler); schedule(); } @@ -422,7 +461,7 @@ get_mmu_context(current); spin_unlock(&scheduler_lock); } - current->tss.ctx = current->mm->context & 0x1fff; + current->tss.ctx = current->mm->context & 0x3ff; spitfire_set_secondary_context (current->tss.ctx); __asm__ __volatile__("flush %g6"); } @@ -584,7 +623,7 @@ p->tss.kregs->u_regs[UREG_FP] = sp; p->tss.flags &= ~SPARC_FLAG_KTHREAD; p->tss.current_ds = USER_DS; - p->tss.ctx = (p->mm->context & 0x1fff); + p->tss.ctx = (p->mm->context & 0x3ff); if (sp != regs->u_regs[UREG_FP]) { unsigned long csp; diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/psycho.c linux/arch/sparc64/kernel/psycho.c --- v2.1.100/linux/arch/sparc64/kernel/psycho.c Thu May 7 22:51:47 1998 +++ linux/arch/sparc64/kernel/psycho.c Fri May 8 00:11:29 1998 @@ -1,4 +1,4 @@ -/* $Id: psycho.c,v 1.50 1998/04/10 12:29:47 ecd Exp $ +/* $Id: psycho.c,v 1.54 1998/05/01 19:16:32 ecd Exp $ * psycho.c: Ultra/AX U2P PCI controller support. * * Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu) @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include /* for sanity check... */ @@ -17,6 +19,7 @@ #undef FIXUP_REGS_DEBUG #undef FIXUP_IRQ_DEBUG #undef FIXUP_VMA_DEBUG +#undef PCI_COOKIE_DEBUG #ifdef PROM_DEBUG #define dprintf prom_printf @@ -94,19 +97,12 @@ */ static int pci_probe_enable = 0; -static inline unsigned long long_align(unsigned long addr) +__initfunc(static void psycho_iommu_init(struct linux_psycho *psycho, int tsbsize)) { - return ((addr + (sizeof(unsigned long) - 1)) & - ~(sizeof(unsigned long) - 1)); -} - -__initfunc(static unsigned long psycho_iommu_init(struct linux_psycho *psycho, - int tsbsize, - unsigned long memory_start)) -{ - unsigned long tsbbase = PAGE_ALIGN(memory_start); + unsigned long tsbbase; unsigned long control, i; unsigned long *iopte; + unsigned long order; /* * Invalidate TLB Entries. @@ -120,9 +116,12 @@ control &= ~(IOMMU_CTRL_DENAB); psycho->psycho_regs->iommu_control = control; - memory_start = (tsbbase + ((tsbsize * 1024) * 8)); + for(order = 0;; order++) { + if((PAGE_SIZE << order) >= ((tsbsize * 1024) * 8)) + break; + } + tsbbase = __get_free_pages(GFP_DMA, order); iopte = (unsigned long *)tsbbase; - for(i = 0; i < (tsbsize * 1024); i++) { *iopte = (IOPTE_VALID | IOPTE_64K | IOPTE_CACHE | IOPTE_WRITE); @@ -154,8 +153,6 @@ break; } psycho->psycho_regs->iommu_control = control; - - return memory_start; } extern void prom_pbm_ranges_init(int node, struct linux_pbm_info *pbm); @@ -164,7 +161,7 @@ /* * Poor man's PCI... */ -__initfunc(unsigned long sabre_init(int pnode, unsigned long memory_start)) +__initfunc(void sabre_init(int pnode)) { struct linux_prom64_registers pr_regs[2]; struct linux_psycho *sabre; @@ -175,8 +172,7 @@ u32 portid; int bus; - sabre = (struct linux_psycho *)memory_start; - memory_start = long_align(memory_start + sizeof(struct linux_psycho)); + sabre = kmalloc(sizeof(struct linux_psycho), GFP_ATOMIC); portid = prom_getintdefault(pnode, "upa-portid", 0xff); @@ -262,7 +258,7 @@ prom_halt(); } - memory_start = psycho_iommu_init(sabre, tsbsize, memory_start); + psycho_iommu_init(sabre, tsbsize); pci_dvma_offset = vdma[0]; printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]); @@ -338,11 +334,15 @@ if (!node) break; } +} - return memory_start; +static __inline__ int +apb_present(struct linux_psycho *psycho) +{ + return psycho->pci_bus ? 1 : 0; } -__initfunc(unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end)) +__initfunc(void pcibios_init(void)) { struct linux_prom64_registers pr_regs[3]; struct linux_psycho *psycho; @@ -355,7 +355,6 @@ dprintf("PCI: Probing for controllers.\n"); #endif - memory_start = long_align(memory_start); node = prom_getchild(prom_root_node); while((node = prom_searchsiblings(node, "pci")) != 0) { struct linux_psycho *search; @@ -365,11 +364,11 @@ err = prom_getproperty(node, "model", namebuf, sizeof(namebuf)); if ((err > 0) && !strncmp(namebuf, "SUNW,sabre", err)) { - memory_start = sabre_init(node, memory_start); + sabre_init(node); goto next_pci; } - psycho = (struct linux_psycho *)memory_start; + psycho = kmalloc(sizeof(struct linux_psycho), GFP_ATOMIC); portid = prom_getintdefault(node, "upa-portid", 0xff); for(search = psycho_root; search; search = search->next) { @@ -385,9 +384,6 @@ } } - memory_start = long_align(memory_start + - sizeof(struct linux_psycho)); - memset(psycho, 0, sizeof(*psycho)); psycho->next = psycho_root; @@ -452,7 +448,7 @@ psycho->pci_config_space); #endif - memory_start = psycho_iommu_init(psycho, 32, memory_start); + psycho_iommu_init(psycho, 32); pci_dvma_offset = 0x80000000UL; is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); @@ -504,14 +500,11 @@ prom_halt(); } - psycho_index_map = (struct linux_psycho **)long_align(memory_start); - memory_start = long_align(memory_start + linux_num_psycho - * sizeof(struct linux_psycho *)); + psycho_index_map = kmalloc(sizeof(struct linux_psycho *) * linux_num_psycho, + GFP_ATOMIC); for (psycho = psycho_root; psycho; psycho = psycho->next) psycho_index_map[psycho->index] = psycho; - - return memory_start; } int pcibios_present(void) @@ -577,40 +570,14 @@ } } -static unsigned long *pci_alloc_arena = NULL; - -static inline void pci_init_alloc_init(unsigned long *mstart) -{ - pci_alloc_arena = mstart; -} - -static inline void pci_init_alloc_fini(void) -{ - pci_alloc_arena = NULL; -} - -__initfunc(static void *pci_init_alloc(int size)) -{ - unsigned long start = long_align(*pci_alloc_arena); - void *mp = (void *)start; - - if(!pci_alloc_arena) { - prom_printf("pci_init_alloc: pci_vma arena not init'd\n"); - prom_halt(); - } - start += size; - *pci_alloc_arena = start; - return mp; -} - static inline struct pci_vma *pci_vma_alloc(void) { - return pci_init_alloc(sizeof(struct pci_vma)); + return kmalloc(sizeof(struct pci_vma), GFP_ATOMIC); } static inline struct pcidev_cookie *pci_devcookie_alloc(void) { - return pci_init_alloc(sizeof(struct pcidev_cookie)); + return kmalloc(sizeof(struct pcidev_cookie), GFP_ATOMIC); } @@ -694,6 +661,14 @@ unsigned short stmp; unsigned int itmp; + for(pdev = pci_devices; pdev; pdev = pdev->next) { + if(pdev->vendor == PCI_VENDOR_ID_SUN && + pdev->device == PCI_DEVICE_ID_SUN_SABRE) { + /* Increase latency timer on top level bridge. */ + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xf8); + break; + } + } for (pdev = sabre->pci_bus->devices; pdev; pdev = pdev->sibling) { if (pdev->vendor == PCI_VENDOR_ID_SUN && pdev->device == PCI_DEVICE_ID_SUN_SIMBA) { @@ -732,12 +707,14 @@ pci_write_config_byte(pdev, APB_PIO_TARGET_LATENCY_TIMER, 0); pci_write_config_byte(pdev, APB_DMA_TARGET_RETRY_LIMIT, 0x80); pci_write_config_byte(pdev, APB_DMA_TARGET_LATENCY_TIMER, 0); + + /* Increase primary latency timer. */ + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xf8); } } } -__initfunc(static void sabre_probe(struct linux_psycho *sabre, - unsigned long *mstart)) +__initfunc(static void sabre_probe(struct linux_psycho *sabre)) { struct pci_bus *pbus = sabre->pci_bus; static unsigned char busno = 0; @@ -745,7 +722,7 @@ pbus->number = pbus->secondary = busno; pbus->sysdata = sabre; - pbus->subordinate = pci_scan_bus(pbus, mstart); + pbus->subordinate = pci_scan_bus(pbus); busno = pbus->subordinate + 1; for(pbus = pbus->children; pbus; pbus = pbus->next) { @@ -759,8 +736,7 @@ } -__initfunc(static void pbm_probe(struct linux_pbm_info *pbm, - unsigned long *mstart)) +__initfunc(static void pbm_probe(struct linux_pbm_info *pbm)) { static struct pci_bus *pchain = NULL; struct pci_bus *pbus = &pbm->pci_bus; @@ -777,7 +753,7 @@ pbm_fixup_busno(pbm, busno); - pbus->subordinate = pci_scan_bus(pbus, mstart); + pbus->subordinate = pci_scan_bus(pbus); /* * Set the maximum subordinate bus of this pbm. @@ -842,6 +818,10 @@ pcp->pbm = pbm; pcp->prom_node = node; pdev->sysdata = pcp; +#ifdef PCI_COOKIE_DEBUG + dprintf("pdev_cookie_fillin: pdev [%02x.%02x]: pbm %p, node %x\n", + pdev->bus->number, pdev->devfn, pbm, node); +#endif } __initfunc(static void fill_in_pbm_cookies(struct pci_bus *pbus, @@ -851,6 +831,11 @@ pbus->sysdata = pbm; +#ifdef PCI_COOKIE_DEBUG + dprintf("fill_in_pbm_cookies: pbus [%02x]: pbm %p\n", + pbus->number, pbm); +#endif + for(pdev = pbus->devices; pdev; pdev = pdev->sibling) pdev_cookie_fillin(pbm, pdev); @@ -973,7 +958,7 @@ { struct pci_vma *vp; - if (pbm->parent->pci_bus) { + if (apb_present(pbm->parent)) { /* * Disallow anything that is not in our IO/MEM map on SIMBA. */ @@ -984,12 +969,8 @@ for (pdev = pbus->devices; pdev; pdev = pdev->sibling) { struct pcidev_cookie *pcp = pdev->sysdata; - if (!pcp) { - prom_printf("record_assignments: " - "no pcidev_cookie for pdev %02x\n", - pdev->devfn); - prom_halt(); - } + if (!pcp) + continue; if (pcp->pbm == pbm) break; } @@ -1448,9 +1429,12 @@ } /* Exported for EBUS probing layer. */ -__initfunc(unsigned int psycho_irq_build(struct linux_pbm_info *pbm, unsigned int full_ino)) +__initfunc(unsigned int psycho_irq_build(struct linux_pbm_info *pbm, + struct pci_dev *pdev, + unsigned int full_ino)) { unsigned long imap_off, ign, ino; + int need_dma_sync = 0; ign = (full_ino & PSYCHO_IMAP_IGN) >> 6; ino = (full_ino & PSYCHO_IMAP_INO); @@ -1540,7 +1524,11 @@ } imap_off -= imap_offset(imap_a_slot0); - return pci_irq_encode(imap_off, pbm->parent->index, ign, ino); + if (apb_present(pbm->parent) && (pdev->bus->number != pbm->pci_first_busno)) { + need_dma_sync = 1; + } + + return pci_irq_encode(imap_off, pbm->parent->index, ign, ino, need_dma_sync); } __initfunc(static int pbm_intmap_match(struct linux_pbm_info *pbm, @@ -1618,7 +1606,7 @@ /* See if we find a matching interrupt-map entry. */ if (pbm_intmap_match(pbm, pdev, preg, &prom_irq)) { - pdev->irq = psycho_irq_build(pbm, + pdev->irq = psycho_irq_build(pbm, pdev, (pbm->parent->upa_portid << 6) | prom_irq); #ifdef FIXUP_IRQ_DEBUG @@ -1627,14 +1615,14 @@ #endif /* See if fully specified already (ie. for onboard devices like hme) */ } else if(((prom_irq & PSYCHO_IMAP_IGN) >> 6) == pbm->parent->upa_portid) { - pdev->irq = psycho_irq_build(pbm, prom_irq); + pdev->irq = psycho_irq_build(pbm, pdev, prom_irq); #ifdef FIXUP_IRQ_DEBUG dprintf("fully specified prom_irq[%x] pdev->irq[%x]", prom_irq, pdev->irq); #endif /* See if onboard device interrupt (i.e. bit 5 set) */ } else if((prom_irq & PSYCHO_IMAP_INO) & 0x20) { - pdev->irq = psycho_irq_build(pbm, + pdev->irq = psycho_irq_build(pbm, pdev, (pbm->parent->upa_portid << 6) | prom_irq); #ifdef FIXUP_IRQ_DEBUG @@ -1669,7 +1657,7 @@ } slot = (slot << 2); - pdev->irq = psycho_irq_build(pbm, + pdev->irq = psycho_irq_build(pbm, pdev, (((portid << 6) & PSYCHO_IMAP_IGN) | (bus | slot | line))); @@ -1818,7 +1806,7 @@ fixup_addr_irq(&psycho->pbm_B); } -__initfunc(unsigned long pcibios_fixup(unsigned long memory_start, unsigned long memory_end)) +__initfunc(void pcibios_fixup(void)) { struct linux_psycho *psycho; @@ -1838,26 +1826,24 @@ for (psycho = psycho_root; psycho; psycho = psycho->next) { /* Probe bus on builtin PCI. */ - if (psycho->pci_bus) - sabre_probe(psycho, &memory_start); + if (apb_present(psycho)) + sabre_probe(psycho); else { /* Probe busses under PBM B. */ - pbm_probe(&psycho->pbm_B, &memory_start); + pbm_probe(&psycho->pbm_B); /* Probe busses under PBM A. */ - pbm_probe(&psycho->pbm_A, &memory_start); + pbm_probe(&psycho->pbm_A); } } - pci_init_alloc_init(&memory_start); - /* Walk all PCI devices found. For each device, and * PCI bridge which is not one of the PSYCHO PBM's, fill in the * sysdata with a pointer to the PBM (for pci_bus's) or * a pci_dev cookie (PBM+PROM_NODE, for pci_dev's). */ for (psycho = psycho_root; psycho; psycho = psycho->next) { - if (psycho->pci_bus) + if (apb_present(psycho)) sabre_cookie_fillin(psycho); fill_in_pbm_cookies(&psycho->pbm_A.pci_bus, @@ -1873,9 +1859,7 @@ psycho_final_fixup(psycho); } - pci_init_alloc_fini(); - - return ebus_init(memory_start, memory_end); + return ebus_init(); } /* "PCI: The emerging standard..." 8-( */ @@ -2257,7 +2241,7 @@ { struct linux_pbm_info *pbm = bus2pbm[bus]; - if (pbm && pbm->parent && pbm->parent->pci_bus) + if (pbm && pbm->parent && apb_present(pbm->parent)) return sabre_read_config_byte(pbm, bus, devfn, where, value); return pbm_read_config_byte(pbm, bus, devfn, where, value); } @@ -2267,7 +2251,7 @@ { struct linux_pbm_info *pbm = bus2pbm[bus]; - if (pbm && pbm->parent && pbm->parent->pci_bus) + if (pbm && pbm->parent && apb_present(pbm->parent)) return sabre_read_config_word(pbm, bus, devfn, where, value); return pbm_read_config_word(pbm, bus, devfn, where, value); } @@ -2277,7 +2261,7 @@ { struct linux_pbm_info *pbm = bus2pbm[bus]; - if (pbm && pbm->parent && pbm->parent->pci_bus) + if (pbm && pbm->parent && apb_present(pbm->parent)) return sabre_read_config_dword(pbm, bus, devfn, where, value); return pbm_read_config_dword(pbm, bus, devfn, where, value); } @@ -2287,7 +2271,7 @@ { struct linux_pbm_info *pbm = bus2pbm[bus]; - if (pbm && pbm->parent && pbm->parent->pci_bus) + if (pbm && pbm->parent && apb_present(pbm->parent)) return sabre_write_config_byte(pbm, bus, devfn, where, value); return pbm_write_config_byte(pbm, bus, devfn, where, value); } @@ -2297,7 +2281,7 @@ { struct linux_pbm_info *pbm = bus2pbm[bus]; - if (pbm && pbm->parent && pbm->parent->pci_bus) + if (pbm && pbm->parent && apb_present(pbm->parent)) return sabre_write_config_word(pbm, bus, devfn, where, value); return pbm_write_config_word(bus2pbm[bus], bus, devfn, where, value); } @@ -2307,7 +2291,7 @@ { struct linux_pbm_info *pbm = bus2pbm[bus]; - if (pbm && pbm->parent && pbm->parent->pci_bus) + if (pbm && pbm->parent && apb_present(pbm->parent)) return sabre_write_config_dword(pbm, bus, devfn, where, value); return pbm_write_config_dword(bus2pbm[bus], bus, devfn, where, value); } diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/ptrace.c linux/arch/sparc64/kernel/ptrace.c --- v2.1.100/linux/arch/sparc64/kernel/ptrace.c Thu May 7 22:51:47 1998 +++ linux/arch/sparc64/kernel/ptrace.c Fri May 8 00:11:29 1998 @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -72,6 +73,41 @@ return pgtable; } +/* We must bypass the L1-cache to avoid alias issues. -DaveM */ +static __inline__ unsigned long read_user_long(unsigned long kvaddr) +{ + unsigned long ret; + + __asm__ __volatile__("ldxa [%1] %2, %0" + : "=r" (ret) + : "r" (__pa(kvaddr)), "i" (ASI_PHYS_USE_EC)); + return ret; +} + +static __inline__ unsigned int read_user_int(unsigned long kvaddr) +{ + unsigned int ret; + + __asm__ __volatile__("lduwa [%1] %2, %0" + : "=r" (ret) + : "r" (__pa(kvaddr)), "i" (ASI_PHYS_USE_EC)); + return ret; +} + +static __inline__ void write_user_long(unsigned long kvaddr, unsigned long val) +{ + __asm__ __volatile__("stxa %0, [%1] %2" + : /* no outputs */ + : "r" (val), "r" (__pa(kvaddr)), "i" (ASI_PHYS_USE_EC)); +} + +static __inline__ void write_user_int(unsigned long kvaddr, unsigned int val) +{ + __asm__ __volatile__("stwa %0, [%1] %2" + : /* no outputs */ + : "r" (val), "r" (__pa(kvaddr)), "i" (ASI_PHYS_USE_EC)); +} + static inline unsigned long get_long(struct task_struct * tsk, struct vm_area_struct * vma, unsigned long addr) { @@ -84,7 +120,7 @@ if (MAP_NR(page) >= max_mapnr) return 0; page += addr & ~PAGE_MASK; - retval = *(unsigned long *) page; + retval = read_user_long(page); flush_page_to_ram(page); return retval; } @@ -103,14 +139,12 @@ unsigned long pgaddr; pgaddr = page + (addr & ~PAGE_MASK); - *(unsigned long *) (pgaddr) = data; + write_user_long(pgaddr, data); __asm__ __volatile__(" membar #StoreStore flush %0 " : : "r" (pgaddr & ~7) : "memory"); - - flush_page_to_ram(page); } /* we're bypassing pagetables, so we have to set the dirty bit ourselves */ /* this should also re-instate whatever read-only mode there was before */ @@ -131,7 +165,7 @@ if (MAP_NR(page) >= max_mapnr) return 0; page += addr & ~PAGE_MASK; - retval = *(unsigned int *) page; + retval = read_user_int(page); flush_page_to_ram(page); return retval; } @@ -150,14 +184,12 @@ unsigned long pgaddr; pgaddr = page + (addr & ~PAGE_MASK); - *(unsigned int *) (pgaddr) = data; + write_user_int(pgaddr, data); __asm__ __volatile__(" membar #StoreStore flush %0 " : : "r" (pgaddr & ~7) : "memory"); - - flush_page_to_ram(page); } /* we're bypassing pagetables, so we have to set the dirty bit ourselves */ /* this should also re-instate whatever read-only mode there was before */ @@ -890,7 +922,7 @@ vma = find_extend_vma(child, src); if (!vma) { pt_error_return(regs, EIO); - goto out; + goto flush_and_out; } pgtable = get_page (child, vma, src, 0); if (src & ~PAGE_MASK) { @@ -904,13 +936,13 @@ if (copy_to_user (dest, ((char *)page) + (src & ~PAGE_MASK), curlen)) { flush_page_to_ram(page); pt_error_return(regs, EFAULT); - goto out; + goto flush_and_out; } flush_page_to_ram(page); } else { if (clear_user (dest, curlen)) { pt_error_return(regs, EFAULT); - goto out; + goto flush_and_out; } } src += curlen; @@ -918,7 +950,7 @@ len -= curlen; } pt_succ_return(regs, 0); - goto out; + goto flush_and_out; } case PTRACE_WRITETEXT: @@ -934,7 +966,7 @@ vma = find_extend_vma(child, dest); if (!vma) { pt_error_return(regs, EIO); - goto out; + goto flush_and_out; } pgtable = get_page (child, vma, dest, 1); if (dest & ~PAGE_MASK) { @@ -951,7 +983,7 @@ set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot))); flush_tlb_page(vma, dest); pt_error_return(regs, EFAULT); - goto out; + goto flush_and_out; } flush_page_to_ram(page); set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot))); @@ -962,7 +994,7 @@ len -= curlen; } pt_succ_return(regs, 0); - goto out; + goto flush_and_out; } case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */ @@ -1040,6 +1072,12 @@ default: pt_error_return(regs, EIO); goto out; + } +flush_and_out: + { + unsigned long va; + for(va = 0; va < (PAGE_SIZE << 1); va += 32) + spitfire_put_dcache_tag(va, 0x0); } out: unlock_kernel(); diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c --- v2.1.100/linux/arch/sparc64/kernel/smp.c Thu Apr 23 20:21:32 1998 +++ linux/arch/sparc64/kernel/smp.c Fri May 8 00:11:29 1998 @@ -85,7 +85,6 @@ { cpu_data[id].udelay_val = loops_per_sec; cpu_data[id].irq_count = 0; - cpu_data[id].last_tlbversion_seen = tlb_context_cache & CTX_VERSION_MASK; cpu_data[id].pgcache_size = 0; cpu_data[id].pgd_cache = NULL; cpu_data[id].pmd_cache = NULL; @@ -368,16 +367,28 @@ __flush_tlb_all(); } +/* We know that the window frames of the user have been flushed + * to the stack before we get here because all callers of us + * are flush_tlb_*() routines, and these run after flush_cache_*() + * which performs the flushw. + */ static void smp_cross_call_avoidance(struct mm_struct *mm) { + u32 ctx; + spin_lock(&scheduler_lock); - get_new_mmu_context(mm, &tlb_context_cache); + get_new_mmu_context(mm); mm->cpu_vm_mask = (1UL << smp_processor_id()); - if(segment_eq(current->tss.current_ds,USER_DS)) { - u32 ctx = mm->context & 0x1fff; - - current->tss.ctx = ctx; - spitfire_set_secondary_context(ctx); + current->tss.ctx = ctx = mm->context & 0x3ff; + spitfire_set_secondary_context(ctx); + __asm__ __volatile__("flush %g6"); + spitfire_flush_dtlb_secondary_context(); + spitfire_flush_itlb_secondary_context(); + __asm__ __volatile__("flush %g6"); + if(!segment_eq(current->tss.current_ds,USER_DS)) { + /* Rarely happens. */ + current->tss.ctx = 0; + spitfire_set_secondary_context(0); __asm__ __volatile__("flush %g6"); } spin_unlock(&scheduler_lock); @@ -385,7 +396,7 @@ void smp_flush_tlb_mm(struct mm_struct *mm) { - u32 ctx = mm->context & 0x1fff; + u32 ctx = mm->context & 0x3ff; if(mm == current->mm && mm->count == 1) { if(mm->cpu_vm_mask == (1UL << smp_processor_id())) @@ -401,7 +412,7 @@ void smp_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - u32 ctx = mm->context & 0x1fff; + u32 ctx = mm->context & 0x3ff; if(mm == current->mm && mm->count == 1) { if(mm->cpu_vm_mask == (1UL << smp_processor_id())) @@ -416,7 +427,7 @@ void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page) { - u32 ctx = mm->context & 0x1fff; + u32 ctx = mm->context & 0x3ff; if(mm == current->mm && mm->count == 1) { if(mm->cpu_vm_mask == (1UL << smp_processor_id())) @@ -424,7 +435,7 @@ return smp_cross_call_avoidance(mm); } #if 0 /* XXX Disabled until further notice... */ - else if(mm != current->mm && mm->count == 1) { + else if(mm->count == 1) { /* Try to handle two special cases to avoid cross calls * in common scenerios where we are swapping process * pages out. diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- v2.1.100/linux/arch/sparc64/kernel/sparc64_ksyms.c Thu Apr 23 20:21:32 1998 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Fri May 8 00:11:29 1998 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.33 1998/04/06 16:09:40 jj Exp $ +/* $Id: sparc64_ksyms.c,v 1.36 1998/04/16 07:07:19 ecd Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -113,10 +113,10 @@ #else EXPORT_SYMBOL(local_irq_count); #endif -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL_PRIVATE(_lock_kernel); EXPORT_SYMBOL_PRIVATE(_unlock_kernel); +EXPORT_SYMBOL(enable_irq); +EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL_PRIVATE(flushw_user); @@ -140,6 +140,12 @@ EXPORT_SYMBOL(pci_dvma_offset); EXPORT_SYMBOL(pci_dvma_mask); EXPORT_SYMBOL(empty_zero_page); +EXPORT_SYMBOL(outsb); +EXPORT_SYMBOL(outsw); +EXPORT_SYMBOL(outsl); +EXPORT_SYMBOL(insb); +EXPORT_SYMBOL(insw); +EXPORT_SYMBOL(insl); #endif /* Solaris/SunOS binary compatibility */ diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c --- v2.1.100/linux/arch/sparc64/kernel/sys_sparc32.c Thu May 7 22:51:47 1998 +++ linux/arch/sparc64/kernel/sys_sparc32.c Fri May 8 00:11:29 1998 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.77 1998/03/29 10:10:50 davem Exp $ +/* $Id: sys_sparc32.c,v 1.83 1998/05/04 05:35:39 jj Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -60,7 +60,7 @@ extern char * getname_quicklist; extern int getname_quickcount; -extern struct semaphore getname_quicklock; +extern spinlock_t getname_quicklock; /* Tuning: increase locality by reusing same pages again... * if getname_quicklist becomes too long on low memory machines, either a limit @@ -70,15 +70,15 @@ static inline char * get_page(void) { char * res; - down(&getname_quicklock); + spin_lock(&getname_quicklock); res = getname_quicklist; if (res) { getname_quicklist = *(char**)res; getname_quickcount--; } - else + spin_unlock(&getname_quicklock); + if (!res) res = (char*)__get_free_page(GFP_KERNEL); - up(&getname_quicklock); return res; } @@ -845,9 +845,6 @@ ret = do_readv_writev32(VERIFY_WRITE, file, (struct iovec32 *)A(vector), count); - if (ret > 0) - current->io_usage += ret; - out: fput(file); bad_file: @@ -872,9 +869,6 @@ ret = do_readv_writev32(VERIFY_READ, file, (struct iovec32 *)A(vector), count); up(&file->f_dentry->d_inode->i_sem); - if (ret > 0) - current->io_usage += ret; - out: fput(file); bad_file: @@ -1148,6 +1142,7 @@ put_user(sec, &tvp->tv_sec); put_user(usec, &tvp->tv_usec); } + current->timeout = 0; if (ret < 0) goto out; @@ -2556,14 +2551,16 @@ return 0; p -= len; pos = p; while (len) { - char *pag; + char *pag = (char *) page[pos/PAGE_SIZE]; int offset, bytes_to_copy; offset = pos % PAGE_SIZE; - if (!(pag = (char *) page[pos/PAGE_SIZE]) && - !(pag = (char *) page[pos/PAGE_SIZE] = - (unsigned long *) get_free_page(GFP_USER))) - return 0; + if(!pag) { + pag = (char *) page[pos/PAGE_SIZE] = get_user_page(pos); + if(!pag) + return 0; + clear_page(pag); + } bytes_to_copy = PAGE_SIZE - offset; if (bytes_to_copy > len) bytes_to_copy = len; @@ -2703,119 +2700,274 @@ s32 usecount; }; -extern asmlinkage int sys_query_module(const char *name_user, int which, char *buf, size_t bufsize, size_t *ret); +/* Query various bits about modules. */ + +extern long get_mod_name(const char *user_name, char **buf); +extern void put_mod_name(char *buf); +extern struct module *find_module(const char *name); +extern struct module kernel_module; + +static int +qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret) +{ + struct module *mod; + size_t nmod, space, len; + + nmod = space = 0; + + for (mod=module_list; mod != &kernel_module; mod=mod->next, ++nmod) { + len = strlen(mod->name)+1; + if (len > bufsize) + goto calc_space_needed; + if (copy_to_user(buf, mod->name, len)) + return -EFAULT; + buf += len; + bufsize -= len; + space += len; + } -asmlinkage int sys32_query_module(u32 name_user, int which, u32 buf, __kernel_size_t32 bufsize, u32 retv) + if (put_user(nmod, ret)) + return -EFAULT; + else + return 0; + +calc_space_needed: + space += len; + while ((mod = mod->next) != &kernel_module) + space += strlen(mod->name)+1; + + if (put_user(space, ret)) + return -EFAULT; + else + return -ENOSPC; +} + +static int +qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret) { - char *buff; - mm_segment_t old_fs = get_fs(); - size_t val; - int ret, i, j; - unsigned long *p; - char *usernam = NULL; - int bufsiz = bufsize; - struct module_info mi; - - switch (which) { - case 0: return sys_query_module ((const char *)A(name_user), which, (char *)A(buf), (size_t)bufsize, (size_t *)A(retv)); - case QM_SYMBOLS: - bufsiz <<= 1; - case QM_MODULES: - case QM_REFS: - case QM_DEPS: - if (name_user) { - usernam = getname32 (name_user); - ret = PTR_ERR(usernam); - if (IS_ERR(usernam)) - return ret; - } - buff = kmalloc (bufsiz, GFP_KERNEL); - if (!buff) { - if (name_user) putname32 (usernam); - return -ENOMEM; + size_t i, space, len; + + if (mod == &kernel_module) + return -EINVAL; + if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING) + if (put_user(0, ret)) + return -EFAULT; + else + return 0; + + space = 0; + for (i = 0; i < mod->ndeps; ++i) { + const char *dep_name = mod->deps[i].dep->name; + + len = strlen(dep_name)+1; + if (len > bufsize) + goto calc_space_needed; + if (copy_to_user(buf, dep_name, len)) + return -EFAULT; + buf += len; + bufsize -= len; + space += len; + } + + if (put_user(i, ret)) + return -EFAULT; + else + return 0; + +calc_space_needed: + space += len; + while (++i < mod->ndeps) + space += strlen(mod->deps[i].dep->name)+1; + + if (put_user(space, ret)) + return -EFAULT; + else + return -ENOSPC; +} + +static int +qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret) +{ + size_t nrefs, space, len; + struct module_ref *ref; + + if (mod == &kernel_module) + return -EINVAL; + if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING) + if (put_user(0, ret)) + return -EFAULT; + else + return 0; + + space = 0; + for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) { + const char *ref_name = ref->ref->name; + + len = strlen(ref_name)+1; + if (len > bufsize) + goto calc_space_needed; + if (copy_to_user(buf, ref_name, len)) + return -EFAULT; + buf += len; + bufsize -= len; + space += len; + } + + if (put_user(nrefs, ret)) + return -EFAULT; + else + return 0; + +calc_space_needed: + space += len; + while ((ref = ref->next_ref) != NULL) + space += strlen(ref->ref->name)+1; + + if (put_user(space, ret)) + return -EFAULT; + else + return -ENOSPC; +} + +static inline int +qm_symbols(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret) +{ + size_t i, space, len; + struct module_symbol *s; + char *strings; + unsigned *vals; + + if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING) + if (put_user(0, ret)) + return -EFAULT; + else + return 0; + + space = mod->nsyms * 2*sizeof(u32); + + i = len = 0; + s = mod->syms; + + if (space > bufsize) + goto calc_space_needed; + + if (!access_ok(VERIFY_WRITE, buf, space)) + return -EFAULT; + + bufsize -= space; + vals = (unsigned *)buf; + strings = buf+space; + + for (; i < mod->nsyms ; ++i, ++s, vals += 2) { + len = strlen(s->name)+1; + if (len > bufsize) + goto calc_space_needed; + + if (copy_to_user(strings, s->name, len) + || __put_user(s->value, vals+0) + || __put_user(space, vals+1)) + return -EFAULT; + + strings += len; + bufsize -= len; + space += len; + } + + if (put_user(i, ret)) + return -EFAULT; + else + return 0; + +calc_space_needed: + for (; i < mod->nsyms; ++i, ++s) + space += strlen(s->name)+1; + + if (put_user(space, ret)) + return -EFAULT; + else + return -ENOSPC; +} + +static inline int +qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret) +{ + int error = 0; + + if (mod == &kernel_module) + return -EINVAL; + + if (sizeof(struct module_info32) <= bufsize) { + struct module_info32 info; + info.addr = (unsigned long)mod; + info.size = mod->size; + info.flags = mod->flags; + info.usecount = (mod_member_present(mod, can_unload) + && mod->can_unload ? -1 : mod->usecount); + + if (copy_to_user(buf, &info, sizeof(struct module_info32))) + return -EFAULT; + } else + error = -ENOSPC; + + if (put_user(sizeof(struct module_info32), ret)) + return -EFAULT; + + return error; +} + +asmlinkage int sys32_query_module(u32 name_user, int which, u32 buf, __kernel_size_t32 bufsize, u32 ret) +{ + struct module *mod; + int err; + + lock_kernel(); + if (name_user == 0) + mod = &kernel_module; + else { + long namelen; + char *name; + + if ((namelen = get_mod_name((char *)A(name_user), &name)) < 0) { + err = namelen; + goto out; } -qmsym_toshort: - set_fs (KERNEL_DS); - ret = sys_query_module (usernam, which, buff, bufsiz, &val); - set_fs (old_fs); - if (which != QM_SYMBOLS) { - if (ret == -ENOSPC || !ret) { - if (put_user (val, (__kernel_size_t32 *)A(retv))) - ret = -EFAULT; - } - if (!ret) { - if (copy_to_user ((char *)A(buf), buff, bufsize)) - ret = -EFAULT; - } - } else { - if (ret == -ENOSPC) { - if (put_user (2 * val, (__kernel_size_t32 *)A(retv))) - ret = -EFAULT; - } - p = (unsigned long *)buff; - if (!ret) { - if (put_user (val, (__kernel_size_t32 *)A(retv))) - ret = -EFAULT; - } - if (!ret) { - j = val * 8; - for (i = 0; i < val; i++, p += 2) { - if (bufsize < (2 * sizeof (u32))) { - bufsiz = 0; - goto qmsym_toshort; - } - if (put_user (p[0], (u32 *)A(buf)) || - __put_user (p[1] - j, (((u32 *)A(buf))+1))) { - ret = -EFAULT; - break; - } - bufsize -= (2 * sizeof (u32)); - buf += (2 * sizeof (u32)); - } - } - if (!ret && val) { - char *strings = buff + ((unsigned long *)buff)[1]; - j = *(p - 1) - ((unsigned long *)buff)[1]; - j = j + strlen (strings + j) + 1; - if (bufsize < j) { - bufsiz = 0; - goto qmsym_toshort; - } - if (copy_to_user ((char *)A(buf), strings, j)) - ret = -EFAULT; - } + err = -ENOENT; + if (namelen == 0) + mod = &kernel_module; + else if ((mod = find_module(name)) == NULL) { + put_mod_name(name); + goto out; } - kfree (buff); - if (name_user) putname32 (usernam); - return ret; + put_mod_name(name); + } + + switch (which) + { + case 0: + err = 0; + break; + case QM_MODULES: + err = qm_modules((char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret)); + break; + case QM_DEPS: + err = qm_deps(mod, (char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret)); + break; + case QM_REFS: + err = qm_refs(mod, (char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret)); + break; + case QM_SYMBOLS: + err = qm_symbols(mod, (char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret)); + break; case QM_INFO: - if (name_user) { - usernam = getname32 (name_user); - ret = PTR_ERR(usernam); - if (IS_ERR(usernam)) - return ret; - } - set_fs (KERNEL_DS); - ret = sys_query_module (usernam, which, (char *)&mi, sizeof (mi), &val); - set_fs (old_fs); - if (!ret) { - if (put_user (sizeof (struct module_info32), (__kernel_size_t32 *)A(retv))) - ret = -EFAULT; - else if (bufsize < sizeof (struct module_info32)) - ret = -ENOSPC; - } - if (!ret) { - if (put_user (mi.addr, &(((struct module_info32 *)A(buf))->addr)) || - __put_user (mi.size, &(((struct module_info32 *)A(buf))->size)) || - __put_user (mi.flags, &(((struct module_info32 *)A(buf))->flags)) || - __put_user (mi.usecount, &(((struct module_info32 *)A(buf))->usecount))) - ret = -EFAULT; - } - if (name_user) putname32 (usernam); - return ret; + err = qm_info(mod, (char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret)); + break; default: - return -EINVAL; + err = -EINVAL; + break; } +out: + unlock_kernel(); + return err; } struct kernel_sym32 { diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S --- v2.1.100/linux/arch/sparc64/kernel/systbls.S Thu Apr 23 20:21:32 1998 +++ linux/arch/sparc64/kernel/systbls.S Fri May 8 00:11:29 1998 @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.41 1998/03/24 05:57:57 ecd Exp $ +/* $Id: systbls.S,v 1.42 1998/04/14 13:49:52 jj Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -40,11 +40,11 @@ /*100*/ .word sys_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending .word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall /*110*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .word sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd /*120*/ .word sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod .word sys_nis_syscall, sys32_setreuid, sys32_setregid, sys_rename, sys_truncate /*130*/ .word sys_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .word sys_nis_syscall, sys_mkdir, sys_rmdir, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_nis_syscall /*140*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit .word sys32_setrlimit, sys_nis_syscall, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write /*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall @@ -99,11 +99,11 @@ /*100*/ .word sys_getpriority, sys_rt_sigreturn, sys_rt_sigaction, sys_rt_sigprocmask, sys_rt_sigpending .word sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall /*110*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_recvmsg, sys_sendmsg - .word sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_nis_syscall + .word sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_getcwd /*120*/ .word sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod .word sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate /*130*/ .word sys_ftruncate, sys_flock, sys_nis_syscall, sys_sendto, sys_shutdown - .word sys_socketpair, sys_mkdir, sys_rmdir, sys_nis_syscall, sys_nis_syscall + .word sys_socketpair, sys_mkdir, sys_rmdir, sys_utimes, sys_nis_syscall /*140*/ .word sys_nis_syscall, sys_getpeername, sys_nis_syscall, sys_nis_syscall, sys_getrlimit .word sys_setrlimit, sys_nis_syscall, sys_prctl, sys_pciconfig_read, sys_pciconfig_write /*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/lib/VIScopy.S linux/arch/sparc64/lib/VIScopy.S --- v2.1.100/linux/arch/sparc64/lib/VIScopy.S Thu Sep 4 12:54:48 1997 +++ linux/arch/sparc64/lib/VIScopy.S Fri May 8 00:11:29 1998 @@ -1,4 +1,4 @@ -/* $Id: VIScopy.S,v 1.14 1997/08/22 15:54:53 jj Exp $ +/* $Id: VIScopy.S,v 1.15 1998/04/26 07:21:54 davem Exp $ * VIScopy.S: High speed copy operations utilizing the UltraSparc * Visual Instruction Set. * @@ -978,7 +978,16 @@ VIScopyfixup_reto2: mov %o2, %o0 VIScopyfixup_ret: - retl + /* If this is copy_from_user(), zero out the rest of the + * kernel buffer. + */ + andcc asi_src, 0x1, %g0 + bne 1f + mov %o0, %o4 + /* XXX Here, somehow get original kernel pointer (was in %o0) + * XXX and bzero() all remaining bytes in kernel buffer. + */ +1: retl wr %g0, 0, %fprs VIScopyfixup1: subcc %g2, 18, %g2 bgeu,a,pt %icc, VIScopyfixup1 diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.1.100/linux/arch/sparc64/mm/init.c Thu Apr 23 20:21:32 1998 +++ linux/arch/sparc64/mm/init.c Fri May 8 00:11:29 1998 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.71 1998/03/27 07:00:08 davem Exp $ +/* $Id: init.c,v 1.81 1998/05/04 05:35:43 jj Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -52,11 +54,6 @@ __bfill64((void *)pmdp, &two_null_pte_table); } -static __inline__ void __init_pgd(pgd_t *pgdp) -{ - __bfill64((void *)pgdp, &two_null_pmd_table); -} - /* * BAD_PAGE is the page that is used for page faults when linux * is out-of-memory. Older versions of linux just did a @@ -125,6 +122,9 @@ printk("%d pages shared\n",shared); printk("%d pages swap cached\n",cached); printk("%ld pages in page table cache\n",pgtable_cache_size); +#ifndef __SMP__ + printk("%ld entries in page dir cache\n",pgd_cache_size); +#endif show_buffers(); #ifdef CONFIG_NET show_net_buffers(); @@ -135,27 +135,47 @@ /* This keeps track of pages used in sparc_alloc_dvma() invocations. */ /* NOTE: All of these are inited to 0 in bss, don't need to make data segment bigger */ -static unsigned long dvma_map_pages[0x10000000 >> 16]; +#define DVMAIO_SIZE 0x2000000 +static unsigned long dvma_map_pages[DVMAIO_SIZE >> 16]; static unsigned long dvma_pages_current_offset; static int dvma_pages_current_index; +static unsigned long dvmaiobase = 0; +static unsigned long dvmaiosz __initdata = 0; /* #define E3000_DEBUG */ -__initfunc(unsigned long iommu_init(int iommu_node, unsigned long memory_start, - unsigned long memory_end, struct linux_sbus *sbus)) +__initfunc(void dvmaio_init(void)) +{ + int i; + + if (!dvmaiobase) { + for (i = 0; sp_banks[i].num_bytes != 0; i++) + if (sp_banks[i].base_addr + sp_banks[i].num_bytes > dvmaiobase) + dvmaiobase = sp_banks[i].base_addr + sp_banks[i].num_bytes; + dvmaiobase = (dvmaiobase + DVMAIO_SIZE + 0x400000 - 1) & ~(0x400000 - 1); + for (i = 0; i < 6; i++) + if (dvmaiobase <= ((1024 * 64 * 1024) << i)) + break; + dvmaiobase = ((1024 * 64 * 1024) << i) - DVMAIO_SIZE; + dvmaiosz = i; + } +} + +__initfunc(void iommu_init(int iommu_node, struct linux_sbus *sbus)) { struct iommu_struct *iommu; struct sysio_regs *sregs; struct linux_prom64_registers rprop; unsigned long impl, vers; unsigned long control, tsbbase; + unsigned long tsbbases[32]; unsigned long *iopte; - u32 rlow, rhigh; - int err, i; - + int err, i, j; + + dvmaio_init(); #ifdef E3000_DEBUG - prom_printf("\niommu_init: [%x:%016lx:%016lx:%p] ", - iommu_node, memory_start, memory_end, sbus); + prom_printf("\niommu_init: [%x:%p] ", + iommu_node, sbus); #endif err = prom_getproperty(iommu_node, "reg", (char *)&rprop, sizeof(rprop)); @@ -163,14 +183,8 @@ prom_printf("iommu_init: Cannot map SYSIO control registers.\n"); prom_halt(); } - rlow = (rprop.phys_addr & 0xffffffff); - rhigh = (rprop.phys_addr >> 32); -#ifdef E3000_DEBUG - prom_printf("rlow[%08x] rhigh[%08x] ", rlow, rhigh); -#endif - sregs = (struct sysio_regs *) sparc_alloc_io(rlow, (void *)0, - sizeof(struct sysio_regs), - "SYSIO Regs", rhigh, 0x0); + sregs = (struct sysio_regs *) __va(rprop.phys_addr); + #ifdef E3000_DEBUG prom_printf("sregs[%p]\n"); #endif @@ -179,9 +193,7 @@ prom_halt(); } - memory_start = (memory_start + 7) & ~7; - iommu = (struct iommu_struct *) memory_start; - memory_start += sizeof(struct iommu_struct); + iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC); #ifdef E3000_DEBUG prom_printf("iommu_init: iommu[%p] ", iommu); @@ -203,26 +215,54 @@ (unsigned int) impl, (unsigned int)vers, (unsigned long) sregs); control &= ~(IOMMU_CTRL_TSBSZ); - control |= (IOMMU_TSBSZ_64K | IOMMU_CTRL_TBWSZ | IOMMU_CTRL_ENAB); + control |= ((IOMMU_TSBSZ_2K * dvmaiosz) | IOMMU_CTRL_TBWSZ | IOMMU_CTRL_ENAB); /* Use only 64k pages, things are layed out in the 32-bit SBUS * address space like this: * - * 0x00000000 ---------------------------------------- - * | Direct physical mappings for most | - * | DVMA to paddr's within this range | - * 0xf0000000 ---------------------------------------- - * | For mappings requested via | - * | sparc_alloc_dvma() | - * 0xffffffff ---------------------------------------- - */ - tsbbase = PAGE_ALIGN(memory_start); - memory_start = (tsbbase + ((64 * 1024) * 8)); + * 0x00000000 ---------------------------------------- + * | Direct physical mappings for most | + * | DVMA to paddr's within this range | + * dvmaiobase ---------------------------------------- + * | For mappings requested via | + * | sparc_alloc_dvma() | + * dvmaiobase+32M ---------------------------------------- + * + * NOTE: we need to order 2 contiguous order 5, that's the largest + * chunk page_alloc will give us. -JJ */ + tsbbase = 0; + if (dvmaiosz == 6) { + memset (tsbbases, 0, sizeof(tsbbases)); + for (i = 0; i < 32; i++) { + tsbbases[i] = __get_free_pages(GFP_DMA, 5); + for (j = 0; j < i; j++) + if (tsbbases[j] == tsbbases[i] + 32768*sizeof(iopte_t)) { + tsbbase = tsbbases[i]; + break; + } else if (tsbbases[i] == tsbbases[j] + 32768*sizeof(iopte_t)) { + tsbbase = tsbbases[j]; + break; + } + if (tsbbase) { + tsbbases[i] = 0; + tsbbases[j] = 0; + break; + } + } + for (i = 0; i < 32; i++) + if (tsbbases[i]) + free_pages(tsbbases[i], 5); + } else + tsbbase = __get_free_pages(GFP_DMA, dvmaiosz); + if (!tsbbase) { + prom_printf("Strange. Could not allocate 512K of contiguous RAM.\n"); + prom_halt(); + } iommu->page_table = (iopte_t *) tsbbase; iopte = (unsigned long *) tsbbase; /* Setup aliased mappings... */ - for(i = 0; i < (65536 - 4096); i++) { + for(i = 0; i < (dvmaiobase >> 16); i++) { *iopte = (IOPTE_VALID | IOPTE_64K | IOPTE_STBUF | IOPTE_CACHE | IOPTE_WRITE); *iopte |= (i << 16); @@ -230,7 +270,7 @@ } /* Clear all sparc_alloc_dvma() maps. */ - for( ; i < 65536; i++) + for( ; i < ((dvmaiobase + DVMAIO_SIZE) >> 16); i++) *iopte++ = 0; #ifdef E3000_DEBUG @@ -252,23 +292,19 @@ #endif printk("IOMMU: Streaming Buffer IMPL[%x] REV[%x] ", (unsigned int)impl, (unsigned int)vers); - printk("FlushFLAG[%p,%016lx] ... ", - (iommu->sbuf_flushflag_va = (unsigned int *)memory_start), - (iommu->sbuf_flushflag_pa = __pa(memory_start))); + iommu->sbuf_flushflag_va = kmalloc(sizeof(unsigned long), GFP_DMA); + printk("FlushFLAG[%016lx] ... ", (iommu->sbuf_flushflag_pa = __pa(iommu->sbuf_flushflag_va))); *(iommu->sbuf_flushflag_va) = 0; - memory_start += sizeof(unsigned long); /* yes, unsigned long, for alignment */ sregs->sbuf_control = (control | SYSIO_SBUFCTRL_SB_EN); #ifdef E3000_DEBUG - prom_printf("done, returning %016lx\n", memory_start); + prom_printf("done, returning\n"); #endif printk("ENABLED\n"); /* Finally enable DVMA arbitration for all devices, just in case. */ sregs->sbus_control |= SYSIO_SBCNTRL_AEN; - - return memory_start; } void mmu_map_dma_area(unsigned long addr, int len, __u32 *dvma_addr, @@ -300,7 +336,7 @@ } /* Stick it in the IOMMU. */ - i = (65536 - 4096) + i; + i = (dvmaiobase >> 16) + i; for_each_sbus(sbus) { struct iommu_struct *iommu = sbus->iommu; unsigned long flags; @@ -314,7 +350,7 @@ } /* Get this out of the way. */ - *dvma_addr = (__u32) ((0xf0000000) + + *dvma_addr = (__u32) ((dvmaiobase) + (dvma_pages_current_index << 16) + (dvma_pages_current_offset)); @@ -345,13 +381,17 @@ { __u32 sbus_addr = (__u32) __pa(vaddr); - if((sbus_addr < 0xf0000000) && - ((sbus_addr + len) < 0xf0000000)) +#ifndef DEBUG_IOMMU + return sbus_addr; +#else + if((sbus_addr < dvmaiobase) && + ((sbus_addr + len) < dvmaiobase)) return sbus_addr; /* "can't happen"... GFP_DMA assures this. */ panic("Very high scsi_one mappings should never happen."); return (__u32)0; +#endif } void mmu_release_scsi_one(u32 vaddr, unsigned long len, struct linux_sbus *sbus) @@ -385,13 +425,17 @@ { while(sz >= 0) { __u32 page = (__u32) __pa(((unsigned long) sg[sz].addr)); - if((page < 0xf0000000) && - (page + sg[sz].len) < 0xf0000000) { +#ifndef DEBUG_IOMMU + sg[sz].dvma_addr = page; +#else + if((page < dvmaiobase) && + (page + sg[sz].len) < dvmaiobase) { sg[sz].dvma_addr = page; } else { /* "can't happen"... GFP_DMA assures this. */ panic("scsi_sgl high mappings should never happen."); } +#endif sz--; } } @@ -485,10 +529,42 @@ } } +static int prom_ditlb_set = 0; int prom_itlb_ent, prom_dtlb_ent; unsigned long prom_itlb_tag, prom_itlb_data; unsigned long prom_dtlb_tag, prom_dtlb_data; +void prom_world(int enter) +{ + if (!prom_ditlb_set) return; + if (enter) { + /* Install PROM world. */ + __asm__ __volatile__("stxa %0, [%1] %2" + : : "r" (prom_dtlb_tag), "r" (TLB_TAG_ACCESS), + "i" (ASI_DMMU)); + membar("#Sync"); + spitfire_put_dtlb_data(62, prom_dtlb_data); + membar("#Sync"); + __asm__ __volatile__("stxa %0, [%1] %2" + : : "r" (prom_itlb_tag), "r" (TLB_TAG_ACCESS), + "i" (ASI_IMMU)); + membar("#Sync"); + spitfire_put_itlb_data(62, prom_itlb_data); + membar("#Sync"); + } else { + __asm__ __volatile__("stxa %%g0, [%0] %1" + : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); + membar("#Sync"); + spitfire_put_dtlb_data(62, 0x0UL); + membar("#Sync"); + __asm__ __volatile__("stxa %%g0, [%0] %1" + : : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU)); + membar("#Sync"); + spitfire_put_itlb_data(62, 0x0UL); + membar("#Sync"); + } +} + void inherit_locked_prom_mappings(int save_p) { int i; @@ -500,8 +576,7 @@ * translations property. The only ones that matter are * the locked PROM tlb entries, so we impose the following * irrecovable rule on the PROM, it is allowed 1 locked - * entry in the ITLB and 1 in the DTLB. We move those - * (if necessary) up into tlb entry 62. + * entry in the ITLB and 1 in the DTLB. * * Supposedly the upper 16GB of the address space is * reserved for OBP, BUT I WISH THIS WAS DOCUMENTED @@ -510,7 +585,7 @@ * systems to coordinate mmu mappings is also COMPLETELY * UNDOCUMENTED!!!!!! Thanks S(t)un! */ - for(i = 0; i < 62; i++) { + for(i = 0; i < 63; i++) { unsigned long data; data = spitfire_get_dtlb_data(i); @@ -528,13 +603,6 @@ spitfire_put_dtlb_data(i, 0x0UL); membar("#Sync"); - /* Re-install it. */ - __asm__ __volatile__("stxa %0, [%1] %2" - : : "r" (tag), "r" (TLB_TAG_ACCESS), - "i" (ASI_DMMU)); - membar("#Sync"); - spitfire_put_dtlb_data(62, data); - membar("#Sync"); dtlb_seen = 1; if(itlb_seen) break; @@ -566,6 +634,8 @@ break; } } + if (save_p) + prom_ditlb_set = 1; } /* Give PROM back his world, done during reboots... */ @@ -628,37 +698,67 @@ : : "r" (pstate)); } -/* We are always protected by scheduler_lock under SMP. */ -void get_new_mmu_context(struct mm_struct *mm, unsigned long *ctx) -{ - unsigned int new_ctx = *ctx; +unsigned long mmu_context_bmap[1UL << (CTX_VERSION_SHIFT - 6)]; - if((new_ctx & ~(CTX_VERSION_MASK)) == 0) { - new_ctx += CTX_FIRST_VERSION; - if(new_ctx == 1) - new_ctx = CTX_FIRST_VERSION; - *ctx = new_ctx; - DO_LOCAL_FLUSH(smp_processor_id()); +/* We are always protected by scheduler_lock under SMP. + * Caller does TLB context flushing on local CPU if necessary. + */ +void get_new_mmu_context(struct mm_struct *mm) +{ + unsigned long ctx = (tlb_context_cache + 1) & ~(CTX_VERSION_MASK); + unsigned long new_ctx; + + if (mm->context != NO_CONTEXT && !((mm->context ^ tlb_context_cache) & CTX_VERSION_MASK)) + clear_bit(mm->context & ~(CTX_VERSION_MASK), mmu_context_bmap); + new_ctx = find_next_zero_bit(mmu_context_bmap, 1UL << CTX_VERSION_SHIFT, ctx); + if (new_ctx >= (1UL << CTX_VERSION_SHIFT)) { + new_ctx = find_next_zero_bit(mmu_context_bmap, ctx, 1); + if (new_ctx >= ctx) { + new_ctx = (tlb_context_cache & CTX_VERSION_MASK) + CTX_FIRST_VERSION; + mmu_context_bmap[0] = 3; + memset(mmu_context_bmap + sizeof(long), 0, sizeof(mmu_context_bmap) - sizeof(long)); + goto out; + } } + set_bit(new_ctx, mmu_context_bmap); + new_ctx |= (tlb_context_cache & CTX_VERSION_MASK); +out: tlb_context_cache = new_ctx; mm->context = new_ctx; - mm->cpu_vm_mask = 0; /* Callers sets it properly. */ - (*ctx)++; + mm->cpu_vm_mask = 0; } -#ifndef __SMP__ -struct pgtable_cache_struct pgt_quicklists; +#ifdef __SMP__ +spinlock_t user_page_lock = SPIN_LOCK_UNLOCKED; #endif +struct upcache user_page_cache[2] __attribute__((aligned(32))); -pgd_t *get_pgd_slow(void) -{ - pgd_t *pgd; - - pgd = (pgd_t *) __get_free_page(GFP_KERNEL); - if(pgd) - __init_pgd(pgd); - return pgd; +unsigned long get_user_page_slow(int which) +{ + unsigned long chunk; + struct upcache *up = &user_page_cache[!which]; + struct page *p; + + do { chunk = __get_free_pages(GFP_KERNEL, 1); } while(chunk==0); + p = mem_map + MAP_NR(chunk); + atomic_set(&p->count, 1); + atomic_set(&(p+1)->count, 1); + p->age = (p+1)->age = PAGE_INITIAL_AGE; + spin_lock(&user_page_lock); + if(up->count < USER_PAGE_WATER) { + struct page *new = p + !which; + new->next = up->list; + up->list = new; + up->count++; + } else + free_pages((chunk+(PAGE_SIZE*(!which))), 0); + spin_unlock(&user_page_lock); + return page_address(p + which); } +#ifndef __SMP__ +struct pgtable_cache_struct pgt_quicklists; +#endif + pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset) { pmd_t *pmd; @@ -747,7 +847,7 @@ pte_clear(ptep); } -#if NOTUSED +#ifdef NOTUSED void sparc_ultra_dump_itlb(void) { int slot; @@ -796,6 +896,7 @@ unsigned long flags; unsigned long shift = alias_base - ((unsigned long)&empty_zero_page); + set_bit(0, mmu_context_bmap); /* We assume physical memory starts at some 4mb multiple, * if this were not true we wouldn't boot up to this point * anyways. @@ -889,6 +990,7 @@ unsigned long tmp = 0, paddr, endaddr; unsigned long end = __pa(end_mem); + dvmaio_init(); for (paddr = __pa(start_mem); paddr < end; ) { for (; sp_banks[tmp].num_bytes != 0; tmp++) if (sp_banks[tmp].base_addr + sp_banks[tmp].num_bytes > paddr) @@ -911,7 +1013,7 @@ endaddr = sp_banks[tmp].base_addr + sp_banks[tmp].num_bytes; while (paddr < endaddr) { mem_map[paddr>>PAGE_SHIFT].flags &= ~(1<= 0xf0000000) + if (paddr >= dvmaiobase) mem_map[paddr>>PAGE_SHIFT].flags &= ~(1<context & 0x1fff) */ +__flush_tlb_mm: /* %o0 == (mm->context & 0x3ff) */ mov SECONDARY_CONTEXT, %g7 9: ldxa [%g7] ASI_DMMU, %g2 cmp %g2, %o0 @@ -33,7 +33,7 @@ retl wrpr %g1, 0, %pstate nop -__flush_tlb_range: /* %o0 == (mm->context & 0x1fff), %o1 == start, %o2 == end */ +__flush_tlb_range: /* %o0 == (mm->context & 0x3ff), %o1 == start, %o2 == end */ sethi %hi(8192 - 1), %g5 or %g5, %lo(8192 - 1), %g5 andn %o1, %g5, %o1 @@ -72,7 +72,7 @@ nop .align 32 -__flush_tlb_page: /* %o0 == (mm->context & 0x1fff), %o1 == page & PAGE_MASK */ +__flush_tlb_page: /* %o0 == (mm->context & 0x3ff), %o1 == page & PAGE_MASK */ mov SECONDARY_CONTEXT, %g7 ldxa [%g7] ASI_DMMU, %g2 cmp %g2, %o0 diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/prom/p1275.c linux/arch/sparc64/prom/p1275.c --- v2.1.100/linux/arch/sparc64/prom/p1275.c Sat Aug 16 09:51:09 1997 +++ linux/arch/sparc64/prom/p1275.c Fri May 8 00:11:29 1998 @@ -1,4 +1,4 @@ -/* $Id: p1275.c,v 1.12 1997/07/26 18:39:01 davem Exp $ +/* $Id: p1275.c,v 1.13 1998/04/24 15:45:35 jj Exp $ * p1275.c: Sun IEEE 1275 PROM low level interface routines * * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -24,6 +24,8 @@ char prom_buffer [3000]; } p1275buf; +extern void prom_world(int); + void prom_cif_interface (void) { __asm__ __volatile__ (" @@ -115,7 +117,11 @@ } va_end(list); + prom_world(1); + prom_cif_interface(); + + prom_world(0); attrs = fmt >> 8; va_start(list, fmt); diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/solaris/signal.h linux/arch/sparc64/solaris/signal.h --- v2.1.100/linux/arch/sparc64/solaris/signal.h Mon Jan 12 15:15:44 1998 +++ linux/arch/sparc64/solaris/signal.h Fri May 8 00:11:29 1998 @@ -1,4 +1,4 @@ -/* $Id: signal.h,v 1.2 1997/09/03 12:29:21 jj Exp $ +/* $Id: signal.h,v 1.3 1998/04/12 06:20:33 davem Exp $ * signal.h: Signal emulation for Solaris * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -106,4 +106,3 @@ #define SOLARIS_POLL_ERR 4 #define SOLARIS_POLL_PRI 5 #define SOLARIS_POLL_HUP 6 - diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/block/Config.in linux/drivers/acorn/block/Config.in --- v2.1.100/linux/drivers/acorn/block/Config.in Wed Apr 8 19:36:25 1998 +++ linux/drivers/acorn/block/Config.in Fri May 8 00:42:38 1998 @@ -2,9 +2,8 @@ # Block device driver configuration # mainmenu_option next_comment -comment 'Acorn-Specific floppy, IDE, and other block devices' +comment 'Acorn-specific block devices' -tristate 'Normal floppy disk support' CONFIG_BLK_DEV_FD bool ' Support expansion card IDE interfaces' CONFIG_BLK_DEV_IDE_CARDS if [ "$CONFIG_BLK_DEV_IDE_CARDS" = "y" ]; then dep_tristate ' ICS IDE interface support' CONFIG_BLK_DEV_IDE_ICSIDE $CONFIG_BLK_DEV_IDE diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/block/fd1772dma.S linux/drivers/acorn/block/fd1772dma.S --- v2.1.100/linux/drivers/acorn/block/fd1772dma.S Wed Dec 31 16:00:00 1969 +++ linux/drivers/acorn/block/fd1772dma.S Fri May 8 00:42:38 1998 @@ -0,0 +1,100 @@ +#include + +@ Code for DMA with the 1772 fdc +.text + + + .global _fdc1772_dataaddr +_fdc1772_fiqdata: +@ Number of bytes left to DMA + .global _fdc1772_bytestogo +_fdc1772_bytestogo: + .word 0 +@ Place to put/get data from in DMA + .global _fdc1772_dataaddr +_fdc1772_dataaddr: + .word 0 + + .global _fdc1772_fdc_int_done +_fdc1772_fdc_int_done: + .word 0 + .global _fdc1772_comendstatus +_fdc1772_comendstatus: + .word 0 + +@ We hang this off DMA channel 1 + .global _fdc1772_comendhandler +_fdc1772_comendhandler: + mov r8,#IOC_BASE + ldrb r9,[r8,#0x34] @ IOC FIQ status + tst r9,#2 + subeqs pc,r14,#4 @ should I leave a space here + orr r9,r8,#0x10000 @ FDC base + adr r8,_fdc1772_fdc_int_done + ldrb r10,[r9,#0] @ FDC status + mov r9,#1 @ Got a FIQ flag + stmia r8,{r9,r10} + subs pc,r14,#4 + + + .global _fdc1772_dma_read +_fdc1772_dma_read: + mov r8,#IOC_BASE + ldrb r9,[r8,#0x34] @ IOC FIQ status + tst r9,#1 + beq _fdc1772_dma_read_notours + orr r8,r8,#0x10000 @ FDC base + ldrb r10,[r8,#0xc] @ Read from FDC data reg (also clears interrupt) + ldmia r11,{r8,r9} + subs r8,r8,#1 @ One less byte to go + @ If there was somewhere for this data to go then store it and update pointers + strplb r10,[r9],#1 @ Store the data and increment the pointer + stmplia r11,{r8,r9} @ Update count/pointers + @ Handle any other interrupts if there are any +_fdc1772_dma_read_notours: + @ Cant branch because this code has been copied down to the FIQ vector + ldr pc,[pc,#-4] + .word _fdc1772_comendhandler + .global _fdc1772_dma_read_end +_fdc1772_dma_read_end: + + .global _fdc1772_dma_write +_fdc1772_dma_write: + mov r8,#IOC_BASE + ldrb r9,[r8,#0x34] @ IOC FIQ status + tst r9,#1 + beq _fdc1772_dma_write_notours + orr r8,r8,#0x10000 @ FDC base + ldmia r11,{r9,r10} + subs r9,r9,#1 @ One less byte to go + @ If there really is some data then get it, store it and update count + ldrplb r12,[r10],#1 + strplb r12,[r8,#0xc] @ write it to FDC data reg + stmplia r11,{r9,r10} @ Update count and pointer - should clear interrupt + @ Handle any other interrupts +_fdc1772_dma_write_notours: + @ Cant branch because this code has been copied down to the FIQ vector + ldr pc,[pc,#-4] + .word _fdc1772_comendhandler + + .global _fdc1772_dma_write_end +_fdc1772_dma_write_end: + + +@ Setup the FIQ R11 to point to the data and store the count, address +@ for this dma +@ R0=count +@ R1=address + .global _fdc1772_setupdma +_fdc1772_setupdma: + @ The big job is flipping in and out of FIQ mode + adr r2,_fdc1772_fiqdata @ This is what we really came here for + stmia r2,{r0,r1} + mov r3, pc + teqp pc,#0x0c000001 @ Disable FIQs, IRQs and switch to FIQ mode + mov r0,r0 @ NOP + mov r11,r2 + teqp r3,#0 @ Normal mode + mov r0,r0 @ NOP + mov pc,r14 + diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/block/ide-rapide.c linux/drivers/acorn/block/ide-rapide.c --- v2.1.100/linux/drivers/acorn/block/ide-rapide.c Mon Feb 23 18:12:03 1998 +++ linux/drivers/acorn/block/ide-rapide.c Fri May 8 00:42:38 1998 @@ -1,10 +1,11 @@ /* - * linux/arch/arm/drivers/block/ide-ics.c + * linux/arch/arm/drivers/block/ide-rapide.c * - * Copyright (c) 1996 Russell King. + * Copyright (c) 1996-1998 Russell King. * * Changelog: * 08-06-1996 RMK Created + * 13-04-1998 RMK Added manufacturer and product IDs */ #include @@ -16,38 +17,39 @@ #include "../../block/ide.h" static const card_ids rapide_cids[] = { + { MANU_YELLOWSTONE, PROD_YELLOWSTONE_RAPIDE32 }, { 0xffff, 0xffff } }; static struct expansion_card *ec[MAX_ECARDS]; static int result[MAX_ECARDS]; -static inline int rapide_register (struct expansion_card *ec) +static inline int rapide_register(struct expansion_card *ec) { unsigned long port = ecard_address (ec, ECARD_MEMC, 0); - return ide_register_port (port, port + 0x206, 4, ec->irq); + return ide_register_port(port, port + 0x206, 4, ec->irq); } -int rapide_init (void) +int rapide_init(void) { int i; for (i = 0; i < MAX_ECARDS; i++) ec[i] = NULL; - ecard_startfind (); + ecard_startfind(); for (i = 0; ; i++) { - if ((ec[i] = ecard_find (0, rapide_cids)) == NULL) + if ((ec[i] = ecard_find(0, rapide_cids)) == NULL) break; - ecard_claim (ec[i]); - result[i] = rapide_register (ec[i]); + ecard_claim(ec[i]); + result[i] = rapide_register(ec[i]); } for (i = 0; i < MAX_ECARDS; i++) if (ec[i] && result[i] < 0) { - ecard_release (ec[i]); + ecard_release(ec[i]); ec[i] = NULL; } return 0; @@ -67,10 +69,10 @@ for (i = 0; i < MAX_ECARDS; i++) if (ec[i]) { unsigned long port; - port = ecard_address (ec[i], ECARD_MEMC, 0); + port = ecard_address(ec[i], ECARD_MEMC, 0); - ide_unregister_port (port, ec[i]->irq, 16); - ecard_release (ec[i]); + ide_unregister_port(port, ec[i]->irq, 16); + ecard_release(ec[i]); ec[i] = NULL; } } diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/block/mfm.S linux/drivers/acorn/block/mfm.S --- v2.1.100/linux/drivers/acorn/block/mfm.S Wed Dec 31 16:00:00 1969 +++ linux/drivers/acorn/block/mfm.S Fri May 8 00:42:38 1998 @@ -0,0 +1,163 @@ +@ Read/Write DMA code for the ST506/MFM hard drive controllers on the A400 +@ motherboard on ST506 podules. +@ (c) David Alan Gilbert (gilbertd@cs.man.ac.uk) 1996 + +#include + +_hdc63463_irqdata: +@ Controller base address + .global _hdc63463_baseaddress +_hdc63463_baseaddress: + .word 0 + + .global _hdc63463_irqpolladdress +_hdc63463_irqpolladdress: + .word 0 + + .global _hdc63463_irqpollmask +_hdc63463_irqpollmask: + .word 0 + +@ where to read/write data from the kernel data space + .global _hdc63463_dataptr +_hdc63463_dataptr: + .word 0 + +@ Number of bytes left to transfer + .global _hdc63463_dataleft +_hdc63463_dataleft: + .word 0 + +@ ------------------------------------------------------------------------- +@ hdc63463_writedma: DMA from host to controller +@ internal reg usage: r0=hdc base address, r1=irq poll address, r2=poll mask +@ r3=data ptr, r4=data left, r5,r6=temporary + .global _hdc63463_writedma +_hdc63463_writedma: + stmfd sp!,{r4-r7} + adr r5,_hdc63463_irqdata + ldmia r5,{r0,r1,r2,r3,r4} + + +writedma_again: + + @ test number of remaining bytes to transfer + cmp r4,#0 + beq writedma_end + bmi writedma_end + + @ Check the hdc is interrupting + ldrb r5,[r1,#0] + tst r5,r2 + beq writedma_end + + @ Transfer a block of upto 256 bytes + cmp r4,#256 + movlt r7,r4 + movge r7,#256 + + @ Check the hdc is still busy and command has not ended and no errors + ldr r5,[r0,#32] @ Status reg - 16 bit - its the top few bits which are status + @ think we should continue DMA until it drops busy - perhaps this was + @ the main problem with corrected errors causing a hang + @tst r5,#0x3c00 @ Test for things which should be off + @bne writedma_end + and r5,r5,#0x8000 @ This is test for things which should be on: Busy + cmp r5,#0x8000 + bne writedma_end + + @ Bytes remaining at end + sub r4,r4,r7 + + @ HDC Write register location + add r0,r0,#32+8 + +writedma_loop: + @ OK - pretty sure we should be doing this + + ldr r5,[r3],#4 @ Get a word to be written + @ get bottom half to be sent first + mov r6,r5,lsl#16 @ Separate the first 2 bytes + orr r2,r6,r6,lsr #16 @ Duplicate them in the bottom half of the word + @ now the top half + mov r6,r5,lsr#16 @ Get 2nd 2 bytes + orr r6,r6,r6,lsl#16 @ Duplicate + @str r6,[r0] @ to hdc + stmia r0,{r2,r6} + subs r7,r7,#4 @ Dec. number of bytes left + bne writedma_loop + + @ If we were too slow we had better go through again - DAG - took out with new interrupt routine + @ sub r0,r0,#32+8 + @ adr r2,_hdc63463_irqdata + @ ldr r2,[r2,#8] + @ b writedma_again + +writedma_end: + adr r5,_hdc63463_irqdata+12 + stmia r5,{r3,r4} + ldmfd sp!,{r4-r7} + RETINSTR(mov,pc,lr) + +@ ------------------------------------------------------------------------- +@ hdc63463_readdma: DMA from controller to host +@ internal reg usage: r0=hdc base address, r1=irq poll address, r2=poll mask +@ r3=data ptr, r4=data left, r5,r6=temporary + .global _hdc63463_readdma +_hdc63463_readdma: + stmfd sp!,{r4-r7} + adr r5,_hdc63463_irqdata + ldmia r5,{r0,r1,r2,r3,r4} + +readdma_again: + @ test number of remaining bytes to transfer + cmp r4,#0 + beq readdma_end + bmi readdma_end + + @ Check the hdc is interrupting + ldrb r5,[r1,#0] + tst r5,r2 + beq readdma_end + + @ Check the hdc is still busy and command has not ended and no errors + ldr r5,[r0,#32] @ Status reg - 16 bit - its the top few bits which are status + @ think we should continue DMA until it drops busy - perhaps this was + @ the main problem with corrected errors causing a hang + @tst r5,#0x3c00 @ Test for things which should be off + @bne readdma_end + and r5,r5,#0x8000 @ This is test for things which should be on: Busy + cmp r5,#0x8000 + bne readdma_end + + @ Transfer a block of upto 256 bytes + cmp r4,#256 + movlt r7,r4 + movge r7,#256 + + @ Bytes remaining at end + sub r4,r4,r7 + + @ Set a pointer to the data register in the HDC + add r0,r0,#8 +readdma_loop: + @ OK - pretty sure we should be doing this + ldmia r0,{r5,r6} + mov r5,r5,lsl#16 + mov r6,r6,lsl#16 + orr r6,r6,r5,lsr #16 + str r6,[r3],#4 + subs r7,r7,#4 @ Decrement bytes to go + bne readdma_loop + + @ Try reading multiple blocks - if this was fast enough then I dont think + @ this should help - NO taken out DAG - new interrupt handler has + @ non-consecutive memory blocks + @ sub r0,r0,#8 + @ b readdma_again + +readdma_end: + adr r5,_hdc63463_irqdata+12 + stmia r5,{r3,r4} + ldmfd sp!,{r4-r7} + RETINSTR(mov,pc,lr) diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/char/Config.in linux/drivers/acorn/char/Config.in --- v2.1.100/linux/drivers/acorn/char/Config.in Wed Dec 31 16:00:00 1969 +++ linux/drivers/acorn/char/Config.in Fri May 8 00:42:38 1998 @@ -0,0 +1,4 @@ +if [ "$CONFIG_SERIAL" != "n" ]; then + tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL + tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL +fi diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/char/Makefile linux/drivers/acorn/char/Makefile --- v2.1.100/linux/drivers/acorn/char/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/acorn/char/Makefile Fri May 8 00:42:38 1998 @@ -0,0 +1,32 @@ +# +# Makefile for the kernel character device drivers. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now inherited from the +# parent makes.. +# + +L_TARGET := acorn-char.a +M_OBJS := +L_OBJS := + +ifeq ($(CONFIG_ATOMWIDE_SERIAL),y) + L_OBJS += serial-atomwide.o +else + ifeq ($(CONFIG_ATOMWIDE_SERIAL),m) + M_OBJS += serial-atomwide.o + endif +endif + +ifeq ($(CONFIG_DUALSP_SERIAL),y) + L_OBJS += serial-dualsp.o +else + ifeq ($(CONFIG_DUALSP_SERIAL),m) + M_OBJS += serial-dualsp.o + endif +endif + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/char/serial-atomwide.c linux/drivers/acorn/char/serial-atomwide.c --- v2.1.100/linux/drivers/acorn/char/serial-atomwide.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acorn/char/serial-atomwide.c Fri May 8 00:42:38 1998 @@ -0,0 +1,20 @@ +/* + * linux/arch/arm/drivers/char/serial-atomwide.c + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 02-05-1996 RMK Created + * 07-05-1996 RMK Altered for greater number of cards. + * 30-07-1996 RMK Now uses generic card code. + */ + +#define MY_CARD_LIST { MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL } +#define MY_NUMPORTS 3 +#define MY_BAUD_BASE (7372800 / 16) +#define MY_INIT atomwide_serial_init +#define MY_BASE_ADDRESS(ec) \ + ecard_address ((ec), ECARD_IOC, ECARD_SLOW) + (0x2000 >> 2) +#define MY_PORT_ADDRESS(port,cardaddr) \ + ((cardaddr) + 0x200 - (port) * 0x100) +#include "serial-card.c" diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/char/serial-card.c linux/drivers/acorn/char/serial-card.c --- v2.1.100/linux/drivers/acorn/char/serial-card.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acorn/char/serial-card.c Fri May 8 00:42:38 1998 @@ -0,0 +1,106 @@ +/* + * linux/arch/arm/drivers/char/serial-module.c + * + * Copyright (c) 1996 Russell King. + * + * A generic handler of serial expansion cards that use 16550s or + * the like. + * + * Definitions: + * MY_PRODS Product numbers to identify this card by + * MY_MANUS Manufacturer numbers to identify this card by + * MY_NUMPORTS Number of ports per card + * MY_BAUD_BASE Baud base for the card + * MY_INIT Initialisation routine name + * MY_BASE_ADDRESS(ec) Return base address for ports + * MY_PORT_ADDRESS + * (port,cardaddr) Return address for port using base address + * from above. + * + * Changelog: + * 30-07-1996 RMK Created + * 22-04-1998 RMK Removed old register_pre_init_serial + */ +#include +#include +#include +#include + +#ifndef NUM_SERIALS +#define NUM_SERIALS MY_NUMPORTS * MAX_ECARDS +#endif + +#ifdef MODULE +static int __serial_ports[NUM_SERIALS]; +static int __serial_pcount; +static struct expansion_card *expcard[MAX_ECARDS]; +#define ADD_ECARD(ec,card) expcard[(card)] = (ec) +#define ADD_PORT(port) __serial_ports[__serial_pcount++] = (port) +#undef MY_INIT +#define MY_INIT init_module +#else +#define ADD_ECARD(ec,card) +#define ADD_PORT(port) +#endif + +static const card_ids serial_cids[] = { MY_CARD_LIST, { 0xffff, 0xffff } }; + +static inline int serial_register_onedev (unsigned long port, int irq) +{ + struct serial_struct req; + + req.baud_base = MY_BAUD_BASE; + req.irq = irq; + req.port = port; + + return register_serial(&req); +} + +int MY_INIT (void) +{ + int card = 0; + + ecard_startfind (); + + do { + struct expansion_card *ec; + unsigned long cardaddr; + int port; + + ec = ecard_find (0, serial_cids); + if (!ec) + break; + + cardaddr = MY_BASE_ADDRESS(ec); + + for (port = 0; port < MY_NUMPORTS; port ++) { + int line; + + line = serial_register_onedev (MY_PORT_ADDRESS(port, cardaddr), ec->irq); + if (line < 0) + break; + ADD_PORT(line); + } + + if (port) { + ecard_claim (ec); + ADD_ECARD(ec, card); + } else + break; + } while (++card < MAX_ECARDS); + return card ? 0 : -ENODEV; +} + +#ifdef MODULE +void cleanup_module (void) +{ + int i; + + for (i = 0; i < __serial_pcount; i++) + unregister_serial (__serial_ports[i]); + + for (i = 0; i < MAX_ECARDS; i++) + if (expcard[i]) + ecard_release (expcard[i]); +} +#endif diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/char/serial-dualsp.c linux/drivers/acorn/char/serial-dualsp.c --- v2.1.100/linux/drivers/acorn/char/serial-dualsp.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acorn/char/serial-dualsp.c Fri May 8 00:42:38 1998 @@ -0,0 +1,18 @@ +/* + * linux/arch/arm/drivers/char/serial-dualsp.c + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 30-07-1996 RMK Created + */ +#define MY_CARD_LIST { MANU_SERPORT, PROD_SERPORT_DSPORT } +#define MY_NUMPORTS 2 +#define MY_BAUD_BASE (3686400 / 16) +#define MY_INIT dualsp_serial_init +#define MY_BASE_ADDRESS(ec) \ + ecard_address (ec, ECARD_IOC, ECARD_SLOW) + (0x2000 >> 2) +#define MY_PORT_ADDRESS(port,cardaddress) \ + ((cardaddress) + (port) * 8) +#include "serial-card.c" + diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/net/ether3.c linux/drivers/acorn/net/ether3.c --- v2.1.100/linux/drivers/acorn/net/ether3.c Wed Apr 8 19:36:25 1998 +++ linux/drivers/acorn/net/ether3.c Fri May 8 00:42:38 1998 @@ -340,6 +340,23 @@ outw(priv->regs.command | CMD_RXON, REG_COMMAND); } +static inline int +ether3_probe_bus_8(struct device *dev, int val) +{ + outb(val & 255, REG_RECVPTR); + outb(val >> 8, REG_RECVPTR + 1); + + return inb(REG_RECVPTR) == (val & 255) && inb(REG_RECVPTR + 1) == (val >> 8); +} + +static inline int +ether3_probe_bus_16(struct device *dev, int val) +{ + outw(val, REG_RECVPTR); + + return inw(REG_RECVPTR) == val; +} + /* * This is the real probe routine. */ @@ -373,15 +390,14 @@ /* Test using Receive Pointer (16-bit register) to find out * how the ether3 is connected to the bus... */ - outb(0, REG_RECVPTR); - outb(1, REG_RECVPTR + 1); - - if (inb(REG_RECVPTR + 1) == 1) { - if (inb(REG_RECVPTR) == 0) - bus_type = BUS_8; - else if (inw(REG_RECVPTR) == 0x101) - bus_type = BUS_16; - } + if (ether3_probe_bus_8(dev, 0x100) && + ether3_probe_bus_8(dev, 0x201)) + bus_type = BUS_8; + + if (bus_type == BUS_UNKNOWN && + ether3_probe_bus_16(dev, 0x101) && + ether3_probe_bus_16(dev, 0x201)) + bus_type = BUS_16; switch (bus_type) { case BUS_UNKNOWN: diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/net/etherh.c linux/drivers/acorn/net/etherh.c --- v2.1.100/linux/drivers/acorn/net/etherh.c Wed Apr 8 19:36:25 1998 +++ linux/drivers/acorn/net/etherh.c Fri May 8 00:42:38 1998 @@ -4,12 +4,15 @@ * NS8390 ANT etherh specific driver * For Acorn machines * + * Thanks to I-Cubed for information on their cards. + * * By Russell King. * * Changelog: - * 08-Dec-1996 RMK 1.00 Created + * 08-12-1996 RMK 1.00 Created * RMK 1.03 Added support for EtherLan500 cards - * 23-Nov-1997 RMK 1.04 Added media autodetection + * 23-11-1997 RMK 1.04 Added media autodetection + * 16-04-1998 RMK 1.05 Improved media autodetection * * Insmod Module Parameters * ------------------------ @@ -54,7 +57,7 @@ { 0xffff, 0xffff } }; -static char *version = "etherh [500/600/600A] ethernet driver (c) 1997 R.M.King v1.04\n"; +static char *version = "etherh [500/600/600A] ethernet driver (c) 1998 R.M.King v1.05\n"; #define ETHERH500_DATAPORT 0x200 /* MEMC */ #define ETHERH500_NS8390 0x000 /* MEMC */ @@ -66,6 +69,7 @@ #define ETHERH_CP_IE 1 #define ETHERH_CP_IF 2 +#define ETHERH_CP_HEARTBEAT 2 #define ETHERH_TX_START_PAGE 1 #define ETHERH_STOP_PAGE 0x7f @@ -77,7 +81,7 @@ * This is an ascii string... */ static int -etherh_addr (char *addr, struct expansion_card *ec) +etherh_addr(char *addr, struct expansion_card *ec) { struct in_chunk_dir cd; char *s; @@ -95,19 +99,80 @@ return ENODEV; } +static void +etherh_setif(struct device *dev) +{ + unsigned long addr; + unsigned long flags; + + save_flags_cli(flags); + + /* set the interface type */ + switch (dev->mem_end) { + case PROD_I3_ETHERLAN600: + case PROD_I3_ETHERLAN600A: + addr = dev->base_addr + EN0_RCNTHI; + + if (ei_status.interface_num) /* 10b2 */ + outb((inb(addr) & 0xf8) | 1, addr); + else /* 10bT */ + outb((inb(addr) & 0xf8), addr); + break; + + case PROD_I3_ETHERLAN500: + addr = dev->rmem_start; + + if (ei_status.interface_num) /* 10b2 */ + outb(inb(addr) & ~ETHERH_CP_IF, addr); + else /* 10bT */ + outb(inb(addr) | ETHERH_CP_IF, addr); + break; + + default: + break; + } + + restore_flags(flags); +} + +static int +etherh_getifstat(struct device *dev) +{ + int stat; + + switch (dev->mem_end) { + case PROD_I3_ETHERLAN600: + case PROD_I3_ETHERLAN600A: + if (ei_status.interface_num) /* 10b2 */ + stat = 1; + else /* 10bT */ + stat = inb(dev->base_addr+EN0_RCNTHI) & 4; + break; + + case PROD_I3_ETHERLAN500: + if (ei_status.interface_num) /* 10b2 */ + stat = 1; + else /* 10bT */ + stat = inb(dev->rmem_start) & ETHERH_CP_HEARTBEAT; + break; + + default: + stat = 0; + break; + } + + return stat != 0; +} + /* * Reset the 8390 (hard reset) */ static void -etherh_reset (struct device *dev) +etherh_reset(struct device *dev) { - unsigned int addr = dev->base_addr; - int crb; + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, dev->base_addr); - if (dev->mem_end == PROD_I3_ETHERLAN600 || dev->mem_end == PROD_I3_ETHERLAN600A) { - crb = inb (addr + EN0_RCNTHI) & 0xf8; - outb (ei_status.interface_num ? crb | 1: crb, addr+EN0_RCNTHI); - } + etherh_setif(dev); } /* @@ -262,9 +327,6 @@ static int etherh_open(struct device *dev) { - unsigned int addr = dev->base_addr; - int crb; - MOD_INC_USE_COUNT; if (request_irq(dev->irq, ei_interrupt, 0, "etherh", dev)) { @@ -272,12 +334,8 @@ return -EAGAIN; } - if (dev->mem_end == PROD_I3_ETHERLAN600 || dev->mem_end == PROD_I3_ETHERLAN600A) { - crb = inb (addr + EN0_RCNTHI) & 0xf8; - outb (ei_status.interface_num ? crb | 1: crb, addr+EN0_RCNTHI); - } - - ei_open (dev); + etherh_reset(dev); + ei_open(dev); return 0; } @@ -302,7 +360,8 @@ { static int version_printed; unsigned int addr, i, reg0, tmp; - char *dev_type; + const char *dev_type; + const char *if_type; addr = dev->base_addr; @@ -352,11 +411,10 @@ dev->name, dev_type, dev->base_addr, dev->irq); for (i = 0; i < 6; i++) - printk (i == 5 ? "%2.2x\n" : "%2.2x:", dev->dev_addr[i]); + printk (i == 5 ? "%2.2x " : "%2.2x:", dev->dev_addr[i]); ei_status.name = "etherh"; ei_status.word16 = 1; - ei_status.interface_num = dev->if_port & 1; ei_status.tx_start_page = ETHERH_TX_START_PAGE; ei_status.rx_start_page = ei_status.tx_start_page + TX_PAGES; ei_status.stop_page = ETHERH_STOP_PAGE; @@ -367,20 +425,36 @@ dev->open = etherh_open; dev->stop = etherh_close; + /* select 10bT */ + ei_status.interface_num = 0; + if_type = "10BaseT"; + etherh_setif(dev); + udelay(1000); + if (!etherh_getifstat(dev)) { + if_type = "10Base2"; + ei_status.interface_num = 1; + etherh_setif(dev); + } + if (!etherh_getifstat(dev)) + if_type = "UNKNOWN"; + + printk("%s\n", if_type); + + etherh_reset(dev); NS8390_init (dev, 0); return 0; } -static void etherh_irq_enable (ecard_t *ec, int irqnr) +static void etherh_irq_enable(ecard_t *ec, int irqnr) { unsigned int ctrl_addr = (unsigned int)ec->irq_data; - outb (inb (ctrl_addr) | ETHERH_CP_IE, ctrl_addr); + outb(inb(ctrl_addr) | ETHERH_CP_IE, ctrl_addr); } -static void etherh_irq_disable (ecard_t *ec, int irqnr) +static void etherh_irq_disable(ecard_t *ec, int irqnr) { unsigned int ctrl_addr = (unsigned int)ec->irq_data; - outb (inb (ctrl_addr) & ~ETHERH_CP_IE, ctrl_addr); + outb(inb(ctrl_addr) & ~ETHERH_CP_IE, ctrl_addr); } static expansioncard_ops_t etherh_ops = { @@ -401,6 +475,7 @@ case PROD_I3_ETHERLAN500: dev->base_addr = ecard_address (ec, ECARD_MEMC, 0) + ETHERH500_NS8390; dev->mem_start = dev->base_addr + ETHERH500_DATAPORT; + dev->rmem_start = (unsigned long) ec->irq_data = (void *)ecard_address (ec, ECARD_IOC, ECARD_FAST) + ETHERH500_CTRLPORT; break; @@ -446,7 +521,6 @@ static int io[MAX_ETHERH_CARDS]; static int irq[MAX_ETHERH_CARDS]; -static int xcvr[MAX_ETHERH_CARDS] = { 1, 1 }; static char ethernames[MAX_ETHERH_CARDS][9]; static struct device *my_ethers[MAX_ETHERH_CARDS]; static struct expansion_card *ec[MAX_ETHERH_CARDS]; @@ -490,7 +564,6 @@ dev->init = etherh_probe1; dev->name = ethernames[i]; - dev->if_port = xcvr[i]; my_ethers[i] = dev; diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/Config.in linux/drivers/acorn/scsi/Config.in --- v2.1.100/linux/drivers/acorn/scsi/Config.in Mon Feb 23 18:12:03 1998 +++ linux/drivers/acorn/scsi/Config.in Fri May 8 00:42:39 1998 @@ -8,6 +8,7 @@ fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then dep_tristate 'CumanaSCSI II support (Experimental)' CONFIG_SCSI_CUMANA_2 $CONFIG_SCSI + dep_tristate 'EESOX support (Experimental)' CONFIG_SCSI_EESOXSCSI $CONFIG_SCSI dep_tristate 'PowerTec support (Experimental)' CONFIG_SCSI_POWERTECSCSI $CONFIG_SCSI comment 'The following drives are not fully supported' diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/Makefile linux/drivers/acorn/scsi/Makefile --- v2.1.100/linux/drivers/acorn/scsi/Makefile Mon Feb 23 18:12:03 1998 +++ linux/drivers/acorn/scsi/Makefile Fri May 8 00:42:39 1998 @@ -72,6 +72,18 @@ endif endif +ifeq ($(CONFIG_SCSI_EESOXSCSI),y) + L_OBJS += eesox.o + CONFIG_QUEUE_BUILTIN=y + CONFIG_FAS216_BUILTIN=y +else + ifeq ($(CONFIG_SCSI_EESOXSCSI),m) + M_OBJS += eesox.o + CONFIG_QUEUE_MODULE=y + CONFIG_FAS216_MODULE=y + endif +endif + ifeq ($(CONFIG_QUEUE_BUILTIN),y) LX_OBJS += queue.o msgqueue.o else diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/acornscsi.c linux/drivers/acorn/scsi/acornscsi.c --- v2.1.100/linux/drivers/acorn/scsi/acornscsi.c Mon Feb 23 18:12:03 1998 +++ linux/drivers/acorn/scsi/acornscsi.c Fri May 8 00:42:39 1998 @@ -2726,7 +2726,7 @@ p = string; - p += sprintf (string, "%s at port %X irq %d v%d.%d.%d" + p += sprintf (string, "%s at port %lX irq %d v%d.%d.%d" #ifdef CONFIG_SCSI_ACORNSCSI_SYNC " SYNC" #endif @@ -2784,12 +2784,12 @@ host->dma.io_port, host->scsi.irq); #endif - p += sprintf (p, "Statistics:\n", - "Queued commands: %-10d Issued commands: %-10d\n" - "Done commands : %-10d Reads : %-10d\n" - "Writes : %-10d Others : %-10d\n" - "Disconnects : %-10d Aborts : %-10d\n" - "Resets : %-10d\n\nLast phases:", + p += sprintf (p, "Statistics:\n" + "Queued commands: %-10u Issued commands: %-10u\n" + "Done commands : %-10u Reads : %-10u\n" + "Writes : %-10u Others : %-10u\n" + "Disconnects : %-10u Aborts : %-10u\n" + "Resets : %-10u\n\nLast phases:", host->stats.queues, host->stats.removes, host->stats.fins, host->stats.reads, host->stats.writes, host->stats.miscs, diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/cumana_1.c linux/drivers/acorn/scsi/cumana_1.c --- v2.1.100/linux/drivers/acorn/scsi/cumana_1.c Wed Apr 8 19:36:25 1998 +++ linux/drivers/acorn/scsi/cumana_1.c Fri May 8 00:42:39 1998 @@ -34,6 +34,11 @@ /* * $Log: cumana_1.c,v $ + * Revision 1.3 1998/05/03 20:45:32 alan + * ARM SCSI update. This adds the eesox driver and massively updates the + * Cumana driver. The folks who bought cumana arent anal retentive all + * docs are secret weenies so now there are docs .. + * * Revision 1.2 1998/03/08 05:49:46 davem * Merge to 2.1.89 * @@ -134,7 +139,7 @@ printk("scsi%d: please jumper the board for a free IRQ.\n", instance->host_no); } - printk("scsi%d: at port %X irq", instance->host_no, instance->io_port); + printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port); if (instance->irq == IRQ_NONE) printk ("s disabled"); else diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/cumana_2.c linux/drivers/acorn/scsi/cumana_2.c --- v2.1.100/linux/drivers/acorn/scsi/cumana_2.c Wed Apr 8 19:36:25 1998 +++ linux/drivers/acorn/scsi/cumana_2.c Fri May 8 00:42:39 1998 @@ -1,15 +1,13 @@ /* * linux/arch/arm/drivers/scsi/cumana_2.c * - * Copyright (C) 1997,1998 Russell King - * - * This driver is based on experimentation. Hence, it may have made - * assumptions about the particular card that I have available, and - * may not be reliable! + * Copyright (C) 1997-1998 Russell King * * Changelog: * 30-08-1997 RMK 0.0.0 Created, READONLY version * 22-01-1998 RMK 0.0.1 Updated to 2.1.80 + * 15-04-1998 RMK 0.0.1 Only do PIO if FAS216 will allow it. + * 02-05-1998 RMK 0.0.2 Updated & added DMA support */ #include @@ -23,352 +21,556 @@ #include #include +#include +#include #include #include -#include +#include #include "../../scsi/sd.h" #include "../../scsi/hosts.h" #include "cumana_2.h" -#include "fas216.h" - -/* Hmm - this should go somewhere else */ -#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE) /* Configuration */ -#define XTALFREQ 40 -#define INT_POLARITY CTRL_INT_HIGH +#define CUMANASCSI2_XTALFREQ 40 +#define CUMANASCSI2_ASYNC_PERIOD 200 +#define CUMANASCSI2_SYNC_DEPTH 8 /* * List of devices that the driver will recognise */ -#define CUMANASCSI2_LIST { MANU_CUMANA, PROD_CUMANA_SCSI_2 } +#define CUMANASCSI2_LIST { MANU_CUMANA, PROD_CUMANA_SCSI_2 } + +#define CUMANASCSI2_STATUS (0) +#define STATUS_INT (1 << 0) +#define STATUS_DRQ (1 << 1) +#define STATUS_LATCHED (1 << 3) + +#define CUMANASCSI2_ALATCH (5) +#define ALATCH_ENA_INT (3) +#define ALATCH_DIS_INT (2) +#define ALATCH_ENA_TERM (5) +#define ALATCH_DIS_TERM (4) +#define ALATCH_ENA_BIT32 (11) +#define ALATCH_DIS_BIT32 (10) +#define ALATCH_ENA_DMA (13) +#define ALATCH_DIS_DMA (12) +#define ALATCH_DMA_OUT (15) +#define ALATCH_DMA_IN (14) + +#define CUMANASCSI2_PSEUDODMA (0x80) + +#define CUMANASCSI2_FAS216_OFFSET (0xc0) +#define CUMANASCSI2_FAS216_SHIFT 0 /* * Version */ #define VER_MAJOR 0 #define VER_MINOR 0 -#define VER_PATCH 1 +#define VER_PATCH 2 static struct expansion_card *ecs[MAX_ECARDS]; +/* + * Use term=0,1,0,0,0 to turn terminators on/off + */ +int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 }; + static struct proc_dir_entry proc_scsi_cumanascsi_2 = { PROC_SCSI_QLOGICFAS, 6, "cumanascs2", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; -/* - * Function: void cumanascsi_2_intr (int irq, void *dev_id, struct pt_regs *regs) - * Purpose : handle interrupts from Cumana SCSI 2 card - * Params : irq - interrupt number - * dev_id - user-defined (Scsi_Host structure) - * regs - processor registers at interrupt +/* Prototype: void cumanascsi_2_irqenable(ec, irqnr) + * Purpose : Enable interrupts on Cumana SCSI 2 card + * Params : ec - expansion card structure + * : irqnr - interrupt number */ -static void cumanascsi_2_intr (int irq, void *dev_id, struct pt_regs *regs) +static void +cumanascsi_2_irqenable(struct expansion_card *ec, int irqnr) { - struct Scsi_Host *instance = (struct Scsi_Host *)dev_id; + unsigned int port = (unsigned int)ec->irq_data; + outb(ALATCH_ENA_INT, port); +} - fas216_intr (instance); +/* Prototype: void cumanascsi_2_irqdisable(ec, irqnr) + * Purpose : Disable interrupts on Cumana SCSI 2 card + * Params : ec - expansion card structure + * : irqnr - interrupt number + */ +static void +cumanascsi_2_irqdisable(struct expansion_card *ec, int irqnr) +{ + unsigned int port = (unsigned int)ec->irq_data; + outb(ALATCH_DIS_INT, port); } -/* - * Function: int cumanascsi_2_dma_setup (instance, SCpnt, direction) - * Purpose : initialises DMA/PIO - * Params : instance - host - * SCpnt - command - * direction - DMA on to/off of card - * Returns : 0 if we should not set CMD_WITHDMA for transfer info command - */ -static fasdmatype_t cumanascsi_2_dma_setup (struct Scsi_Host *instance, Scsi_Pointer *SCp, fasdmadir_t direction) -{ - /* - * We don't do DMA - */ - return fasdma_pseudo; +static const expansioncard_ops_t cumanascsi_2_ops = { + cumanascsi_2_irqenable, + cumanascsi_2_irqdisable, + NULL, + NULL +}; + +/* Prototype: void cumanascsi_2_terminator_ctl(host, on_off) + * Purpose : Turn the Cumana SCSI 2 terminators on or off + * Params : host - card to turn on/off + * : on_off - !0 to turn on, 0 to turn off + */ +static void +cumanascsi_2_terminator_ctl(struct Scsi_Host *host, int on_off) +{ + CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata; + + if (on_off) { + info->terms = 1; + outb (ALATCH_ENA_TERM, info->alatch); + } else { + info->terms = 0; + outb (ALATCH_DIS_TERM, info->alatch); + } } -/* - * Function: int cumanascsi_2_dma_pseudo (instance, SCpnt, direction, transfer) - * Purpose : handles pseudo DMA - * Params : instance - host - * SCpnt - command - * direction - DMA on to/off of card - * transfer - minimum number of bytes we expect to transfer - * Returns : bytes transfered +/* Prototype: void cumanascsi_2_intr(irq, *dev_id, *regs) + * Purpose : handle interrupts from Cumana SCSI 2 card + * Params : irq - interrupt number + * dev_id - user-defined (Scsi_Host structure) + * regs - processor registers at interrupt */ -static int -cumanascsi_2_dma_pseudo (struct Scsi_Host *instance, Scsi_Pointer *SCp, - fasdmadir_t direction, int transfer) +static void +cumanascsi_2_intr(int irq, void *dev_id, struct pt_regs *regs) { - CumanaScsi2_Info *info = (CumanaScsi2_Info *)instance->hostdata; - unsigned int length; - unsigned char *addr; + struct Scsi_Host *host = (struct Scsi_Host *)dev_id; - length = SCp->this_residual; - addr = SCp->ptr; + fas216_intr(host); +} - if (direction == DMA_OUT) -#if 0 - while (length > 1) { - unsigned long word; +static void +cumanascsi_2_invalidate(char *addr, long len, fasdmadir_t direction) +{ + unsigned int page; + if (direction == DMA_OUT) { + for (page = (unsigned int) addr; len > 0; + page += PAGE_SIZE, len -= PAGE_SIZE) + flush_page_to_ram(page); + } else + flush_cache_range(current->mm, (unsigned long)addr, + (unsigned long)addr + len); +} - if (inb (REG_STAT(&info->info)) & STAT_INT) - goto end; +/* Prototype: fasdmatype_t cumanascsi_2_dma_setup(host, SCpnt, direction, min_type) + * Purpose : initialises DMA/PIO + * Params : host - host + * SCpnt - command + * direction - DMA on to/off of card + * min_type - minimum DMA support that we must have for this transfer + * Returns : type of transfer to be performed + */ +static fasdmatype_t +cumanascsi_2_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp, + fasdmadir_t direction, fasdmatype_t min_type) +{ + CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata; + int dmach = host->dma_channel; - if (!(inb (info->cstatus) & CSTATUS_DRQ)) - continue; + outb(ALATCH_DIS_DMA, info->alatch); - word = *addr | (*addr + 1) << 8; - outw (info->dmaarea); - addr += 2; - length -= 2; + if (dmach != NO_DMA && + (min_type == fasdma_real_all || SCp->this_residual >= 512)) { + int buf; + + for (buf = 1; buf <= SCp->buffers_residual && + buf < NR_SG; buf++) { + info->dmasg[buf].address = __virt_to_bus( + (unsigned long)SCp->buffer[buf].address); + info->dmasg[buf].length = SCp->buffer[buf].length; + + cumanascsi_2_invalidate(SCp->buffer[buf].address, + SCp->buffer[buf].length, + direction); + } + + info->dmasg[0].address = __virt_to_phys((unsigned long)SCp->ptr); + info->dmasg[0].length = SCp->this_residual; + cumanascsi_2_invalidate(SCp->ptr, + SCp->this_residual, direction); + + disable_dma(dmach); + set_dma_sg(dmach, info->dmasg, buf); + if (direction == DMA_OUT) { + outb(ALATCH_DMA_OUT, info->alatch); + set_dma_mode(dmach, DMA_MODE_WRITE); + } else { + outb(ALATCH_DMA_IN, info->alatch); + set_dma_mode(dmach, DMA_MODE_READ); + } + enable_dma(dmach); + outb(ALATCH_ENA_DMA, info->alatch); + outb(ALATCH_DIS_BIT32, info->alatch); + return fasdma_real_all; } -#else - printk ("PSEUDO_OUT???\n"); -#endif - else { - if (transfer && (transfer & 255)) { - while (length >= 256) { - if (inb (REG_STAT(&info->info)) & STAT_INT) - goto end; - - if (!(inb (info->cstatus) & CSTATUS_DRQ)) - continue; - insw (info->dmaarea, addr, 256 >> 1); - addr += 256; - length -= 256; - } - } + /* + * If we're not doing DMA, + * we'll do pseudo DMA + */ + return fasdma_pio; +} + +/* + * Prototype: void cumanascsi_2_dma_pseudo(host, SCpnt, direction, transfer) + * Purpose : handles pseudo DMA + * Params : host - host + * SCpnt - command + * direction - DMA on to/off of card + * transfer - minimum number of bytes we expect to transfer + */ +static void +cumanascsi_2_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp, + fasdmadir_t direction, int transfer) +{ + CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata; + unsigned int length; + unsigned char *addr; + + length = SCp->this_residual; + addr = SCp->ptr; - while (length > 0) { - unsigned long word; + if (direction == DMA_OUT) +#if 0 + while (length > 1) { + unsigned long word; + unsigned int status = inb(info->status); + + if (status & STATUS_INT) + goto end; + + if (!(status & STATUS_DRQ)) + continue; + + word = *addr | (*addr + 1) << 8; + outw (info->dmaarea); + addr += 2; + length -= 2; + } +#else + printk ("PSEUDO_OUT???\n"); +#endif + else { + if (transfer && (transfer & 255)) { + while (length >= 256) { + unsigned int status = inb(info->status); - if (inb (REG_STAT(&info->info)) & STAT_INT) - goto end; + if (status & STATUS_INT) + goto end; - if (!(inb (info->cstatus) & CSTATUS_DRQ)) - continue; + if (!(status & STATUS_DRQ)) + continue; - word = inw (info->dmaarea); - *addr++ = word; - if (--length > 0) { - *addr++ = word >> 8; - length --; - } + insw(info->dmaarea, addr, 256 >> 1); + addr += 256; + length -= 256; + } + } + + while (length > 0) { + unsigned long word; + unsigned int status = inb(info->status); + + if (status & STATUS_INT) + goto end; + + if (!(status & STATUS_DRQ)) + continue; + + word = inw (info->dmaarea); + *addr++ = word; + if (--length > 0) { + *addr++ = word >> 8; + length --; + } + } } - } end: - return SCp->this_residual - length; } -/* - * Function: int cumanascsi_2_dma_stop (instance, SCpnt) - * Purpose : stops DMA/PIO - * Params : instance - host - * SCpnt - command - */ -static void cumanascsi_2_dma_stop (struct Scsi_Host *instance, Scsi_Pointer *SCp) -{ - /* - * no DMA to stop - */ +/* Prototype: int cumanascsi_2_dma_stop(host, SCpnt) + * Purpose : stops DMA/PIO + * Params : host - host + * SCpnt - command + */ +static void +cumanascsi_2_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp) +{ + CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata; + if (host->dma_channel != NO_DMA) { + outb(ALATCH_DIS_DMA, info->alatch); + disable_dma(host->dma_channel); + } } -/* - * Function: int cumanascsi_2_detect (Scsi_Host_Template * tpnt) - * Purpose : initialises Cumana SCSI 2 driver - * Params : tpnt - template for this SCSI adapter - * Returns : >0 if host found, 0 otherwise. - */ -int cumanascsi_2_detect (Scsi_Host_Template *tpnt) -{ - static const card_ids cumanascsi_2_cids[] = { CUMANASCSI2_LIST, { 0xffff, 0xffff} }; - int count = 0; - struct Scsi_Host *instance; +/* Prototype: int cumanascsi_2_detect(Scsi_Host_Template * tpnt) + * Purpose : initialises Cumana SCSI 2 driver + * Params : tpnt - template for this SCSI adapter + * Returns : >0 if host found, 0 otherwise. + */ +int +cumanascsi_2_detect(Scsi_Host_Template *tpnt) +{ + static const card_ids cumanascsi_2_cids[] = + { CUMANASCSI2_LIST, { 0xffff, 0xffff} }; + int count = 0; + struct Scsi_Host *host; - tpnt->proc_dir = &proc_scsi_cumanascsi_2; - memset (ecs, 0, sizeof (ecs)); + tpnt->proc_dir = &proc_scsi_cumanascsi_2; + memset(ecs, 0, sizeof (ecs)); - ecard_startfind (); + ecard_startfind(); - while (1) { - CumanaScsi2_Info *info; + while (1) { + CumanaScsi2_Info *info; - ecs[count] = ecard_find (0, cumanascsi_2_cids); - if (!ecs[count]) - break; + ecs[count] = ecard_find(0, cumanascsi_2_cids); + if (!ecs[count]) + break; + + ecard_claim(ecs[count]); + + host = scsi_register(tpnt, sizeof (CumanaScsi2_Info)); + if (!host) { + ecard_release(ecs[count]); + break; + } + + host->io_port = ecard_address(ecs[count], ECARD_MEMC, 0); + host->irq = ecs[count]->irq; + host->dma_channel = ecs[count]->dma; + info = (CumanaScsi2_Info *)host->hostdata; + + info->terms = term[count] ? 1 : 0; + cumanascsi_2_terminator_ctl(host, info->terms); + + info->info.scsi.io_port = host->io_port + CUMANASCSI2_FAS216_OFFSET; + info->info.scsi.io_shift = CUMANASCSI2_FAS216_SHIFT; + info->info.scsi.irq = host->irq; + info->info.ifcfg.clockrate = CUMANASCSI2_XTALFREQ; + info->info.ifcfg.select_timeout = 255; + info->info.ifcfg.asyncperiod = CUMANASCSI2_ASYNC_PERIOD; + info->info.ifcfg.sync_max_depth = CUMANASCSI2_SYNC_DEPTH; + info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; + info->info.dma.setup = cumanascsi_2_dma_setup; + info->info.dma.pseudo = cumanascsi_2_dma_pseudo; + info->info.dma.stop = cumanascsi_2_dma_stop; + info->dmaarea = host->io_port + CUMANASCSI2_PSEUDODMA; + info->status = host->io_port + CUMANASCSI2_STATUS; + info->alatch = host->io_port + CUMANASCSI2_ALATCH; + + ecs[count]->irqaddr = (unsigned char *)ioaddr(info->status); + ecs[count]->irqmask = STATUS_INT; + ecs[count]->irq_data = (void *)info->alatch; + ecs[count]->ops = (expansioncard_ops_t *)&cumanascsi_2_ops; + + request_region(host->io_port + CUMANASCSI2_FAS216_OFFSET, + 16 << CUMANASCSI2_FAS216_SHIFT, "cumanascsi2-fas"); + + if (host->irq != NO_IRQ && + request_irq(host->irq, cumanascsi_2_intr, + SA_INTERRUPT, "cumanascsi2", host)) { + printk("scsi%d: IRQ%d not free, interrupts disabled\n", + host->host_no, host->irq); + host->irq = NO_IRQ; + info->info.scsi.irq = NO_IRQ; + } + + if (host->dma_channel != NO_DMA && + request_dma(host->dma_channel, "cumanascsi2")) { + printk("scsi%d: DMA%d not free, DMA disabled\n", + host->host_no, host->dma_channel); + host->dma_channel = NO_DMA; + } - ecard_claim (ecs[count]); - - instance = scsi_register (tpnt, sizeof (CumanaScsi2_Info)); - if (!instance) { - ecard_release (ecs[count]); - break; + fas216_init(host); + ++count; } + return count; +} - instance->io_port = ecard_address (ecs[count], ECARD_MEMC, 0); - instance->irq = ecs[count]->irq; - - ecs[count]->irqaddr = (unsigned char *)BUS_ADDR(instance->io_port); - ecs[count]->irqmask = CSTATUS_IRQ; +/* Prototype: int cumanascsi_2_release(struct Scsi_Host * host) + * Purpose : releases all resources used by this adapter + * Params : host - driver host structure to return info for. + */ +int cumanascsi_2_release(struct Scsi_Host *host) +{ + int i; - request_region (instance->io_port , 1, "cumanascsi2-stat"); - request_region (instance->io_port + 128, 64, "cumanascsi2-dma"); - request_region (instance->io_port + 192, 16, "cumanascsi2-fas"); - if (request_irq (instance->irq, cumanascsi_2_intr, SA_INTERRUPT, "cumanascsi2", instance)) { - printk ("scsi%d: IRQ%d not free, interrupts disabled\n", - instance->host_no, instance->irq); - } + fas216_release(host); - info = (CumanaScsi2_Info *)instance->hostdata; - info->info.scsi.io_port = instance->io_port + 192; - info->info.scsi.irq = instance->irq; - info->info.ifcfg.clockrate = XTALFREQ; - info->info.ifcfg.select_timeout = 255; - info->info.dma.setup = cumanascsi_2_dma_setup; - info->info.dma.pseudo = cumanascsi_2_dma_pseudo; - info->info.dma.stop = cumanascsi_2_dma_stop; - info->dmaarea = instance->io_port + 128; - info->cstatus = instance->io_port; - - fas216_init (instance); - ++count; - } - return count; + if (host->irq != NO_IRQ) + free_irq(host->irq, host); + if (host->dma_channel != NO_DMA) + free_dma(host->dma_channel); + release_region(host->io_port + CUMANASCSI2_FAS216_OFFSET, + 16 << CUMANASCSI2_FAS216_SHIFT); + + for (i = 0; i < MAX_ECARDS; i++) + if (ecs[i] && host->io_port == ecard_address (ecs[i], ECARD_MEMC, 0)) + ecard_release (ecs[i]); + return 0; } -/* - * Function: int cumanascsi_2_release (struct Scsi_Host * host) - * Purpose : releases all resources used by this adapter - * Params : host - driver host structure to return info for. - * Returns : nothing - */ -int cumanascsi_2_release (struct Scsi_Host *instance) -{ - int i; - - fas216_release (instance); - - if (instance->irq != 255) - free_irq (instance->irq, instance); - release_region (instance->io_port, 1); - release_region (instance->io_port + 128, 32); - release_region (instance->io_port + 192, 16); - - for (i = 0; i < MAX_ECARDS; i++) - if (ecs[i] && instance->io_port == ecard_address (ecs[i], ECARD_MEMC, 0)) - ecard_release (ecs[i]); - return 0; +/* Prototype: const char *cumanascsi_2_info(struct Scsi_Host * host) + * Purpose : returns a descriptive string about this interface, + * Params : host - driver host structure to return info for. + * Returns : pointer to a static buffer containing null terminated string. + */ +const char *cumanascsi_2_info(struct Scsi_Host *host) +{ + CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata; + static char string[100], *p; + + p = string; + p += sprintf(string, "%s at port %lX ", + host->hostt->name, host->io_port); + + if (host->irq != NO_IRQ) + p += sprintf(p, "irq %d ", host->irq); + else + p += sprintf(p, "NO IRQ "); + + if (host->dma_channel != NO_DMA) + p += sprintf(p, "dma %d ", host->dma_channel); + else + p += sprintf(p, "NO DMA "); + + p += sprintf(p, "v%d.%d.%d scsi %s", + VER_MAJOR, VER_MINOR, VER_PATCH, + info->info.scsi.type); + + p += sprintf(p, " terminators %s", + info->terms ? "on" : "off"); + + return string; } -/* - * Function: const char *cumanascsi_2_info (struct Scsi_Host * host) - * Purpose : returns a descriptive string about this interface, - * Params : host - driver host structure to return info for. - * Returns : pointer to a static buffer containing null terminated string. - */ -const char *cumanascsi_2_info (struct Scsi_Host *host) -{ - CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata; - static char string[100], *p; - - p = string; - p += sprintf (string, "%s at port %X irq %d v%d.%d.%d scsi %s", - host->hostt->name, host->io_port, host->irq, - VER_MAJOR, VER_MINOR, VER_PATCH, - info->info.scsi.type); +/* Prototype: int cumanascsi_2_set_proc_info(struct Scsi_Host *host, char *buffer, int length) + * Purpose : Set a driver specific function + * Params : host - host to setup + * : buffer - buffer containing string describing operation + * : length - length of string + * Returns : -EINVAL, or 0 + */ +static int +cumanascsi_2_set_proc_info(struct Scsi_Host *host, char *buffer, int length) +{ + int ret = length; - return string; + if (length >= 11 && strcmp(buffer, "CUMANASCSI2") == 0) { + buffer += 11; + length -= 11; + + if (length >= 5 && strncmp(buffer, "term=", 5) == 0) { + if (buffer[5] == '1') + cumanascsi_2_terminator_ctl(host, 1); + else if (buffer[5] == '0') + cumanascsi_2_terminator_ctl(host, 0); + else + ret = -EINVAL; + } else + ret = -EINVAL; + } else + ret = -EINVAL; + + return ret; } -/* - * Function: int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset, +/* Prototype: int cumanascsi_2_proc_info(char *buffer, char **start, off_t offset, * int length, int host_no, int inout) - * Purpose : Return information about the driver to a user process accessing - * the /proc filesystem. - * Params : buffer - a buffer to write information to - * start - a pointer into this buffer set by this routine to the start - * of the required information. - * offset - offset into information that we have read upto. - * length - length of buffer - * host_no - host number to return information for - * inout - 0 for reading, 1 for writing. - * Returns : length of data written to buffer. + * Purpose : Return information about the driver to a user process accessing + * the /proc filesystem. + * Params : buffer - a buffer to write information to + * start - a pointer into this buffer set by this routine to the start + * of the required information. + * offset - offset into information that we have read upto. + * length - length of buffer + * host_no - host number to return information for + * inout - 0 for reading, 1 for writing. + * Returns : length of data written to buffer. */ int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset, int length, int host_no, int inout) { - int pos, begin; - struct Scsi_Host *host = scsi_hostlist; - CumanaScsi2_Info *info; - Scsi_Device *scd; - - while (host) { - if (host->host_no == host_no) - break; - host = host->next; - } - if (!host) - return 0; + int pos, begin; + struct Scsi_Host *host = scsi_hostlist; + CumanaScsi2_Info *info; + Scsi_Device *scd; + + while (host) { + if (host->host_no == host_no) + break; + host = host->next; + } + if (!host) + return 0; - info = (CumanaScsi2_Info *)host->hostdata; - if (inout == 1) - return -EINVAL; + if (inout == 1) + return cumanascsi_2_set_proc_info(host, buffer, length); - begin = 0; - pos = sprintf (buffer, + info = (CumanaScsi2_Info *)host->hostdata; + + begin = 0; + pos = sprintf(buffer, "Cumana SCSI II driver version %d.%d.%d\n", VER_MAJOR, VER_MINOR, VER_PATCH); - pos += sprintf (buffer + pos, - "Address: %08X IRQ : %d\n" - "FAS : %s\n\n" + pos += sprintf(buffer + pos, + "Address: %08lX IRQ : %d DMA : %d\n" + "FAS : %-10s TERM: %-3s\n\n" "Statistics:\n", - host->io_port, host->irq, info->info.scsi.type); + host->io_port, host->irq, host->dma_channel, + info->info.scsi.type, info->terms ? "on" : "off"); - pos += sprintf (buffer+pos, - "Queued commands: %-10ld Issued commands: %-10ld\n" - "Done commands : %-10ld Reads : %-10ld\n" - "Writes : %-10ld Others : %-10ld\n" - "Disconnects : %-10ld Aborts : %-10ld\n" - "Resets : %-10ld\n", - info->info.stats.queues, info->info.stats.removes, - info->info.stats.fins, info->info.stats.reads, - info->info.stats.writes, info->info.stats.miscs, - info->info.stats.disconnects, info->info.stats.aborts, - info->info.stats.resets); - - pos += sprintf (buffer+pos, "\nAttached devices:%s\n", host->host_queue ? "" : " none"); - - for (scd = host->host_queue; scd; scd = scd->next) { - int len; - - proc_print_scsidevice (scd, buffer, &len, pos); - pos += len; - pos += sprintf (buffer+pos, "Extensions: "); - if (scd->tagged_supported) - pos += sprintf (buffer+pos, "TAG %sabled [%d] ", - scd->tagged_queue ? "en" : "dis", - scd->current_tag); - pos += sprintf (buffer+pos, "\n"); - - if (pos + begin < offset) { - begin += pos; - pos = 0; + pos += sprintf(buffer+pos, + "Queued commands: %-10u Issued commands: %-10u\n" + "Done commands : %-10u Reads : %-10u\n" + "Writes : %-10u Others : %-10u\n" + "Disconnects : %-10u Aborts : %-10u\n" + "Resets : %-10u\n", + info->info.stats.queues, info->info.stats.removes, + info->info.stats.fins, info->info.stats.reads, + info->info.stats.writes, info->info.stats.miscs, + info->info.stats.disconnects, info->info.stats.aborts, + info->info.stats.resets); + + pos += sprintf(buffer+pos, "\nAttached devices:%s\n", host->host_queue ? "" : " none"); + + for (scd = host->host_queue; scd; scd = scd->next) { + int len; + + proc_print_scsidevice(scd, buffer, &len, pos); + pos += len; + pos += sprintf(buffer+pos, "Extensions: "); + if (scd->tagged_supported) + pos += sprintf(buffer+pos, "TAG %sabled [%d] ", + scd->tagged_queue ? "en" : "dis", + scd->current_tag); + pos += sprintf(buffer+pos, "\n"); + + if (pos + begin < offset) { + begin += pos; + pos = 0; + } + if (pos + begin > offset + length) + break; } - if (pos + begin > offset + length) - break; - } - - *start = buffer + (offset - begin); - pos -= offset - begin; - if (pos > length) - pos = length; - return pos; + *start = buffer + (offset - begin); + pos -= offset - begin; + if (pos > length) + pos = length; + + return pos; } #ifdef MODULE diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/cumana_2.h linux/drivers/acorn/scsi/cumana_2.h --- v2.1.100/linux/drivers/acorn/scsi/cumana_2.h Mon Feb 23 18:12:03 1998 +++ linux/drivers/acorn/scsi/cumana_2.h Fri May 8 00:42:39 1998 @@ -1,7 +1,7 @@ /* * Cumana SCSI II driver * - * Copyright (C) 1997 Russell King + * Copyright (C) 1997-1998 Russell King */ #ifndef CUMANA_2_H #define CUMANA_2_H @@ -57,12 +57,19 @@ #ifndef HOSTS_C +#include + +#define NR_SG 256 + typedef struct { - FAS216_Info info; + FAS216_Info info; - /* other info... */ - unsigned int cstatus; /* card status register */ - unsigned int dmaarea; /* Pseudo DMA area */ + /* other info... */ + unsigned int status; /* card status register */ + unsigned int alatch; /* Control register */ + unsigned int terms; /* Terminator state */ + unsigned int dmaarea; /* Pseudo DMA area */ + dmasg_t dmasg[NR_SG]; /* Scatter DMA list */ } CumanaScsi2_Info; #define CSTATUS_IRQ (1 << 0) diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/eesox.c linux/drivers/acorn/scsi/eesox.c --- v2.1.100/linux/drivers/acorn/scsi/eesox.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acorn/scsi/eesox.c Fri May 8 00:42:39 1998 @@ -0,0 +1,582 @@ +/* + * linux/arch/arm/drivers/scsi/eesox.c + * + * Copyright (C) 1997-1998 Russell King + * + * This driver is based on experimentation. Hence, it may have made + * assumptions about the particular card that I have available, and + * may not be reliable! + * + * Changelog: + * 01-10-1997 RMK Created, READONLY version + * 15-02-1998 RMK READ/WRITE version + * added DMA support and hardware definitions + * 14-03-1998 RMK Updated DMA support + * Added terminator control + * 15-04-1998 RMK Only do PIO if FAS216 will allow it. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../../scsi/sd.h" +#include "../../scsi/hosts.h" +#include "eesox.h" + +#define NO_IRQ 255 +#define NO_DMA 255 + +/* Configuration */ +#define EESOX_XTALFREQ 40 +#define EESOX_ASYNC_PERIOD 200 +#define EESOX_SYNC_DEPTH 7 + +/* + * List of devices that the driver will recognise + */ +#define EESOXSCSI_LIST { MANU_EESOX, PROD_EESOX_SCSI2 } + +#define EESOX_FAS216_OFFSET 0xc00 +#define EESOX_FAS216_SHIFT 3 + +#define EESOX_STATUS 0xa00 +#define EESOX_STAT_INTR 0x01 +#define EESOX_STAT_DMA 0x02 + +#define EESOX_CONTROL 0xa00 +#define EESOX_INTR_ENABLE 0x04 +#define EESOX_TERM_ENABLE 0x02 +#define EESOX_RESET 0x01 + +#define EESOX_DMA_OFFSET 0xe00 + +/* + * Version + */ +#define VER_MAJOR 0 +#define VER_MINOR 0 +#define VER_PATCH 2 + +static struct expansion_card *ecs[MAX_ECARDS]; + +/* + * Use term=0,1,0,0,0 to turn terminators on/off + */ +int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 }; + +static struct proc_dir_entry proc_scsi_eesox = { + PROC_SCSI_QLOGICISP, 5, "eesox", + S_IFDIR | S_IRUGO | S_IXUGO, 2 +}; + +/* Prototype: void eesoxscsi_irqenable(ec, irqnr) + * Purpose : Enable interrupts on EESOX SCSI card + * Params : ec - expansion card structure + * : irqnr - interrupt number + */ +static void +eesoxscsi_irqenable(struct expansion_card *ec, int irqnr) +{ + struct control *control = (struct control *)ec->irq_data; + + control->control |= EESOX_INTR_ENABLE; + + outb(control->control, control->io_port); +} + +/* Prototype: void eesoxscsi_irqdisable(ec, irqnr) + * Purpose : Disable interrupts on EESOX SCSI card + * Params : ec - expansion card structure + * : irqnr - interrupt number + */ +static void +eesoxscsi_irqdisable(struct expansion_card *ec, int irqnr) +{ + struct control *control = (struct control *)ec->irq_data; + + control->control &= ~EESOX_INTR_ENABLE; + + outb(control->control, control->io_port); +} + +static const expansioncard_ops_t eesoxscsi_ops = { + eesoxscsi_irqenable, + eesoxscsi_irqdisable, + NULL, + NULL +}; + +/* Prototype: void eesoxscsi_terminator_ctl(*host, on_off) + * Purpose : Turn the EESOX SCSI terminators on or off + * Params : host - card to turn on/off + * : on_off - !0 to turn on, 0 to turn off + */ +static void +eesoxscsi_terminator_ctl(struct Scsi_Host *host, int on_off) +{ + EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata; + unsigned long flags; + + save_flags_cli(flags); + if (on_off) + info->control.control |= EESOX_TERM_ENABLE; + else + info->control.control &= ~EESOX_TERM_ENABLE; + restore_flags(flags); + + outb(info->control.control, info->control.io_port); +} + +/* Prototype: void eesoxscsi_intr(irq, *dev_id, *regs) + * Purpose : handle interrupts from EESOX SCSI card + * Params : irq - interrupt number + * dev_id - user-defined (Scsi_Host structure) + * regs - processor registers at interrupt + */ +static void +eesoxscsi_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct Scsi_Host *host = (struct Scsi_Host *)dev_id; + + fas216_intr(host); +} + +static void +eesoxscsi_invalidate(char *addr, long len, fasdmadir_t direction) +{ + unsigned int page; + + if (direction == DMA_OUT) { + for(page = (unsigned int) addr; len > 0; + page += PAGE_SIZE, len -= PAGE_SIZE) + flush_page_to_ram(page); + } else + flush_cache_range(current->mm, (unsigned long)addr, + (unsigned long)addr + len); +} + +/* Prototype: fasdmatype_t eesoxscsi_dma_setup(host, SCpnt, direction, min_type) + * Purpose : initialises DMA/PIO + * Params : host - host + * SCpnt - command + * direction - DMA on to/off of card + * min_type - minimum DMA support that we must have for this transfer + * Returns : type of transfer to be performed + */ +static fasdmatype_t +eesoxscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp, + fasdmadir_t direction, fasdmatype_t min_type) +{ + EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata; + int dmach = host->dma_channel; + + if (dmach != NO_DMA && + (min_type == fasdma_real_all || SCp->this_residual >= 512)) { + int buf; + + for(buf = 1; buf <= SCp->buffers_residual && + buf < NR_SG; buf++) { + info->dmasg[buf].address = __virt_to_bus( + (unsigned long)SCp->buffer[buf].address); + info->dmasg[buf].length = SCp->buffer[buf].length; + + eesoxscsi_invalidate(SCp->buffer[buf].address, + SCp->buffer[buf].length, + direction); + } + + info->dmasg[0].address = __virt_to_phys((unsigned long)SCp->ptr); + info->dmasg[0].length = SCp->this_residual; + eesoxscsi_invalidate(SCp->ptr, + SCp->this_residual, direction); + + disable_dma(dmach); + set_dma_sg(dmach, info->dmasg, buf); + set_dma_mode(dmach, + direction == DMA_OUT ? DMA_MODE_WRITE : + DMA_MODE_READ); + enable_dma(dmach); + return fasdma_real_all; + } + /* + * We don't do DMA, we only do slow PIO + * + * Some day, we will do Pseudo DMA + */ + return fasdma_pseudo; +} + +static void +eesoxscsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp, + fasdmadir_t dir, int transfer_size) +{ + EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata; + unsigned int status; + unsigned int length = SCp->this_residual; + union { + unsigned char *c; + unsigned short *s; + unsigned long *l; + } buffer; + + buffer.c = SCp->ptr; + + status = inb(host->io_port + EESOX_STATUS); + if (dir == DMA_IN) { + while (length > 8) { + if (status & EESOX_STAT_DMA) { + unsigned long l1, l2; + + l1 = inw(info->dmaarea); + l1 |= inw(info->dmaarea) << 16; + l2 = inw(info->dmaarea); + l2 |= inw(info->dmaarea) << 16; + *buffer.l++ = l1; + *buffer.l++ = l2; + length -= 8; + } else if (status & EESOX_STAT_INTR) + goto end; + status = inb(host->io_port + EESOX_STATUS); + } + + while (length > 1) { + if (status & EESOX_STAT_DMA) { + *buffer.s++ = inw(info->dmaarea); + length -= 2; + } else if (status & EESOX_STAT_INTR) + goto end; + status = inb(host->io_port + EESOX_STATUS); + } + + while (length > 0) { + if (status & EESOX_STAT_DMA) { + *buffer.c++ = inw(info->dmaarea); + length -= 1; + } else if (status & EESOX_STAT_INTR) + goto end; + status = inb(host->io_port + EESOX_STATUS); + } + } else { + while (length > 8) { + if (status & EESOX_STAT_DMA) { + unsigned long l1, l2; + + l1 = *buffer.l++; + l2 = *buffer.l++; + + outw(l1, info->dmaarea); + outw(l1 >> 16, info->dmaarea); + outw(l2, info->dmaarea); + outw(l2 >> 16, info->dmaarea); + length -= 8; + } else if (status & EESOX_STAT_INTR) + goto end; + status = inb(host->io_port + EESOX_STATUS); + } + + while (length > 1) { + if (status & EESOX_STAT_DMA) { + outw(*buffer.s++, info->dmaarea); + length -= 2; + } else if (status & EESOX_STAT_INTR) + goto end; + status = inb(host->io_port + EESOX_STATUS); + } + + while (length > 0) { + if (status & EESOX_STAT_DMA) { + outw(*buffer.c++, info->dmaarea); + length -= 1; + } else if (status & EESOX_STAT_INTR) + goto end; + status = inb(host->io_port + EESOX_STATUS); + } + } +end: +} + +/* Prototype: int eesoxscsi_dma_stop(host, SCpnt) + * Purpose : stops DMA/PIO + * Params : host - host + * SCpnt - command + */ +static void +eesoxscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp) +{ + if (host->dma_channel != NO_DMA) + disable_dma(host->dma_channel); +} + +/* Prototype: int eesoxscsi_detect(Scsi_Host_Template * tpnt) + * Purpose : initialises EESOX SCSI driver + * Params : tpnt - template for this SCSI adapter + * Returns : >0 if host found, 0 otherwise. + */ +int +eesoxscsi_detect(Scsi_Host_Template *tpnt) +{ + static const card_ids eesoxscsi_cids[] = + { EESOXSCSI_LIST, { 0xffff, 0xffff} }; + int count = 0; + struct Scsi_Host *host; + + tpnt->proc_dir = &proc_scsi_eesox; + memset(ecs, 0, sizeof (ecs)); + + ecard_startfind(); + + while(1) { + EESOXScsi_Info *info; + + ecs[count] = ecard_find(0, eesoxscsi_cids); + if (!ecs[count]) + break; + + ecard_claim(ecs[count]); + + host = scsi_register(tpnt, sizeof (EESOXScsi_Info)); + if (!host) { + ecard_release(ecs[count]); + break; + } + + host->io_port = ecard_address(ecs[count], ECARD_IOC, ECARD_FAST); + host->irq = ecs[count]->irq; + host->dma_channel = ecs[count]->dma; + info = (EESOXScsi_Info *)host->hostdata; + + info->control.io_port = host->io_port + EESOX_CONTROL; + info->control.control = term[count] ? EESOX_TERM_ENABLE : 0; + outb(info->control.control, info->control.io_port); + + ecs[count]->irqaddr = (unsigned char *) + ioaddr(host->io_port + EESOX_STATUS); + ecs[count]->irqmask = EESOX_STAT_INTR; + ecs[count]->irq_data = &info->control; + ecs[count]->ops = (expansioncard_ops_t *)&eesoxscsi_ops; + + info->info.scsi.io_port = host->io_port + EESOX_FAS216_OFFSET; + info->info.scsi.io_shift = EESOX_FAS216_SHIFT; + info->info.scsi.irq = host->irq; + info->info.ifcfg.clockrate = EESOX_XTALFREQ; + info->info.ifcfg.select_timeout = 255; + info->info.ifcfg.asyncperiod = EESOX_ASYNC_PERIOD; + info->info.ifcfg.sync_max_depth = EESOX_SYNC_DEPTH; + info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; + info->info.dma.setup = eesoxscsi_dma_setup; + info->info.dma.pseudo = eesoxscsi_dma_pseudo; + info->info.dma.stop = eesoxscsi_dma_stop; + info->dmaarea = host->io_port + EESOX_DMA_OFFSET; + + request_region(host->io_port + EESOX_FAS216_OFFSET, + 16 << EESOX_FAS216_SHIFT, "eesox2-fas"); + + if (request_irq(host->irq, eesoxscsi_intr, + SA_INTERRUPT, "eesox", host)) { + printk("scsi%d: IRQ%d not free, interrupts disabled\n", + host->host_no, host->irq); + host->irq = NO_IRQ; + } + + if (request_dma(host->dma_channel, "eesox")) { + printk("scsi%d: DMA%d not free, DMA disabled\n", + host->host_no, host->dma_channel); + host->dma_channel = NO_DMA; + } + + fas216_init(host); + ++count; + } + return count; +} + +/* Prototype: int eesoxscsi_release(struct Scsi_Host * host) + * Purpose : releases all resources used by this adapter + * Params : host - driver host structure to return info for. + */ +int eesoxscsi_release(struct Scsi_Host *host) +{ + int i; + + fas216_release(host); + + if (host->irq != NO_IRQ) + free_irq(host->irq, host); + if (host->dma_channel != NO_DMA) + free_dma(host->dma_channel); + release_region(host->io_port + EESOX_FAS216_OFFSET, 16 << EESOX_FAS216_SHIFT); + + for (i = 0; i < MAX_ECARDS; i++) + if (ecs[i] && + host->io_port == ecard_address(ecs[i], ECARD_IOC, ECARD_FAST)) + ecard_release(ecs[i]); + return 0; +} + +/* Prototype: const char *eesoxscsi_info(struct Scsi_Host * host) + * Purpose : returns a descriptive string about this interface, + * Params : host - driver host structure to return info for. + * Returns : pointer to a static buffer containing null terminated string. + */ +const char *eesoxscsi_info(struct Scsi_Host *host) +{ + EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata; + static char string[100], *p; + + p = string; + p += sprintf(string, "%s at port %lX ", + host->hostt->name, host->io_port); + + if (host->irq != NO_IRQ) + p += sprintf(p, "irq %d ", host->irq); + else + p += sprintf(p, "NO IRQ "); + + if (host->dma_channel != NO_DMA) + p += sprintf(p, "dma %d ", host->dma_channel); + else + p += sprintf(p, "NO DMA "); + + p += sprintf(p, "v%d.%d.%d scsi %s", VER_MAJOR, VER_MINOR, VER_PATCH, + info->info.scsi.type); + + p += sprintf(p, " terminators %s", + info->control.control & EESOX_TERM_ENABLE ? "on" : "off"); + + return string; +} + +/* Prototype: int eesoxscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length) + * Purpose : Set a driver specific function + * Params : host - host to setup + * : buffer - buffer containing string describing operation + * : length - length of string + * Returns : -EINVAL, or 0 + */ +static int +eesoxscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length) +{ + int ret = length; + + if (length >= 9 && strncmp(buffer, "EESOXSCSI", 9) == 0) { + buffer += 9; + length -= 9; + + if (length >= 5 && strncmp(buffer, "term=", 5) == 0) { + if (buffer[5] == '1') + eesoxscsi_terminator_ctl(host, 1); + else if (buffer[5] == '0') + eesoxscsi_terminator_ctl(host, 0); + else + ret = -EINVAL; + } else + ret = -EINVAL; + } else + ret = -EINVAL; + + return ret; +} + +/* Prototype: int eesoxscsi_proc_info(char *buffer, char **start, off_t offset, + * int length, int host_no, int inout) + * Purpose : Return information about the driver to a user process accessing + * the /proc filesystem. + * Params : buffer - a buffer to write information to + * start - a pointer into this buffer set by this routine to the start + * of the required information. + * offset - offset into information that we have read upto. + * length - length of buffer + * host_no - host number to return information for + * inout - 0 for reading, 1 for writing. + * Returns : length of data written to buffer. + */ +int eesoxscsi_proc_info(char *buffer, char **start, off_t offset, + int length, int host_no, int inout) +{ + int pos, begin; + struct Scsi_Host *host = scsi_hostlist; + EESOXScsi_Info *info; + Scsi_Device *scd; + + while (host) { + if (host->host_no == host_no) + break; + host = host->next; + } + if (!host) + return 0; + + if (inout == 1) + return eesoxscsi_set_proc_info(host, buffer, length); + + info = (EESOXScsi_Info *)host->hostdata; + + begin = 0; + pos = sprintf(buffer, + "EESOX SCSI driver version %d.%d.%d\n", + VER_MAJOR, VER_MINOR, VER_PATCH); + pos += sprintf(buffer + pos, + "Address: %08lX IRQ : %d DMA : %d\n" + "FAS : %-10s TERM: %-3s\n\n" + "Statistics:\n", + host->io_port, host->irq, host->dma_channel, + info->info.scsi.type, info->control.control & EESOX_TERM_ENABLE ? "on" : "off"); + + pos += sprintf(buffer+pos, + "Queued commands: %-10u Issued commands: %-10u\n" + "Done commands : %-10u Reads : %-10u\n" + "Writes : %-10u Others : %-10u\n" + "Disconnects : %-10u Aborts : %-10u\n" + "Resets : %-10u\n", + info->info.stats.queues, info->info.stats.removes, + info->info.stats.fins, info->info.stats.reads, + info->info.stats.writes, info->info.stats.miscs, + info->info.stats.disconnects, info->info.stats.aborts, + info->info.stats.resets); + + pos += sprintf (buffer+pos, "\nAttached devices:%s\n", host->host_queue ? "" : " none"); + + for (scd = host->host_queue; scd; scd = scd->next) { + int len; + + proc_print_scsidevice (scd, buffer, &len, pos); + pos += len; + pos += sprintf (buffer+pos, "Extensions: "); + if (scd->tagged_supported) + pos += sprintf (buffer+pos, "TAG %sabled [%d] ", + scd->tagged_queue ? "en" : "dis", + scd->current_tag); + pos += sprintf (buffer+pos, "\n"); + + if (pos + begin < offset) { + begin += pos; + pos = 0; + } + } + *start = buffer + (offset - begin); + pos -= offset - begin; + if (pos > length) + pos = length; + + return pos; +} + +#ifdef MODULE +Scsi_Host_Template driver_template = EESOXSCSI; + +#include "../../scsi/scsi_module.c" +#endif diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/eesox.h linux/drivers/acorn/scsi/eesox.h --- v2.1.100/linux/drivers/acorn/scsi/eesox.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acorn/scsi/eesox.h Fri May 8 00:42:39 1998 @@ -0,0 +1,81 @@ +/* + * EESOX SCSI driver + * + * Copyright (C) 1997-1998 Russell King + */ +#ifndef EESOXSCSI_H +#define EESOXSCSI_H + +extern int eesoxscsi_detect (Scsi_Host_Template *); +extern int eesoxscsi_release (struct Scsi_Host *); +extern const char *eesoxscsi_info (struct Scsi_Host *); +extern int eesoxscsi_proc_info (char *buffer, char **start, off_t offset, + int length, int hostno, int inout); + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#ifndef CAN_QUEUE +/* + * Default queue size + */ +#define CAN_QUEUE 1 +#endif + +#ifndef CMD_PER_LUN +#define CMD_PER_LUN 1 +#endif + +#ifndef SCSI_ID +/* + * Default SCSI host ID + */ +#define SCSI_ID 7 +#endif + +#include + +#include "fas216.h" + +#define EESOXSCSI { \ +proc_info: eesoxscsi_proc_info, \ +name: "EESOX SCSI", \ +detect: eesoxscsi_detect, /* detect */ \ +release: eesoxscsi_release, /* release */ \ +info: eesoxscsi_info, /* info */ \ +command: fas216_command, /* command */ \ +queuecommand: fas216_queue_command, /* queuecommand */ \ +abort: fas216_abort, /* abort */ \ +reset: fas216_reset, /* reset */ \ +bios_param: scsicam_bios_param, /* biosparam */ \ +can_queue: CAN_QUEUE, /* can queue */ \ +this_id: SCSI_ID, /* scsi host id */ \ +sg_tablesize: SG_ALL, /* sg_tablesize */ \ +cmd_per_lun: CAN_QUEUE, /* cmd per lun */ \ +use_clustering: DISABLE_CLUSTERING \ + } + +#ifndef HOSTS_C + +#include + +#define NR_SG 256 + +struct control { + unsigned int io_port; + unsigned int control; +}; + +typedef struct { + FAS216_Info info; + + struct control control; + + unsigned int dmaarea; /* Pseudo DMA area */ + dmasg_t dmasg[NR_SG]; /* Scatter DMA list */ +} EESOXScsi_Info; + +#endif /* HOSTS_C */ + +#endif /* EESOXSCSI_H */ diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/fas216.c linux/drivers/acorn/scsi/fas216.c --- v2.1.100/linux/drivers/acorn/scsi/fas216.c Wed Apr 8 19:36:25 1998 +++ linux/drivers/acorn/scsi/fas216.c Fri May 8 00:42:39 1998 @@ -3,8 +3,9 @@ * * Copyright (C) 1997 Russell King * - * Based in information in qlogicfas.c by Tom Zerucha, Michael Griffith, and - * other sources. + * Based on information in qlogicfas.c by Tom Zerucha, Michael Griffith, and + * other sources, including: + * the AMD Am53CF94 data sheet * * This is a generic driver. To use it, have a look at cumana_2.c. You * should define your own structure that overlays FAS216_Info, eg: @@ -18,6 +19,13 @@ * 14-09-1997 RMK Started disconnect support * 08-02-1998 RMK Corrected real DMA support * 15-02-1998 RMK Started sync xfer support + * 06-04-1998 RMK Tightened conditions for printing incomplete + * transfers + * 02-05-1998 RMK Added extra checks in fas216_reset + * + * Todo: + * - tighten up the MESSAGE_REJECT support. + * - allow individual devices to enable sync xfers. */ #include @@ -31,6 +39,7 @@ #include #include +#include #include #include #include @@ -43,7 +52,34 @@ #define VER_MAJOR 0 #define VER_MINOR 0 -#define VER_PATCH 2 +#define VER_PATCH 3 + +#define SCSI2_TAG + +/* NOTE: SCSI2 Synchronous transfers *require* DMA according to + * the data sheet. This restriction is crazy, especially when + * you only want to send 16 bytes! What were the guys who + * designed this chip on at that time? Did they read the SCSI2 + * spec at all? The following sections are taken from the SCSI2 + * standard (s2r10) concerning this: + * + * > IMPLEMENTORS NOTES: + * > (1) Re-negotiation at every selection is not recommended, since a + * > significant performance impact is likely. + * + * > The implied synchronous agreement shall remain in effect until a BUS DEVICE + * > RESET message is received, until a hard reset condition occurs, or until one + * > of the two SCSI devices elects to modify the agreement. The default data + * > transfer mode is asynchronous data transfer mode. The default data transfer + * > mode is entered at power on, after a BUS DEVICE RESET message, or after a hard + * > reset condition. + * + * In total, this means that once you have elected to use synchronous + * transfers, you must always use DMA. + * + * I was thinking that this was a good chip until I found this restriction ;( + */ +#define SCSI2_SYNC #undef NO_DISCONNECTS #undef DEBUG_CONNECT @@ -51,9 +87,95 @@ #undef DEBUG_FUNCTIONDONE #undef DEBUG_MESSAGES -static char *fas216_bus_phase (int stat) +#undef CHECK_STRUCTURE + +static struct { int stat, ssr, isr, ph; } list[8]; +static int ptr; + +static void fas216_dumpstate(FAS216_Info *info) +{ + printk("FAS216 registers:\n"); + printk(" CTCL=%02X CTCM=%02X CMD=%02X STAT=%02X" + " INST=%02X IS=%02X CFIS=%02X", + inb(REG_CTCL(info)), inb(REG_CTCM(info)), + inb(REG_CMD(info)), inb(REG_STAT(info)), + inb(REG_INST(info)), inb(REG_IS(info)), + inb(REG_CFIS(info))); + printk(" CNTL1=%02X CNTL2=%02X CNTL3=%02X CTCH=%02X\n", + inb(REG_CNTL1(info)), inb(REG_CNTL2(info)), + inb(REG_CNTL3(info)), inb(REG_CTCH(info))); +} + +static void fas216_dumpinfo(FAS216_Info *info) +{ + static int used = 0; + int i; + + if (used++) + return; + + printk("FAS216_Info = \n"); + printk(" { magic_start=%lX host=%p SCpnt=%p origSCpnt=%p\n", + info->magic_start, info->host, info->SCpnt, + info->origSCpnt); + printk(" scsi={ io_port=%X io_shift=%X irq=%X cfg={ %X %X %X %X }\n", + info->scsi.io_port, info->scsi.io_shift, info->scsi.irq, + info->scsi.cfg[0], info->scsi.cfg[1], info->scsi.cfg[2], + info->scsi.cfg[3]); + printk(" type=%p phase=%X reconnected = { target=%d lun=%d tag=%d }\n", + info->scsi.type, info->scsi.phase, + info->scsi.reconnected.target, + info->scsi.reconnected.lun, info->scsi.reconnected.tag); + printk(" SCp = { ptr=%p this_residual=%X buffer=%p buffers_residual=%X }\n", + info->scsi.SCp.ptr, info->scsi.SCp.this_residual, + info->scsi.SCp.buffer, info->scsi.SCp.buffers_residual); + printk(" msgs async_stp=%X last_message=%X disconnectable=%d aborting=%d }\n", + info->scsi.async_stp, info->scsi.last_message, + info->scsi.disconnectable, info->scsi.aborting); + printk(" stats={ queues=%X removes=%X fins=%X reads=%X writes=%X miscs=%X disconnects=%X aborts=%X resets=%X }\n", + info->stats.queues, info->stats.removes, info->stats.fins, + info->stats.reads, info->stats.writes, info->stats.miscs, + info->stats.disconnects, info->stats.aborts, info->stats.resets); + printk(" ifcfg={ clockrate=%X select_timeout=%X asyncperiod=%X sync_max_depth=%X }\n", + info->ifcfg.clockrate, info->ifcfg.select_timeout, + info->ifcfg.asyncperiod, info->ifcfg.sync_max_depth); + for (i = 0; i < 8; i++) { + printk(" busyluns[%d]=%X dev[%d]={ disconnect_ok=%d stp=%X sof=%X negstate=%X }\n", + i, info->busyluns[i], i, + info->device[i].disconnect_ok, info->device[i].stp, + info->device[i].sof, info->device[i].negstate); + } + printk(" dma={ transfer_type=%X setup=%p pseudo=%p stop=%p }\n", + info->dma.transfer_type, info->dma.setup, + info->dma.pseudo, info->dma.stop); + printk(" internal_done=%X magic_end=%lX\n", + info->internal_done, info->magic_end); +} + +#ifdef CHECK_STRUCTURE +static void fas216_checkmagic(FAS216_Info *info, const char *func) +{ + int corruption = 0; + if (info->magic_start != MAGIC) { + printk(KERN_CRIT "FAS216 Error: magic at start corrupted\n"); + corruption++; + } + if (info->magic_end != MAGIC) { + printk(KERN_CRIT "FAS216 Error: magic at end corrupted\n"); + corruption++; + } + if (corruption) { + fas216_dumpinfo(info); + panic("scsi memory space corrupted in %s", func); + } +} +#else +#define fas216_checkmagic(info,func) +#endif + +static const char *fas216_bus_phase(int stat) { - static char *phases[] = { + static const char *phases[] = { "DATA OUT", "DATA IN", "COMMAND", "STATUS", "MISC OUT", "MISC IN", @@ -63,7 +185,26 @@ return phases[stat & STAT_BUSMASK]; } -static char fas216_target (FAS216_Info *info) +static const char *fas216_drv_phase(FAS216_Info *info) +{ + switch (info->scsi.phase) { + case PHASE_IDLE: return "idle"; + case PHASE_SELECTION: return "selection"; + case PHASE_MESSAGESENT: return "message sent"; + case PHASE_RECONNECTED: return "reconnected"; + case PHASE_DATAOUT: return "data out"; + case PHASE_DATAIN: return "data in"; + case PHASE_MSGOUT: return "message out"; + case PHASE_MSGIN: return "message in"; + case PHASE_AFTERMSGOUT: return "after message out"; + case PHASE_STATUS: return "status"; + case PHASE_DISCONNECT: return "disconnect"; + case PHASE_DONE: return "done"; + default: return "???"; + } +} + +static char fas216_target(FAS216_Info *info) { if (info->SCpnt) return '0' + info->SCpnt->target; @@ -71,15 +212,41 @@ return 'H'; } -static void fas216_done (FAS216_Info *info, unsigned int result); +static void add_debug_list(int stat, int ssr, int isr, int ph) +{ + list[ptr].stat = stat; + list[ptr].ssr = ssr; + list[ptr].isr = isr; + list[ptr].ph = ph; + + ptr = (ptr + 1) & 7; +} + +static void print_debug_list(void) +{ + int i; + + i = ptr; + + printk(KERN_ERR "SCSI state trail: "); + do { + printk("%02X:%02X:%02X:%02X ", + list[i].stat, list[i].ssr, + list[i].isr, list[i].ph); + i = (i + 1) & 7; + } while (i != ptr); + printk("\n"); +} + +static void fas216_done(FAS216_Info *info, unsigned int result); -/* Function: int fas216_clockrate (unsigned int clock) +/* Function: int fas216_clockrate(unsigned int clock) * Purpose : calculate correct value to be written into clock conversion * factor register. * Params : clock - clock speed in MHz * Returns : CLKF_ value */ -static int fas216_clockrate (int clock) +static int fas216_clockrate(int clock) { if (clock <= 10 || clock > 40) { printk(KERN_CRIT @@ -102,6 +269,8 @@ { int value = (info->ifcfg.clockrate * ns) / 1000; + fas216_checkmagic(info, "fas216_syncperiod"); + if (value < 4) value = 4; else if (value > 35) @@ -110,16 +279,21 @@ return value & 31; } -/* Function: void fas216_updateptrs (FAS216_Info *info, int bytes_transferred) +/* Function: void fas216_updateptrs(FAS216_Info *info, int bytes_transferred) * Purpose : update data pointers after transfer suspended/paused * Params : info - interface's local pointer to update * bytes_transferred - number of bytes transferred */ static void -fas216_updateptrs (FAS216_Info *info, int bytes_transferred) +fas216_updateptrs(FAS216_Info *info, int bytes_transferred) { - unsigned char *ptr = info->scsi.SCp.ptr; - unsigned int residual = info->scsi.SCp.this_residual; + unsigned char *ptr; + unsigned int residual; + + fas216_checkmagic(info, "fas216_updateptrs"); + + ptr = info->scsi.SCp.ptr; + residual = info->scsi.SCp.this_residual; info->SCpnt->request_bufflen -= bytes_transferred; @@ -144,50 +318,61 @@ info->scsi.SCp.this_residual = residual; } -/* Function: void fas216_pio (FAS216_Info *info, fasdmadir_t direction) +/* Function: void fas216_pio(FAS216_Info *info, fasdmadir_t direction) * Purpose : transfer data off of/on to card using programmed IO * Params : info - interface to transfer data to/from * direction - direction to transfer data (DMA_OUT/DMA_IN) * Notes : this is incredibly slow */ static void -fas216_pio (FAS216_Info *info, fasdmadir_t direction) +fas216_pio(FAS216_Info *info, fasdmadir_t direction) { - unsigned int length = info->scsi.SCp.this_residual; - char *ptr = info->scsi.SCp.ptr; + unsigned int residual; + char *ptr; + int correction; + + fas216_checkmagic(info, "fas216_pio"); + + residual = info->scsi.SCp.this_residual; + ptr = info->scsi.SCp.ptr; if (direction == DMA_OUT) { - while (length > 0) { + while (residual > 0) { if ((inb(REG_CFIS(info)) & CFIS_CF) < 8) { outb(*ptr++, REG_FF(info)); - length -= 1; + residual -= 1; } else if (inb(REG_STAT(info)) & STAT_INT) break; } + correction = inb(REG_CFIS(info)) & CFIS_CF; } else { - while (length > 0) { + while (residual > 0) { if ((inb(REG_CFIS(info)) & CFIS_CF) != 0) { *ptr++ = inb(REG_FF(info)); - length -= 1; + residual -= 1; } else if (inb(REG_STAT(info)) & STAT_INT) break; } + correction = 0; } - if (length == 0) { + ptr -= correction; + residual += correction; + + if (residual == 0) { if (info->scsi.SCp.buffers_residual) { info->scsi.SCp.buffer++; info->scsi.SCp.buffers_residual--; ptr = (unsigned char *)info->scsi.SCp.buffer->address; - length = info->scsi.SCp.buffer->length; + residual = info->scsi.SCp.buffer->length; } else { ptr = NULL; - length = 0; + residual = 0; } } info->scsi.SCp.ptr = ptr; - info->scsi.SCp.this_residual = length; + info->scsi.SCp.this_residual = residual; } /* Function: void fas216_starttransfer(FAS216_Info *info, @@ -197,77 +382,81 @@ * direction - transfer direction (DMA_OUT/DMA_IN) */ static void -fas216_starttransfer(FAS216_Info *info, fasdmadir_t direction) +fas216_starttransfer(FAS216_Info *info, fasdmadir_t direction, int flush_fifo) { fasdmatype_t dmatype; + fas216_checkmagic(info, "fas216_starttransfer"); + info->scsi.phase = (direction == DMA_OUT) ? PHASE_DATAOUT : PHASE_DATAIN; - if (info->dma.transfer_type == fasdma_real_block || - info->dma.transfer_type == fasdma_real_all) { + if (info->dma.transfer_type != fasdma_none && + info->dma.transfer_type != fasdma_pio) { unsigned long total, residual; - if (info->dma.transfer_type == fasdma_real_block) - total = info->scsi.SCp.this_residual; - else + if (info->dma.transfer_type == fasdma_real_all) total = info->SCpnt->request_bufflen; + else + total = info->scsi.SCp.this_residual; residual = (inb(REG_CFIS(info)) & CFIS_CF) + inb(REG_CTCL(info)) + (inb(REG_CTCM(info)) << 8) + (inb(REG_CTCH(info)) << 16); - fas216_updateptrs (info, total - residual); - info->dma.transfer_type = fasdma_none; + fas216_updateptrs(info, total - residual); } + info->dma.transfer_type = fasdma_none; if (!info->scsi.SCp.ptr) { - printk ("scsi%d.%c: null buffer passed to " + printk("scsi%d.%c: null buffer passed to " "fas216_starttransfer\n", info->host->host_no, - fas216_target (info)); + fas216_target(info)); return; } - dmatype = fasdma_none; + /* flush FIFO */ + if (flush_fifo) + outb(CMD_FLUSHFIFO, REG_CMD(info)); + + /* + * Default to PIO mode or DMA mode if we have a synchronous + * transfer agreement. + */ + if (info->device[info->SCpnt->target].sof && info->dma.setup) + dmatype = fasdma_real_all; + else + dmatype = fasdma_pio; + if (info->dma.setup) dmatype = info->dma.setup(info->host, &info->scsi.SCp, - direction); - + direction, dmatype); info->dma.transfer_type = dmatype; switch (dmatype) { - case fasdma_none: + case fasdma_pio: + outb(0, REG_SOF(info)); + outb(info->scsi.async_stp, REG_STP(info)); outb(info->scsi.SCp.this_residual, REG_STCL(info)); outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info)); outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info)); - outb(CMD_NOP | CMD_WITHDMA, REG_CMD(info)); outb(CMD_TRANSFERINFO, REG_CMD(info)); - fas216_pio (info, direction); + fas216_pio(info, direction); break; - case fasdma_pseudo: { - int transferred; - + case fasdma_pseudo: outb(info->scsi.SCp.this_residual, REG_STCL(info)); outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info)); outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info)); - outb(CMD_NOP | CMD_WITHDMA, REG_CMD(info)); outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info)); - - transferred = - info->dma.pseudo(info->host, &info->scsi.SCp, - direction, info->SCpnt->transfersize); - - fas216_updateptrs (info, transferred); - } + info->dma.pseudo(info->host, &info->scsi.SCp, + direction, info->SCpnt->transfersize); break; case fasdma_real_block: outb(info->scsi.SCp.this_residual, REG_STCL(info)); outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info)); outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info)); - outb(CMD_NOP | CMD_WITHDMA, REG_CMD(info)); - outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info)); break; @@ -275,58 +464,66 @@ outb(info->SCpnt->request_bufflen, REG_STCL(info)); outb(info->SCpnt->request_bufflen >> 8, REG_STCM(info)); outb(info->SCpnt->request_bufflen >> 16, REG_STCH(info)); - outb(CMD_NOP | CMD_WITHDMA, REG_CMD(info)); - outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info)); break; + + default: + printk(KERN_ERR "scsi%d.%d: invalid FAS216 DMA type\n", + info->host->host_no, fas216_target(info)); + break; } } -/* Function: void fas216_stoptransfer (FAS216_Info *info) +/* Function: void fas216_stoptransfer(FAS216_Info *info) * Purpose : Stop a DMA transfer onto / off of the card * Params : info - interface from which device disconnected from */ static void -fas216_stoptransfer (FAS216_Info *info) +fas216_stoptransfer(FAS216_Info *info) { - if (info->dma.transfer_type == fasdma_real_block || - info->dma.transfer_type == fasdma_real_all) { + fas216_checkmagic(info, "fas216_stoptransfer"); + + if (info->dma.transfer_type != fasdma_none && + info->dma.transfer_type != fasdma_pio) { unsigned long total, residual; - if (info->dma.stop) - info->dma.stop (info->host, &info->scsi.SCp); + if ((info->dma.transfer_type == fasdma_real_all || + info->dma.transfer_type == fasdma_real_block) && + info->dma.stop) + info->dma.stop(info->host, &info->scsi.SCp); - if (info->dma.transfer_type == fasdma_real_block) - total = info->scsi.SCp.this_residual; - else + if (info->dma.transfer_type == fasdma_real_all) total = info->SCpnt->request_bufflen; + else + total = info->scsi.SCp.this_residual; residual = (inb(REG_CFIS(info)) & CFIS_CF) + inb(REG_CTCL(info)) + (inb(REG_CTCM(info)) << 8) + (inb(REG_CTCH(info)) << 16); - fas216_updateptrs (info, total - residual); - + fas216_updateptrs(info, total - residual); info->dma.transfer_type = fasdma_none; } } -/* Function: void fas216_disconnected_intr (FAS216_Info *info) +/* Function: void fas216_disconnected_intr(FAS216_Info *info) * Purpose : handle device disconnection * Params : info - interface from which device disconnected from */ static void -fas216_disconnect_intr (FAS216_Info *info) +fas216_disconnect_intr(FAS216_Info *info) { + fas216_checkmagic(info, "fas216_disconnected_intr"); + #ifdef DEBUG_CONNECT printk("scsi%d.%c: disconnect phase=%02X\n", info->host->host_no, - fas216_target (info), info->scsi.phase); + fas216_target(info), info->scsi.phase); #endif - msgqueue_flush (&info->scsi.msgs); + msgqueue_flush(&info->scsi.msgs); switch (info->scsi.phase) { case PHASE_SELECTION: /* while selecting - no target */ - fas216_done (info, DID_NO_CONNECT); + fas216_done(info, DID_NO_CONNECT); break; case PHASE_DISCONNECT: /* message in - disconnecting */ @@ -338,33 +535,36 @@ break; case PHASE_DONE: /* at end of command - complete */ - fas216_done (info, DID_OK); + fas216_done(info, DID_OK); break; case PHASE_AFTERMSGOUT: /* message out - possible ABORT message */ if (info->scsi.last_message == ABORT) { info->scsi.aborting = 0; - fas216_done (info, DID_ABORT); + fas216_done(info, DID_ABORT); break; } default: /* huh? */ - printk(KERN_ERR "scsi%d.%c: unexpected disconnect in phase %d\n", - info->host->host_no, fas216_target (info), info->scsi.phase); + printk(KERN_ERR "scsi%d.%c: unexpected disconnect in phase %s\n", + info->host->host_no, fas216_target(info), fas216_drv_phase(info)); + print_debug_list(); fas216_stoptransfer(info); - fas216_done (info, DID_ERROR); + fas216_done(info, DID_ERROR); break; } } -/* Function: void fas216_reselected_intr (FAS216_Info *info) +/* Function: void fas216_reselected_intr(FAS216_Info *info) * Purpose : Start reconnection of a device * Params : info - interface which was reselected */ static void -fas216_reselected_intr (FAS216_Info *info) +fas216_reselected_intr(FAS216_Info *info) { - unsigned char target, identify_msg, ok; + unsigned char target, identify_msg, ok; + + fas216_checkmagic(info, "fas216_reselected_intr"); if (info->scsi.phase == PHASE_SELECTION && info->SCpnt) { Scsi_Cmnd *SCpnt = info->SCpnt; @@ -378,555 +578,733 @@ #ifdef DEBUG_CONNECT printk("scsi%d.%c: reconnect phase=%02X\n", info->host->host_no, - fas216_target (info), info->scsi.phase); + fas216_target(info), info->scsi.phase); #endif - msgqueue_flush (&info->scsi.msgs); - - if ((inb(REG_CFIS(info)) & CFIS_CF) != 2) { - printk (KERN_ERR "scsi%d.H: incorrect number of bytes after reselect\n", - info->host->host_no); - outb(CMD_SETATN, REG_CMD(info)); - msgqueue_addmsg (&info->scsi.msgs, 1, MESSAGE_REJECT); - info->scsi.phase = PHASE_MSGOUT; - outb(CMD_MSGACCEPTED, REG_CMD(info)); - return; - } + msgqueue_flush(&info->scsi.msgs); - target = inb(REG_FF(info)); - identify_msg = inb(REG_FF(info)); + if ((inb(REG_CFIS(info)) & CFIS_CF) != 2) { + printk(KERN_ERR "scsi%d.H: incorrect number of bytes after reselect\n", + info->host->host_no); + outb(CMD_SETATN, REG_CMD(info)); + msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); + info->scsi.phase = PHASE_MSGOUT; + outb(CMD_MSGACCEPTED, REG_CMD(info)); + return; + } - ok = 1; - if (!(target & (1 << info->host->this_id))) { - printk (KERN_ERR "scsi%d.H: invalid host id on reselect\n", info->host->host_no); - ok = 0; - } + target = inb(REG_FF(info)); + identify_msg = inb(REG_FF(info)); - if (!(identify_msg & 0x80)) { - printk (KERN_ERR "scsi%d.H: no IDENTIFY message on reselect, got msg %02X\n", - info->host->host_no, identify_msg); - ok = 0; - } + ok = 1; + if (!(target & (1 << info->host->this_id))) { + printk(KERN_ERR "scsi%d.H: invalid host id on reselect\n", info->host->host_no); + ok = 0; + } - if (!ok) { - /* - * Something went wrong - abort the command on - * the target. Should this be INITIATOR_ERROR ? - */ - outb(CMD_SETATN, REG_CMD(info)); - msgqueue_addmsg (&info->scsi.msgs, 1, ABORT); - info->scsi.phase = PHASE_MSGOUT; - outb(CMD_MSGACCEPTED, REG_CMD(info)); - return; - } + if (!(identify_msg & 0x80)) { + printk(KERN_ERR "scsi%d.H: no IDENTIFY message on reselect, got msg %02X\n", + info->host->host_no, identify_msg); + ok = 0; + } - target &= ~(1 << info->host->this_id); - switch (target) { - case 1: target = 0; break; - case 2: target = 1; break; - case 4: target = 2; break; - case 8: target = 3; break; - case 16: target = 4; break; - case 32: target = 5; break; - case 64: target = 6; break; - case 128: target = 7; break; - default: target = info->host->this_id; break; - } - - identify_msg &= 7; - info->scsi.reconnected.target = target; - info->scsi.reconnected.lun = identify_msg; - info->scsi.reconnected.tag = 0; - - ok = 0; - if (info->scsi.disconnectable && info->SCpnt && - info->SCpnt->target == target && info->SCpnt->lun == identify_msg) - ok = 1; + if (!ok) { + /* + * Something went wrong - abort the command on + * the target. Should this be INITIATOR_ERROR ? + */ + outb(CMD_SETATN, REG_CMD(info)); + msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); + info->scsi.phase = PHASE_MSGOUT; + outb(CMD_MSGACCEPTED, REG_CMD(info)); + return; + } - if (!ok && queue_probetgtlun (&info->queues.disconnected, target, identify_msg)) - ok = 1; + target &= ~(1 << info->host->this_id); + switch (target) { + case 1: target = 0; break; + case 2: target = 1; break; + case 4: target = 2; break; + case 8: target = 3; break; + case 16: target = 4; break; + case 32: target = 5; break; + case 64: target = 6; break; + case 128: target = 7; break; + default: target = info->host->this_id; break; + } + + identify_msg &= 7; + info->scsi.reconnected.target = target; + info->scsi.reconnected.lun = identify_msg; + info->scsi.reconnected.tag = 0; - if (ok) { - info->scsi.phase = PHASE_RECONNECTED; - outb(target, REG_SDID(info)); - } else { - /* - * Our command structure not found - abort the command on the target - * Should this be INITIATOR_ERROR ? - */ - outb(CMD_SETATN, REG_CMD(info)); - msgqueue_addmsg (&info->scsi.msgs, 1, ABORT); - info->scsi.phase = PHASE_MSGOUT; - } - outb(CMD_MSGACCEPTED, REG_CMD(info)); + ok = 0; + if (info->scsi.disconnectable && info->SCpnt && + info->SCpnt->target == target && info->SCpnt->lun == identify_msg) + ok = 1; + + if (!ok && queue_probetgtlun(&info->queues.disconnected, target, identify_msg)) + ok = 1; + + if (ok) { + info->scsi.phase = PHASE_RECONNECTED; + outb(target, REG_SDID(info)); + } else { + /* + * Our command structure not found - abort the command on the target + * Should this be INITIATOR_ERROR ? + */ + outb(CMD_SETATN, REG_CMD(info)); + msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); + info->scsi.phase = PHASE_MSGOUT; + } + outb(CMD_MSGACCEPTED, REG_CMD(info)); } -/* Function: void fas216_finish_reconnect (FAS216_Info *info) +/* Function: void fas216_finish_reconnect(FAS216_Info *info) * Purpose : finish reconnection sequence for device * Params : info - interface which caused function done interrupt */ static void -fas216_finish_reconnect (FAS216_Info *info) +fas216_finish_reconnect(FAS216_Info *info) { + fas216_checkmagic(info, "fas216_reconnect"); + #ifdef DEBUG_CONNECT -printk ("Connected: %1X %1X %02X, reconnected: %1X %1X %02X\n", - info->SCpnt->target, info->SCpnt->lun, info->SCpnt->tag, - info->scsi.reconnected.target, info->scsi.reconnected.lun, - info->scsi.reconnected.tag); + printk("Connected: %1X %1X %02X, reconnected: %1X %1X %02X\n", + info->SCpnt->target, info->SCpnt->lun, info->SCpnt->tag, + info->scsi.reconnected.target, info->scsi.reconnected.lun, + info->scsi.reconnected.tag); #endif - if (info->scsi.disconnectable && info->SCpnt) { - info->scsi.disconnectable = 0; - if (info->SCpnt->target == info->scsi.reconnected.target && - info->SCpnt->lun == info->scsi.reconnected.lun && - info->SCpnt->tag == info->scsi.reconnected.tag) { + if (info->scsi.disconnectable && info->SCpnt) { + info->scsi.disconnectable = 0; + if (info->SCpnt->target == info->scsi.reconnected.target && + info->SCpnt->lun == info->scsi.reconnected.lun && + info->SCpnt->tag == info->scsi.reconnected.tag) { #ifdef DEBUG_CONNECT - printk ("scsi%d.%c: reconnected", - info->host->host_no, fas216_target (info)); + printk("scsi%d.%c: reconnected", + info->host->host_no, fas216_target(info)); #endif - } else { - queue_add_cmd_tail (&info->queues.disconnected, info->SCpnt); + } else { + queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt); #ifdef DEBUG_CONNECT - printk ("scsi%d.%c: had to move command to disconnected queue\n", - info->host->host_no, fas216_target (info)); + printk("scsi%d.%c: had to move command to disconnected queue\n", + info->host->host_no, fas216_target(info)); #endif - info->SCpnt = NULL; + info->SCpnt = NULL; + } } - } - if (!info->SCpnt) { - info->SCpnt = queue_remove_tgtluntag (&info->queues.disconnected, - info->scsi.reconnected.target, - info->scsi.reconnected.lun, - info->scsi.reconnected.tag); + if (!info->SCpnt) { + info->SCpnt = queue_remove_tgtluntag(&info->queues.disconnected, + info->scsi.reconnected.target, + info->scsi.reconnected.lun, + info->scsi.reconnected.tag); #ifdef DEBUG_CONNECT - printk ("scsi%d.%c: had to get command", - info->host->host_no, fas216_target (info)); + printk("scsi%d.%c: had to get command", + info->host->host_no, fas216_target(info)); #endif - } - if (!info->SCpnt) { - outb(CMD_SETATN, REG_CMD(info)); - msgqueue_addmsg (&info->scsi.msgs, 1, ABORT); - info->scsi.phase = PHASE_MSGOUT; - info->scsi.aborting = 1; - } else { - /* - * Restore data pointer from SAVED data pointer - */ - info->scsi.SCp = info->SCpnt->SCp; + } + if (!info->SCpnt) { + outb(CMD_SETATN, REG_CMD(info)); + msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); + info->scsi.phase = PHASE_MSGOUT; + info->scsi.aborting = 1; + } else { + /* + * Restore data pointer from SAVED data pointer + */ + info->scsi.SCp = info->SCpnt->SCp; #ifdef DEBUG_CONNECT - printk (", data pointers: [%p, %X]", - info->scsi.SCp.ptr, info->scsi.SCp.this_residual); + printk(", data pointers: [%p, %X]", + info->scsi.SCp.ptr, info->scsi.SCp.this_residual); #endif - } + } #ifdef DEBUG_CONNECT - printk ("\n"); + printk("\n"); #endif } -/* Function: void fas216_message (FAS216_Info *info) +/* Function: void fas216_message(FAS216_Info *info) * Purpose : handle a function done interrupt from FAS216 chip * Params : info - interface which caused function done interrupt */ -static void fas216_message (FAS216_Info *info) +static void fas216_message(FAS216_Info *info) { - unsigned char message[16]; - unsigned int msglen = 1; + unsigned char message[16]; + unsigned int msglen = 1; + + fas216_checkmagic(info, "fas216_message"); + + message[0] = inb(REG_FF(info)); - message[0] = inb(REG_FF(info)); + if (message[0] == EXTENDED_MESSAGE) { + int tout; + outb(CMD_MSGACCEPTED, REG_CMD(info)); + for (tout = 1000000; tout; tout--) + if (inb(REG_STAT(info)) & STAT_INT) + break; + inb(REG_INST(info)); + outb(CMD_TRANSFERINFO, REG_CMD(info)); + for (tout = 1000000; tout; tout--) + if (inb(REG_STAT(info)) & STAT_INT) + break; + inb(REG_INST(info)); - if (message[0] == EXTENDED_MESSAGE) { - message[1] = inb(REG_FF(info)); + message[1] = inb(REG_FF(info)); - for (msglen = 2; msglen < message[1]; msglen++) - message[msglen] = inb(REG_FF(info)); - } + for (msglen = 2; msglen < message[1] + 2; msglen++) { + outb(CMD_MSGACCEPTED, REG_CMD(info)); + for (tout = 1000000; tout; tout--) + if (inb(REG_STAT(info)) & STAT_INT) + break; + inb(REG_INST(info)); + outb(CMD_TRANSFERINFO, REG_CMD(info)); + for (tout = 1000000; tout; tout--) + if (inb(REG_STAT(info)) & STAT_INT) + break; + inb(REG_INST(info)); + + message[msglen] = inb(REG_FF(info)); + } + } #ifdef DEBUG_MESSAGES - { - int i; + { + int i; + + printk("scsi%d.%c: message in: ", + info->host->host_no, fas216_target(info)); + for (i = 0; i < msglen; i++) + printk("%02X ", message[i]); + printk("\n"); + } +#endif + if (info->scsi.phase == PHASE_RECONNECTED) { + if (message[0] == SIMPLE_QUEUE_TAG) + info->scsi.reconnected.tag = message[1]; + fas216_finish_reconnect(info); + info->scsi.phase = PHASE_MSGIN; + } - printk ("scsi%d.%c: message in: ", - info->host->host_no, fas216_target (info)); - for (i = 0; i < msglen; i++) - printk ("%02X ", message[i]); - printk ("\n"); - } -#endif - if (info->scsi.phase == PHASE_RECONNECTED) { - if (message[0] == SIMPLE_QUEUE_TAG) - info->scsi.reconnected.tag = message[1]; - fas216_finish_reconnect (info); - info->scsi.phase = PHASE_MSGIN; - } - - switch (message[0]) { - case COMMAND_COMPLETE: - printk ("fas216: command complete with no status in MESSAGE_IN?\n"); - break; + switch (message[0]) { + case COMMAND_COMPLETE: + printk("fas216: command complete with no status in MESSAGE_IN?\n"); + break; - case SAVE_POINTERS: - /* - * Save current data pointer to SAVED data pointer - */ - info->SCpnt->SCp = info->scsi.SCp; + case SAVE_POINTERS: + /* + * Save current data pointer to SAVED data pointer + */ + info->SCpnt->SCp = info->scsi.SCp; #if defined (DEBUG_MESSAGES) || defined (DEBUG_CONNECT) - printk ("scsi%d.%c: save data pointers: [%p, %X]\n", - info->host->host_no, fas216_target (info), - info->scsi.SCp.ptr, info->scsi.SCp.this_residual); + printk("scsi%d.%c: save data pointers: [%p, %X]\n", + info->host->host_no, fas216_target(info), + info->scsi.SCp.ptr, info->scsi.SCp.this_residual); #endif - break; + break; - case RESTORE_POINTERS: - /* - * Restore current data pointer from SAVED data pointer - */ - info->scsi.SCp = info->SCpnt->SCp; + case RESTORE_POINTERS: + /* + * Restore current data pointer from SAVED data pointer + */ + info->scsi.SCp = info->SCpnt->SCp; #if defined (DEBUG_MESSAGES) || defined (DEBUG_CONNECT) - printk ("scsi%d.%c: restore data pointers: [%p, %X]\n", - info->host->host_no, fas216_target (info), - info->scsi.SCp.ptr, info->scsi.SCp.this_residual); + printk("scsi%d.%c: restore data pointers: [%p, %X]\n", + info->host->host_no, fas216_target(info), + info->scsi.SCp.ptr, info->scsi.SCp.this_residual); #endif - break; + break; + + case DISCONNECT: + info->scsi.phase = PHASE_DISCONNECT; + break; + + case MESSAGE_REJECT: + printk("scsi%d.%c: reject, last message %04X\n", + info->host->host_no, fas216_target(info), + info->scsi.last_message); + break; + + case SIMPLE_QUEUE_TAG: + /* handled above */ + printk("scsi%d.%c: reconnect queue tag %02X\n", + info->host->host_no, fas216_target(info), + message[1]); + break; + + case EXTENDED_MESSAGE: + switch (message[2]) { + case EXTENDED_SDTR: /* Sync transfer negociation request/reply */ + switch (info->device[info->SCpnt->target].negstate) { + case syncneg_invalid: + msgqueue_flush(&info->scsi.msgs); + outb(CMD_SETATN, REG_CMD(info)); + msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); + info->scsi.phase = PHASE_MSGOUT; + break; - case DISCONNECT: - info->scsi.phase = PHASE_DISCONNECT; - break; - - case MESSAGE_REJECT: - printk ("scsi%d.%c: reject, last message %04X\n", - info->host->host_no, fas216_target (info), - info->scsi.last_message); - break; - - case SIMPLE_QUEUE_TAG: - /* handled above */ - printk ("scsi%d.%c: reconnect queue tag %02X\n", - info->host->host_no, fas216_target (info), - message[1]); - break; - - case EXTENDED_MESSAGE: - switch (message[2]) { - case EXTENDED_SDTR: /* Sync transfer negociation request/reply */ + default: + if (message[4] > info->ifcfg.sync_max_depth) + message[4] = info->ifcfg.sync_max_depth; + if (message[3] < 1000 / info->ifcfg.clockrate) + message[3] = 1000 / info->ifcfg.clockrate; + + outb(CMD_SETATN, REG_CMD(info)); + msgqueue_addmsg(&info->scsi.msgs, 5, + EXTENDED_MESSAGE, 3, EXTENDED_SDTR, + message[3], message[4]); + info->scsi.phase = PHASE_MSGOUT; + case syncneg_sent: + info->device[info->SCpnt->target].negstate = syncneg_complete; + info->device[info->SCpnt->target].sof = message[4]; + info->device[info->SCpnt->target].stp = + fas216_syncperiod(info, message[3] * 4); + printk(KERN_NOTICE "scsi%d.%c: using synchronous transfer, offset %d, %d ns\n", + info->host->host_no, fas216_target(info), message[4], message[3] * 4); + outb(info->device[info->SCpnt->target].sof, REG_SOF(info)); + outb(info->device[info->SCpnt->target].stp, REG_STP(info)); + break; + } + break; + + case EXTENDED_WDTR: /* Wide transfer negociation request/reply */ + /* We don't do wide transfers - reject message */ + default: + printk("scsi%d.%c: unrecognised extended message %02X, rejecting\n", + info->host->host_no, fas216_target(info), + message[2]); + msgqueue_flush(&info->scsi.msgs); + outb(CMD_SETATN, REG_CMD(info)); + msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); + info->scsi.phase = PHASE_MSGOUT; + break; + } + break; - case EXTENDED_WDTR: /* Wide transfer negociation request/reply */ - /* We don't do wide transfers - reject message */ default: - printk("scsi%d.%c: unrecognised extended message %02X, rejecting\n", - info->host->host_no, fas216_target (info), - message[2]); - msgqueue_flush (&info->scsi.msgs); + printk("scsi%d.%c: unrecognised message %02X, rejecting\n", + info->host->host_no, fas216_target(info), + message[0]); + msgqueue_flush(&info->scsi.msgs); outb(CMD_SETATN, REG_CMD(info)); - msgqueue_addmsg (&info->scsi.msgs, 1, MESSAGE_REJECT); + msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); info->scsi.phase = PHASE_MSGOUT; break; } - break; + outb(CMD_MSGACCEPTED, REG_CMD(info)); +} - default: - printk ("scsi%d.%c: unrecognised message %02X, rejecting\n", - info->host->host_no, fas216_target (info), - message[0]); - msgqueue_flush (&info->scsi.msgs); - outb(CMD_SETATN, REG_CMD(info)); - msgqueue_addmsg (&info->scsi.msgs, 1, MESSAGE_REJECT); - info->scsi.phase = PHASE_MSGOUT; - break; - } - outb(CMD_MSGACCEPTED, REG_CMD(info)); +/* Function: void fas216_send_command(FAS216_Info *info) + * Purpose : send a command to a target after all message bytes have been sent + * Params : info - interface which caused bus service + */ +static void fas216_send_command(FAS216_Info *info) +{ + int i; + + fas216_checkmagic(info, "fas216_send_command"); + + outb(CMD_NOP|CMD_WITHDMA, REG_CMD(info)); + outb(CMD_FLUSHFIFO, REG_CMD(info)); + + /* load command */ + for (i = 0; i < info->SCpnt->cmd_len; i++) + outb(info->SCpnt->cmnd[i], REG_FF(info)); + + outb(CMD_TRANSFERINFO, REG_CMD(info)); } -/* Function: void fas216_busservice_intr (FAS216_Info *info, unsigned int stat, unsigned int ssr) - * Purpose : handle a bus service interrupt from FAS216 chip - * Params : info - interface which caused bus service interrupt - * stat - Status register contents - * ssr - SCSI Status register contents +/* Function: int fas216_busservice_selection(FAS216_Info *info, unsigned int stat) + * Purpose : handle bus service in selection phase + * Params : info - interface which caused bus service + * Returns : 0 if unable to service this interrupt */ -static void fas216_busservice_intr (FAS216_Info *info, unsigned int stat, unsigned int ssr) +static int fas216_busservice_selection(FAS216_Info *info, unsigned int stat) { - int i; -#ifdef DEBUG_BUSSERVICE - printk("scsi%d.%c: bus service: stat=%02X ssr=%02X phase=%02X\n", - info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase); -#endif - switch (ssr & IS_BITS) { - case IS_COMPLETE: /* last action completed */ - outb(CMD_NOP, REG_CMD(info)); + fas216_checkmagic(info, "fas216_busservice_selection"); - switch (info->scsi.phase) { - case PHASE_SELECTION: /* while selecting - selected target */ - switch (stat & STAT_BUSMASK) { - case STAT_DATAOUT: /* data out phase */ - fas216_starttransfer (info, DMA_OUT); - break; + switch (stat & STAT_BUSMASK) { + case STAT_DATAOUT: /* data out phase */ + fas216_starttransfer(info, DMA_OUT, 1); + return 1; - case STAT_DATAIN: /* data in phase */ - fas216_starttransfer (info, DMA_IN); - break; + case STAT_DATAIN: /* data in phase */ + fas216_starttransfer(info, DMA_IN, 0); + return 1; - case STAT_STATUS: /* status phase */ + case STAT_STATUS: /* status phase */ info->scsi.phase = PHASE_STATUS; outb(CMD_INITCMDCOMPLETE, REG_CMD(info)); - break; + return 1; - case STAT_MESGIN: /* message in phase */ + case STAT_MESGIN: /* message in phase */ info->scsi.phase = PHASE_MSGIN; outb(CMD_TRANSFERINFO, REG_CMD(info)); - break; + return 1; - default: /* other */ - printk ("scsi%d.%c: bus phase %s after connect?\n", - info->host->host_no, fas216_target (info), - fas216_bus_phase (stat)); - break; - } - break; + case STAT_MESGOUT:{ /* message out phase */ + char *msg; + int start = 1, msglen; - case PHASE_DATAIN: /* while transfering data in */ - switch (stat & STAT_BUSMASK) { - case STAT_DATAIN: /* continue data in phase */ - fas216_starttransfer (info, DMA_IN); - break; + /* load message bytes, but don't forget to miss the first + * byte! + */ + while ((msg = msgqueue_getnextmsg(&info->scsi.msgs, &msglen)) != NULL) { + int i; - case STAT_STATUS: - fas216_stoptransfer(info); - info->scsi.phase = PHASE_STATUS; - outb(CMD_INITCMDCOMPLETE, REG_CMD(info)); - break; + for (i = start; i < msglen; i++) + outb(msg[i], REG_FF(info)); + start = 0; + } + outb(CMD_TRANSFERINFO, REG_CMD(info)); + info->scsi.phase = PHASE_MESSAGESENT; + return 1; + } + default: + return 0; + } +} - case STAT_MESGIN: /* message in phase */ - fas216_stoptransfer(info); +/* Function: int fas216_busservice_messagesent(FAS216_Info *info, unsigned int stat) + * Purpose : handle bus service after the IDENTIFY message has been sent + * Params : info - interface which caused bus service + * Returns : 0 if unable to service this interrupt + */ +static int fas216_busservice_messagesent(FAS216_Info *info, unsigned int stat) +{ + fas216_checkmagic(info, "fas216_busservice_messagesent"); + + switch (stat & STAT_BUSMASK) { + case STAT_MESGIN: /* message in phase */ info->scsi.phase = PHASE_MSGIN; + outb(CMD_FLUSHFIFO, REG_CMD(info)); outb(CMD_TRANSFERINFO, REG_CMD(info)); - break; + return 1; - default: - printk ("scsi%d.%c: bus phase %s after data in?\n", - info->host->host_no, fas216_target (info), - fas216_bus_phase (stat)); - } - break; - - case PHASE_DATAOUT: /* while transfering data out */ - switch (stat & STAT_BUSMASK) { - case STAT_DATAOUT: - fas216_starttransfer (info, DMA_OUT); - break; + case STAT_COMMAND: /* command phase */ + fas216_send_command(info); + return 1; + + default: + return 0; + } +} - case STAT_STATUS: +/* Function: int fas216_busservice_dataphase(FAS216_Info *info, unsigned int stat) + * Purpose : handle bus service in a data in/out phase. + * Params : info - interface which caused bus service + * Returns : 0 if unable to service this interrupt + * Note : We do not allow the device to change the data direction! + */ +static int fas216_busservice_dataphase(FAS216_Info *info, unsigned int stat) +{ + fas216_checkmagic(info, "fas216_busservice_dataphase"); + + switch (stat & STAT_BUSMASK) { + case STAT_DATAIN: /* continue data in phase */ + if (info->scsi.phase == PHASE_DATAIN) { + fas216_starttransfer(info, DMA_IN, 0); + return 1; + } else + return 0; + + case STAT_DATAOUT: /* continue data out phase */ + if (info->scsi.phase == PHASE_DATAOUT) { + fas216_starttransfer(info, DMA_OUT, 0); + return 1; + } else + return 0; + + case STAT_STATUS: /* status in phase */ fas216_stoptransfer(info); info->scsi.phase = PHASE_STATUS; - outb(CMD_FLUSHFIFO, REG_CMD(info)); outb(CMD_INITCMDCOMPLETE, REG_CMD(info)); - break; + return 1; - case STAT_MESGIN: /* message in phase */ + case STAT_MESGIN: /* message in phase */ fas216_stoptransfer(info); info->scsi.phase = PHASE_MSGIN; - outb(CMD_FLUSHFIFO, REG_CMD(info)); outb(CMD_TRANSFERINFO, REG_CMD(info)); - break; + return 1; + + default: + return 0; + } +} + +/* Function: int fas216_busservice_reconnected(FAS216_Info *info, unsigned int stat) + * Purpose : handle bus service in after a reconnection + * Params : info - interface which caused bus service + * Returns : 0 if unable to service this interrupt + * Note : We do not allow the device to change the data direction! + */ +static int fas216_busservice_reconnected(FAS216_Info *info, unsigned int stat) +{ + fas216_checkmagic(info, "fas216_busservice_reconnected"); - default: - printk ("scsi%d.%c: bus phase %s after data out?\n", - info->host->host_no, fas216_target (info), - fas216_bus_phase (stat)); - } - break; - - case PHASE_RECONNECTED: /* newly reconnected device */ - /* - * Command reconnected - if MESGIN, get message - it may be - * the tag. If not, get command out of the disconnected queue - */ - switch (stat & STAT_BUSMASK) { - case STAT_MESGIN: + switch (stat & STAT_BUSMASK) { + case STAT_MESGIN: outb(CMD_TRANSFERINFO, REG_CMD(info)); - break; + return 1; - case STAT_STATUS: - fas216_finish_reconnect (info); + case STAT_STATUS: + fas216_finish_reconnect(info); info->scsi.phase = PHASE_STATUS; outb(CMD_INITCMDCOMPLETE, REG_CMD(info)); - break; + return 1; - case STAT_DATAOUT: /* data out phase */ - fas216_finish_reconnect (info); - fas216_starttransfer (info, DMA_OUT); - break; - - case STAT_DATAIN: /* data in phase */ - fas216_finish_reconnect (info); - fas216_starttransfer (info, DMA_IN); - break; - - default: - printk ("scsi%d.%c: bus phase %s after reconnect?\n", - info->host->host_no, fas216_target (info), - fas216_bus_phase (stat)); - } - break; - - case PHASE_MSGIN: - switch (stat & STAT_BUSMASK) { - case STAT_MESGIN: - outb(CMD_TRANSFERINFO, REG_CMD(info)); - break; + case STAT_DATAOUT: /* data out phase */ + fas216_finish_reconnect(info); + fas216_starttransfer(info, DMA_OUT, 1); + return 1; + + case STAT_DATAIN: /* data in phase */ + fas216_finish_reconnect(info); + fas216_starttransfer(info, DMA_IN, 0); + return 1; + + default: + return 0; + } +} - default: - printk ("scsi%d.%c: bus phase %s after message in?\n", - info->host->host_no, fas216_target (info), - fas216_bus_phase (stat)); - } - break; - - case PHASE_MSGOUT: - if ((stat & STAT_BUSMASK) != STAT_MESGOUT) { - printk ("scsi%d.%c: didn't manage MESSAGE OUT phase\n", - info->host->host_no, fas216_target (info)); - } else { - unsigned int msglen; +/* Function: int fas216_busservice_messageout(FAS216_Info *info, unsigned int stat) + * Purpose : handle bus service to send a message + * Params : info - interface which caused bus service + * Returns : 0 if unable to service this interrupt + * Note : We do not allow the device to change the data direction! + */ +static int fas216_busservice_messageout(FAS216_Info *info, unsigned int stat) +{ + fas216_checkmagic(info, "fas216_busservice_messageout"); - msglen = msgqueue_msglength (&info->scsi.msgs); + if ((stat & STAT_BUSMASK) != STAT_MESGOUT) { + printk("scsi%d.%c: didn't manage MESSAGE OUT phase\n", + info->host->host_no, fas216_target(info)); + return 0; + } else { + unsigned int msglen = msgqueue_msglength(&info->scsi.msgs); outb(CMD_FLUSHFIFO, REG_CMD(info)); if (msglen == 0) - outb(NOP, REG_FF(info)); + outb(NOP, REG_FF(info)); else { - char *msg; + char *msg; - while ((msg = msgqueue_getnextmsg (&info->scsi.msgs, &msglen)) != NULL) { - for (i = 0; i < msglen; i++) - outb(msg[i], REG_FF(info)); - } + while ((msg = msgqueue_getnextmsg(&info->scsi.msgs, &msglen)) != NULL) { + int i; + + for (i = 0; i < msglen; i++) + outb(msg[i], REG_FF(info)); + } } outb(CMD_TRANSFERINFO, REG_CMD(info)); info->scsi.phase = PHASE_AFTERMSGOUT; - } - break; + return 1; + } +} - case PHASE_AFTERMSGOUT: - switch (stat & STAT_BUSMASK) { - case STAT_MESGIN: - info->scsi.phase = PHASE_MSGIN; - outb(CMD_TRANSFERINFO, REG_CMD(info)); - break; +/* Function: void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) + * Purpose : handle a bus service interrupt from FAS216 chip + * Params : info - interface which caused bus service interrupt + * stat - Status register contents + * ssr - SCSI Status register contents + */ +static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) +{ + fas216_checkmagic(info, "fas216_busservice_intr"); + +#ifdef DEBUG_BUSSERVICE + printk("scsi%d.%c: bus service: stat=%02X ssr=%02X phase=%02X\n", + info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase); +#endif + switch (ssr & IS_BITS) { + case IS_MSGBYTESENT: /* select with ATN and stop steps completed */ + case IS_COMPLETE: /* last action completed */ + outb(CMD_NOP, REG_CMD(info)); - default: - printk ("scsi%d.%c: bus phase %s after message out\n", - info->host->host_no, fas216_target (info), - fas216_bus_phase (stat)); - } - break; - - case PHASE_DISCONNECT: - printk ("scsi%d.%c: disconnect message received, but bus service %s?\n", - info->host->host_no, fas216_target (info), - fas216_bus_phase (stat)); - outb(CMD_SETATN, REG_CMD(info)); - msgqueue_addmsg (&info->scsi.msgs, 1, ABORT); - info->scsi.phase = PHASE_MSGOUT; - info->scsi.aborting = 1; - outb(CMD_TRANSFERINFO, REG_CMD(info)); - break; + switch (info->scsi.phase) { + case PHASE_SELECTION: /* while selecting - selected target */ + if (!fas216_busservice_selection(info, stat)) + printk("scsi%d.%c: bus phase %s after connect?\n", + info->host->host_no, fas216_target(info), + fas216_bus_phase(stat)); + break; + + case PHASE_MESSAGESENT: + if (!fas216_busservice_messagesent(info, stat)) + printk("scsi%d.%c: bus phase %s after message sent?\n", + info->host->host_no, fas216_target(info), + fas216_bus_phase(stat)); + break; + + case PHASE_DATAIN: /* while transfering data in */ + case PHASE_DATAOUT: /* while transfering data out */ + if (!fas216_busservice_dataphase(info, stat)) + printk("scsi%d.%c: bus phase %s after %s?\n", + info->host->host_no, fas216_target(info), + fas216_bus_phase(stat), fas216_drv_phase(info)); + break; + + case PHASE_RECONNECTED: /* newly reconnected device */ + /* + * Command reconnected - if MESGIN, get message - it may be + * the tag. If not, get command out of the disconnected queue + */ + if (!fas216_busservice_reconnected(info, stat)) + printk("scsi%d.%c: bus phase %s after reconnect?\n", + info->host->host_no, fas216_target(info), + fas216_bus_phase(stat)); + break; + + case PHASE_MSGIN: + case PHASE_AFTERMSGOUT: + switch (stat & STAT_BUSMASK) { + case STAT_MESGIN: + info->scsi.phase = PHASE_MSGIN; + outb(CMD_TRANSFERINFO, REG_CMD(info)); + break; + + case STAT_COMMAND: /* command phase */ + fas216_send_command(info); + info->scsi.phase = PHASE_SELECTION; + break; + + default: + printk("scsi%d.%c: bus phase %s after %s?\n", + info->host->host_no, fas216_target(info), + fas216_bus_phase(stat), + fas216_drv_phase(info)); + } + break; + + case PHASE_MSGOUT: + if (!fas216_busservice_messageout(info, stat)) + printk("scsi%d.%c: bus phase %s instead of message out?\n", + info->host->host_no, fas216_target(info), + fas216_bus_phase(stat)); + break; + + case PHASE_DISCONNECT: + printk("scsi%d.%c: disconnect message received, but bus service %s?\n", + info->host->host_no, fas216_target(info), + fas216_bus_phase(stat)); + outb(CMD_SETATN, REG_CMD(info)); + msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); + info->scsi.phase = PHASE_MSGOUT; + info->scsi.aborting = 1; + outb(CMD_TRANSFERINFO, REG_CMD(info)); + break; + + default: + printk("scsi%d.%c: internal phase %s for bus service?" + " What do I do with this?\n", + info->host->host_no, fas216_target(info), + fas216_drv_phase(info)); + } + break; default: - printk ("scsi%d.%c: internal phase %d for bus service?" - " What do I do with this?\n", - info->host->host_no, fas216_target (info), - info->scsi.phase); + printk("scsi%d.%c: bus service at step %d?\n", + info->host->host_no, fas216_target(info), + ssr & IS_BITS); } - break; - - default: - printk ("scsi%d.%c: bus service at step %d?\n", - info->host->host_no, fas216_target (info), - ssr & IS_BITS); - } } -/* Function: void fas216_funcdone_intr (FAS216_Info *info, unsigned int stat, unsigned int ssr) +/* Function: void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) * Purpose : handle a function done interrupt from FAS216 chip * Params : info - interface which caused function done interrupt * stat - Status register contents * ssr - SCSI Status register contents */ -static void fas216_funcdone_intr (FAS216_Info *info, unsigned int stat, unsigned int ssr) +static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) { - int status, message; + int status, message; + + fas216_checkmagic(info, "fas216_funcdone_intr"); + #ifdef DEBUG_FUNCTIONDONE - printk("scsi%d.%c: function done: stat=%X ssr=%X phase=%02X\n", - info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase); + printk("scsi%d.%c: function done: stat=%X ssr=%X phase=%02X\n", + info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase); #endif - switch (info->scsi.phase) { - case PHASE_STATUS: /* status phase - read status and msg */ - status = inb(REG_FF(info)); - message = inb(REG_FF(info)); - info->scsi.SCp.Message = message; - info->scsi.SCp.Status = status; - info->scsi.phase = PHASE_DONE; - outb(CMD_MSGACCEPTED, REG_CMD(info)); - break; + switch (info->scsi.phase) { + case PHASE_STATUS: /* status phase - read status and msg */ + status = inb(REG_FF(info)); + message = inb(REG_FF(info)); + info->scsi.SCp.Message = message; + info->scsi.SCp.Status = status; + info->scsi.phase = PHASE_DONE; + outb(CMD_MSGACCEPTED, REG_CMD(info)); + break; - case PHASE_IDLE: /* reselected? */ - case PHASE_MSGIN: /* message in phase */ - case PHASE_RECONNECTED: /* reconnected command */ - if ((stat & STAT_BUSMASK) == STAT_MESGIN) { - fas216_message (info); - break; - } + case PHASE_IDLE: /* reselected? */ + case PHASE_MSGIN: /* message in phase */ + case PHASE_RECONNECTED: /* reconnected command */ + if ((stat & STAT_BUSMASK) == STAT_MESGIN) { + fas216_message(info); + break; + } - default: - printk ("scsi%d.%c: internal phase %d for function done?" - " What do I do with this?\n", - info->host->host_no, fas216_target (info), - info->scsi.phase); - } + default: + printk("scsi%d.%c: internal phase %s for function done?" + " What do I do with this?\n", + info->host->host_no, fas216_target(info), + fas216_drv_phase(info)); + } } -/* Function: void fas216_intr (struct Scsi_Host *instance) +/* Function: void fas216_intr(struct Scsi_Host *instance) * Purpose : handle interrupts from the interface to progress a command * Params : instance - interface to service */ -void fas216_intr (struct Scsi_Host *instance) +void fas216_intr(struct Scsi_Host *instance) { - FAS216_Info *info = (FAS216_Info *)instance->hostdata; - unsigned char isr, ssr, stat; + FAS216_Info *info = (FAS216_Info *)instance->hostdata; + unsigned char isr, ssr, stat; + + fas216_checkmagic(info, "fas216_intr"); - stat = inb(REG_STAT(info)); - ssr = inb(REG_IS(info)); - isr = inb(REG_INST(info)); - - if (isr & INST_BUSRESET) - printk ("scsi%d.H: fas216: bus reset detected\n", instance->host_no); - else if (isr & INST_ILLEGALCMD) - printk (KERN_CRIT "scsi%d.H: illegal command given\n", instance->host_no); - else if (isr & INST_DISCONNECT) - fas216_disconnect_intr (info); - else if (isr & INST_RESELECTED) /* reselected */ - fas216_reselected_intr (info); - else if (isr & INST_BUSSERVICE) /* bus service request */ - fas216_busservice_intr (info, stat, ssr); - else if (isr & INST_FUNCDONE) /* function done */ - fas216_funcdone_intr (info, stat, ssr); - else - printk ("scsi%d.%c: unknown interrupt received:" - " phase %d isr %02X ssr %02X stat %02X\n", - instance->host_no, fas216_target (info), - info->scsi.phase, isr, ssr, stat); + stat = inb(REG_STAT(info)); + ssr = inb(REG_IS(info)); + isr = inb(REG_INST(info)); + + add_debug_list(stat, ssr, isr, info->scsi.phase); + + if (stat & STAT_INT) { + if (isr & INST_BUSRESET) + printk("scsi%d.H: fas216: bus reset detected\n", instance->host_no); + else if (isr & INST_ILLEGALCMD) + printk(KERN_CRIT "scsi%d.H: illegal command given\n", instance->host_no); + else if (isr & INST_DISCONNECT) + fas216_disconnect_intr(info); + else if (isr & INST_RESELECTED) /* reselected */ + fas216_reselected_intr(info); + else if (isr & INST_BUSSERVICE) /* bus service request */ + fas216_busservice_intr(info, stat, ssr); + else if (isr & INST_FUNCDONE) /* function done */ + fas216_funcdone_intr(info, stat, ssr); + else + printk("scsi%d.%c: unknown interrupt received:" + " phase %s isr %02X ssr %02X stat %02X\n", + instance->host_no, fas216_target(info), + fas216_drv_phase(info), isr, ssr, stat); + } } -/* Function: void fas216_kick (FAS216_Info *info) +/* Function: void fas216_kick(FAS216_Info *info) * Purpose : kick a command to the interface - interface should be idle * Params : info - our host interface to kick * Notes : Interrupts are always disabled! */ -static void fas216_kick (FAS216_Info *info) +static void fas216_kick(FAS216_Info *info) { Scsi_Cmnd *SCpnt; int i, msglen, from_queue = 0; + fas216_checkmagic(info, "fas216_kick"); + if (info->origSCpnt) { SCpnt = info->origSCpnt; info->origSCpnt = NULL; @@ -943,11 +1321,11 @@ return; if (info->scsi.disconnectable && info->SCpnt) { - queue_add_cmd_tail (&info->queues.disconnected, info->SCpnt); + queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt); info->scsi.disconnectable = 0; info->SCpnt = NULL; printk("scsi%d.%c: moved command to disconnected queue\n", - info->host->host_no, fas216_target (info)); + info->host->host_no, fas216_target(info)); } /* @@ -1004,7 +1382,7 @@ } /* build outgoing message bytes */ - msgqueue_flush (&info->scsi.msgs); + msgqueue_flush(&info->scsi.msgs); if (info->device[SCpnt->target].disconnect_ok) msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(1, SCpnt->lun)); else @@ -1015,7 +1393,8 @@ msgqueue_addmsg(&info->scsi.msgs, 2, SIMPLE_QUEUE_TAG, SCpnt->tag); /* add synchronous negociation */ - if (info->device[SCpnt->target].negstate == syncneg_start) { + if (SCpnt->cmnd[0] == REQUEST_SENSE && + info->device[SCpnt->target].negstate == syncneg_start) { info->device[SCpnt->target].negstate = syncneg_sent; msgqueue_addmsg(&info->scsi.msgs, 5, EXTENDED_MESSAGE, 3, EXTENDED_SDTR, @@ -1040,9 +1419,12 @@ outb(info->device[SCpnt->target].sof, REG_SOF(info)); outb(info->device[SCpnt->target].stp, REG_STP(info)); - msglen = msgqueue_msglength (&info->scsi.msgs); + msglen = msgqueue_msglength(&info->scsi.msgs); if (msglen == 1 || msglen == 3) { + /* + * We have an easy message length to send... + */ char *msg; /* load message bytes */ @@ -1060,6 +1442,22 @@ else outb(CMD_SELECTATN3, REG_CMD(info)); } else { + /* + * We have an unusual number of message bytes to send. + * Load first byte into fifo, and issue SELECT with ATN and + * stop steps. + * Note: we only peek at t his message - we need the rest + * later on! + */ + int thismsg; + char *msg = msgqueue_peeknextmsg(&info->scsi.msgs, &thismsg); + + if (!msg || thismsg < 1) + printk(KERN_CRIT "scsi%d.%c: no message to send, but %d bytes\n", + info->host->host_no, fas216_target(info), msglen); + else + outb(msg[0], REG_FF(info)); + outb(CMD_SELECTATNSTOP, REG_CMD(info)); } @@ -1070,79 +1468,95 @@ /* should now get either DISCONNECT or (FUNCTION DONE with BUS SERVICE) intr */ } -/* Function: void fas216_done (FAS216_Info *info, unsigned int result) +/* Function: void fas216_done(FAS216_Info *info, unsigned int result) * Purpose : complete processing for command * Params : info - interface that completed * result - driver byte of result */ -static void fas216_done (FAS216_Info *info, unsigned int result) +static void fas216_done(FAS216_Info *info, unsigned int result) { - Scsi_Cmnd *SCpnt = info->SCpnt; + Scsi_Cmnd *SCpnt; - if (info->scsi.aborting) { - printk ("scsi%d.%c: uncaught abort - returning DID_ABORT\n", - info->host->host_no, fas216_target (info)); - result = DID_ABORT; - info->scsi.aborting = 0; - } + fas216_checkmagic(info, "fas216_done"); - info->stats.fins += 1; + SCpnt = info->SCpnt; - if (SCpnt) { - info->scsi.phase = PHASE_IDLE; - info->SCpnt = NULL; + if (info->scsi.aborting) { + printk("scsi%d.%c: uncaught abort - returning DID_ABORT\n", + info->host->host_no, fas216_target(info)); + result = DID_ABORT; + info->scsi.aborting = 0; + } + + info->stats.fins += 1; + + if (SCpnt) { + info->scsi.phase = PHASE_IDLE; + info->SCpnt = NULL; - SCpnt->result = result << 16 | info->scsi.SCp.Message << 8 | + SCpnt->result = result << 16 | info->scsi.SCp.Message << 8 | info->scsi.SCp.Status; - /* - * In theory, this should not happen, but just in case it does. - */ - if (info->scsi.SCp.ptr && result == DID_OK) { - switch (status_byte (SCpnt->result)) { - case CHECK_CONDITION: - case COMMAND_TERMINATED: - case BUSY: - case QUEUE_FULL: - case RESERVATION_CONFLICT: - break; + /* + * In theory, this should not happen, but just in case it does. + */ + if (info->scsi.SCp.ptr && result == DID_OK) { + switch (SCpnt->cmnd[0]) { + case INQUIRY: + case START_STOP: + case READ_CAPACITY: + break; - default: - printk (KERN_ERR "scsi%d.H: incomplete data transfer " - "detected: result=%08X command=", - info->host->host_no, SCpnt->result); - print_command (SCpnt->cmnd); - } - } + default: + switch (status_byte(SCpnt->result)) { + case CHECK_CONDITION: + case COMMAND_TERMINATED: + case BUSY: + case QUEUE_FULL: + case RESERVATION_CONFLICT: + break; + + default: + printk(KERN_ERR "scsi%d.H: incomplete data transfer " + "detected: res=%08X ptr=%p len=%X command=", + info->host->host_no, SCpnt->result, + info->scsi.SCp.ptr, info->scsi.SCp.this_residual); + print_command(SCpnt->cmnd); + } + } + } #ifdef DEBUG_CONNECT - printk ("scsi%d.%c: scsi command (%p) complete, result=%08X\n", - info->host->host_no, fas216_target (info), - SCpnt, SCpnt->result); + printk("scsi%d.%c: scsi command (%p) complete, result=%08X\n", + info->host->host_no, fas216_target(info), + SCpnt, SCpnt->result); #endif - if (!SCpnt->scsi_done) - panic ("scsi%d.H: null scsi_done function in fas216_done", info->host->host_no); + if (!SCpnt->scsi_done) + panic("scsi%d.H: null scsi_done function in " + "fas216_done", info->host->host_no); - clear_bit (SCpnt->target * 8 + SCpnt->lun, info->busyluns); + clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); - SCpnt->scsi_done (SCpnt); - } else - panic ("scsi%d.H: null command in fas216_done", info->host->host_no); + SCpnt->scsi_done(SCpnt); + } else + panic("scsi%d.H: null command in fas216_done", info->host->host_no); - if (info->scsi.irq != NO_IRQ) - fas216_kick (info); + if (info->scsi.irq != NO_IRQ) + fas216_kick(info); } -/* Function: int fas216_queue_command (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) +/* Function: int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) * Purpose : queue a command for adapter to process. * Params : SCpnt - Command to queue * done - done function to call once command is complete * Returns : 0 - success, else error */ -int fas216_queue_command (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) +int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + fas216_checkmagic(info, "fas216_queue_command"); + #ifdef DEBUG_CONNECT printk("scsi%d.%c: received queuable command (%p) %02X\n", SCpnt->host->host_no, '0' + SCpnt->target, @@ -1185,47 +1599,51 @@ /* add command into execute queue and let it complete under * the drivers interrupts. */ - if (!queue_add_cmd_ordered (&info->queues.issue, SCpnt)) { + if (!queue_add_cmd_ordered(&info->queues.issue, SCpnt)) { SCpnt->result = DID_ERROR << 16; - done (SCpnt); + done(SCpnt); } - save_flags_cli (flags); + save_flags_cli(flags); if (!info->SCpnt || info->scsi.disconnectable) - fas216_kick (info); - restore_flags (flags); + fas216_kick(info); + restore_flags(flags); } else { /* no interrupts to rely on - we'll have to handle the * command ourselves. For now, we give up. */ SCpnt->result = DID_ERROR << 16; - done (SCpnt); + done(SCpnt); } return 0; } -/* Function: void fas216_internal_done (Scsi_Cmnd *SCpnt) +/* Function: void fas216_internal_done(Scsi_Cmnd *SCpnt) * Purpose : trigger restart of a waiting thread in fas216_command * Params : SCpnt - Command to wake */ -static void fas216_internal_done (Scsi_Cmnd *SCpnt) +static void fas216_internal_done(Scsi_Cmnd *SCpnt) { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + fas216_checkmagic(info, "fas216_internal_done"); + info->internal_done = 1; } -/* Function: int fas216_command (Scsi_Cmnd *SCpnt) +/* Function: int fas216_command(Scsi_Cmnd *SCpnt) * Purpose : queue a command for adapter to process. * Params : SCpnt - Command to queue * Returns : scsi result code */ -int fas216_command (Scsi_Cmnd *SCpnt) +int fas216_command(Scsi_Cmnd *SCpnt) { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; unsigned long flags; + fas216_checkmagic(info, "fas216_command"); + info->internal_done = 0; - fas216_queue_command (SCpnt, fas216_internal_done); + fas216_queue_command(SCpnt, fas216_internal_done); /* * This wastes time, since we can't return until the command is @@ -1233,13 +1651,13 @@ * However, we must re-enable interrupts, or else we'll be * waiting forever. */ - save_flags (flags); - sti (); + save_flags(flags); + sti(); while (!info->internal_done) - barrier (); + barrier(); - restore_flags (flags); + restore_flags(flags); return SCpnt->result; } @@ -1262,7 +1680,7 @@ *SCpntp1 = NULL; SCpnt->result = result; - SCpnt->scsi_done (SCpnt); + SCpnt->scsi_done(SCpnt); } if (SCpnt == *SCpntp2) @@ -1309,28 +1727,33 @@ return FAILED; } -/* Function: int fas216_abort (Scsi_Cmnd *SCpnt) +/* Function: int fas216_abort(Scsi_Cmnd *SCpnt) * Purpose : abort a command if something horrible happens. * Params : SCpnt - Command that is believed to be causing a problem. * Returns : one of SCSI_ABORT_ macros. */ -int fas216_abort (Scsi_Cmnd *SCpnt) +int fas216_abort(Scsi_Cmnd *SCpnt) { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; int result = SCSI_ABORT_SNOOZE; + fas216_checkmagic(info, "fas216_abort"); + info->stats.aborts += 1; + print_debug_list(); + fas216_dumpinfo(info); + fas216_dumpstate(info); printk(KERN_WARNING "scsi%d: fas216_abort: ", info->host->host_no); do { /* If command is waiting in the issue queue, then we can * simply remove the command and return abort status */ - if (queue_removecmd (&info->queues.issue, SCpnt)) { + if (queue_removecmd(&info->queues.issue, SCpnt)) { SCpnt->result = DID_ABORT << 16; - SCpnt->scsi_done (SCpnt); - printk ("command on issue queue"); + SCpnt->scsi_done(SCpnt); + printk("command on issue queue"); result = SCSI_ABORT_SUCCESS; break; } @@ -1338,14 +1761,14 @@ /* If the command is on the disconencted queue, we need to * reconnect to the device */ - if (queue_cmdonqueue (&info->queues.disconnected, SCpnt)) - printk ("command on disconnected queue"); + if (queue_cmdonqueue(&info->queues.disconnected, SCpnt)) + printk("command on disconnected queue"); /* If the command is connected, we need to flag that the * command needs to be aborted */ if (info->SCpnt == SCpnt) - printk ("command executing"); + printk("command executing"); /* If the command is pending for execution, then again * this is simple - we remove it and report abort status @@ -1353,14 +1776,14 @@ if (info->origSCpnt == SCpnt) { info->origSCpnt = NULL; SCpnt->result = DID_ABORT << 16; - SCpnt->scsi_done (SCpnt); - printk ("command waiting for execution"); + SCpnt->scsi_done(SCpnt); + printk("command waiting for execution"); result = SCSI_ABORT_SUCCESS; break; } } while (0); - printk ("\n"); + printk("\n"); return result; } @@ -1371,12 +1794,15 @@ */ static void fas216_reset_state(FAS216_Info *info) { + syncneg_t negstate; int i; + fas216_checkmagic(info, "fas216_reset_state"); + /* * Clear out all stale info in our state structure */ - memset (info->busyluns, 0, sizeof (info->busyluns)); + memset(info->busyluns, 0, sizeof(info->busyluns)); msgqueue_flush(&info->scsi.msgs); info->scsi.reconnected.target = 0; info->scsi.reconnected.lun = 0; @@ -1385,6 +1811,16 @@ info->scsi.last_message = 0; info->scsi.aborting = 0; info->scsi.phase = PHASE_IDLE; + info->scsi.async_stp = fas216_syncperiod(info, info->ifcfg.asyncperiod); + + if (info->host->dma_channel == NO_DMA || !info->dma.setup) + negstate = syncneg_invalid; + else +#ifdef SCSI2_SYNC + negstate = syncneg_start; +#else + negstate = syncneg_invalid; +#endif for (i = 0; i < 8; i++) { #ifndef NO_DISCONNECTS @@ -1392,13 +1828,9 @@ #else info->device[i].disconnect_ok = 0; #endif - info->device[i].stp = fas216_syncperiod(info, info->ifcfg.asyncperiod); + info->device[i].negstate = negstate; + info->device[i].stp = info->scsi.async_stp; info->device[i].sof = 0; -#ifdef SCSI2SYNC - info->device[i].negstate = syncneg_start; -#else - info->device[i].negstate = syncneg_complete; -#endif } } @@ -1408,17 +1840,19 @@ */ static void fas216_init_chip(FAS216_Info *info) { + fas216_checkmagic(info, "fas216_init_chip"); + outb(fas216_clockrate(info->ifcfg.clockrate), REG_CLKF(info)); outb(info->scsi.cfg[0], REG_CNTL1(info)); outb(info->scsi.cfg[1], REG_CNTL2(info)); outb(info->scsi.cfg[2], REG_CNTL3(info)); outb(info->ifcfg.select_timeout, REG_STIM(info)); outb(0, REG_SOF(info)); - outb(fas216_syncperiod(info, info->ifcfg.asyncperiod), REG_STP(info)); + outb(info->scsi.async_stp, REG_STP(info)); outb(info->scsi.cfg[0], REG_CNTL1(info)); } -/* Function: int fas216_reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags) +/* Function: int fas216_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) * Purpose : resets the adapter if something horrible happens. * Params : SCpnt - Command that is believed to be causing a problem. * reset_flags - flags indicating reset type that is believed @@ -1426,51 +1860,72 @@ * Returns : one of SCSI_RESET_ macros, or'd with the SCSI_RESET_*_RESET * macros. */ -int fas216_reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags) +int fas216_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; Scsi_Cmnd *SCptr; int result = 0; + fas216_checkmagic(info, "fas216_reset"); + + /* + * Validate that command is actually on one of our queues if we're doing + * an asynchronous reset + */ + if (reset_flags & SCSI_RESET_ASYNCHRONOUS && + SCpnt && + info->SCpnt != SCpnt && + info->origSCpnt != SCpnt && + !queue_cmdonqueue(&info->queues.disconnected, SCpnt) && + !queue_cmdonqueue(&info->queues.issue, SCpnt)) { + printk("scsi%d: fas216_reset: asynchronous reset for unknown command\n", + info->host->host_no); + return SCSI_RESET_NOT_RUNNING; + } + info->stats.resets += 1; + print_debug_list(); printk(KERN_WARNING "scsi%d: fas216_reset: ", info->host->host_no); + if (SCpnt) + printk(" for target %d ", SCpnt->target); outb(info->scsi.cfg[3], REG_CNTL3(info)); fas216_stoptransfer(info); - fas216_reset_state(info); - if (reset_flags & SCSI_RESET_SUGGEST_HOST_RESET) { + switch (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET)) { + case SCSI_RESET_SUGGEST_BUS_RESET: + outb(CMD_RESETSCSI, REG_CMD(info)); + outb(CMD_NOP, REG_CMD(info)); + result |= SCSI_RESET_BUS_RESET; + break; + + case SCSI_RESET_SUGGEST_HOST_RESET: outb(CMD_RESETCHIP, REG_CMD(info)); outb(CMD_NOP, REG_CMD(info)); result |= SCSI_RESET_HOST_RESET; - } - - if (reset_flags & SCSI_RESET_SUGGEST_BUS_RESET) { - outb(CMD_RESETSCSI, REG_CMD(info)); - outb(CMD_NOP, REG_CMD(info)); - result |= SCSI_RESET_BUS_RESET; - } + break; - if (!(reset_flags & - (SCSI_RESET_SUGGEST_BUS_RESET|SCSI_RESET_SUGGEST_HOST_RESET))) { + default: outb(CMD_RESETCHIP, REG_CMD(info)); outb(CMD_NOP, REG_CMD(info)); outb(CMD_RESETSCSI, REG_CMD(info)); result |= SCSI_RESET_HOST_RESET | SCSI_RESET_BUS_RESET; + break; } - if (result & SCSI_RESET_HOST_RESET) - fas216_init_chip(info); + udelay(300); + fas216_reset_state(info); + fas216_init_chip(info); /* * Signal all commands in progress have been reset */ - fas216_reportstatus (&info->SCpnt, &SCpnt, DID_RESET << 16); + fas216_reportstatus(&info->SCpnt, &SCpnt, DID_RESET << 16); - while ((SCptr = queue_remove (&info->queues.disconnected)) != NULL) - fas216_reportstatus (&SCptr, &SCpnt, DID_RESET << 16); + while ((SCptr = queue_remove(&info->queues.disconnected)) != NULL) + fas216_reportstatus(&SCptr, &SCpnt, DID_RESET << 16); if (SCpnt) { /* @@ -1483,42 +1938,45 @@ queue_removecmd(&info->queues.issue, SCpnt); SCpnt->result = DID_RESET << 16; - SCpnt->scsi_done (SCpnt); + SCpnt->scsi_done(SCpnt); } - printk ("\n"); + printk("\n"); return result | SCSI_RESET_SUCCESS; } -/* Function: int fas216_init (struct Scsi_Host *instance) +/* Function: int fas216_init(struct Scsi_Host *instance) * Purpose : initialise FAS/NCR/AMD SCSI ic. * Params : instance - a driver-specific filled-out structure * Returns : 0 on success */ -int fas216_init (struct Scsi_Host *instance) +int fas216_init(struct Scsi_Host *instance) { FAS216_Info *info = (FAS216_Info *)instance->hostdata; unsigned long flags; int target_jiffies; + info->magic_start = MAGIC; + info->magic_end = MAGIC; + info->host = instance; info->scsi.cfg[0] = instance->this_id; info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE; - info->scsi.cfg[2] = CNTL3_ADIDCHK | CNTL3_G2CB | CNTL3_FASTSCSI | CNTL3_FASTCLK; + info->scsi.cfg[2] = info->ifcfg.cntl3 | CNTL3_ADIDCHK | CNTL3_G2CB; info->scsi.type = "unknown"; info->SCpnt = NULL; fas216_reset_state(info); - memset (&info->stats, 0, sizeof (info->stats)); + memset(&info->stats, 0, sizeof(info->stats)); - msgqueue_initialise (&info->scsi.msgs); + msgqueue_initialise(&info->scsi.msgs); - if (!queue_initialise (&info->queues.issue)) + if (!queue_initialise(&info->queues.issue)) return 1; - if (!queue_initialise (&info->queues.disconnected)) { - queue_free (&info->queues.issue); + if (!queue_initialise(&info->queues.disconnected)) { + queue_free(&info->queues.issue); return 1; } @@ -1555,8 +2013,7 @@ break; } - udelay (300); - + udelay(300); /* now for the real initialisation */ fas216_init_chip(info); @@ -1565,32 +2022,39 @@ /* scsi standard says 250ms */ target_jiffies = jiffies + (25 * HZ) / 100; - save_flags (flags); - sti (); + save_flags(flags); + sti(); - while (jiffies < target_jiffies) barrier (); + while (jiffies < target_jiffies) barrier(); - restore_flags (flags); + restore_flags(flags); outb(info->scsi.cfg[0], REG_CNTL1(info)); inb(REG_INST(info)); + /* now for the real initialisation */ + fas216_init_chip(info); + + fas216_checkmagic(info, "fas216_init"); + return 0; } -/* Function: int fas216_release (struct Scsi_Host *instance) +/* Function: int fas216_release(struct Scsi_Host *instance) * Purpose : release all resources and put everything to bed for * FAS/NCR/AMD SCSI ic. * Params : instance - a driver-specific filled-out structure * Returns : 0 on success */ -int fas216_release (struct Scsi_Host *instance) +int fas216_release(struct Scsi_Host *instance) { FAS216_Info *info = (FAS216_Info *)instance->hostdata; + fas216_checkmagic(info, "fas216_release"); + outb(CMD_RESETCHIP, REG_CMD(info)); - queue_free (&info->queues.disconnected); - queue_free (&info->queues.issue); + queue_free(&info->queues.disconnected); + queue_free(&info->queues.issue); return 0; } @@ -1609,12 +2073,12 @@ #ifdef MODULE -int init_module (void) +int init_module(void) { return 0; } -void cleanup_module (void) +void cleanup_module(void) { } #endif diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/fas216.h linux/drivers/acorn/scsi/fas216.h --- v2.1.100/linux/drivers/acorn/scsi/fas216.h Wed Apr 8 19:36:25 1998 +++ linux/drivers/acorn/scsi/fas216.h Fri May 8 00:42:39 1998 @@ -55,8 +55,8 @@ /* status register (read) */ #define REG_STAT(x) ((x)->scsi.io_port + (4 << (x)->scsi.io_shift)) -#define STAT_IO (1 << 0) /* IO phase */ -#define STAT_CD (1 << 1) /* CD phase */ +#define STAT_IO (1 << 0) /* IO phase */ +#define STAT_CD (1 << 1) /* CD phase */ #define STAT_MSG (1 << 2) /* MSG phase */ #define STAT_TRANSFERDONE (1 << 3) /* Transfer completed */ #define STAT_TRANSFERCNTZ (1 << 4) /* Transfer counter is zero */ @@ -98,6 +98,7 @@ #define IS_NOTCOMMAND 0x02 /* Not in command state */ #define IS_EARLYPHASE 0x03 /* Early phase change */ #define IS_COMPLETE 0x04 /* Command ok */ +#define IS_SOF 0x08 /* Sync off flag */ /* Transfer period step (write) */ #define REG_STP(x) ((x)->scsi.io_port + (6 << (x)->scsi.io_shift)) @@ -170,6 +171,7 @@ typedef enum { PHASE_IDLE, /* we're not planning on doing anything */ PHASE_SELECTION, /* selecting a device */ + PHASE_MESSAGESENT, /* selected, and we're sending cmd */ PHASE_RECONNECTED, /* reconnected */ PHASE_DATAOUT, /* data out to device */ PHASE_DATAIN, /* data in from device */ @@ -188,6 +190,7 @@ typedef enum { fasdma_none, /* No dma */ + fasdma_pio, /* PIO mode */ fasdma_pseudo, /* Pseudo DMA */ fasdma_real_block, /* Real DMA, on block by block basis */ fasdma_real_all /* Real DMA, on request by request */ @@ -196,10 +199,14 @@ typedef enum { syncneg_start, /* Negociate with device for Sync xfers */ syncneg_sent, /* Sync Xfer negociation sent */ - syncneg_complete /* Sync Xfer complete */ + syncneg_complete, /* Sync Xfer complete */ + syncneg_invalid /* Sync Xfer not supported */ } syncneg_t; +#define MAGIC 0x441296bdUL + typedef struct { + unsigned long magic_start; struct Scsi_Host *host; /* host */ Scsi_Cmnd *SCpnt; /* currently processing command */ Scsi_Cmnd *origSCpnt; /* original connecting command */ @@ -208,7 +215,7 @@ struct { unsigned int io_port; /* base address of FAS216 */ unsigned int io_shift; /* shift to adjust reg offsets by */ - unsigned char irq; /* interrupt */ + unsigned int irq; /* interrupt */ unsigned char cfg[4]; /* configuration registers */ const char *type; /* chip type */ phase_t phase; /* current phase */ @@ -223,6 +230,7 @@ MsgQueue_t msgs; /* message queue for connected device */ + unsigned int async_stp; /* Async transfer STP value */ unsigned short last_message; /* last message to be sent */ unsigned char disconnectable:1; /* this command can be disconnected */ @@ -246,8 +254,9 @@ struct { unsigned char clockrate; /* clock rate of FAS device (MHz) */ unsigned char select_timeout; /* timeout (R5) */ - unsigned int asyncperiod; /* Async transfer period (ns) */ unsigned char sync_max_depth; /* Synchronous xfer max fifo depth */ + unsigned char cntl3; /* Control Reg 3 */ + unsigned int asyncperiod; /* Async transfer period (ns) */ } ifcfg; /* queue handling */ @@ -268,13 +277,15 @@ /* dma */ struct { fasdmatype_t transfer_type; /* current type of DMA transfer */ - fasdmatype_t (*setup) (struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction); - int (*pseudo)(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, int transfer); + fasdmatype_t (*setup) (struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, fasdmatype_t min_dma); + void (*pseudo)(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, int transfer); void (*stop) (struct Scsi_Host *host, Scsi_Pointer *SCp); } dma; /* miscellaneous */ int internal_done; /* flag to indicate request done */ + + unsigned long magic_end; } FAS216_Info; /* Function: int fas216_init (struct Scsi_Host *instance) diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/msgqueue.c linux/drivers/acorn/scsi/msgqueue.c --- v2.1.100/linux/drivers/acorn/scsi/msgqueue.c Mon Feb 23 18:12:03 1998 +++ linux/drivers/acorn/scsi/msgqueue.c Fri May 8 00:42:39 1998 @@ -11,12 +11,12 @@ #include "msgqueue.h" /* - * Function: struct msgqueue_entry *mqe_alloc (MsgQueue_t *msgq) + * Function: struct msgqueue_entry *mqe_alloc(MsgQueue_t *msgq) * Purpose : Allocate a message queue entry * Params : msgq - message queue to claim entry for * Returns : message queue entry or NULL. */ -static struct msgqueue_entry *mqe_alloc (MsgQueue_t *msgq) +static struct msgqueue_entry *mqe_alloc(MsgQueue_t *msgq) { struct msgqueue_entry *mq; @@ -27,12 +27,12 @@ } /* - * Function: void mqe_free (MsgQueue_t *msgq, struct msgqueue_entry *mq) + * Function: void mqe_free(MsgQueue_t *msgq, struct msgqueue_entry *mq) * Purpose : free a message queue entry * Params : msgq - message queue to free entry from * mq - message queue entry to free */ -static void mqe_free (MsgQueue_t *msgq, struct msgqueue_entry *mq) +static void mqe_free(MsgQueue_t *msgq, struct msgqueue_entry *mq) { if (mq) { mq->next = msgq->free; @@ -41,11 +41,11 @@ } /* - * Function: void msgqueue_initialise (MsgQueue_t *msgq) + * Function: void msgqueue_initialise(MsgQueue_t *msgq) * Purpose : initialise a message queue * Params : msgq - queue to initialise */ -void msgqueue_initialise (MsgQueue_t *msgq) +void msgqueue_initialise(MsgQueue_t *msgq) { int i; @@ -60,21 +60,21 @@ /* - * Function: void msgqueue_free (MsgQueue_t *msgq) + * Function: void msgqueue_free(MsgQueue_t *msgq) * Purpose : free a queue * Params : msgq - queue to free */ -void msgqueue_free (MsgQueue_t *msgq) +void msgqueue_free(MsgQueue_t *msgq) { } /* - * Function: int msgqueue_msglength (MsgQueue_t *msgq) + * Function: int msgqueue_msglength(MsgQueue_t *msgq) * Purpose : calculate the total length of all messages on the message queue * Params : msgq - queue to examine * Returns : number of bytes of messages in queue */ -int msgqueue_msglength (MsgQueue_t *msgq) +int msgqueue_msglength(MsgQueue_t *msgq) { struct msgqueue_entry *mq = msgq->qe; int length = 0; @@ -86,19 +86,19 @@ } /* - * Function: char *msgqueue_getnextmsg (MsgQueue_t *msgq, int *length) + * Function: char *msgqueue_getnextmsg(MsgQueue_t *msgq, int *length) * Purpose : return a message & its length * Params : msgq - queue to obtain message from * length - pointer to int for message length - * Returns : pointer to message string + * Returns : pointer to message string, or NULL */ -char *msgqueue_getnextmsg (MsgQueue_t *msgq, int *length) +char *msgqueue_getnextmsg(MsgQueue_t *msgq, int *length) { struct msgqueue_entry *mq; if ((mq = msgq->qe) != NULL) { msgq->qe = mq->next; - mqe_free (msgq, mq); + mqe_free(msgq, mq); *length = mq->length; } @@ -106,26 +106,42 @@ } /* - * Function: int msgqueue_addmsg (MsgQueue_t *msgq, int length, ...) + * Function: char *msgqueue_peeknextmsg(MsgQueue_t *msgq, int *length) + * Purpose : return next message & length without removing it from the list + * Params : msgq - queue to obtain message from + * : length - pointer to int for message length + * Returns : pointer to message string, or NULL + */ +char *msgqueue_peeknextmsg(MsgQueue_t *msgq, int *length) +{ + struct msgqueue_entry *mq = msgq->qe; + + *length = mq ? mq->length : 0; + + return mq ? mq->msg : NULL; +} + +/* + * Function: int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...) * Purpose : add a message onto a message queue * Params : msgq - queue to add message on * length - length of message * ... - message bytes * Returns : != 0 if successful */ -int msgqueue_addmsg (MsgQueue_t *msgq, int length, ...) +int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...) { - struct msgqueue_entry *mq = mqe_alloc (msgq); + struct msgqueue_entry *mq = mqe_alloc(msgq); va_list ap; if (mq) { struct msgqueue_entry **mqp; int i; - va_start (ap, length); + va_start(ap, length); for (i = 0; i < length; i++) - mq->msg[i] = va_arg (ap, unsigned char); - va_end (ap); + mq->msg[i] = va_arg(ap, unsigned char); + va_end(ap); mq->length = length; mq->next = NULL; @@ -141,17 +157,17 @@ } /* - * Function: void msgqueue_flush (MsgQueue_t *msgq) + * Function: void msgqueue_flush(MsgQueue_t *msgq) * Purpose : flush all messages from message queue * Params : msgq - queue to flush */ -void msgqueue_flush (MsgQueue_t *msgq) +void msgqueue_flush(MsgQueue_t *msgq) { struct msgqueue_entry *mq, *mqnext; for (mq = msgq->qe; mq; mq = mqnext) { mqnext = mq->next; - mqe_free (msgq, mq); + mqe_free(msgq, mq); } msgq->qe = NULL; } @@ -160,16 +176,17 @@ EXPORT_SYMBOL(msgqueue_free); EXPORT_SYMBOL(msgqueue_msglength); EXPORT_SYMBOL(msgqueue_getnextmsg); +EXPORT_SYMBOL(msgqueue_peeknextmsg); EXPORT_SYMBOL(msgqueue_addmsg); EXPORT_SYMBOL(msgqueue_flush); #ifdef MODULE -int init_module (void) +int init_module(void) { return 0; } -void cleanup_module (void) +void cleanup_module(void) { } #endif diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/msgqueue.h linux/drivers/acorn/scsi/msgqueue.h --- v2.1.100/linux/drivers/acorn/scsi/msgqueue.h Mon Feb 23 18:12:03 1998 +++ linux/drivers/acorn/scsi/msgqueue.h Fri May 8 00:42:39 1998 @@ -47,9 +47,18 @@ * Purpose : return a message & its length * Params : msgq - queue to obtain message from * length - pointer to int for message length - * Returns : pointer to message string + * Returns : pointer to message string, or NULL */ extern char *msgqueue_getnextmsg (MsgQueue_t *msgq, int *length); + +/* + * Function: char *msgqueue_peeknextmsg(MsgQueue_t *msgq, int *length) + * Purpose : return next message & length without removing it from the list + * Params : msgq - queue to obtain message from + * : length - pointer to int for message length + * Returns : pointer to message string, or NULL + */ +extern char *msgqueue_peeknextmsg(MsgQueue_t *msgq, int *length); /* * Function: int msgqueue_addmsg (MsgQueue_t *msgq, int length, ...) diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/oak.c linux/drivers/acorn/scsi/oak.c --- v2.1.100/linux/drivers/acorn/scsi/oak.c Wed Apr 8 19:36:25 1998 +++ linux/drivers/acorn/scsi/oak.c Fri May 8 00:42:39 1998 @@ -33,6 +33,11 @@ /* * $Log: oak.c,v $ + * Revision 1.3 1998/05/03 20:45:37 alan + * ARM SCSI update. This adds the eesox driver and massively updates the + * Cumana driver. The folks who bought cumana arent anal retentive all + * docs are secret weenies so now there are docs .. + * * Revision 1.2 1998/03/08 05:49:48 davem * Merge to 2.1.89 * @@ -122,7 +127,7 @@ printk("scsi%d: that the board had an interrupt!\n", instance->host_no); } - printk("scsi%d: at port %X irq", instance->host_no, instance->io_port); + printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port); if (instance->irq == IRQ_NONE) printk ("s disabled"); else diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/powertec.c linux/drivers/acorn/scsi/powertec.c --- v2.1.100/linux/drivers/acorn/scsi/powertec.c Mon Feb 23 18:12:03 1998 +++ linux/drivers/acorn/scsi/powertec.c Fri May 8 00:42:39 1998 @@ -1,15 +1,17 @@ /* * linux/arch/arm/drivers/scsi/powertec.c * - * Copyright (C) 1997 Russell King + * Copyright (C) 1997-1998 Russell King * * This driver is based on experimentation. Hence, it may have made * assumptions about the particular card that I have available, and * may not be reliable! * * Changelog: - * 01-10-1997 RMK Created, READONLY version - * 15-02-1998 RMK Added DMA support and hardware definitions + * 01-10-1997 RMK Created, READONLY version. + * 15-02-1998 RMK Added DMA support and hardware definitions. + * 15-04-1998 RMK Only do PIO if FAS216 will allow it. + * 02-05-1998 RMK Moved DMA sg list into per-interface structure. */ #include @@ -23,10 +25,10 @@ #include #include -#include -#include #include #include +#include +#include #include #include "../../scsi/sd.h" @@ -36,7 +38,7 @@ /* Configuration */ #define POWERTEC_XTALFREQ 40 #define POWERTEC_ASYNC_PERIOD 200 -#define POWERTEC_SYNC_DEPTH 16 +#define POWERTEC_SYNC_DEPTH 7 /* * List of devices that the driver will recognise @@ -45,8 +47,16 @@ #define POWERTEC_FAS216_OFFSET 0xc00 #define POWERTEC_FAS216_SHIFT 4 + #define POWERTEC_INTR_STATUS 0x800 #define POWERTEC_INTR_BIT 0x80 + +#define POWERTEC_RESET_CONTROL 0x406 +#define POWERTEC_RESET_BIT 1 + +#define POWERTEC_TERM_CONTROL 0x806 +#define POWERTEC_TERM_ENABLE 1 + #define POWERTEC_INTR_CONTROL 0x407 #define POWERTEC_INTR_ENABLE 1 #define POWERTEC_INTR_DISABLE 0 @@ -56,19 +66,24 @@ */ #define VER_MAJOR 0 #define VER_MINOR 0 -#define VER_PATCH 1 +#define VER_PATCH 2 static struct expansion_card *ecs[MAX_ECARDS]; +/* + * Use term=0,1,0,0,0 to turn terminators on/off + */ +int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 }; + static struct proc_dir_entry proc_scsi_powertec = { PROC_SCSI_QLOGICISP, 8, "powertec", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; -/* Function: void powertecscsi_irqenable(ec, irqnr) - * Purpose : Enable interrupts on powertec SCSI card - * Params : ec - expansion card structure - * : irqnr - interrupt number +/* Prototype: void powertecscsi_irqenable(ec, irqnr) + * Purpose : Enable interrupts on Powertec SCSI card + * Params : ec - expansion card structure + * : irqnr - interrupt number */ static void powertecscsi_irqenable(struct expansion_card *ec, int irqnr) @@ -77,10 +92,10 @@ outb(POWERTEC_INTR_ENABLE, port); } -/* Function: void powertecscsi_irqdisable(ec, irqnr) - * Purpose : Disable interrupts on powertec SCSI card - * Params : ec - expansion card structure - * : irqnr - interrupt number +/* Prototype: void powertecscsi_irqdisable(ec, irqnr) + * Purpose : Disable interrupts on Powertec SCSI card + * Params : ec - expansion card structure + * : irqnr - interrupt number */ static void powertecscsi_irqdisable(struct expansion_card *ec, int irqnr) @@ -96,19 +111,36 @@ NULL }; -/* Function: void powertecscsi_intr(int irq, void *dev_id, - * struct pt_regs *regs) - * Purpose : handle interrupts from Powertec SCSI card - * Params : irq - interrupt number - * dev_id - user-defined (Scsi_Host structure) - * regs - processor registers at interrupt +/* Prototype: void powertecscsi_terminator_ctl(host, on_off) + * Purpose : Turn the Powertec SCSI terminators on or off + * Params : host - card to turn on/off + * : on_off - !0 to turn on, 0 to turn off + */ +static void +powertecscsi_terminator_ctl(struct Scsi_Host *host, int on_off) +{ + PowerTecScsi_Info *info = (PowerTecScsi_Info *)host->hostdata; + + if (on_off) + info->control.terms = POWERTEC_TERM_ENABLE; + else + info->control.terms = 0; + + outb(info->control.terms, info->control.term_port); +} + +/* Prototype: void powertecscsi_intr(irq, *dev_id, *regs) + * Purpose : handle interrupts from Powertec SCSI card + * Params : irq - interrupt number + * dev_id - user-defined (Scsi_Host structure) + * regs - processor registers at interrupt */ static void powertecscsi_intr(int irq, void *dev_id, struct pt_regs *regs) { - struct Scsi_Host *instance = (struct Scsi_Host *)dev_id; + struct Scsi_Host *host = (struct Scsi_Host *)dev_id; - fas216_intr(instance); + fas216_intr(host); } static void @@ -125,66 +157,73 @@ (unsigned long)addr + len); } -/* Function: fasdmatype_t powertecscsi_dma_setup(instance, SCpnt, direction) - * Purpose : initialises DMA/PIO - * Params : instance - host - * SCpnt - command - * direction - DMA on to/off of card - * Returns : type of transfer to be performed +/* Prototype: fasdmatype_t powertecscsi_dma_setup(host, SCpnt, direction, min_type) + * Purpose : initialises DMA/PIO + * Params : host - host + * SCpnt - command + * direction - DMA on to/off of card + * min_type - minimum DMA support that we must have for this transfer + * Returns : type of transfer to be performed */ static fasdmatype_t -powertecscsi_dma_setup(struct Scsi_Host *instance, Scsi_Pointer *SCp, - fasdmadir_t direction) +powertecscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp, + fasdmadir_t direction, fasdmatype_t min_type) { - if (instance->dma_channel != NO_DMA && SCp->this_residual >= 512) { + PowerTecScsi_Info *info = (PowerTecScsi_Info *)host->hostdata; + int dmach = host->dma_channel; + + if (dmach != NO_DMA && + (min_type == fasdma_real_all || SCp->this_residual >= 512)) { int buf; -static dmasg_t dmasg[256]; - for (buf = 1; buf <= SCp->buffers_residual; buf++) { - dmasg[buf].address = __virt_to_bus( + for (buf = 1; buf <= SCp->buffers_residual && + buf < NR_SG; buf++) { + info->dmasg[buf].address = __virt_to_bus( (unsigned long)SCp->buffer[buf].address); - dmasg[buf].length = SCp->buffer[buf].length; + info->dmasg[buf].length = SCp->buffer[buf].length; powertecscsi_invalidate(SCp->buffer[buf].address, SCp->buffer[buf].length, direction); } - dmasg[0].address = __virt_to_phys((unsigned long)SCp->ptr); - dmasg[0].length = SCp->this_residual; + info->dmasg[0].address = __virt_to_phys((unsigned long)SCp->ptr); + info->dmasg[0].length = SCp->this_residual; powertecscsi_invalidate(SCp->ptr, SCp->this_residual, direction); - disable_dma(instance->dma_channel); - set_dma_sg(instance->dma_channel, dmasg, buf); - set_dma_mode(instance->dma_channel, + disable_dma(dmach); + set_dma_sg(dmach, info->dmasg, buf); + set_dma_mode(dmach, direction == DMA_OUT ? DMA_MODE_WRITE : DMA_MODE_READ); - enable_dma(instance->dma_channel); + enable_dma(dmach); return fasdma_real_all; } + /* - * We don't do DMA, we only do slow PIO + * If we're not doing DMA, + * we'll do slow PIO */ - return fasdma_none; + return fasdma_pio; } -/* Function: int powertecscsi_dma_stop(instance, SCpnt) - * Purpose : stops DMA/PIO - * Params : instance - host - * SCpnt - command +/* Prototype: int powertecscsi_dma_stop(host, SCpnt) + * Purpose : stops DMA/PIO + * Params : host - host + * SCpnt - command */ static void -powertecscsi_dma_stop(struct Scsi_Host *instance, Scsi_Pointer *SCp) +powertecscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp) { - if (instance->dma_channel != NO_DMA) - disable_dma(instance->dma_channel); + if (host->dma_channel != NO_DMA) + disable_dma(host->dma_channel); } -/* Function: int powertecscsi_detect(Scsi_Host_Template * tpnt) - * Purpose : initialises PowerTec SCSI driver - * Params : tpnt - template for this SCSI adapter - * Returns : >0 if host found, 0 otherwise. +/* Prototype: int powertecscsi_detect(Scsi_Host_Template * tpnt) + * Purpose : initialises PowerTec SCSI driver + * Params : tpnt - template for this SCSI adapter + * Returns : >0 if host found, 0 otherwise. */ int powertecscsi_detect(Scsi_Host_Template *tpnt) @@ -192,14 +231,14 @@ static const card_ids powertecscsi_cids[] = { POWERTECSCSI_LIST, { 0xffff, 0xffff} }; int count = 0; - struct Scsi_Host *instance; + struct Scsi_Host *host; tpnt->proc_dir = &proc_scsi_powertec; memset(ecs, 0, sizeof (ecs)); ecard_startfind(); - while(1) { + while (1) { PowerTecScsi_Info *info; ecs[count] = ecard_find(0, powertecscsi_cids); @@ -208,88 +247,94 @@ ecard_claim(ecs[count]); - instance = scsi_register(tpnt, sizeof (PowerTecScsi_Info)); - if (!instance) { + host = scsi_register(tpnt, sizeof (PowerTecScsi_Info)); + if (!host) { ecard_release(ecs[count]); break; } - instance->io_port = ecard_address(ecs[count], ECARD_IOC, 0); - instance->irq = ecs[count]->irq; - - ecs[count]->irqaddr = (unsigned char *) - ioaddr(instance->io_port + POWERTEC_INTR_STATUS); - ecs[count]->irqmask = POWERTEC_INTR_BIT; - ecs[count]->irq_data = (void *) - (instance->io_port + POWERTEC_INTR_CONTROL); - ecs[count]->ops = (expansioncard_ops_t *)&powertecscsi_ops; - - request_region(instance->io_port + POWERTEC_FAS216_OFFSET, - 16 << POWERTEC_FAS216_SHIFT, "powertec2-fas"); + host->io_port = ecard_address(ecs[count], ECARD_IOC, ECARD_FAST); + host->irq = ecs[count]->irq; + host->dma_channel = ecs[count]->dma; + info = (PowerTecScsi_Info *)host->hostdata; + + info->control.term_port = host->io_port + POWERTEC_TERM_CONTROL; + info->control.terms = term[count] ? POWERTEC_TERM_ENABLE : 0; + powertecscsi_terminator_ctl(host, info->control.terms); - if (request_irq(instance->irq, powertecscsi_intr, - SA_INTERRUPT, "powertec", instance)) { + info->info.scsi.io_port = + host->io_port + POWERTEC_FAS216_OFFSET; + info->info.scsi.io_shift= POWERTEC_FAS216_SHIFT; + info->info.scsi.irq = host->irq; + info->info.ifcfg.clockrate = POWERTEC_XTALFREQ; + info->info.ifcfg.select_timeout = 255; + info->info.ifcfg.asyncperiod = POWERTEC_ASYNC_PERIOD; + info->info.ifcfg.sync_max_depth = POWERTEC_SYNC_DEPTH; + info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; + info->info.dma.setup = powertecscsi_dma_setup; + info->info.dma.pseudo = NULL; + info->info.dma.stop = powertecscsi_dma_stop; + + ecs[count]->irqaddr = (unsigned char *) + ioaddr(host->io_port + POWERTEC_INTR_STATUS); + ecs[count]->irqmask = POWERTEC_INTR_BIT; + ecs[count]->irq_data = (void *) + (host->io_port + POWERTEC_INTR_CONTROL); + ecs[count]->ops = (expansioncard_ops_t *)&powertecscsi_ops; + + request_region(host->io_port + POWERTEC_FAS216_OFFSET, + 16 << POWERTEC_FAS216_SHIFT, "powertec2-fas"); + + if (host->irq != NO_IRQ && + request_irq(host->irq, powertecscsi_intr, + SA_INTERRUPT, "powertec", host)) { printk("scsi%d: IRQ%d not free, interrupts disabled\n", - instance->host_no, instance->irq); - instance->irq = NO_IRQ; + host->host_no, host->irq); + host->irq = NO_IRQ; + info->info.scsi.irq = NO_IRQ; } - info = (PowerTecScsi_Info *)instance->hostdata; - - instance->dma_channel = 3; /* slot 1 */ - if (request_dma(instance->dma_channel, "powertec")) { + if (host->dma_channel != NO_DMA && + request_dma(host->dma_channel, "powertec")) { printk("scsi%d: DMA%d not free, DMA disabled\n", - instance->host_no, instance->dma_channel); - instance->dma_channel = NO_DMA; + host->host_no, host->dma_channel); + host->dma_channel = NO_DMA; } - info->info.scsi.io_port = - instance->io_port + POWERTEC_FAS216_OFFSET; - info->info.scsi.io_shift= POWERTEC_FAS216_SHIFT; - info->info.scsi.irq = instance->irq; - info->info.ifcfg.clockrate = POWERTEC_XTALFREQ; - info->info.ifcfg.select_timeout = 255; - info->info.ifcfg.asyncperiod = POWERTEC_ASYNC_PERIOD; - info->info.ifcfg.sync_max_depth = POWERTEC_SYNC_DEPTH; - info->info.dma.setup = powertecscsi_dma_setup; - info->info.dma.pseudo = NULL; - info->info.dma.stop = powertecscsi_dma_stop; - - fas216_init(instance); + fas216_init(host); ++count; } return count; } -/* Function: int powertecscsi_release(struct Scsi_Host * host) - * Purpose : releases all resources used by this adapter - * Params : host - driver host structure to return info for. - * Returns : nothing +/* Prototype: int powertecscsi_release(struct Scsi_Host * host) + * Purpose : releases all resources used by this adapter + * Params : host - driver host structure to return info for. */ -int powertecscsi_release(struct Scsi_Host *instance) +int powertecscsi_release(struct Scsi_Host *host) { int i; - fas216_release(instance); + fas216_release(host); - if (instance->irq != NO_IRQ) - free_irq(instance->irq, instance); - if (instance->dma_channel != NO_DMA) - free_dma(instance->dma_channel); - release_region(instance->io_port + POWERTEC_FAS216_OFFSET, + if (host->irq != NO_IRQ) + free_irq(host->irq, host); + if (host->dma_channel != NO_DMA) + free_dma(host->dma_channel); + release_region(host->io_port + POWERTEC_FAS216_OFFSET, 16 << POWERTEC_FAS216_SHIFT); for (i = 0; i < MAX_ECARDS; i++) if (ecs[i] && - instance->io_port == ecard_address(ecs[i], ECARD_IOC, 0)) + host->io_port == ecard_address(ecs[i], ECARD_IOC, ECARD_FAST)) ecard_release(ecs[i]); return 0; } -/* Function: const char *powertecscsi_info(struct Scsi_Host * host) - * Purpose : returns a descriptive string about this interface, - * Params : host - driver host structure to return info for. - * Returns : pointer to a static buffer containing null terminated string. +/* Prototype: const char *powertecscsi_info(struct Scsi_Host * host) + * Purpose : returns a descriptive string about this interface, + * Params : host - driver host structure to return info for. + * Returns : pointer to a static buffer containing null terminated string. */ const char *powertecscsi_info(struct Scsi_Host *host) { @@ -297,7 +342,7 @@ static char string[100], *p; p = string; - p += sprintf(string, "%s at port %X ", + p += sprintf(string, "%s at port %lX ", host->hostt->name, host->io_port); if (host->irq != NO_IRQ) @@ -314,21 +359,55 @@ VER_MAJOR, VER_MINOR, VER_PATCH, info->info.scsi.type); + p += sprintf(p, " terminators %s", + info->control.terms ? "on" : "off"); + return string; } -/* Function: int powertecscsi_proc_info(char *buffer, char **start, off_t offset, +/* Prototype: int powertecscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length) + * Purpose : Set a driver specific function + * Params : host - host to setup + * : buffer - buffer containing string describing operation + * : length - length of string + * Returns : -EINVAL, or 0 + */ +static int +powertecscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length) +{ + int ret = length; + + if (length >= 12 && strncmp(buffer, "POWERTECSCSI", 12) == 0) { + buffer += 12; + length -= 12; + + if (length >= 5 && strncmp(buffer, "term=", 5) == 0) { + if (buffer[5] == '1') + powertecscsi_terminator_ctl(host, 1); + else if (buffer[5] == '0') + powertecscsi_terminator_ctl(host, 0); + else + ret = -EINVAL; + } else + ret = -EINVAL; + } else + ret = -EINVAL; + + return ret; +} + +/* Prototype: int powertecscsi_proc_info(char *buffer, char **start, off_t offset, * int length, int host_no, int inout) - * Purpose : Return information about the driver to a user process accessing - * the /proc filesystem. - * Params : buffer - a buffer to write information to - * start - a pointer into this buffer set by this routine to the start - * of the required information. - * offset - offset into information that we have read upto. - * length - length of buffer - * host_no - host number to return information for - * inout - 0 for reading, 1 for writing. - * Returns : length of data written to buffer. + * Purpose : Return information about the driver to a user process accessing + * the /proc filesystem. + * Params : buffer - a buffer to write information to + * start - a pointer into this buffer set by this routine to the start + * of the required information. + * offset - offset into information that we have read upto. + * length - length of buffer + * host_no - host number to return information for + * inout - 0 for reading, 1 for writing. + * Returns : length of data written to buffer. */ int powertecscsi_proc_info(char *buffer, char **start, off_t offset, int length, int host_no, int inout) @@ -346,27 +425,28 @@ if (!host) return 0; - info = (PowerTecScsi_Info *)host->hostdata; if (inout == 1) - return -EINVAL; + return powertecscsi_set_proc_info(host, buffer, length); + + info = (PowerTecScsi_Info *)host->hostdata; begin = 0; pos = sprintf(buffer, "PowerTec SCSI driver version %d.%d.%d\n", VER_MAJOR, VER_MINOR, VER_PATCH); pos += sprintf(buffer + pos, - "Address: %08X IRQ : %d DMA : %d\n" - "FAS : %s\n\n" + "Address: %08lX IRQ : %d DMA : %d\n" + "FAS : %-10s TERM: %-3s\n\n" "Statistics:\n", host->io_port, host->irq, host->dma_channel, - info->info.scsi.type); + info->info.scsi.type, info->control.terms ? "on" : "off"); pos += sprintf(buffer+pos, - "Queued commands: %-10d Issued commands: %-10d\n" - "Done commands : %-10d Reads : %-10d\n" - "Writes : %-10d Others : %-10d\n" - "Disconnects : %-10d Aborts : %-10d\n" - "Resets : %-10d\n", + "Queued commands: %-10u Issued commands: %-10u\n" + "Done commands : %-10u Reads : %-10u\n" + "Writes : %-10u Others : %-10u\n" + "Disconnects : %-10u Aborts : %-10u\n" + "Resets : %-10u\n", info->info.stats.queues, info->info.stats.removes, info->info.stats.fins, info->info.stats.reads, info->info.stats.writes, info->info.stats.miscs, diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/powertec.h linux/drivers/acorn/scsi/powertec.h --- v2.1.100/linux/drivers/acorn/scsi/powertec.h Wed Apr 8 19:36:25 1998 +++ linux/drivers/acorn/scsi/powertec.h Fri May 8 00:42:39 1998 @@ -1,7 +1,7 @@ /* * PowerTec SCSI driver * - * Copyright (C) 1997 Russell King + * Copyright (C) 1997-1998 Russell King */ #ifndef POWERTECSCSI_H #define POWERTECSCSI_H @@ -64,10 +64,20 @@ #ifndef HOSTS_C +#include + +#define NR_SG 256 + typedef struct { - FAS216_Info info; + FAS216_Info info; + + struct { + unsigned int term_port; + unsigned int terms; + } control; - /* other info... */ + /* other info... */ + dmasg_t dmasg[NR_SG]; /* Scatter DMA list */ } PowerTecScsi_Info; #endif /* HOSTS_C */ diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/queue.c linux/drivers/acorn/scsi/queue.c --- v2.1.100/linux/drivers/acorn/scsi/queue.c Mon Feb 23 18:12:03 1998 +++ linux/drivers/acorn/scsi/queue.c Fri May 8 00:42:39 1998 @@ -298,7 +298,7 @@ else queue->tail = NULL; } else { - prev->next = q->next; + prev->next = q->next; if (prev->next) prev->next->prev = prev; else diff -u --recursive --new-file v2.1.100/linux/drivers/ap1000/apfddi.c linux/drivers/ap1000/apfddi.c --- v2.1.100/linux/drivers/ap1000/apfddi.c Fri Feb 7 05:54:54 1997 +++ linux/drivers/ap1000/apfddi.c Fri May 8 00:47:24 1998 @@ -488,6 +488,13 @@ int apfddi_init(struct device *dev) { int i; + + /* + * Check if this thing has already been initialised. + */ + if (apfddi_device != NULL) + return -ENODEV; + printk("apfddi_init(): Initialising fddi interface\n"); apfddi_device = dev; @@ -523,12 +530,6 @@ memset(dev->broadcast, 0xFF, ETH_ALEN); - dev->family = AF_INET; - dev->pa_addr = in_aton("150.203.142.28"); /* hibana-f */ - dev->pa_mask = in_aton("255.255.255.0"); - dev->pa_brdaddr = dev->pa_addr | ~dev->pa_mask; - dev->pa_alen = 4; - return(0); } diff -u --recursive --new-file v2.1.100/linux/drivers/ap1000/bif.c linux/drivers/ap1000/bif.c --- v2.1.100/linux/drivers/ap1000/bif.c Thu Feb 12 20:56:05 1998 +++ linux/drivers/ap1000/bif.c Fri May 8 00:47:24 1998 @@ -127,7 +127,6 @@ dev->rebuild_header = bif_rebuild_header; dev->open = bif_open; dev->flags = IFF_NOARP; /* Don't use ARP on this device */ - dev->family = AF_INET; dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL); if (dev->priv == NULL) return -ENOMEM; @@ -138,10 +137,6 @@ dev->stop = bif_stop; dev->get_stats = bif_get_stats; - /* Initialise the bif device structure */ - for (i = 0; i < DEV_NUMBUFFS; i++) - skb_queue_head_init(&dev->buffs[i]); - dev->set_mac_address = bif_set_mac_address; dev->header_cache_update = NULL; dev->do_ioctl = bif_do_ioctl; @@ -149,12 +144,9 @@ dev->set_multicast_list = bif_set_multicast_list; memset(dev->broadcast, 0xFF, ETH_ALEN); - - dev->pa_addr = 0; - dev->pa_brdaddr = 0; - dev->pa_mask = 0; - dev->pa_alen = 4; + dev_init_buffers(dev); + return(0); } diff -u --recursive --new-file v2.1.100/linux/drivers/ap1000/ddv.c linux/drivers/ap1000/ddv.c --- v2.1.100/linux/drivers/ap1000/ddv.c Thu May 7 22:51:47 1998 +++ linux/drivers/ap1000/ddv.c Fri May 8 00:47:24 1998 @@ -60,6 +60,8 @@ to make things a bit more efficient */ #define SECTOR_BLOCK_SHIFT 9 +#define SECTOR_MASK ((BLOCK_SIZE >> 9) - 1) + /* try to read ahead a bit */ #define DDV_READ_AHEAD 64 diff -u --recursive --new-file v2.1.100/linux/drivers/block/Config.in linux/drivers/block/Config.in --- v2.1.100/linux/drivers/block/Config.in Mon Apr 6 17:40:59 1998 +++ linux/drivers/block/Config.in Fri May 8 18:12:30 1998 @@ -60,7 +60,7 @@ comment 'Additional Block Devices' tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP -#tristate 'Network block device support' CONFIG_BLK_DEV_NBD +tristate 'Network block device support' CONFIG_BLK_DEV_NBD bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then tristate ' Linear (append) mode' CONFIG_MD_LINEAR diff -u --recursive --new-file v2.1.100/linux/drivers/block/Makefile linux/drivers/block/Makefile --- v2.1.100/linux/drivers/block/Makefile Mon Apr 6 17:40:59 1998 +++ linux/drivers/block/Makefile Fri May 8 18:12:30 1998 @@ -38,6 +38,22 @@ endif endif +ifeq ($(CONFIG_AMIGA_FLOPPY),y) + L_OBJS += amiflop.o +else + ifeq ($(CONFIG_AMIGA_FLOPPY),m) + M_OBJS += amiflop.o + endif +endif + +ifeq ($(CONFIG_ATARI_FLOPPY),y) + L_OBJS += ataflop.o +else + ifeq ($(CONFIG_ATARI_FLOPPY),m) + M_OBJS += ataflop.o + endif +endif + ifeq ($(CONFIG_ATARI_ACSI),y) LX_OBJS += acsi.o else @@ -91,9 +107,7 @@ else ifeq ($(CONFIG_BLK_DEV_IDE),m) MIX_OBJS += ide.o - ifeq ($(CONFIG_PROC_FS),y) - M_OBJS += ide-proc.o - endif + # ide-mod includes ide-proc M_OBJS += ide-mod.o MX_OBJS += ide-probe.o endif diff -u --recursive --new-file v2.1.100/linux/drivers/block/acsi.c linux/drivers/block/acsi.c --- v2.1.100/linux/drivers/block/acsi.c Thu May 7 22:51:47 1998 +++ linux/drivers/block/acsi.c Fri May 8 18:12:30 1998 @@ -1851,7 +1851,7 @@ if (unregister_blkdev( MAJOR_NR, "ad" ) != 0) printk( KERN_ERR "acsi: cleanup_module failed\n"); - + for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) if (*gdp == &acsi_gendisk) break; diff -u --recursive --new-file v2.1.100/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.1.100/linux/drivers/block/floppy.c Thu May 7 22:51:48 1998 +++ linux/drivers/block/floppy.c Fri May 8 00:27:34 1998 @@ -694,7 +694,7 @@ DPRINT("checking disk change line for drive %d\n",drive); DPRINT("jiffies=%ld\n", jiffies); DPRINT("disk change line=%x\n",fd_inb(FD_DIR)&0x80); - DPRINT("flags=%x\n",UDRS->flags); + DPRINT("flags=%lx\n",UDRS->flags); } #endif if (UDP->flags & FD_BROKEN_DCL) diff -u --recursive --new-file v2.1.100/linux/drivers/block/hd.c linux/drivers/block/hd.c --- v2.1.100/linux/drivers/block/hd.c Thu May 7 22:51:48 1998 +++ linux/drivers/block/hd.c Fri May 8 18:12:30 1998 @@ -73,6 +73,8 @@ static int reset = 0; static int hd_error = 0; +#define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0) + /* * This struct defines the HD's and their types. */ diff -u --recursive --new-file v2.1.100/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v2.1.100/linux/drivers/block/ide.c Thu May 7 22:51:48 1998 +++ linux/drivers/block/ide.c Fri May 8 18:12:30 1998 @@ -3,7 +3,6 @@ * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ -#define _IDE_C /* needed by */ /* * Maintained by Mark Lord @@ -98,6 +97,8 @@ #undef REALLY_SLOW_IO /* most systems can safely undef this */ +#define _IDE_C /* Tell ide.h it's really us */ + #include #include #include @@ -147,6 +148,28 @@ * This is declared extern in ide.h, for access by other IDE modules: */ ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */ + +/* + * This is our end_request replacement function. + */ +void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup) +{ + struct request *req; + unsigned long flags; + + spin_lock_irqsave(&io_request_lock,flags); + req = hwgroup->rq; + + if (end_that_request_first(req, uptodate, DEVICE_NAME)) + goto out; + add_blkdev_randomness(MAJOR(req->rq_dev)); + hwgroup->drive->queue = req->next; + blk_dev[MAJOR(req->rq_dev)].current_request = NULL; + hwgroup->rq = NULL; + end_that_request_last(req); +out: + spin_unlock_irqrestore(&io_request_lock,flags); +} #if (DISK_RECOVERY_TIME > 0) /* diff -u --recursive --new-file v2.1.100/linux/drivers/block/ide.h linux/drivers/block/ide.h --- v2.1.100/linux/drivers/block/ide.h Thu May 7 22:51:48 1998 +++ linux/drivers/block/ide.h Fri May 8 18:21:47 1998 @@ -508,10 +508,13 @@ #endif /* - * One final include file, which references some of the data/defns from above + * We need blk.h, but we replace its end_request by our own version. */ -#define IDE_DRIVER /* "parameter" for blk.h */ +#define IDE_DRIVER /* Toggle some magic bits in blk.h */ +#define LOCAL_END_REQUEST /* Don't generate end_request in blk.h */ #include + +void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup); /* * This is used for (nearly) all data transfers from/to the IDE interface diff -u --recursive --new-file v2.1.100/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.1.100/linux/drivers/block/ll_rw_blk.c Tue Apr 14 14:29:20 1998 +++ linux/drivers/block/ll_rw_blk.c Fri May 8 18:12:30 1998 @@ -435,7 +435,7 @@ /* look for a free request. */ /* Loop uses two requests, 1 for loop and 1 for the real device. * Cut max_req in half to avoid running out and deadlocking. */ - if (major == LOOP_MAJOR) + if ((major == LOOP_MAJOR) || (major == NBD_MAJOR)) max_req >>= 1; /* @@ -452,7 +452,7 @@ if (!req) { /* MD and loop can't handle plugging without deadlocking */ if (major != MD_MAJOR && major != LOOP_MAJOR && - major != DDV_MAJOR) + major != DDV_MAJOR && major != NBD_MAJOR) plug_device(blk_dev + major); /* is atomic */ } else switch (major) { case IDE0_MAJOR: /* same as HD_MAJOR */ @@ -669,7 +669,7 @@ } buffersize = PAGE_SIZE / nb; - if (major == LOOP_MAJOR) + if ((major == LOOP_MAJOR) || (major == NBD_MAJOR)) max_req >>= 1; for (j=0, i=0; ierrors = 0; + if (!uptodate) { + printk("end_request: I/O error, dev %s (%s), sector %lu\n", + kdevname(req->rq_dev), name, req->sector); + if ((bh = req->bh) != NULL) { + nsect = bh->b_size >> 9; + req->nr_sectors--; + req->nr_sectors &= ~(nsect - 1); + req->sector += nsect; + req->sector &= ~(nsect - 1); + } + } + + if ((bh = req->bh) != NULL) { + req->bh = bh->b_reqnext; + bh->b_reqnext = NULL; + bh->b_end_io(bh, uptodate); + if ((bh = req->bh) != NULL) { + req->current_nr_sectors = bh->b_size >> 9; + if (req->nr_sectors < req->current_nr_sectors) { + req->nr_sectors = req->current_nr_sectors; + printk("end_request: buffer-list destroyed\n"); + } + req->buffer = bh->b_data; + return 1; + } + } + return 0; +} + +void +end_that_request_last( struct request *req ) +{ + if (req->sem != NULL) + up(req->sem); + req->rq_status = RQ_INACTIVE; + wake_up(&wait_for_request); +} + __initfunc(int blk_dev_init(void)) { struct request * req; @@ -771,10 +823,17 @@ #ifdef CONFIG_MAC_FLOPPY swim3_init(); #endif +#ifdef CONFIG_AMIGA_FLOPPY + amiga_floppy_init(); +#endif +#ifdef CONFIG_ATARI_FLOPPY + atari_floppy_init(); +#endif #ifdef CONFIG_BLK_DEV_FD floppy_init(); #else -#if !defined (__mc68000__) && !defined(CONFIG_PMAC) && !defined(__sparc__) +#if !defined (__mc68000__) && !defined(CONFIG_PMAC) && !defined(__sparc__)\ + && !defined(CONFIG_APUS) outb_p(0xc, 0x3f2); #endif #endif @@ -820,7 +879,12 @@ #ifdef CONFIG_DDV ddv_init(); #endif +#ifdef CONFIG_BLK_DEV_NBD + nbd_init(); +#endif return 0; }; EXPORT_SYMBOL(io_request_lock); +EXPORT_SYMBOL(end_that_request_first); +EXPORT_SYMBOL(end_that_request_last); diff -u --recursive --new-file v2.1.100/linux/drivers/block/md.c linux/drivers/block/md.c --- v2.1.100/linux/drivers/block/md.c Thu May 7 22:51:48 1998 +++ linux/drivers/block/md.c Fri May 8 00:17:13 1998 @@ -70,7 +70,6 @@ static struct hd_struct md_hd_struct[MAX_MD_DEV]; static int md_blocksizes[MAX_MD_DEV]; int md_maxreadahead[MAX_MD_DEV]; -static struct md_thread md_threads[MAX_MD_THREADS]; #if SUPPORT_RECONSTRUCTION static struct md_thread *md_sync_thread = NULL; #endif /* SUPPORT_RECONSTRUCTION */ @@ -97,6 +96,8 @@ static struct md_personality *pers[MAX_PERSONALITY]={NULL, }; struct md_dev md_dev[MAX_MD_DEV]; +int md_thread(void * arg); + static struct gendisk *find_gendisk (kdev_t dev) { struct gendisk *tmp=gendisk_head; @@ -803,39 +804,98 @@ { printk ("Got md request, not good..."); return; -} +} + +void md_wakeup_thread(struct md_thread *thread) +{ + set_bit(THREAD_WAKEUP, &thread->flags); + wake_up(&thread->wqueue); +} -/* - * We run MAX_MD_THREADS from md_init() and arbitrate them in run time. - * This is not so elegant, but how can we use kernel_thread() from within - * loadable modules? - */ struct md_thread *md_register_thread (void (*run) (void *), void *data) { - int i; - for (i = 0; i < MAX_MD_THREADS; i++) { - if (md_threads[i].run == NULL) { - md_threads[i].run = run; - md_threads[i].data = data; - return md_threads + i; - } + struct md_thread *thread = (struct md_thread *) + kmalloc(sizeof(struct md_thread), GFP_KERNEL); + int ret; + struct semaphore sem = MUTEX_LOCKED; + + if (!thread) return NULL; + + memset(thread, 0, sizeof(struct md_thread)); + init_waitqueue(&thread->wqueue); + + thread->sem = &sem; + thread->run = run; + thread->data = data; + ret = kernel_thread(md_thread, thread, 0); + if (ret < 0) { + kfree(thread); + return NULL; } - return NULL; + down(&sem); + return thread; } void md_unregister_thread (struct md_thread *thread) { + struct semaphore sem = MUTEX_LOCKED; + + thread->sem = &sem; thread->run = NULL; - thread->data = NULL; - thread->flags = 0; + if (thread->tsk) + printk("Killing md_thread %d %p %s\n", + thread->tsk->pid, thread->tsk, thread->tsk->comm); + else + printk("Aiee. md_thread has 0 tsk\n"); + send_sig(SIGKILL, thread->tsk, 1); + printk("downing on %p\n", &sem); + down(&sem); } -void md_wakeup_thread(struct md_thread *thread) +#define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM)) + +int md_thread(void * arg) { - set_bit(THREAD_WAKEUP, &thread->flags); - wake_up(&thread->wqueue); -} + struct md_thread *thread = arg; + + lock_kernel(); + exit_mm(current); + exit_files(current); + exit_fs(current); + + current->session = 1; + current->pgrp = 1; + sprintf(current->comm, "md_thread"); + siginitsetinv(¤t->blocked, SHUTDOWN_SIGS); + thread->tsk = current; + up(thread->sem); + for (;;) { + cli(); + if (!test_bit(THREAD_WAKEUP, &thread->flags)) { + do { + spin_lock(¤t->sigmask_lock); + flush_signals(current); + spin_unlock(¤t->sigmask_lock); + interruptible_sleep_on(&thread->wqueue); + cli(); + if (test_bit(THREAD_WAKEUP, &thread->flags)) + break; + if (!thread->run) { + sti(); + up(thread->sem); + return 0; + } + } while (signal_pending(current)); + } + sti(); + clear_bit(THREAD_WAKEUP, &thread->flags); + if (thread->run) { + thread->run(thread->data); + run_task_queue(&tq_disk); + } + } +} EXPORT_SYMBOL(md_size); EXPORT_SYMBOL(md_maxreadahead); @@ -981,37 +1041,6 @@ return 0; } -int md_thread(void * arg) -{ - struct md_thread *thread = arg; - - current->session = 1; - current->pgrp = 1; - sprintf(current->comm, "md_thread"); - - lock_kernel(); - for (;;) { - sti(); - clear_bit(THREAD_WAKEUP, &thread->flags); - if (thread->run) { - thread->run(thread->data); - run_task_queue(&tq_disk); - } - cli(); - if (!test_bit(THREAD_WAKEUP, &thread->flags)) { - do { - spin_lock(¤t->sigmask_lock); - flush_signals(current); - spin_unlock(¤t->sigmask_lock); - interruptible_sleep_on(&thread->wqueue); - cli(); - if (test_bit(THREAD_WAKEUP, &thread->flags)) - break; - } while (signal_pending(current)); - } - } -} - static md_descriptor_t *get_spare(struct md_dev *mddev) { int i; @@ -1281,8 +1310,6 @@ __initfunc(int md_init (void)) { - int i; - printk ("md driver %d.%d.%d MAX_MD_DEV=%d, MAX_REAL=%d\n", MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION, MAX_MD_DEV, MAX_REAL); @@ -1291,15 +1318,6 @@ { printk ("Unable to get major %d for md\n", MD_MAJOR); return (-1); - } - - memset(md_threads, 0, MAX_MD_THREADS * sizeof(struct md_thread)); - printk("md: starting %d kernel threads\n", MAX_MD_THREADS); - for (i = 0; i < MAX_MD_THREADS; i++) { - md_threads[i].run = NULL; - init_waitqueue(&md_threads[i].wqueue); - md_threads[i].flags = 0; - kernel_thread (md_thread, md_threads + i, 0); } blk_dev[MD_MAJOR].request_fn=DEVICE_REQUEST; diff -u --recursive --new-file v2.1.100/linux/drivers/block/raid0.c linux/drivers/block/raid0.c --- v2.1.100/linux/drivers/block/raid0.c Sat Nov 8 11:39:12 1997 +++ linux/drivers/block/raid0.c Fri May 8 00:17:13 1998 @@ -104,7 +104,7 @@ md_size[minor]/data->smallest->size + (md_size[minor]%data->smallest->size ? 1 : 0); - printk ("raid0 : Allocating %d bytes for hash.\n",sizeof(struct raid0_hash)*nb_zone); + printk ("raid0 : Allocating %ld bytes for hash.\n",(long)sizeof(struct raid0_hash)*nb_zone); if ((data->hash_table=vmalloc (sizeof (struct raid0_hash)*nb_zone)) == NULL) { vfree(data->strip_zone); diff -u --recursive --new-file v2.1.100/linux/drivers/block/raid5.c linux/drivers/block/raid5.c --- v2.1.100/linux/drivers/block/raid5.c Thu May 7 22:51:48 1998 +++ linux/drivers/block/raid5.c Fri May 8 00:17:13 1998 @@ -21,6 +21,7 @@ #include #include #include +#include static struct md_personality raid5_personality; @@ -741,10 +742,16 @@ return blocknr; } +#ifdef HAVE_ARCH_XORBLOCK static void xor_block(struct buffer_head *dest, struct buffer_head *source) { - int lines = dest->b_size / (sizeof (int)) / 8, i; - int *destp = (int *) dest->b_data, *sourcep = (int *) source->b_data; + __xor_block((char *) dest->b_data, (char *) source->b_data, dest->b_size); +} +#else +static void xor_block(struct buffer_head *dest, struct buffer_head *source) +{ + long lines = dest->b_size / (sizeof (long)) / 8, i; + long *destp = (long *) dest->b_data, *sourcep = (long *) source->b_data; for (i = lines; i > 0; i--) { *(destp + 0) ^= *(sourcep + 0); @@ -759,6 +766,7 @@ sourcep += 8; } } +#endif static void compute_block(struct stripe_head *sh, int dd_idx) { diff -u --recursive --new-file v2.1.100/linux/drivers/block/swim3.c linux/drivers/block/swim3.c --- v2.1.100/linux/drivers/block/swim3.c Sun Dec 21 17:41:24 1997 +++ linux/drivers/block/swim3.c Fri May 8 18:12:30 1998 @@ -21,6 +21,7 @@ #include #include #include +#include #define MAJOR_NR FLOPPY_MAJOR #include @@ -134,9 +135,11 @@ int ref_count; int expect_cyl; struct timer_list timeout; + int timeout_pending; int ejected; struct wait_queue *wait; int wanted; + int in_media_bay; char dbdma_cmd_space[5 * sizeof(struct dbdma_cmd)]; }; @@ -161,6 +164,8 @@ static int swim3_readbit(struct floppy_state *fs, int bit); static void do_fd_request(void); static void start_request(struct floppy_state *fs); +static void set_timeout(struct floppy_state *fs, int nticks, + void (*proc)(unsigned long)); static void scan_track(struct floppy_state *fs); static void seek_track(struct floppy_state *fs, int n); static void init_dma(struct dbdma_cmd *cp, int cmd, void *buf, int count); @@ -179,10 +184,10 @@ unsigned int cmd, unsigned long param); static int floppy_open(struct inode *inode, struct file *filp); static int floppy_release(struct inode *inode, struct file *filp); -static long floppy_read(struct inode *inode, struct file *filp, - char *buf, unsigned long count); -static long floppy_write(struct inode *inode, struct file *filp, - const char *buf, unsigned long count); +static ssize_t floppy_read(struct file *filp, char *buf, + size_t count, loff_t *ppos); +static ssize_t floppy_write(struct file *filp, const char *buf, + size_t count, loff_t *ppos); static int floppy_check_change(kdev_t dev); static int floppy_revalidate(kdev_t dev); int swim3_init(void); @@ -294,6 +299,22 @@ } } +static void set_timeout(struct floppy_state *fs, int nticks, + void (*proc)(unsigned long)) +{ + unsigned long flags; + + save_flags(flags); cli(); + if (fs->timeout_pending) + del_timer(&fs->timeout); + fs->timeout.expires = jiffies + nticks; + fs->timeout.function = proc; + fs->timeout.data = (unsigned long) fs; + add_timer(&fs->timeout); + fs->timeout_pending = 1; + restore_flags(flags); +} + static inline void scan_track(struct floppy_state *fs) { volatile struct swim3 *sw = fs->swim3; @@ -304,11 +325,7 @@ out_8(&sw->control_bis, SCAN_TRACK); /* enable intr when track found */ out_8(&sw->intr_enable, ERROR | SEEN_SECTOR); - /* enable timeout */ - fs->timeout.expires = jiffies + HZ; - fs->timeout.function = scan_timeout; - fs->timeout.data = (unsigned long) fs; - add_timer(&fs->timeout); + set_timeout(fs, HZ, scan_timeout); /* enable timeout */ } static inline void seek_track(struct floppy_state *fs, int n) @@ -327,11 +344,7 @@ out_8(&sw->control_bis, DO_SEEK); /* enable intr when seek finished */ out_8(&sw->intr_enable, ERROR | SEEK_DONE); - /* enable timeout */ - fs->timeout.expires = jiffies + HZ/2; - fs->timeout.function = seek_timeout; - fs->timeout.data = (unsigned long) fs; - add_timer(&fs->timeout); + set_timeout(fs, HZ/2, seek_timeout); /* enable timeout */ } static inline void init_dma(struct dbdma_cmd *cp, int cmd, @@ -384,11 +397,7 @@ (CURRENT->cmd == WRITE? WRITE_SECTORS: 0) | SCAN_TRACK); /* enable intr when transfer complete */ out_8(&sw->intr_enable, ERROR | TRANSFER_DONE); - /* enable timeout */ - fs->timeout.expires = jiffies + 2*HZ; - fs->timeout.function = xfer_timeout; - fs->timeout.data = (unsigned long) fs; - add_timer(&fs->timeout); + set_timeout(fs, 2*HZ, xfer_timeout); /* enable timeout */ } static void act(struct floppy_state *fs) @@ -434,10 +443,7 @@ in_8(&sw->intr); /* clear DATA_CHANGED */ if (in_8(&sw->status) & DATA) { /* seek_complete is not yet true */ - fs->timeout.expires = jiffies + HZ/2; - fs->timeout.function = seek_timeout; - fs->timeout.data = (unsigned long) fs; - add_timer(&fs->timeout); + set_timeout(fs, HZ/2, seek_timeout); return; } out_8(&sw->intr_enable, 0); @@ -474,6 +480,7 @@ struct floppy_state *fs = (struct floppy_state *) data; volatile struct swim3 *sw = fs->swim3; + fs->timeout_pending = 0; out_8(&sw->control_bic, SCAN_TRACK); out_8(&sw->select, RELAX); out_8(&sw->intr_enable, 0); @@ -493,6 +500,7 @@ struct floppy_state *fs = (struct floppy_state *) data; volatile struct swim3 *sw = fs->swim3; + fs->timeout_pending = 0; if (fs->state == settling) { printk(KERN_ERR "swim3: MSI sel=%x ctrl=%x stat=%x intr=%x ie=%x\n", sw->select, sw->control, sw->status, sw->intr, sw->intr_enable); @@ -520,6 +528,7 @@ struct dbdma_cmd *cp = fs->dma_cmd; unsigned long s; + fs->timeout_pending = 0; st_le32(&dr->control, RUN << 16); out_8(&sw->intr_enable, 0); out_8(&sw->control_bic, WRITE_SECTORS | SCAN_TRACK); @@ -550,6 +559,9 @@ err = in_8(&sw->error); intr = in_8(&sw->intr); +#if 0 + printk(KERN_DEBUG "swim3 intr state=%d intr=%x err=%x\n", fs->state, intr, err); +#endif if ((intr & ERROR) && fs->state != do_transfer) printk(KERN_ERR "swim3_interrupt, state=%d, cmd=%x, intr=%x, err=%x\n", fs->state, CURRENT->cmd, intr, err); @@ -560,6 +572,7 @@ out_8(&sw->select, RELAX); out_8(&sw->intr_enable, 0); del_timer(&fs->timeout); + fs->timeout_pending = 0; if (sw->ctrack == 0xff) { printk(KERN_ERR "swim3: seen sector but cyl=ff?\n"); fs->cur_cyl = -1; @@ -589,6 +602,7 @@ out_8(&sw->select, RELAX); out_8(&sw->intr_enable, 0); del_timer(&fs->timeout); + fs->timeout_pending = 0; if (fs->state == seeking) ++fs->retries; fs->state = settling; @@ -598,6 +612,7 @@ case settling: out_8(&sw->intr_enable, 0); del_timer(&fs->timeout); + fs->timeout_pending = 0; act(fs); break; case do_transfer: @@ -610,6 +625,7 @@ out_8(&sw->control_bic, WRITE_SECTORS | SCAN_TRACK); out_8(&sw->select, RELAX); del_timer(&fs->timeout); + fs->timeout_pending = 0; if (CURRENT->cmd == WRITE) ++cp; stat = ld_le16(&cp->xfer_status); @@ -772,6 +788,12 @@ sw = fs->swim3; err = 0; if (fs->ref_count == 0) { + if (fs->in_media_bay && !check_media_bay(MB_FD)) + return -ENXIO; + out_8(&sw->mode, 0x95); + out_8(&sw->control_bic, 0xff); + out_8(&sw->reg5, 0x28); + udelay(1); out_8(&sw->intr_enable, 0); out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE); swim3_action(fs, MOTOR_ON); @@ -905,9 +927,10 @@ return ret; } -static long floppy_read(struct inode *inode, struct file *filp, - char *buf, unsigned long count) +static ssize_t floppy_read(struct file *filp, char *buf, + size_t count, loff_t *ppos) { + struct inode *inode = filp->f_dentry->d_inode; struct floppy_state *fs; if (MINOR(inode->i_rdev) != 0) @@ -915,12 +938,13 @@ fs = &floppy_states[0]; if (fs->ejected) return -ENXIO; - return block_read(inode, filp, buf, count); + return block_read(filp, buf, count, ppos); } -static long floppy_write(struct inode *inode, struct file *filp, - const char *buf, unsigned long count) +static ssize_t floppy_write(struct file * filp, const char * buf, + size_t count, loff_t *ppos) { + struct inode * inode = filp->f_dentry->d_inode; struct floppy_state *fs; if (MINOR(inode->i_rdev) != 0) @@ -928,7 +952,7 @@ fs = &floppy_states[0]; if (fs->ejected) return -ENXIO; - return block_write(inode, filp, buf, count); + return block_write(filp, buf, count, ppos); } static void floppy_off(unsigned int nr) @@ -955,9 +979,16 @@ { struct device_node *swims; struct floppy_state *fs = &floppy_states[0]; - volatile struct swim3 *sw; + int is_3400 = 0; + + if (find_devices("media-bay") != NULL) { + /* assume this is a PB3400 */ + swims = find_devices("floppy"); + is_3400 = 1; + } else { + swims = find_devices("swim3"); + } - swims = find_devices("swim3"); if (swims == NULL) return 0; @@ -982,13 +1013,14 @@ fs->state = idle; fs->swim3 = (volatile struct swim3 *) swims->addrs[0].address; fs->dma = (struct dbdma_regs *) swims->addrs[1].address; - fs->swim3_intr = swims->intrs[0]; - fs->dma_intr = swims->intrs[1]; + fs->swim3_intr = swims->intrs[0].line; + fs->dma_intr = swims->intrs[1].line; fs->cur_cyl = -1; fs->cur_sector = -1; fs->secpercyl = 36; fs->secpertrack = 18; fs->total_secs = 2880; + fs->in_media_bay = is_3400; fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space); memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd)); @@ -1004,10 +1036,7 @@ return -EBUSY; } - sw = fs->swim3; - out_8(&sw->mode, 0x95); - out_8(&sw->control_bic, 0xff); - out_8(&sw->reg5, 0x28); + init_timer(&fs->timeout); do_floppy = NULL; diff -u --recursive --new-file v2.1.100/linux/drivers/block/xd.c linux/drivers/block/xd.c --- v2.1.100/linux/drivers/block/xd.c Thu May 7 22:51:48 1998 +++ linux/drivers/block/xd.c Thu May 7 23:53:35 1998 @@ -708,8 +708,7 @@ switch (address) { case 0x00000: case 0xC8000: break; /*initial: 0x320 */ - case 0xCA000: if (xd[3]<=0) xd_iobase = 0x324; - break; + case 0xCA000: xd_iobase = 0x324; case 0xD0000: /*5150CX*/ case 0xD8000: break; /*5150CX & 5150XL*/ default: printk("xd_dtc_init_controller: unsupported BIOS address %06x\n",address); diff -u --recursive --new-file v2.1.100/linux/drivers/char/hfmodem/refclock.c linux/drivers/char/hfmodem/refclock.c --- v2.1.100/linux/drivers/char/hfmodem/refclock.c Tue Aug 5 09:48:55 1997 +++ linux/drivers/char/hfmodem/refclock.c Thu May 7 23:50:19 1998 @@ -65,49 +65,13 @@ /* --------------------------------------------------------------------- */ #ifdef __i386__ - __initfunc(static void i386_capability(void)) { - unsigned long flags; - unsigned long fl1; - union { - struct { - unsigned int ebx, edx, ecx; - } r; - unsigned char s[13]; - } id; - unsigned int eax; - unsigned int x86_capability; - - save_flags(flags); - flags |= 0x200000; - restore_flags(flags); - save_flags(flags); - fl1 = flags; - flags &= ~0x200000; - restore_flags(flags); - save_flags(flags); - if (!(fl1 & 0x200000) || (flags & 0x200000)) { - printk(KERN_WARNING "%s: cpu does not support CPUID\n", hfmodem_drvname); - return; - } - __asm__ ("cpuid" : "=a" (eax), "=b" (id.r.ebx), "=c" (id.r.ecx), "=d" (id.r.edx) : - "0" (0)); - id.s[12] = 0; - if (eax < 1) { - printk(KERN_WARNING "%s: cpu (vendor string %s) does not support capability " - "list\n", hfmodem_drvname, id.s); - return; - } - printk(KERN_INFO "%s: cpu: vendor string %s ", hfmodem_drvname, id.s); - __asm__ ("cpuid" : "=a" (eax), "=d" (x86_capability) : "0" (1) : "ebx", "ecx"); - printk("fam %d mdl %d step %d cap 0x%x\n", (eax >> 8) & 15, (eax >> 4) & 15, eax & 15, - x86_capability); - if (x86_capability & 0x10) + if (boot_cpu_data.x86_capability & 0x10) rdtsc_ok = 1; else printk(KERN_INFO "%s: cpu does not support the rdtsc instruction\n", hfmodem_drvname); -} +} #endif /* __i386__ */ /* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.1.100/linux/drivers/char/sysrq.c linux/drivers/char/sysrq.c --- v2.1.100/linux/drivers/char/sysrq.c Thu Feb 12 20:56:06 1998 +++ linux/drivers/char/sysrq.c Fri May 8 17:54:39 1998 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -188,7 +189,7 @@ printk("R/O\n"); return; } - quota_off(dev, -1); + DQUOT_OFF(dev); fsync_dev(dev); flags = MS_RDONLY; if (sb->s_op && sb->s_op->remount_fs) { diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/Makefile linux/drivers/macintosh/Makefile --- v2.1.100/linux/drivers/macintosh/Makefile Thu Apr 23 20:21:33 1998 +++ linux/drivers/macintosh/Makefile Fri May 8 00:25:50 1998 @@ -19,10 +19,10 @@ L_OBJS := via-cuda.o adb.o nvram.o macio-adb.o via-pmu.o mediabay.o endif -ifeq ($(CONFIG_SERIAL)$(CONFIG_PMAC),yy) +ifeq ($(CONFIG_MAC_SERIAL),y) LX_OBJS += macserial.o else - ifeq ($(CONFIG_SERIAL)$(CONFIG_PMAC),my) + ifeq ($(CONFIG_MAC_SERIAL),m) MX_OBJS += macserial.o endif endif diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/adb.c linux/drivers/macintosh/adb.c --- v2.1.100/linux/drivers/macintosh/adb.c Thu Apr 23 20:21:33 1998 +++ linux/drivers/macintosh/adb.c Fri May 8 00:25:50 1998 @@ -17,8 +17,9 @@ #include #include #include +#include -enum adb_hw adb_hardware; +enum adb_hw adb_hardware = ADB_NONE; int (*adb_send_request)(struct adb_request *req, int sync); int (*adb_autopoll)(int on); static void adb_scan_bus(void); @@ -29,6 +30,8 @@ int handler_id; } adb_handler[16]; +__openfirmware + static int adb_nodev(void) { return -1; @@ -137,7 +140,6 @@ void adb_init(void) { - adb_hardware = ADB_NONE; adb_send_request = (void *) adb_nodev; adb_autopoll = (void *) adb_nodev; if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) ) diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/aty.c linux/drivers/macintosh/aty.c --- v2.1.100/linux/drivers/macintosh/aty.c Thu Apr 23 20:21:33 1998 +++ linux/drivers/macintosh/aty.c Fri May 8 00:25:50 1998 @@ -25,6 +25,7 @@ #include #include #include +#include #include "pmac-cons.h" #include "aty.h" @@ -150,6 +151,8 @@ &aty_vt_reg_init_19, &aty_vt_reg_init_20 }; + +__openfirmware static inline int aty_vram_reqd(int vmode, int cmode) diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/chips.c linux/drivers/macintosh/chips.c --- v2.1.100/linux/drivers/macintosh/chips.c Thu Apr 23 20:21:33 1998 +++ linux/drivers/macintosh/chips.c Fri May 8 00:25:50 1998 @@ -22,6 +22,7 @@ #include #include #include +#include #include "pmac-cons.h" #include "chips.h" @@ -31,6 +32,8 @@ static unsigned char *io_space; static unsigned long chips_base_phys; static unsigned long chips_io_phys; + +__openfirmware void map_chips_display(struct device_node *dp) diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/control.c linux/drivers/macintosh/control.c --- v2.1.100/linux/drivers/macintosh/control.c Thu Apr 23 20:21:33 1998 +++ linux/drivers/macintosh/control.c Fri May 8 00:25:50 1998 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "pmac-cons.h" #include "control.h" @@ -265,6 +266,8 @@ &control_reg_init_19, &control_reg_init_20 }; + +__openfirmware /* * Get the monitor sense value. diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/imstt.c linux/drivers/macintosh/imstt.c --- v2.1.100/linux/drivers/macintosh/imstt.c Sat May 2 14:19:53 1998 +++ linux/drivers/macintosh/imstt.c Fri May 8 00:25:50 1998 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include "pmac-cons.h" @@ -480,6 +481,8 @@ static int read_imstt_sense(void); static int imstt_vram_reqd(int vmode, int cmode); + +__openfirmware #if 0 static int get_tvp_ireg(int iaddr) diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c --- v2.1.100/linux/drivers/macintosh/mac_keyb.c Thu Apr 23 20:21:33 1998 +++ linux/drivers/macintosh/mac_keyb.c Fri May 8 00:25:50 1998 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -28,7 +29,7 @@ #define KEYB_LEDREG 2 /* register # for leds on ADB keyboard */ #define MOUSE_DATAREG 0 /* reg# for movement/button codes from mouse */ -static u_short macplain_map[NR_KEYS] = __initdata { +static u_short macplain_map[NR_KEYS] __initdata = { 0xfb61, 0xfb73, 0xfb64, 0xfb66, 0xfb68, 0xfb67, 0xfb7a, 0xfb78, 0xfb63, 0xfb76, 0xf200, 0xfb62, 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb79, 0xfb74, 0xf031, 0xf032, 0xf033, 0xf034, 0xf036, 0xf035, @@ -194,6 +195,8 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, /* scroll lock */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; + +__openfirmware int mackbd_setkeycode(unsigned int scancode, unsigned int keycode) { diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/macio-adb.c linux/drivers/macintosh/macio-adb.c --- v2.1.100/linux/drivers/macintosh/macio-adb.c Thu Apr 23 20:21:33 1998 +++ linux/drivers/macintosh/macio-adb.c Fri May 8 00:25:50 1998 @@ -14,6 +14,7 @@ #include #include #include +#include struct preg { unsigned char r; @@ -63,6 +64,8 @@ static int macio_adb_autopoll(int on); static void macio_adb_poll(void); static void completed(void); + +__openfirmware void macio_adb_init(void) { diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c --- v2.1.100/linux/drivers/macintosh/macserial.c Thu May 7 22:51:50 1998 +++ linux/drivers/macintosh/macserial.c Fri May 8 00:25:50 1998 @@ -36,6 +36,7 @@ #ifdef CONFIG_KGDB #include #endif +#include #include "macserial.h" @@ -79,9 +80,9 @@ #endif #define ZS_CLOCK 3686400 /* Z8530 RTxC input clock rate */ -DECLARE_TASK_QUEUE(tq_serial); +static DECLARE_TASK_QUEUE(tq_serial); -struct tty_driver serial_driver, callout_driver; +static struct tty_driver serial_driver, callout_driver; static int serial_refcount; /* serial subtype definitions */ @@ -127,6 +128,8 @@ static unsigned char tmp_buf[4096]; /* This is cheating */ static struct semaphore tmp_buf_sem = MUTEX; +__openfirmware + static inline int serial_paranoia_check(struct mac_serial *info, dev_t device, const char *routine) { @@ -281,7 +284,7 @@ { info->event |= 1 << event; queue_task(&info->tqueue, &tq_serial); - mark_bh(SERIAL_BH); + mark_bh(MACSERIAL_BH); } static _INLINE_ void receive_chars(struct mac_serial *info, @@ -410,7 +413,7 @@ /* * This is the serial driver's generic interrupt routine */ -void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) +static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct mac_serial *info = (struct mac_serial *) dev_id; unsigned char zs_intreg; @@ -1311,7 +1314,7 @@ /* * rs_hangup() --- called by tty_hangup() when a hangup is signaled. */ -void rs_hangup(struct tty_struct *tty) +static void rs_hangup(struct tty_struct *tty) { struct mac_serial * info = (struct mac_serial *)tty->driver_data; @@ -1464,7 +1467,7 @@ * the IRQ chain. It also performs the serial-specific * initialization for the tty structure. */ -int rs_open(struct tty_struct *tty, struct file * filp) +static int rs_open(struct tty_struct *tty, struct file * filp) { struct mac_serial *info; int retval, line; @@ -1599,14 +1602,14 @@ } /* rs_init inits the driver */ -int rs_init(void) +int macserial_init(void) { int channel, i; unsigned long flags; struct mac_serial *info; /* Setup base handler, and timer table. */ - init_bh(SERIAL_BH, do_serial_bh); + init_bh(MACSERIAL_BH, do_serial_bh); timer_table[RS_TIMER].fn = rs_timer; timer_table[RS_TIMER].expires = 0; @@ -1722,6 +1725,7 @@ return 0; } +#if 0 /* * register_serial and unregister_serial allows for serial ports to be * configured at run-time, to support PCMCIA modems. @@ -1736,6 +1740,7 @@ { return; } +#endif /* * ------------------------------------------------------------ @@ -1864,10 +1869,9 @@ /* * Register console. */ -__initfunc (long serial_console_init(long kmem_start, long kmem_end)) +__initfunc (void serial_console_init(void)) { register_console(&sercons); - return kmem_start; } #endif /* ifdef CONFIG_SERIAL_CONSOLE */ #ifdef CONFIG_KGDB diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/mediabay.c linux/drivers/macintosh/mediabay.c --- v2.1.100/linux/drivers/macintosh/mediabay.c Thu Apr 23 20:21:33 1998 +++ linux/drivers/macintosh/mediabay.c Fri May 8 00:25:50 1998 @@ -21,6 +21,7 @@ #include #include #include +#include struct media_bay_hw { unsigned char b0; @@ -84,6 +85,8 @@ * an infinite loop calling the media bay interrupt handler. * Therefore we do it all by polling the media bay once each tick. */ + +__pmac /* I don't know of any chrp with a mediabay -- Cort */ void media_bay_init(void) diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/nvram.c linux/drivers/macintosh/nvram.c --- v2.1.100/linux/drivers/macintosh/nvram.c Mon Jan 12 15:18:14 1998 +++ linux/drivers/macintosh/nvram.c Fri May 8 00:25:50 1998 @@ -9,8 +9,11 @@ #include #include #include +#include #define NVRAM_SIZE 8192 + +__openfirmware static long long nvram_llseek(struct file *file, loff_t offset, int origin) { diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/platinum.c linux/drivers/macintosh/platinum.c --- v2.1.100/linux/drivers/macintosh/platinum.c Thu Apr 23 20:21:33 1998 +++ linux/drivers/macintosh/platinum.c Fri May 8 00:25:50 1998 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "pmac-cons.h" #include "platinum.h" @@ -351,6 +352,8 @@ &platinum_reg_init_19, &platinum_reg_init_20 }; + +__openfirmware /* * Get the monitor sense value. diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/pmac-cons.c linux/drivers/macintosh/pmac-cons.c --- v2.1.100/linux/drivers/macintosh/pmac-cons.c Thu Apr 23 20:21:33 1998 +++ linux/drivers/macintosh/pmac-cons.c Fri May 8 00:25:50 1998 @@ -6,6 +6,7 @@ */ #include #include +#include #include #include #include @@ -23,6 +24,7 @@ #include #define INCLUDE_LINUX_LOGO_DATA #include +#include #include #include #include @@ -193,6 +195,8 @@ aty_setmode, aty_set_palette, aty_set_blanking }, { "ATY,mach64_3DU", map_aty_display, aty_init, aty_setmode, aty_set_palette, aty_set_blanking }, + { "ATY,XCLAIM3DPro", map_aty_display, aty_init, + aty_setmode, aty_set_palette, aty_set_blanking }, #endif #ifdef CONFIG_IMSTT_VIDEO { "IMS,tt128mb", map_imstt_display_ibm, imstt_init, @@ -225,6 +229,8 @@ #define cmapsz (16*256) extern unsigned char vga_font[cmapsz]; +__openfirmware + static inline unsigned pixel32(int currcons, int cidx) { cidx *= 3; @@ -637,20 +643,20 @@ color_mode = ints[2]; } -unsigned long -con_type_init(unsigned long mem_start, const char **type_p) +void +con_type_init(const char **type_p) { + unsigned long nb = MAX_TEXT_COLS * MAX_TEXT_ROWS * 2; + if (current_display == NULL) - return mem_start; + return; current_display->init_interface(); can_do_color = 1; video_type = VIDEO_TYPE_PMAC; *type_p = display_info.name; - video_mem_base = mem_start; - mem_start += MAX_TEXT_COLS * MAX_TEXT_ROWS * 2; - video_mem_term = mem_start; + video_mem_base = (unsigned long) kmalloc(nb, GFP_ATOMIC); + video_mem_term = video_mem_base + nb; memset((char *) video_mem_base, 0, video_screen_size); - return mem_start; } int diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/valkyrie.c linux/drivers/macintosh/valkyrie.c --- v2.1.100/linux/drivers/macintosh/valkyrie.c Thu Apr 23 20:21:33 1998 +++ linux/drivers/macintosh/valkyrie.c Fri May 8 00:25:50 1998 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "pmac-cons.h" #include "valkyrie.h" @@ -141,6 +142,8 @@ &valkyrie_reg_init_15, NULL, NULL, NULL, NULL, NULL }; + +__openfirmware /* * Get the monitor sense value. diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/via-cuda.c linux/drivers/macintosh/via-cuda.c --- v2.1.100/linux/drivers/macintosh/via-cuda.c Thu Apr 23 20:21:33 1998 +++ linux/drivers/macintosh/via-cuda.c Fri May 8 00:25:50 1998 @@ -20,6 +20,7 @@ #include #include #include +#include static volatile unsigned char *via; @@ -72,6 +73,7 @@ static unsigned char *reply_ptr; static int reading_reply; static int data_index; +static struct device_node *vias; static int init_via(void); static void cuda_start(void); @@ -80,11 +82,11 @@ static int cuda_adb_send_request(struct adb_request *req, int sync); static int cuda_adb_autopoll(int on); +__openfirmware + void -via_cuda_init() +find_via_cuda() { - struct device_node *vias; - vias = find_devices("via-cuda"); if (vias == 0) return; @@ -111,12 +113,21 @@ } via = (volatile unsigned char *) ioremap(vias->addrs->address, 0x2000); + cuda_state = idle; + if (!init_via()) { printk(KERN_ERR "init_via failed\n"); - return; + via = NULL; } - cuda_state = idle; + adb_hardware = ADB_VIACUDA; +} + +void +via_cuda_init(void) +{ + if (via == NULL) + return; if (request_irq(vias->intrs[0].line, via_interrupt, 0, "VIA", (void *)0)) { printk(KERN_ERR "VIA: can't get irq %d\n", vias->intrs[0].line); @@ -128,7 +139,6 @@ via[IER] = IER_SET|SR_INT; eieio(); /* enable interrupt from SR */ /* Set function pointers */ - adb_hardware = ADB_VIACUDA; adb_send_request = cuda_adb_send_request; adb_autopoll = cuda_adb_autopoll; } diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c --- v2.1.100/linux/drivers/macintosh/via-pmu.c Thu Apr 23 20:21:33 1998 +++ linux/drivers/macintosh/via-pmu.c Fri May 8 00:25:50 1998 @@ -23,6 +23,7 @@ #include #include #include +#include static volatile unsigned char *via; @@ -79,6 +80,7 @@ static int pmu_adb_flags; static int adb_dev_map = 0; static struct adb_request bright_req_1, bright_req_2; +static struct device_node *vias; static int init_pmu(void); static int pmu_queue_request(struct adb_request *req); @@ -138,11 +140,11 @@ /*f8*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, }; +__openfirmware + void -via_pmu_init() +find_via_pmu() { - struct device_node *vias; - vias = find_devices("via-pmu"); if (vias == 0) return; @@ -174,8 +176,20 @@ pmu_state = idle; if (!init_pmu()) + via = NULL; + + adb_hardware = ADB_VIAPMU; +} + +void +via_pmu_init(void) +{ + if (vias == NULL) return; + bright_req_1.complete = 1; + bright_req_2.complete = 1; + if (request_irq(vias->intrs[0].line, via_pmu_interrupt, 0, "VIA-PMU", (void *)0)) { printk(KERN_ERR "VIA-PMU: can't get irq %d\n", @@ -187,12 +201,8 @@ out_8(&via[IER], IER_SET | SR_INT | CB1_INT); /* Set function pointers */ - adb_hardware = ADB_VIAPMU; adb_send_request = pmu_adb_send_request; adb_autopoll = pmu_adb_autopoll; - - bright_req_1.complete = 1; - bright_req_2.complete = 1; } static int diff -u --recursive --new-file v2.1.100/linux/drivers/net/8390.c linux/drivers/net/8390.c --- v2.1.100/linux/drivers/net/8390.c Thu Feb 12 20:56:07 1998 +++ linux/drivers/net/8390.c Thu May 7 23:50:19 1998 @@ -33,6 +33,8 @@ Alexey Kuznetsov : use the 8390's six bit hash multicast filter. Paul Gortmaker : tweak ANK's above multicast changes a bit. Paul Gortmaker : update packet statistics for v2.1.x + Alan Cox : support arbitary stupid port mappings on the + 68K Macintosh. Support >16bit I/O spaces Sources: @@ -41,8 +43,9 @@ */ static const char *version = - "8390.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; + "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; +#include #include #include #include @@ -55,7 +58,7 @@ #include #include #include -#include +#include #include #include #include @@ -115,50 +118,53 @@ */ int ei_open(struct device *dev) { - struct ei_device *ei_local = (struct ei_device *) dev->priv; + struct ei_device *ei_local = (struct ei_device *) dev->priv; - /* This can't happen unless somebody forgot to call ethdev_init(). */ - if (ei_local == NULL) { - printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name); - return -ENXIO; - } - - NS8390_init(dev, 1); - dev->start = 1; - ei_local->irqlock = 0; - return 0; + /* This can't happen unless somebody forgot to call ethdev_init(). */ + if (ei_local == NULL) + { + printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name); + return -ENXIO; + } + + NS8390_init(dev, 1); + dev->start = 1; + ei_local->irqlock = 0; + return 0; } /* Opposite of above. Only used when "ifconfig down" is done. */ int ei_close(struct device *dev) { - NS8390_init(dev, 0); - dev->start = 0; - return 0; + NS8390_init(dev, 0); + dev->start = 0; + return 0; } static int ei_start_xmit(struct sk_buff *skb, struct device *dev) { - int e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) dev->priv; - int length, send_length, output_page; - -/* - * We normally shouldn't be called if dev->tbusy is set, but the - * existing code does anyway. If it has been too long since the - * last Tx, we assume the board has died and kick it. - */ + int e8390_base = dev->base_addr; + struct ei_device *ei_local = (struct ei_device *) dev->priv; + int length, send_length, output_page; + + /* + * We normally shouldn't be called if dev->tbusy is set, but the + * existing code does anyway. If it has been too long since the + * last Tx, we assume the board has died and kick it. + */ - if (dev->tbusy) { /* Do timeouts, just like the 8003 driver. */ + if (dev->tbusy) + { /* Do timeouts, just like the 8003 driver. */ int txsr = inb(e8390_base+EN0_TSR), isr; int tickssofar = jiffies - dev->trans_start; - if (tickssofar < TX_TIMEOUT || (tickssofar < (TX_TIMEOUT+5) && ! (txsr & ENTSR_PTX))) { + if (tickssofar < TX_TIMEOUT || (tickssofar < (TX_TIMEOUT+5) && ! (txsr & ENTSR_PTX))) return 1; - } + ei_local->stat.tx_errors++; isr = inb(e8390_base+EN0_ISR); - if (dev->start == 0) { - printk("%s: xmit on stopped card\n", dev->name); + if (dev->start == 0) + { + printk(KERN_WARNING "%s: xmit on stopped card\n", dev->name); return 1; } @@ -169,138 +175,153 @@ */ printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n", - dev->name, (txsr & ENTSR_ABT) ? "excess collisions." : - (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar); + dev->name, (txsr & ENTSR_ABT) ? "excess collisions." : + (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar); - if (!isr && !ei_local->stat.tx_packets) { - /* The 8390 probably hasn't gotten on the cable yet. */ - ei_local->interface_num ^= 1; /* Try a different xcvr. */ + if (!isr && !ei_local->stat.tx_packets) + { + /* The 8390 probably hasn't gotten on the cable yet. */ + ei_local->interface_num ^= 1; /* Try a different xcvr. */ } /* Try to restart the card. Perhaps the user has fixed something. */ ei_reset_8390(dev); NS8390_init(dev, 1); dev->trans_start = jiffies; - } + } - length = skb->len; + length = skb->len; - /* Mask interrupts from the ethercard. */ - outb_p(0x00, e8390_base + EN0_IMR); - disable_irq(dev->irq); - synchronize_irq(); - if (dev->interrupt) { - printk("%s: Tx request while isr active.\n",dev->name); - outb_p(ENISR_ALL, e8390_base + EN0_IMR); - enable_irq(dev->irq); - ei_local->stat.tx_errors++; - dev_kfree_skb(skb); - return 0; - } - ei_local->irqlock = 1; + /* Mask interrupts from the ethercard. */ + outb_p(0x00, e8390_base + EN0_IMR); + disable_irq(dev->irq); + synchronize_irq(); + if (dev->interrupt) + { + printk(KERN_WARNING "%s: Tx request while isr active.\n",dev->name); + outb_p(ENISR_ALL, e8390_base + EN0_IMR); + enable_irq(dev->irq); + ei_local->stat.tx_errors++; + dev_kfree_skb(skb); + return 0; + } + ei_local->irqlock = 1; - send_length = ETH_ZLEN < length ? length : ETH_ZLEN; + send_length = ETH_ZLEN < length ? length : ETH_ZLEN; #ifdef EI_PINGPONG - /* - * We have two Tx slots available for use. Find the first free - * slot, and then perform some sanity checks. With two Tx bufs, - * you get very close to transmitting back-to-back packets. With - * only one Tx buf, the transmitter sits idle while you reload the - * card, leaving a substantial gap between each transmitted packet. - */ - - if (ei_local->tx1 == 0) { - output_page = ei_local->tx_start_page; - ei_local->tx1 = send_length; - if (ei_debug && ei_local->tx2 > 0) - printk("%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n", - dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing); - } else if (ei_local->tx2 == 0) { - output_page = ei_local->tx_start_page + TX_1X_PAGES; - ei_local->tx2 = send_length; - if (ei_debug && ei_local->tx1 > 0) - printk("%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n", - dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing); - } else { /* We should never get here. */ - if (ei_debug) - printk("%s: No Tx buffers free! irq=%d tx1=%d tx2=%d last=%d\n", - dev->name, dev->interrupt, ei_local->tx1, ei_local->tx2, ei_local->lasttx); - ei_local->irqlock = 0; - dev->tbusy = 1; - outb_p(ENISR_ALL, e8390_base + EN0_IMR); - enable_irq(dev->irq); - ei_local->stat.tx_errors++; - return 1; - } - - /* - * Okay, now upload the packet and trigger a send if the transmitter - * isn't already sending. If it is busy, the interrupt handler will - * trigger the send later, upon receiving a Tx done interrupt. - */ + /* + * We have two Tx slots available for use. Find the first free + * slot, and then perform some sanity checks. With two Tx bufs, + * you get very close to transmitting back-to-back packets. With + * only one Tx buf, the transmitter sits idle while you reload the + * card, leaving a substantial gap between each transmitted packet. + */ - ei_block_output(dev, length, skb->data, output_page); - if (! ei_local->txing) { - ei_local->txing = 1; - NS8390_trigger_send(dev, send_length, output_page); - dev->trans_start = jiffies; - if (output_page == ei_local->tx_start_page) { - ei_local->tx1 = -1; - ei_local->lasttx = -1; - } else { - ei_local->tx2 = -1; - ei_local->lasttx = -2; + if (ei_local->tx1 == 0) + { + output_page = ei_local->tx_start_page; + ei_local->tx1 = send_length; + if (ei_debug && ei_local->tx2 > 0) + printk(KERN_DEBUG "%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n", + dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing); + } + else if (ei_local->tx2 == 0) + { + output_page = ei_local->tx_start_page + TX_1X_PAGES; + ei_local->tx2 = send_length; + if (ei_debug && ei_local->tx1 > 0) + printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n", + dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing); + } + else + { /* We should never get here. */ + if (ei_debug) + printk(KERN_DEBUG "%s: No Tx buffers free! irq=%d tx1=%d tx2=%d last=%d\n", + dev->name, dev->interrupt, ei_local->tx1, ei_local->tx2, ei_local->lasttx); + ei_local->irqlock = 0; + dev->tbusy = 1; + outb_p(ENISR_ALL, e8390_base + EN0_IMR); + enable_irq(dev->irq); + ei_local->stat.tx_errors++; + return 1; + } + + /* + * Okay, now upload the packet and trigger a send if the transmitter + * isn't already sending. If it is busy, the interrupt handler will + * trigger the send later, upon receiving a Tx done interrupt. + */ + + ei_block_output(dev, length, skb->data, output_page); + if (! ei_local->txing) + { + ei_local->txing = 1; + NS8390_trigger_send(dev, send_length, output_page); + dev->trans_start = jiffies; + if (output_page == ei_local->tx_start_page) + { + ei_local->tx1 = -1; + ei_local->lasttx = -1; + } + else + { + ei_local->tx2 = -1; + ei_local->lasttx = -2; + } } - } else - ei_local->txqueue++; + else ei_local->txqueue++; - dev->tbusy = (ei_local->tx1 && ei_local->tx2); + dev->tbusy = (ei_local->tx1 && ei_local->tx2); #else /* EI_PINGPONG */ - /* - * Only one Tx buffer in use. You need two Tx bufs to come close to - * back-to-back transmits. Expect a 20 -> 25% performance hit on - * reasonable hardware if you only use one Tx buffer. - */ - - ei_block_output(dev, length, skb->data, ei_local->tx_start_page); - ei_local->txing = 1; - NS8390_trigger_send(dev, send_length, ei_local->tx_start_page); - dev->trans_start = jiffies; - dev->tbusy = 1; + /* + * Only one Tx buffer in use. You need two Tx bufs to come close to + * back-to-back transmits. Expect a 20 -> 25% performance hit on + * reasonable hardware if you only use one Tx buffer. + */ + + ei_block_output(dev, length, skb->data, ei_local->tx_start_page); + ei_local->txing = 1; + NS8390_trigger_send(dev, send_length, ei_local->tx_start_page); + dev->trans_start = jiffies; + dev->tbusy = 1; #endif /* EI_PINGPONG */ - /* Turn 8390 interrupts back on. */ - ei_local->irqlock = 0; - outb_p(ENISR_ALL, e8390_base + EN0_IMR); - enable_irq(dev->irq); + /* Turn 8390 interrupts back on. */ + ei_local->irqlock = 0; + outb_p(ENISR_ALL, e8390_base + EN0_IMR); + enable_irq(dev->irq); - dev_kfree_skb (skb); - ei_local->stat.tx_bytes += send_length; + dev_kfree_skb (skb); + ei_local->stat.tx_bytes += send_length; - return 0; + return 0; } /* The typical workload of the driver: Handle the ether interface interrupts. */ + void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct device *dev = dev_id; - int e8390_base; - int interrupts, nr_serviced = 0; - struct ei_device *ei_local; + int e8390_base; + int interrupts, nr_serviced = 0; + struct ei_device *ei_local; - if (dev == NULL) { + if (dev == NULL) + { printk ("net_interrupt(): irq %d for unknown device.\n", irq); return; - } - e8390_base = dev->base_addr; - ei_local = (struct ei_device *) dev->priv; - if (dev->interrupt || ei_local->irqlock) { + } + + e8390_base = dev->base_addr; + ei_local = (struct ei_device *) dev->priv; + if (dev->interrupt || ei_local->irqlock) + { #if 1 /* This might just be an interrupt for a PCI device sharing this line */ /* The "irqlock" check is only for testing. */ printk(ei_local->irqlock @@ -310,39 +331,42 @@ inb_p(e8390_base + EN0_IMR)); #endif return; - } + } - dev->interrupt = 1; - sti(); + dev->interrupt = 1; + sti(); - /* Change to page 0 and read the intr status reg. */ - outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD); - if (ei_debug > 3) + /* Change to page 0 and read the intr status reg. */ + outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD); + if (ei_debug > 3) printk("%s: interrupt(isr=%#2.2x).\n", dev->name, inb_p(e8390_base + EN0_ISR)); - /* !!Assumption!! -- we stay in page 0. Don't break this. */ - while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0 - && ++nr_serviced < MAX_SERVICE) { - if (dev->start == 0) { - printk("%s: interrupt from stopped card\n", dev->name); + /* !!Assumption!! -- we stay in page 0. Don't break this. */ + while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0 + && ++nr_serviced < MAX_SERVICE) + { + if (dev->start == 0) + { + printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name); interrupts = 0; break; } - if (interrupts & ENISR_OVER) { + if (interrupts & ENISR_OVER) ei_rx_overrun(dev); - } else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) { + else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) + { /* Got a good (?) packet. */ ei_receive(dev); } /* Push the next to-transmit packet through. */ - if (interrupts & ENISR_TX) { + if (interrupts & ENISR_TX) ei_tx_intr(dev); - } else if (interrupts & ENISR_TX_ERR) { + else if (interrupts & ENISR_TX_ERR) ei_tx_err(dev); - } - if (interrupts & ENISR_COUNTERS) { + if (interrupts & ENISR_COUNTERS) + { ei_local->stat.rx_frame_errors += inb_p(e8390_base + EN0_COUNTER0); ei_local->stat.rx_crc_errors += inb_p(e8390_base + EN0_COUNTER1); ei_local->stat.rx_missed_errors+= inb_p(e8390_base + EN0_COUNTER2); @@ -350,16 +374,19 @@ } /* Ignore any RDC interrupts that make it back to here. */ - if (interrupts & ENISR_RDC) { + if (interrupts & ENISR_RDC) + { outb_p(ENISR_RDC, e8390_base + EN0_ISR); } outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD); - } + } - if (interrupts && ei_debug) { + if (interrupts && ei_debug) + { outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD); - if (nr_serviced >= MAX_SERVICE) { + if (nr_serviced >= MAX_SERVICE) + { printk("%s: Too much work at interrupt, status %#2.2x\n", dev->name, interrupts); outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */ @@ -367,9 +394,9 @@ printk("%s: unknown interrupt %#2x\n", dev->name, interrupts); outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */ } - } - dev->interrupt = 0; - return; + } + dev->interrupt = 0; + return; } /* @@ -383,128 +410,143 @@ static void ei_tx_err(struct device *dev) { - int e8390_base = dev->base_addr; - unsigned char txsr = inb_p(e8390_base+EN0_TSR); - unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU); - struct ei_device *ei_local = (struct ei_device *) dev->priv; + int e8390_base = dev->base_addr; + struct ei_device *ei_local = (struct ei_device *) dev->priv; + unsigned char txsr = inb_p(e8390_base+EN0_TSR); + unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU); #ifdef VERBOSE_ERROR_DUMP - printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr); - if (txsr & ENTSR_ABT) + printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr); + if (txsr & ENTSR_ABT) printk("excess-collisions "); - if (txsr & ENTSR_ND) + if (txsr & ENTSR_ND) printk("non-deferral "); - if (txsr & ENTSR_CRS) + if (txsr & ENTSR_CRS) printk("lost-carrier "); - if (txsr & ENTSR_FU) + if (txsr & ENTSR_FU) printk("FIFO-underrun "); - if (txsr & ENTSR_CDH) + if (txsr & ENTSR_CDH) printk("lost-heartbeat "); - printk("\n"); + printk("\n"); #endif - outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */ + outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */ - if (tx_was_aborted) + if (tx_was_aborted) ei_tx_intr(dev); - else { + else + { ei_local->stat.tx_errors++; if (txsr & ENTSR_CRS) ei_local->stat.tx_carrier_errors++; if (txsr & ENTSR_CDH) ei_local->stat.tx_heartbeat_errors++; if (txsr & ENTSR_OWC) ei_local->stat.tx_window_errors++; - } + } } /* We have finished a transmit: check for errors and then trigger the next packet to be sent. */ + static void ei_tx_intr(struct device *dev) { - int e8390_base = dev->base_addr; - int status = inb(e8390_base + EN0_TSR); - struct ei_device *ei_local = (struct ei_device *) dev->priv; + int e8390_base = dev->base_addr; + struct ei_device *ei_local = (struct ei_device *) dev->priv; + int status = inb(e8390_base + EN0_TSR); - outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */ + outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */ #ifdef EI_PINGPONG - /* - * There are two Tx buffers, see which one finished, and trigger - * the send of another one if it exists. - */ - ei_local->txqueue--; - if (ei_local->tx1 < 0) { - if (ei_local->lasttx != 1 && ei_local->lasttx != -1) - printk("%s: bogus last_tx_buffer %d, tx1=%d.\n", - ei_local->name, ei_local->lasttx, ei_local->tx1); - ei_local->tx1 = 0; - dev->tbusy = 0; - if (ei_local->tx2 > 0) { - ei_local->txing = 1; - NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6); - dev->trans_start = jiffies; - ei_local->tx2 = -1, - ei_local->lasttx = 2; - } else - ei_local->lasttx = 20, ei_local->txing = 0; - } else if (ei_local->tx2 < 0) { - if (ei_local->lasttx != 2 && ei_local->lasttx != -2) - printk("%s: bogus last_tx_buffer %d, tx2=%d.\n", - ei_local->name, ei_local->lasttx, ei_local->tx2); - ei_local->tx2 = 0; - dev->tbusy = 0; - if (ei_local->tx1 > 0) { - ei_local->txing = 1; - NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page); - dev->trans_start = jiffies; - ei_local->tx1 = -1; - ei_local->lasttx = 1; - } else - ei_local->lasttx = 10, ei_local->txing = 0; - } else - printk("%s: unexpected TX-done interrupt, lasttx=%d.\n", - dev->name, ei_local->lasttx); + /* + * There are two Tx buffers, see which one finished, and trigger + * the send of another one if it exists. + */ + ei_local->txqueue--; + + if (ei_local->tx1 < 0) + { + if (ei_local->lasttx != 1 && ei_local->lasttx != -1) + printk(KERN_ERR "%s: bogus last_tx_buffer %d, tx1=%d.\n", + ei_local->name, ei_local->lasttx, ei_local->tx1); + ei_local->tx1 = 0; + dev->tbusy = 0; + if (ei_local->tx2 > 0) + { + ei_local->txing = 1; + NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6); + dev->trans_start = jiffies; + ei_local->tx2 = -1, + ei_local->lasttx = 2; + } + else ei_local->lasttx = 20, ei_local->txing = 0; + } + else if (ei_local->tx2 < 0) + { + if (ei_local->lasttx != 2 && ei_local->lasttx != -2) + printk("%s: bogus last_tx_buffer %d, tx2=%d.\n", + ei_local->name, ei_local->lasttx, ei_local->tx2); + ei_local->tx2 = 0; + dev->tbusy = 0; + if (ei_local->tx1 > 0) + { + ei_local->txing = 1; + NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page); + dev->trans_start = jiffies; + ei_local->tx1 = -1; + ei_local->lasttx = 1; + } + else + ei_local->lasttx = 10, ei_local->txing = 0; + } + else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n", + dev->name, ei_local->lasttx); #else /* EI_PINGPONG */ - /* - * Single Tx buffer: mark it free so another packet can be loaded. - */ - ei_local->txing = 0; - dev->tbusy = 0; + /* + * Single Tx buffer: mark it free so another packet can be loaded. + */ + ei_local->txing = 0; + dev->tbusy = 0; #endif - /* Minimize Tx latency: update the statistics after we restart TXing. */ - if (status & ENTSR_COL) - ei_local->stat.collisions++; - if (status & ENTSR_PTX) - ei_local->stat.tx_packets++; - else { - ei_local->stat.tx_errors++; - if (status & ENTSR_ABT) { - ei_local->stat.tx_aborted_errors++; - ei_local->stat.collisions += 16; - } - if (status & ENTSR_CRS) ei_local->stat.tx_carrier_errors++; - if (status & ENTSR_FU) ei_local->stat.tx_fifo_errors++; - if (status & ENTSR_CDH) ei_local->stat.tx_heartbeat_errors++; - if (status & ENTSR_OWC) ei_local->stat.tx_window_errors++; - } - - mark_bh (NET_BH); + /* Minimize Tx latency: update the statistics after we restart TXing. */ + if (status & ENTSR_COL) + ei_local->stat.collisions++; + if (status & ENTSR_PTX) + ei_local->stat.tx_packets++; + else + { + ei_local->stat.tx_errors++; + if (status & ENTSR_ABT) + { + ei_local->stat.tx_aborted_errors++; + ei_local->stat.collisions += 16; + } + if (status & ENTSR_CRS) + ei_local->stat.tx_carrier_errors++; + if (status & ENTSR_FU) + ei_local->stat.tx_fifo_errors++; + if (status & ENTSR_CDH) + ei_local->stat.tx_heartbeat_errors++; + if (status & ENTSR_OWC) + ei_local->stat.tx_window_errors++; + } + mark_bh (NET_BH); } /* We have a good packet(s), get it/them out of the buffers. */ static void ei_receive(struct device *dev) { - int e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) dev->priv; - unsigned char rxing_page, this_frame, next_frame; - unsigned short current_offset; - int rx_pkt_count = 0; - struct e8390_pkt_hdr rx_frame; - int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page; + int e8390_base = dev->base_addr; + struct ei_device *ei_local = (struct ei_device *) dev->priv; + unsigned char rxing_page, this_frame, next_frame; + unsigned short current_offset; + int rx_pkt_count = 0; + struct e8390_pkt_hdr rx_frame; + int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page; - while (++rx_pkt_count < 10) { + while (++rx_pkt_count < 10) + { int pkt_len, pkt_stat; /* Get the rx page (incoming packet pointer). */ @@ -520,7 +562,7 @@ /* Someday we'll omit the previous, iff we never get this message. (There is at least one clone claimed to have a problem.) */ if (ei_debug > 0 && this_frame != ei_local->current_page) - printk("%s: mismatched read page pointers %2x vs %2x.\n", + printk(KERN_ERR "%s: mismatched read page pointers %2x vs %2x.\n", dev->name, this_frame, ei_local->current_page); if (this_frame == rxing_page) /* Read all the frames? */ @@ -547,24 +589,30 @@ continue; } - if (pkt_len < 60 || pkt_len > 1518) { + if (pkt_len < 60 || pkt_len > 1518) + { if (ei_debug) - printk("%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n", + printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n", dev->name, rx_frame.count, rx_frame.status, rx_frame.next); ei_local->stat.rx_errors++; ei_local->stat.rx_length_errors++; - } else if ((pkt_stat & 0x0F) == ENRSR_RXOK) { + } + else if ((pkt_stat & 0x0F) == ENRSR_RXOK) + { struct sk_buff *skb; skb = dev_alloc_skb(pkt_len+2); - if (skb == NULL) { + if (skb == NULL) + { if (ei_debug > 1) - printk("%s: Couldn't allocate a sk_buff of size %d.\n", + printk(KERN_DEBUG "%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, pkt_len); ei_local->stat.rx_dropped++; break; - } else { + } + else + { skb_reserve(skb,2); /* IP headers on 16 byte boundaries */ skb->dev = dev; skb_put(skb, pkt_len); /* Make room */ @@ -576,9 +624,11 @@ if (pkt_stat & ENRSR_PHY) ei_local->stat.multicast++; } - } else { + } + else + { if (ei_debug) - printk("%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n", + printk(KERN_DEBUG "%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n", dev->name, rx_frame.status, rx_frame.next, rx_frame.count); ei_local->stat.rx_errors++; @@ -596,12 +646,12 @@ } ei_local->current_page = next_frame; outb_p(next_frame-1, e8390_base+EN0_BOUNDARY); - } + } - /* We used to also ack ENISR_OVER here, but that would sometimes mask - a real overrun, leaving the 8390 in a stopped state with rec'vr off. */ - outb_p(ENISR_RX+ENISR_RX_ERR, e8390_base+EN0_ISR); - return; + /* We used to also ack ENISR_OVER here, but that would sometimes mask + a real overrun, leaving the 8390 in a stopped state with rec'vr off. */ + outb_p(ENISR_RX+ENISR_RX_ERR, e8390_base+EN0_ISR); + return; } /* @@ -611,93 +661,99 @@ * This includes causing "the NIC to defer indefinitely when it is stopped * on a busy network." Ugh. */ + static void ei_rx_overrun(struct device *dev) { - int e8390_base = dev->base_addr; - unsigned char was_txing, must_resend = 0; - struct ei_device *ei_local = (struct ei_device *) dev->priv; - - /* - * Record whether a Tx was in progress and then issue the - * stop command. - */ - was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS; - outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); - - if (ei_debug > 1) - printk("%s: Receiver overrun.\n", dev->name); - ei_local->stat.rx_over_errors++; - - /* - * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total. - * Early datasheets said to poll the reset bit, but now they say that - * it "is not a reliable indicator and subsequently should be ignored." - * We wait at least 10ms. - */ - udelay(10*1000); - - /* - * Reset RBCR[01] back to zero as per magic incantation. - */ - outb_p(0x00, e8390_base+EN0_RCNTLO); - outb_p(0x00, e8390_base+EN0_RCNTHI); - - /* - * See if any Tx was interrupted or not. According to NS, this - * step is vital, and skipping it will cause no end of havoc. - */ - if (was_txing) { - unsigned char tx_completed = inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR); - if (!tx_completed) must_resend = 1; - } - - /* - * Have to enter loopback mode and then restart the NIC before - * you are allowed to slurp packets up off the ring. - */ - outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); - outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD); - - /* - * Clear the Rx ring of all the debris, and ack the interrupt. - */ - ei_receive(dev); - outb_p(ENISR_OVER, e8390_base+EN0_ISR); - - /* - * Leave loopback mode, and resend any packet that got stopped. - */ - outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); - if (must_resend) - outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD); - + int e8390_base = dev->base_addr; + unsigned char was_txing, must_resend = 0; + struct ei_device *ei_local = (struct ei_device *) dev->priv; + + /* + * Record whether a Tx was in progress and then issue the + * stop command. + */ + was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS; + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); + + if (ei_debug > 1) + printk(KERN_DEBUG "%s: Receiver overrun.\n", dev->name); + ei_local->stat.rx_over_errors++; + + /* + * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total. + * Early datasheets said to poll the reset bit, but now they say that + * it "is not a reliable indicator and subsequently should be ignored." + * We wait at least 10ms. + */ + + udelay(10*1000); + + /* + * Reset RBCR[01] back to zero as per magic incantation. + */ + outb_p(0x00, e8390_base+EN0_RCNTLO); + outb_p(0x00, e8390_base+EN0_RCNTHI); + + /* + * See if any Tx was interrupted or not. According to NS, this + * step is vital, and skipping it will cause no end of havoc. + */ + + if (was_txing) + { + unsigned char tx_completed = inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR); + if (!tx_completed) + must_resend = 1; + } + + /* + * Have to enter loopback mode and then restart the NIC before + * you are allowed to slurp packets up off the ring. + */ + outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); + outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD); + + /* + * Clear the Rx ring of all the debris, and ack the interrupt. + */ + ei_receive(dev); + outb_p(ENISR_OVER, e8390_base+EN0_ISR); + + /* + * Leave loopback mode, and resend any packet that got stopped. + */ + outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); + if (must_resend) + outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD); } static struct net_device_stats *get_stats(struct device *dev) { - short ioaddr = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) dev->priv; + int ioaddr = dev->base_addr; + struct ei_device *ei_local = (struct ei_device *) dev->priv; - /* If the card is stopped, just return the present stats. */ - if (dev->start == 0) return &ei_local->stat; - - /* Read the counter registers, assuming we are in page 0. */ - ei_local->stat.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0); - ei_local->stat.rx_crc_errors += inb_p(ioaddr + EN0_COUNTER1); - ei_local->stat.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2); + /* If the card is stopped, just return the present stats. */ + if (dev->start == 0) + return &ei_local->stat; + + /* Read the counter registers, assuming we are in page 0. */ + ei_local->stat.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0); + ei_local->stat.rx_crc_errors += inb_p(ioaddr + EN0_COUNTER1); + ei_local->stat.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2); - return &ei_local->stat; + return &ei_local->stat; } /* * Update the given Autodin II CRC value with another data byte. */ + static inline u32 update_crc(u8 byte, u32 current_crc) { int bit; u8 ah = 0; - - for (bit=0; bit<8; bit++) { + for (bit=0; bit<8; bit++) + { u8 carry = (current_crc>>31); current_crc <<= 1; ah = ((ah<<1) | carry) ^ byte; @@ -713,14 +769,17 @@ * Form the 64 bit 8390 multicast table from the linked list of addresses * associated with this dev structure. */ + static inline void make_mc_bits(u8 *bits, struct device *dev) { struct dev_mc_list *dmi; - for (dmi=dev->mc_list; dmi; dmi=dmi->next) { + for (dmi=dev->mc_list; dmi; dmi=dmi->next) + { int i; u32 crc; - if (dmi->dmi_addrlen != ETH_ALEN) { + if (dmi->dmi_addrlen != ETH_ALEN) + { printk(KERN_INFO "%s: invalid multicast address length given.\n", dev->name); continue; } @@ -741,17 +800,19 @@ static void set_multicast_list(struct device *dev) { - short ioaddr = dev->base_addr; + int e8390_base = dev->base_addr; int i; unsigned long flags; - struct ei_device *ei = (struct ei_device*)dev->priv; + struct ei_device *ei_local = (struct ei_device*)dev->priv; - if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) { - memset(ei->mcfilter, 0, 8); + if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) + { + memset(ei_local->mcfilter, 0, 8); if (dev->mc_list) - make_mc_bits(ei->mcfilter, dev); - } else - memset(ei->mcfilter, 0xFF, 8); /* mcast set to accept-all */ + make_mc_bits(ei_local->mcfilter, dev); + } + else + memset(ei_local->mcfilter, 0xFF, 8); /* mcast set to accept-all */ /* * DP8390 manuals don't specify any magic sequence for altering @@ -761,30 +822,35 @@ * to stopping the NIC, loading the table and then restarting. */ if (dev->start) - outb_p(E8390_RXCONFIG, ioaddr + EN0_RXCR); + outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); save_flags(flags); cli(); - outb_p(E8390_NODMA + E8390_PAGE1, ioaddr + E8390_CMD); - for(i = 0; i < 8; i++) - outb_p(ei->mcfilter[i], ioaddr + EN1_MULT + i); - outb_p(E8390_NODMA + E8390_PAGE0, ioaddr + E8390_CMD); + outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD); + for(i = 0; i < 8; i++) + { + outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i)); + if(inb_p(e8390_base + EN1_MULT_SHIFT(i))!=ei_local->mcfilter[i]) + printk(KERN_ERR "Multicast filter read/write mismap %d\n",i); + } + outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD); restore_flags(flags); - if(dev->flags&IFF_PROMISC) - outb_p(E8390_RXCONFIG | 0x18, ioaddr + EN0_RXCR); + if(dev->flags&IFF_PROMISC) + outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR); else if(dev->flags&IFF_ALLMULTI || dev->mc_list) - outb_p(E8390_RXCONFIG | 0x08, ioaddr + EN0_RXCR); - else - outb_p(E8390_RXCONFIG, ioaddr + EN0_RXCR); + outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR); + else + outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); } /* Initialize the rest of the 8390 device structure. */ __initfunc(int ethdev_init(struct device *dev)) { - if (ei_debug > 1) + if (ei_debug > 1) printk(version); - if (dev->priv == NULL) { + if (dev->priv == NULL) + { struct ei_device *ei_local; dev->priv = kmalloc(sizeof(struct ei_device), GFP_KERNEL); @@ -792,106 +858,116 @@ return -ENOMEM; memset(dev->priv, 0, sizeof(struct ei_device)); ei_local = (struct ei_device *)dev->priv; - } + } - dev->hard_start_xmit = &ei_start_xmit; - dev->get_stats = get_stats; - dev->set_multicast_list = &set_multicast_list; + dev->hard_start_xmit = &ei_start_xmit; + dev->get_stats = get_stats; + dev->set_multicast_list = &set_multicast_list; - ether_setup(dev); + ether_setup(dev); - return 0; + return 0; } + /* This page of functions should be 8390 generic */ /* Follow National Semi's recommendations for initializing the "NIC". */ + void NS8390_init(struct device *dev, int startp) { - int e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) dev->priv; - int i; - int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48; - unsigned long flags; - - /* Follow National Semi's recommendations for initing the DP83902. */ - outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base); /* 0x21 */ - outb_p(endcfg, e8390_base + EN0_DCFG); /* 0x48 or 0x49 */ - /* Clear the remote byte count registers. */ - outb_p(0x00, e8390_base + EN0_RCNTLO); - outb_p(0x00, e8390_base + EN0_RCNTHI); - /* Set to monitor and loopback mode -- this is vital!. */ - outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */ - outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */ - /* Set the transmit page and receive ring. */ - outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR); - ei_local->tx1 = ei_local->tx2 = 0; - outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG); - outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/ - ei_local->current_page = ei_local->rx_start_page; /* assert boundary+1 */ - outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG); - /* Clear the pending interrupts and mask. */ - outb_p(0xFF, e8390_base + EN0_ISR); - outb_p(0x00, e8390_base + EN0_IMR); - - /* Copy the station address into the DS8390 registers. */ - save_flags(flags); - cli(); - outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base); /* 0x61 */ - for(i = 0; i < 6; i++) { - outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS + i); - } - - outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG); - outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base); - restore_flags(flags); - dev->tbusy = 0; - dev->interrupt = 0; - ei_local->tx1 = ei_local->tx2 = 0; - ei_local->txing = 0; - if (startp) { + int e8390_base = dev->base_addr; + struct ei_device *ei_local = (struct ei_device *) dev->priv; + int i; + int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48; + unsigned long flags; + + if(sizeof(struct e8390_pkt_hdr)!=4) + panic("8390.c: header struct mispacked\n"); + /* Follow National Semi's recommendations for initing the DP83902. */ + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */ + outb_p(endcfg, e8390_base + EN0_DCFG); /* 0x48 or 0x49 */ + /* Clear the remote byte count registers. */ + outb_p(0x00, e8390_base + EN0_RCNTLO); + outb_p(0x00, e8390_base + EN0_RCNTHI); + /* Set to monitor and loopback mode -- this is vital!. */ + outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */ + outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */ + /* Set the transmit page and receive ring. */ + outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR); + ei_local->tx1 = ei_local->tx2 = 0; + outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG); + outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/ + ei_local->current_page = ei_local->rx_start_page; /* assert boundary+1 */ + outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG); + /* Clear the pending interrupts and mask. */ + outb_p(0xFF, e8390_base + EN0_ISR); + outb_p(0x00, e8390_base + EN0_IMR); + + /* Copy the station address into the DS8390 registers. */ + save_flags(flags); + cli(); + outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */ + for(i = 0; i < 6; i++) + { + outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i)); + if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i]) + printk(KERN_ERR "Hw. address read/write mismap %d\n",i); + } + + outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); + restore_flags(flags); + dev->tbusy = 0; + dev->interrupt = 0; + ei_local->tx1 = ei_local->tx2 = 0; + ei_local->txing = 0; + + if (startp) + { outb_p(0xff, e8390_base + EN0_ISR); outb_p(ENISR_ALL, e8390_base + EN0_IMR); - outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD); outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */ /* 3c503 TechMan says rxconfig only after the NIC is started. */ outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on, */ set_multicast_list(dev); /* (re)load the mcast table */ - } - return; + } + return; } /* Trigger a transmit start, assuming the length is valid. */ static void NS8390_trigger_send(struct device *dev, unsigned int length, int start_page) { - int e8390_base = dev->base_addr; + struct ei_device *ei_local = (struct ei_device *) dev->priv; + int e8390_base = dev->base_addr; - outb_p(E8390_NODMA+E8390_PAGE0, e8390_base); + outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD); - if (inb_p(e8390_base) & E8390_TRANS) { - printk("%s: trigger_send() called with the transmitter busy.\n", - dev->name); + if (inb_p(e8390_base) & E8390_TRANS) + { + printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n", + dev->name); return; - } - outb_p(length & 0xff, e8390_base + EN0_TCNTLO); - outb_p(length >> 8, e8390_base + EN0_TCNTHI); - outb_p(start_page, e8390_base + EN0_TPSR); - outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base); - return; + } + outb_p(length & 0xff, e8390_base + EN0_TCNTLO); + outb_p(length >> 8, e8390_base + EN0_TCNTHI); + outb_p(start_page, e8390_base + EN0_TPSR); + outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD); } #ifdef MODULE int init_module(void) { - return 0; + return 0; } -void -cleanup_module(void) +void cleanup_module(void) { } + #endif /* MODULE */ /* diff -u --recursive --new-file v2.1.100/linux/drivers/net/8390.h linux/drivers/net/8390.h --- v2.1.100/linux/drivers/net/8390.h Wed Oct 22 08:28:35 1997 +++ linux/drivers/net/8390.h Thu May 7 23:50:19 1998 @@ -75,6 +75,7 @@ unsigned char saved_irq; /* Original dev->irq value. */ /* The new statistics table. */ struct net_device_stats stat; + unsigned char *reg_offset; /* Register mapping table */ }; /* The maximum number of 8390 interrupt service routines called per IRQ. */ @@ -104,34 +105,41 @@ #define E8390_PAGE1 0x40 /* using the two high-order bits */ #define E8390_PAGE2 0x80 /* Page 3 is invalid. */ -#define E8390_CMD 0x00 /* The command register (for all pages) */ + +#ifndef CONFIG_MAC +#define EI_SHIFT(x) (x) +#else +#define EI_SHIFT(x) (ei_local->reg_offset[x]) +#endif + +#define E8390_CMD EI_SHIFT(0x00) /* The command register (for all pages) */ /* Page 0 register offsets. */ -#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */ -#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */ -#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */ -#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */ -#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */ -#define EN0_TSR 0x04 /* Transmit status reg RD */ -#define EN0_TPSR 0x04 /* Transmit starting page WR */ -#define EN0_NCR 0x05 /* Number of collision reg RD */ -#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */ -#define EN0_FIFO 0x06 /* FIFO RD */ -#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */ -#define EN0_ISR 0x07 /* Interrupt status reg RD WR */ -#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */ -#define EN0_RSARLO 0x08 /* Remote start address reg 0 */ -#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */ -#define EN0_RSARHI 0x09 /* Remote start address reg 1 */ -#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */ -#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */ -#define EN0_RSR 0x0c /* rx status reg RD */ -#define EN0_RXCR 0x0c /* RX configuration reg WR */ -#define EN0_TXCR 0x0d /* TX configuration reg WR */ -#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */ -#define EN0_DCFG 0x0e /* Data configuration reg WR */ -#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */ -#define EN0_IMR 0x0f /* Interrupt mask reg WR */ -#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */ +#define EN0_CLDALO EI_SHIFT(0x01) /* Low byte of current local dma addr RD */ +#define EN0_STARTPG EI_SHIFT(0x01) /* Starting page of ring bfr WR */ +#define EN0_CLDAHI EI_SHIFT(0x02) /* High byte of current local dma addr RD */ +#define EN0_STOPPG EI_SHIFT(0x02) /* Ending page +1 of ring bfr WR */ +#define EN0_BOUNDARY EI_SHIFT(0x03) /* Boundary page of ring bfr RD WR */ +#define EN0_TSR EI_SHIFT(0x04) /* Transmit status reg RD */ +#define EN0_TPSR EI_SHIFT(0x04) /* Transmit starting page WR */ +#define EN0_NCR EI_SHIFT(0x05) /* Number of collision reg RD */ +#define EN0_TCNTLO EI_SHIFT(0x05) /* Low byte of tx byte count WR */ +#define EN0_FIFO EI_SHIFT(0x06) /* FIFO RD */ +#define EN0_TCNTHI EI_SHIFT(0x06) /* High byte of tx byte count WR */ +#define EN0_ISR EI_SHIFT(0x07) /* Interrupt status reg RD WR */ +#define EN0_CRDALO EI_SHIFT(0x08) /* low byte of current remote dma address RD */ +#define EN0_RSARLO EI_SHIFT(0x08) /* Remote start address reg 0 */ +#define EN0_CRDAHI EI_SHIFT(0x09) /* high byte, current remote dma address RD */ +#define EN0_RSARHI EI_SHIFT(0x09) /* Remote start address reg 1 */ +#define EN0_RCNTLO EI_SHIFT(0x0a) /* Remote byte count reg WR */ +#define EN0_RCNTHI EI_SHIFT(0x0b) /* Remote byte count reg WR */ +#define EN0_RSR EI_SHIFT(0x0c) /* rx status reg RD */ +#define EN0_RXCR EI_SHIFT(0x0c) /* RX configuration reg WR */ +#define EN0_TXCR EI_SHIFT(0x0d) /* TX configuration reg WR */ +#define EN0_COUNTER0 EI_SHIFT(0x0d) /* Rcv alignment error counter RD */ +#define EN0_DCFG EI_SHIFT(0x0e) /* Data configuration reg WR */ +#define EN0_COUNTER1 EI_SHIFT(0x0e) /* Rcv CRC error counter RD */ +#define EN0_IMR EI_SHIFT(0x0f) /* Interrupt mask reg WR */ +#define EN0_COUNTER2 EI_SHIFT(0x0f) /* Rcv missed frame error counter RD */ /* Bits in EN0_ISR - Interrupt status register */ #define ENISR_RX 0x01 /* Receiver, no error */ @@ -148,9 +156,11 @@ #define ENDCFG_WTS 0x01 /* word transfer mode selection */ /* Page 1 register offsets. */ -#define EN1_PHYS 0x01 /* This board's physical enet addr RD WR */ -#define EN1_CURPAG 0x07 /* Current memory page RD WR */ -#define EN1_MULT 0x08 /* Multicast filter mask array (8 bytes) RD WR */ +#define EN1_PHYS EI_SHIFT(0x01) /* This board's physical enet addr RD WR */ +#define EN1_PHYS_SHIFT(i) EI_SHIFT(i+1) /* Get and set mac address */ +#define EN1_CURPAG EI_SHIFT(0x07) /* Current memory page RD WR */ +#define EN1_MULT EI_SHIFT(0x08) /* Multicast filter mask array (8 bytes) RD WR */ +#define EN1_MULT_SHIFT(i) EI_SHIFT(8+i) /* Get and set multicast filter */ /* Bits in received packet status byte and EN0_RSR*/ #define ENRSR_RXOK 0x01 /* Received a good packet */ @@ -158,7 +168,7 @@ #define ENRSR_FAE 0x04 /* frame alignment error */ #define ENRSR_FO 0x08 /* FIFO overrun */ #define ENRSR_MPA 0x10 /* missed pkt */ -#define ENRSR_PHY 0x20 /* physical/multicase address */ +#define ENRSR_PHY 0x20 /* physical/multicast address */ #define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */ #define ENRSR_DEF 0x80 /* deferring */ diff -u --recursive --new-file v2.1.100/linux/drivers/net/Config.in linux/drivers/net/Config.in --- v2.1.100/linux/drivers/net/Config.in Thu Apr 23 20:21:33 1998 +++ linux/drivers/net/Config.in Fri May 8 00:20:47 1998 @@ -34,8 +34,8 @@ if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then tristate '3c501 support' CONFIG_EL1 tristate '3c503 support' CONFIG_EL2 + tristate '3c505 support' CONFIG_ELPLUS if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate '3c505 support' CONFIG_ELPLUS tristate '3c507 support' CONFIG_EL16 if [ "$CONFIG_MCA" = "y" ]; then tristate '3c523 support' CONFIG_ELMC @@ -62,6 +62,10 @@ fi tristate 'NI5210 support' CONFIG_NI52 tristate 'NI6510 support' CONFIG_NI65 + fi + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'RealTek 8129/8139 (not 8019/8029!) support' CONFIG_RTL8139 + tristate 'Packet Engines Yellowfin Gigabit-NIC support' CONFIG_YELLOWFIN fi bool 'Other ISA cards' CONFIG_NET_ISA if [ "$CONFIG_NET_ISA" = "y" ]; then diff -u --recursive --new-file v2.1.100/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v2.1.100/linux/drivers/net/Makefile Wed Apr 8 19:36:26 1998 +++ linux/drivers/net/Makefile Fri May 8 00:20:47 1998 @@ -71,7 +71,6 @@ L_OBJS += sk_g16.o endif - ifeq ($(CONFIG_HP100),y) L_OBJS += hp100.o else @@ -419,6 +418,22 @@ endif endif +ifeq ($(CONFIG_RTL8139),y) +L_OBJS += rtl8139.o +else + ifeq ($(CONFIG_RTL8139),m) + M_OBJS += rtl8139.o + endif +endif + +ifeq ($(CONFIG_YELLOWFIN),y) +L_OBJS += yellowfin.o +else + ifeq ($(CONFIG_YELLOWFIN),m) + M_OBJS += yellowfin.o + endif +endif + ifeq ($(CONFIG_WAVELAN),y) L_OBJS += wavelan.o else @@ -747,7 +762,7 @@ endif ifeq ($(CONFIG_VENDOR_SANGOMA),y) - L_OBJS += sdladrv.o + LX_OBJS += sdladrv.o L_OBJS += sdlamain.o ifeq ($(CONFIG_WANPIPE_X25),y) L_OBJS += sdla_x25.o diff -u --recursive --new-file v2.1.100/linux/drivers/net/Space.c linux/drivers/net/Space.c --- v2.1.100/linux/drivers/net/Space.c Wed Apr 8 19:36:26 1998 +++ linux/drivers/net/Space.c Fri May 8 00:20:47 1998 @@ -95,6 +95,10 @@ extern int cs89x0_probe(struct device *dev); extern int ethertap_probe(struct device *dev); extern int epic100_probe(struct device *dev); +extern int rtl8139_probe(struct device *dev); + +/* Gigabit Ethernet adapters */ +extern int yellowfin_probe(struct device *dev); /* Detachable devices ("pocket adaptors") */ extern int atp_init(struct device *); @@ -105,6 +109,9 @@ extern int dfx_probe(struct device *dev); extern int apfddi_init(struct device *dev); +/* HIPPI boards */ +extern int cern_hippi_probe(struct device *); + __initfunc(static int ethif_probe(struct device *dev)) { @@ -291,6 +298,12 @@ #ifdef CONFIG_EPIC100 && epic100_probe(dev) #endif +#ifdef CONFIG_RTL8139 + && rtl8139_probe(dev) +#endif +#ifdef CONFIG_YELLOWFIN + && yellowfin_probe(dev) +#endif && 1 ) { return 1; /* -ENODEV or -EAGAIN would be more accurate. */ } @@ -320,6 +333,28 @@ } #endif +#ifdef CONFIG_HIPPI +static int hippi_probe(struct device *dev) +{ + /* + * Damn this is ugly. + * + * Why the heck would we want to determine this from the base + * address? Stupid PC'ism .... grrrrr. + */ + if (dev->base_addr == -1) + return 1; + + if (1 +#ifdef CONFIG_CERN_HIPPI + && cern_hippi_probe(dev) +#endif + && 1 ) { + return 1; /* -ENODEV or -EAGAIN would be more accurate. */ + } + return 0; +} +#endif #ifdef CONFIG_ETHERTAP static struct device tap0_dev = { "tap0", 0, 0, 0, 0, NETLINK_TAPBASE, 0, 0, 0, 0, NEXT_DEV, ethertap_probe, }; @@ -539,6 +574,20 @@ {"fddi0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi1_dev, fddiif_probe}; #undef NEXT_DEV #define NEXT_DEV (&fddi0_dev) +#endif + +#ifdef CONFIG_HIPPI + static struct device hip3_dev = + {"hip3", 0, 0, 0, 0, -1, 0, 0, 0, 0, NEXT_DEV, hippi_probe}; + static struct device hip2_dev = + {"hip2", 0, 0, 0, 0, -1, 0, 0, 0, 0, &hip3_dev, hippi_probe}; + static struct device hip1_dev = + {"hip1", 0, 0, 0, 0, -1, 0, 0, 0, 0, &hip2_dev, hippi_probe}; + static struct device hip0_dev = + {"hip0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &hip1_dev, hippi_probe}; + +#undef NEXT_DEV +#define NEXT_DEV (&hip0_dev) #endif #ifdef CONFIG_APBIF diff -u --recursive --new-file v2.1.100/linux/drivers/net/am79c961a.c linux/drivers/net/am79c961a.c --- v2.1.100/linux/drivers/net/am79c961a.c Mon Feb 23 18:12:05 1998 +++ linux/drivers/net/am79c961a.c Fri May 8 00:42:39 1998 @@ -1,11 +1,10 @@ /* - * linux/drivers/net/am79c961.c + * linux/drivers/net/am79c961.c * - * Derived from various things including skeleton.c + * Derived from various things including skeleton.c * - * R.M.King 1995. + * R.M.King 1995. */ - #include #include #include @@ -35,33 +34,42 @@ #include "am79c961a.h" static unsigned int net_debug = NET_DEBUG; -static void am79c961_setmulticastlist (struct device *dev); + +static void +am79c961_setmulticastlist (struct device *dev); static char *version = "am79c961 ethernet driver (c) 1995 R.M.King v0.00\n"; -static void write_rreg (unsigned long base, unsigned int reg, unsigned short val) +#define FUNC_PROLOGUE \ + struct dev_priv *priv = (struct dev_priv *)dev->priv + +/* --------------------------------------------------------------------------- */ + +static void +write_rreg (unsigned long base, unsigned int reg, unsigned short val) { - __asm__(" - strh %1, [%2] @ NET_RAP - strh %0, [%2, #-4] @ NET_RDP - " : : "r" (val), "r" (reg), "r" (0xf0000464)); + __asm__(" + strh %1, [%2] @ NET_RAP + strh %0, [%2, #-4] @ NET_RDP + " : : "r" (val), "r" (reg), "r" (0xf0000464)); } static inline void write_ireg (unsigned long base, unsigned int reg, unsigned short val) { - __asm__(" - strh %1, [%2] @ NET_RAP - strh %0, [%2, #8] @ NET_RDP - " : : "r" (val), "r" (reg), "r" (0xf0000464)); + __asm__(" + strh %1, [%2] @ NET_RAP + strh %0, [%2, #8] @ NET_RDP + " : : "r" (val), "r" (reg), "r" (0xf0000464)); } #define am_writeword(dev,off,val)\ - __asm__("\ - strh %0, [%1]\ - " : : "r" ((val) & 0xffff), "r" (0xe0000000 + ((off) << 1))); + __asm__("\ + strh %0, [%1]\ + " : : "r" ((val) & 0xffff), "r" (0xe0000000 + ((off) << 1))); -static inline void am_writebuffer(struct device *dev, unsigned int offset, unsigned char *buf, unsigned int length) +static inline void +am_writebuffer(struct device *dev, unsigned int offset, unsigned char *buf, unsigned int length) { offset = 0xe0000000 + (offset << 1); length = (length + 1) & ~1; @@ -72,8 +80,7 @@ buf += 2; length -= 2; } - while (length > 8) - { + while (length > 8) { unsigned int tmp, tmp2; __asm__ __volatile__(" ldmia %1!, {%2, %3} @@ -107,7 +114,8 @@ return v; } -static inline unsigned short am_readword (struct device *dev, unsigned long off) +static inline unsigned short +am_readword (struct device *dev, unsigned long off) { unsigned long address = 0xe0000000 + (off << 1); unsigned short val; @@ -118,7 +126,8 @@ return val; } -static inline void am_readbuffer(struct device *dev, unsigned int offset, unsigned char *buf, unsigned int length) +static inline void +am_readbuffer(struct device *dev, unsigned int offset, unsigned char *buf, unsigned int length) { offset = 0xe0000000 + (offset << 1); length = (length + 1) & ~1; @@ -158,12 +167,8 @@ } } -/* - * From here on is mostly non ARM specific. Watch the fact it knows - * the chip can hit all memory (kmalloc). - */ - -static int am79c961_ramtest(struct device *dev, unsigned int val) +static int +am79c961_ramtest(struct device *dev, unsigned int val) { unsigned char *buffer = kmalloc (65536, GFP_KERNEL); int i, error = 0, errorcount = 0; @@ -190,9 +195,10 @@ return errorcount; } -static void am79c961_init_for_open(struct device *dev) +static void +am79c961_init_for_open(struct device *dev) { - struct dev_priv *priv = (struct dev_priv *)dev->priv; + struct dev_priv *priv = (struct dev_priv *)dev->priv; unsigned long hdr_addr, first_free_addr; unsigned long flags; unsigned char *p; @@ -212,9 +218,8 @@ priv->rxtail = 0; priv->rxhdr = hdr_addr; - for (i = 0; i < RX_BUFFERS; i++) - { - priv->rxbuffer[i] = first_free_addr; + for (i = 0; i < RX_BUFFERS; i++) { + priv->rxbuffer[i] = first_free_addr; am_writeword (dev, hdr_addr, first_free_addr); am_writeword (dev, hdr_addr + 2, RMD_OWN); am_writeword (dev, hdr_addr + 4, (-1600)); @@ -225,9 +230,8 @@ priv->txhead = 0; priv->txtail = 0; priv->txhdr = hdr_addr; - for (i = 0; i < TX_BUFFERS; i++) - { - priv->txbuffer[i] = first_free_addr; + for (i = 0; i < TX_BUFFERS; i++) { + priv->txbuffer[i] = first_free_addr; am_writeword (dev, hdr_addr, first_free_addr); am_writeword (dev, hdr_addr + 2, 0); am_writeword (dev, hdr_addr + 4, 0); @@ -251,7 +255,7 @@ write_rreg (dev->base_addr, BASERXH, 0); write_rreg (dev->base_addr, BASETXL, priv->txhdr); write_rreg (dev->base_addr, BASERXH, 0); - write_rreg (dev->base_addr, POLLINT, 0); + write_rreg (dev->base_addr, POLLINT, 0); write_rreg (dev->base_addr, SIZERXR, -RX_BUFFERS); write_rreg (dev->base_addr, SIZETXR, -TX_BUFFERS); write_rreg (dev->base_addr, CSR0, CSR0_STOP); @@ -259,7 +263,8 @@ write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT); } -static int am79c961_init(struct device *dev) +static int +am79c961_init(struct device *dev) { unsigned long flags; @@ -280,15 +285,14 @@ /* * This is the real probe routine. */ - -static int am79c961_probe1(struct device *dev) +static int +am79c961_probe1(struct device *dev) { static unsigned version_printed = 0; struct dev_priv *priv; int i; - if (!dev->priv) - { + if (!dev->priv) { dev->priv = kmalloc (sizeof (struct dev_priv), GFP_KERNEL); if (!dev->priv) return -ENOMEM; @@ -300,21 +304,19 @@ /* * The PNP initialisation should have been done by the ether bootp loader. */ - inb ((dev->base_addr + NET_RESET) >> 1); /* reset the device */ udelay (5); if (inb (dev->base_addr >> 1) != 0x08 || - inb ((dev->base_addr >> 1) + 1) != 00 || - inb ((dev->base_addr >> 1) + 2) != 0x2b) - { + inb ((dev->base_addr >> 1) + 1) != 00 || + inb ((dev->base_addr >> 1) + 2) != 0x2b) { kfree (dev->priv); dev->priv = NULL; return -ENODEV; - } + } - /* + /* * Ok, we've found a valid hw ID */ @@ -325,14 +327,12 @@ request_region (dev->base_addr, 0x18, "am79c961"); /* Retrive and print the ethernet address. */ - for (i = 0; i < 6; i++) - { - dev->dev_addr[i] = inb ((dev->base_addr >> 1) + i) & 0xff; + for (i = 0; i < 6; i++) { + dev->dev_addr[i] = inb ((dev->base_addr >> 1) + i) & 0xff; printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]); } - if (am79c961_init(dev)) - { + if (am79c961_init(dev)) { kfree (dev->priv); dev->priv = NULL; return -ENODEV; @@ -346,10 +346,12 @@ /* Fill in the fields of the device structure with ethernet values. */ ether_setup(dev); + return 0; } -int am79c961_probe(struct device *dev) +int +am79c961_probe(struct device *dev) { static int initialised = 0; @@ -371,10 +373,10 @@ * registers that "should" only need to be set once at boot, so that * there is non-reboot way to recover if something goes wrong. */ - -static int am79c961_open(struct device *dev) +static int +am79c961_open(struct device *dev) { - struct dev_priv *priv = (struct dev_priv *)dev->priv; + struct dev_priv *priv = (struct dev_priv *)dev->priv; MOD_INC_USE_COUNT; @@ -384,6 +386,7 @@ return -EAGAIN; am79c961_init_for_open(dev); + dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; @@ -393,13 +396,14 @@ /* * The inverse routine to am79c961_open(). */ - -static int am79c961_close(struct device *dev) +static int +am79c961_close(struct device *dev) { dev->tbusy = 1; dev->start = 0; am79c961_init(dev); + free_irq (dev->irq, dev); MOD_DEC_USE_COUNT; @@ -410,10 +414,9 @@ * Get the current statistics. This may be called with the card open or * closed. */ - static struct enet_statistics *am79c961_getstats (struct device *dev) { - struct dev_priv *priv = (struct dev_priv *)dev->priv; + struct dev_priv *priv = (struct dev_priv *)dev->priv; return &priv->stats; } @@ -423,7 +426,6 @@ * We don't attempt any packet filtering. The card may have a SEEQ 8004 * in which does not have the other ethernet address registers present... */ - static void am79c961_setmulticastlist (struct device *dev) { unsigned long flags; @@ -441,18 +443,16 @@ } /* - * Transmit a packet + * Transmit a packet */ - -static int am79c961_sendpacket(struct sk_buff *skb, struct device *dev) +static int +am79c961_sendpacket(struct sk_buff *skb, struct device *dev) { struct dev_priv *priv = (struct dev_priv *)dev->priv; - if (!dev->tbusy) - { + if (!dev->tbusy) { again: - if (!test_and_set_bit(0, (void*)&dev->tbusy)) - { + if (!test_and_set_bit(0, (void*)&dev->tbusy)) { unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned int hdraddr, bufaddr; unsigned long flags; @@ -474,17 +474,12 @@ if (!(am_readword (dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN)) dev->tbusy = 0; - dev_kfree_skb (skb, FREE_WRITE); + dev_kfree_skb (skb); return 0; - } - else - { + } else printk(KERN_ERR "%s: Transmitter access conflict.\n", dev->name); return 1; - } - } - else - { + } else { int tickssofar = jiffies - dev->trans_start; if (tickssofar < 5) return 1; @@ -496,7 +491,8 @@ } } -static void am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static void +am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct device *dev = (struct device *)dev_id; struct dev_priv *priv = (struct dev_priv *)dev->priv; @@ -508,6 +504,7 @@ #endif dev->interrupt = 1; + status = read_rreg (dev->base_addr, CSR0); write_rreg (dev->base_addr, CSR0, status & (CSR0_TINT|CSR0_RINT|CSR0_MISS|CSR0_IENA)); @@ -529,14 +526,13 @@ /* * If we have a good packet(s), get it/them out of the buffers. */ - -static void am79c961_rx(struct device *dev, struct dev_priv *priv) +static void +am79c961_rx(struct device *dev, struct dev_priv *priv) { unsigned long hdraddr; unsigned long pktaddr; - do - { + do { unsigned long status; struct sk_buff *skb; int len; @@ -552,18 +548,15 @@ if (priv->rxtail >= RX_BUFFERS) priv->rxtail = 0; - if ((status & (RMD_ERR|RMD_STP|RMD_ENP)) != (RMD_STP|RMD_ENP)) - { + if ((status & (RMD_ERR|RMD_STP|RMD_ENP)) != (RMD_STP|RMD_ENP)) { am_writeword (dev, hdraddr + 2, RMD_OWN); priv->stats.rx_errors ++; - if (status & RMD_ERR) - { + if (status & RMD_ERR) { if (status & RMD_FRAM) priv->stats.rx_frame_errors ++; if (status & RMD_CRC) priv->stats.rx_crc_errors ++; - } - else if (status & RMD_STP) + } else if (status & RMD_STP) priv->stats.rx_length_errors ++; continue; } @@ -595,8 +588,8 @@ /* * Update stats for the transmitted packet */ - -static void am79c961_tx(struct device *dev, struct dev_priv *priv) +static void +am79c961_tx(struct device *dev, struct dev_priv *priv) { do { unsigned long hdraddr; diff -u --recursive --new-file v2.1.100/linux/drivers/net/com90xx.c linux/drivers/net/com90xx.c --- v2.1.100/linux/drivers/net/com90xx.c Mon Feb 23 18:12:05 1998 +++ linux/drivers/net/com90xx.c Fri May 8 00:20:47 1998 @@ -1,28 +1,28 @@ -/* $Id: com90xx.c,v 1.6 1997/11/09 11:05:01 mj Exp $ +/* $Id: com90xx.c,v 1.9 1998/03/21 18:02:51 alan Exp $ - Derived from the original arcnet.c, - Written 1994-1996 by Avery Pennarun, - which was in turn derived from skeleton.c by Donald Becker. + Derived from the original arcnet.c, + Written 1994-1996 by Avery Pennarun, + which was in turn derived from skeleton.c by Donald Becker. - Contact Avery at: apenwarr@bond.net or - RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9 + Contact Avery at: apenwarr@bond.net or + RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9 - ********************** + ********************** - The original copyright of skeleton.c was as follows: + The original copyright of skeleton.c was as follows: - skeleton.c Written 1993 by Donald Becker. - Copyright 1993 United States Government as represented by the - Director, National Security Agency. This software may only be used - and distributed according to the terms of the GNU Public License as - modified by SRC, incorporated herein by reference. + skeleton.c Written 1993 by Donald Becker. + Copyright 1993 United States Government as represented by the + Director, National Security Agency. This software may only be used + and distributed according to the terms of the GNU Public License as + modified by SRC, incorporated herein by reference. - ********************** + ********************** - For more details, see drivers/net/arcnet.c + For more details, see drivers/net/arcnet.c - ********************** -*/ + ********************** + */ #include @@ -94,34 +94,34 @@ #ifdef MODULE static #endif - int arc90xx_probe(struct device *dev); -static void arc90xx_rx(struct device *dev,int recbuf); -static int arc90xx_found(struct device *dev,int ioaddr,int airq,u_long shmem,int more); -static void arc90xx_inthandler (struct device *dev); -static int arc90xx_reset (struct device *dev, int reset_delay); -static void arc90xx_setmask (struct device *dev, u_char mask); -static void arc90xx_command (struct device *dev, u_char command); -static u_char arc90xx_status (struct device *dev); -static void arc90xx_prepare_tx(struct device *dev,u_char *hdr,int hdrlen, - char *data,int length,int daddr,int exceptA, int offset); -static void arc90xx_openclose(int open); +int arc90xx_probe(struct device *dev); +static void arc90xx_rx(struct device *dev, int recbuf); +static int arc90xx_found(struct device *dev, int ioaddr, int airq, u_long shmem, int more); +static void arc90xx_inthandler(struct device *dev); +static int arc90xx_reset(struct device *dev, int reset_delay); +static void arc90xx_setmask(struct device *dev, u_char mask); +static void arc90xx_command(struct device *dev, u_char command); +static u_char arc90xx_status(struct device *dev); +static void arc90xx_prepare_tx(struct device *dev, u_char * hdr, int hdrlen, + char *data, int length, int daddr, int exceptA, int offset); +static void arc90xx_openclose(int open); /* Module parameters */ #ifdef MODULE -static int io=0x0; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */ -static int irq=0; /* or use the insmod io= irq= shmem= options */ -static int shmem=0; -static char *device; /* use eg. device="arc1" to change name */ +static int io = 0x0; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */ +static int irq = 0; /* or use the insmod io= irq= shmem= options */ +static int shmem = 0; +static char *device; /* use eg. device="arc1" to change name */ MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); MODULE_PARM(shmem, "i"); MODULE_PARM(device, "s"); #else -__initfunc(void com90xx_setup (char *str, int *ints)); -char __initdata com90xx_explicit=0; +__initfunc(void com90xx_setup(char *str, int *ints)); +char __initdata com90xx_explicit = 0; extern struct device arcnet_devs[]; extern char arcnet_dev_names[][10]; @@ -139,12 +139,12 @@ #define _STATUS (ioaddr+0) /* readable */ #define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */ #define _RESET (ioaddr+8) /* software reset (on read) */ -#define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */ -#define _ADDR_HI (ioaddr+15) /* Control registers for said */ +#define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */ +#define _ADDR_HI (ioaddr+15) /* Control registers for said */ #define _ADDR_LO (ioaddr+14) -#define _CONFIG (ioaddr+2) /* Configuration register */ +#define _CONFIG (ioaddr+2) /* Configuration register */ -#define RDDATAflag 0x00 /* Next access is a read/~write */ +#define RDDATAflag 0x00 /* Next access is a read/~write */ #define ARCSTATUS inb(_STATUS) #define ACOMMAND(cmd) outb((cmd),_COMMAND) @@ -153,7 +153,7 @@ #define ARCRESET inb(_RESET) static const char *version = - "com90xx.c: v3.00 97/11/09 Avery Pennarun et al.\n"; +"com90xx.c: v3.00 97/11/09 Avery Pennarun et al.\n"; /**************************************************************************** @@ -166,7 +166,7 @@ * If dev->base_addr == 0, probe all likely locations. * If dev->base_addr == 1, always return failure. * If dev->base_addr == 2, allocate space for the device and return success - * (detachable devices only). + * (detachable devices only). * * NOTE: the list of possible ports/shmems is static, so it is retained * across calls to arcnet_probe. So, if more than one ARCnet probe is made, @@ -175,811 +175,736 @@ * FIXME: grab all devices in one shot and eliminate the big static array. */ -static int ports[(0x3f0 - 0x200) / 16 + 1] __initdata = { 0 }; -static u_long shmems[(0xFF800 - 0xA0000) / 2048 + 1] __initdata = { 0 }; +static int ports[(0x3f0 - 0x200) / 16 + 1] __initdata = { + 0 +}; +static u_long shmems[(0xFF800 - 0xA0000) / 2048 + 1] __initdata = { + 0 +}; __initfunc(int arc90xx_probe(struct device *dev)) { - static int init_once = 0; - static int numports=sizeof(ports)/sizeof(ports[0]), - numshmems=sizeof(shmems)/sizeof(shmems[0]); - int count,status,delayval,ioaddr,numprint,airq,retval=-ENODEV, - openparen=0; - unsigned long airqmask; - int *port; - u_long *shmem; - - if (!init_once) - { - for (count=0x200; count<=0x3f0; count+=16) - ports[(count-0x200)/16] = count; - for (count=0xA0000; count<=0xFF800; count+=2048) - shmems[(count-0xA0000)/2048] = count; - BUGLVL(D_NORMAL) printk(version); - BUGMSG(D_DURING,"space used for probe buffers: %d+%d=%d bytes\n", - sizeof(ports),sizeof(shmems), - sizeof(ports)+sizeof(shmems)); - } - init_once++; - - BUGMSG(D_INIT,"given: base %lXh, IRQ %d, shmem %lXh\n", - dev->base_addr,dev->irq,dev->mem_start); - - if (dev->base_addr > 0x1ff) /* Check a single specified port */ - { - ports[0]=dev->base_addr; - numports=1; - } - else if (dev->base_addr > 0) /* Don't probe at all. */ - return -ENXIO; - - if (dev->mem_start) - { - shmems[0]=dev->mem_start; - numshmems=1; - } - - /* Stage 1: abandon any reserved ports, or ones with status==0xFF - * (empty), and reset any others by reading the reset port. - */ - BUGMSG(D_INIT,"Stage 1: "); - numprint=0; - for (port = &ports[0]; port-ports8) - { - BUGMSG2(D_INIT,"\n"); - BUGMSG(D_INIT,"Stage 1: "); - numprint=1; - } - BUGMSG2(D_INIT,"%Xh ",*port); - - ioaddr=*port; - - if (check_region(*port, ARCNET_TOTAL_SIZE)) - { - BUGMSG2(D_INIT_REASONS,"(check_region)\n"); - BUGMSG(D_INIT_REASONS,"Stage 1: "); - BUGLVL(D_INIT_REASONS) numprint=0; - *port=ports[numports-1]; - numports--; - port--; - continue; - } - - if (ARCSTATUS == 0xFF) - { - BUGMSG2(D_INIT_REASONS,"(empty)\n"); - BUGMSG(D_INIT_REASONS,"Stage 1: "); - BUGLVL(D_INIT_REASONS) numprint=0; - *port=ports[numports-1]; - numports--; - port--; - continue; - } - - ARCRESET; /* begin resetting card */ - - BUGMSG2(D_INIT_REASONS,"\n"); - BUGMSG(D_INIT_REASONS,"Stage 1: "); - BUGLVL(D_INIT_REASONS) numprint=0; - } - BUGMSG2(D_INIT,"\n"); - - if (!numports) - { - BUGMSG(D_NORMAL,"Stage 1: No ARCnet cards found.\n"); - return -ENODEV; - } - - /* Stage 2: we have now reset any possible ARCnet cards, so we can't - * do anything until they finish. If D_INIT, print the list of - * cards that are left. - */ - BUGMSG(D_INIT,"Stage 2: "); - numprint=0; - for (port = &ports[0]; port-ports8) - { - BUGMSG2(D_INIT,"\n"); - BUGMSG(D_INIT,"Stage 2: "); - numprint=1; - } - BUGMSG2(D_INIT,"%Xh ",*port); - } - BUGMSG2(D_INIT,"\n"); - JIFFER(RESETtime); - - /* Stage 3: abandon any shmem addresses that don't have the signature - * 0xD1 byte in the right place, or are read-only. - */ - BUGMSG(D_INIT,"Stage 3: "); - numprint=0; - for (shmem = &shmems[0]; shmem-shmems8) - { - BUGMSG2(D_INIT,"\n"); - BUGMSG(D_INIT,"Stage 3: "); - numprint=1; - } - BUGMSG2(D_INIT,"%lXh ",*shmem); - - ptr=(u_long)(*shmem); - - if (readb(ptr) != TESTvalue) - { - BUGMSG2(D_INIT_REASONS,"(mem=%02Xh, not %02Xh)\n", - readb(ptr),TESTvalue); - BUGMSG(D_INIT_REASONS,"Stage 3: "); - BUGLVL(D_INIT_REASONS) numprint=0; - *shmem=shmems[numshmems-1]; - numshmems--; - shmem--; - continue; - } - - /* By writing 0x42 to the TESTvalue location, we also make - * sure no "mirror" shmem areas show up - if they occur - * in another pass through this loop, they will be discarded - * because *cptr != TESTvalue. - */ - writeb(0x42,ptr); - if (readb(ptr) != 0x42) - { - BUGMSG2(D_INIT_REASONS,"(read only)\n"); - BUGMSG(D_INIT_REASONS,"Stage 3: "); - *shmem=shmems[numshmems-1]; - numshmems--; - shmem--; - continue; - } - - BUGMSG2(D_INIT_REASONS,"\n"); - BUGMSG(D_INIT_REASONS,"Stage 3: "); - BUGLVL(D_INIT_REASONS) numprint=0; - } - BUGMSG2(D_INIT,"\n"); - - if (!numshmems) - { - BUGMSG(D_NORMAL,"Stage 3: No ARCnet cards found.\n"); - return -ENODEV; - } - - /* Stage 4: something of a dummy, to report the shmems that are - * still possible after stage 3. - */ - BUGMSG(D_INIT,"Stage 4: "); - numprint=0; - for (shmem = &shmems[0]; shmem-shmems8) - { - BUGMSG2(D_INIT,"\n"); - BUGMSG(D_INIT,"Stage 4: "); - numprint=1; - } - BUGMSG2(D_INIT,"%lXh ",*shmem); - } - BUGMSG2(D_INIT,"\n"); - - /* Stage 5: for any ports that have the correct status, can disable - * the RESET flag, and (if no irq is given) generate an autoirq, - * register an ARCnet device. - * - * Currently, we can only register one device per probe, so quit - * after the first one is found. - */ - BUGMSG(D_INIT,"Stage 5: "); - numprint=0; - for (port = &ports[0]; port-ports8) - { - BUGMSG2(D_INIT,"\n"); - BUGMSG(D_INIT,"Stage 5: "); - numprint=1; - } - BUGMSG2(D_INIT,"%Xh ",*port); - - ioaddr=*port; - status=ARCSTATUS; - - if ((status & 0x9D) - != (NORXflag|RECONflag|TXFREEflag|RESETflag)) - { - BUGMSG2(D_INIT_REASONS,"(status=%Xh)\n",status); - BUGMSG(D_INIT_REASONS,"Stage 5: "); - BUGLVL(D_INIT_REASONS) numprint=0; - *port=ports[numports-1]; - numports--; - port--; - continue; - } - - ACOMMAND(CFLAGScmd|RESETclear|CONFIGclear); - status=ARCSTATUS; - if (status & RESETflag) - { - BUGMSG2(D_INIT_REASONS," (eternal reset, status=%Xh)\n", - status); - BUGMSG(D_INIT_REASONS,"Stage 5: "); - BUGLVL(D_INIT_REASONS) numprint=0; - *port=ports[numports-1]; - numports--; - port--; - continue; - } - - /* skip this completely if an IRQ was given, because maybe - * we're on a machine that locks during autoirq! - */ - if (!dev->irq) - { - /* if we do this, we're sure to get an IRQ since the - * card has just reset and the NORXflag is on until - * we tell it to start receiving. - */ - airqmask = probe_irq_on(); - AINTMASK(NORXflag); - udelay(1); - AINTMASK(0); - airq = probe_irq_off(airqmask); - - if (airq<=0) - { - BUGMSG2(D_INIT_REASONS,"(airq=%d)\n",airq); - BUGMSG(D_INIT_REASONS,"Stage 5: "); - BUGLVL(D_INIT_REASONS) numprint=0; - *port=ports[numports-1]; - numports--; - port--; - continue; - } - } - else - { - airq=dev->irq; - } - - BUGMSG2(D_INIT,"(%d,", airq); - openparen=1; - - /* Everything seems okay. But which shmem, if any, puts - * back its signature byte when the card is reset? - * - * If there are multiple cards installed, there might be - * multiple shmems still in the list. - */ -#ifdef FAST_PROBE - if (numports>1 || numshmems>1) - { - ARCRESET; - JIFFER(RESETtime); - } - else - { - /* just one shmem and port, assume they match */ - writeb(TESTvalue,shmems[0]); + static int init_once = 0; + static int numports = sizeof(ports) / sizeof(ports[0]), numshmems = sizeof(shmems) / sizeof(shmems[0]); + int count, status, delayval, ioaddr, numprint, airq, retval = -ENODEV, + openparen = 0; + unsigned long airqmask; + int *port; + u_long *shmem; + + if (!init_once) { + for (count = 0x200; count <= 0x3f0; count += 16) + ports[(count - 0x200) / 16] = count; + for (count = 0xA0000; count <= 0xFF800; count += 2048) + shmems[(count - 0xA0000) / 2048] = count; + BUGLVL(D_NORMAL) printk(version); + BUGMSG(D_DURING, "space used for probe buffers: %d+%d=%d bytes\n", + sizeof(ports), sizeof(shmems), + sizeof(ports) + sizeof(shmems)); + } + init_once++; + + BUGMSG(D_INIT, "given: base %lXh, IRQ %d, shmem %lXh\n", + dev->base_addr, dev->irq, dev->mem_start); + + if (dev->base_addr > 0x1ff) { /* Check a single specified port */ + ports[0] = dev->base_addr; + numports = 1; + } else if (dev->base_addr > 0) /* Don't probe at all. */ + return -ENXIO; + + if (dev->mem_start) { + shmems[0] = dev->mem_start; + numshmems = 1; + } + /* Stage 1: abandon any reserved ports, or ones with status==0xFF + * (empty), and reset any others by reading the reset port. + */ + BUGMSG(D_INIT, "Stage 1: "); + numprint = 0; + for (port = &ports[0]; port - ports < numports; port++) { + numprint++; + if (numprint > 8) { + BUGMSG2(D_INIT, "\n"); + BUGMSG(D_INIT, "Stage 1: "); + numprint = 1; + } + BUGMSG2(D_INIT, "%Xh ", *port); + + ioaddr = *port; + + if (check_region(*port, ARCNET_TOTAL_SIZE)) { + BUGMSG2(D_INIT_REASONS, "(check_region)\n"); + BUGMSG(D_INIT_REASONS, "Stage 1: "); + BUGLVL(D_INIT_REASONS) numprint = 0; + *port = ports[numports - 1]; + numports--; + port--; + continue; + } + if (ARCSTATUS == 0xFF) { + BUGMSG2(D_INIT_REASONS, "(empty)\n"); + BUGMSG(D_INIT_REASONS, "Stage 1: "); + BUGLVL(D_INIT_REASONS) numprint = 0; + *port = ports[numports - 1]; + numports--; + port--; + continue; + } + ARCRESET; /* begin resetting card */ + + BUGMSG2(D_INIT_REASONS, "\n"); + BUGMSG(D_INIT_REASONS, "Stage 1: "); + BUGLVL(D_INIT_REASONS) numprint = 0; + } + BUGMSG2(D_INIT, "\n"); + + if (!numports) { + BUGMSG(D_NORMAL, "Stage 1: No ARCnet cards found.\n"); + return -ENODEV; + } + /* Stage 2: we have now reset any possible ARCnet cards, so we can't + * do anything until they finish. If D_INIT, print the list of + * cards that are left. + */ + BUGMSG(D_INIT, "Stage 2: "); + numprint = 0; + for (port = &ports[0]; port - ports < numports; port++) { + numprint++; + if (numprint > 8) { + BUGMSG2(D_INIT, "\n"); + BUGMSG(D_INIT, "Stage 2: "); + numprint = 1; + } + BUGMSG2(D_INIT, "%Xh ", *port); + } + BUGMSG2(D_INIT, "\n"); + JIFFER(RESETtime); + + /* Stage 3: abandon any shmem addresses that don't have the signature + * 0xD1 byte in the right place, or are read-only. + */ + BUGMSG(D_INIT, "Stage 3: "); + numprint = 0; + for (shmem = &shmems[0]; shmem - shmems < numshmems; shmem++) { + u_long ptr; + + numprint++; + if (numprint > 8) { + BUGMSG2(D_INIT, "\n"); + BUGMSG(D_INIT, "Stage 3: "); + numprint = 1; + } + BUGMSG2(D_INIT, "%lXh ", *shmem); + + ptr = (u_long) (*shmem); + + if (readb(ptr) != TESTvalue) { + BUGMSG2(D_INIT_REASONS, "(mem=%02Xh, not %02Xh)\n", + readb(ptr), TESTvalue); + BUGMSG(D_INIT_REASONS, "Stage 3: "); + BUGLVL(D_INIT_REASONS) numprint = 0; + *shmem = shmems[numshmems - 1]; + numshmems--; + shmem--; + continue; + } + /* By writing 0x42 to the TESTvalue location, we also make + * sure no "mirror" shmem areas show up - if they occur + * in another pass through this loop, they will be discarded + * because *cptr != TESTvalue. + */ + writeb(0x42, ptr); + if (readb(ptr) != 0x42) { + BUGMSG2(D_INIT_REASONS, "(read only)\n"); + BUGMSG(D_INIT_REASONS, "Stage 3: "); + *shmem = shmems[numshmems - 1]; + numshmems--; + shmem--; + continue; + } + BUGMSG2(D_INIT_REASONS, "\n"); + BUGMSG(D_INIT_REASONS, "Stage 3: "); + BUGLVL(D_INIT_REASONS) numprint = 0; + } + BUGMSG2(D_INIT, "\n"); + + if (!numshmems) { + BUGMSG(D_NORMAL, "Stage 3: No ARCnet cards found.\n"); + return -ENODEV; + } + /* Stage 4: something of a dummy, to report the shmems that are + * still possible after stage 3. + */ + BUGMSG(D_INIT, "Stage 4: "); + numprint = 0; + for (shmem = &shmems[0]; shmem - shmems < numshmems; shmem++) { + numprint++; + if (numprint > 8) { + BUGMSG2(D_INIT, "\n"); + BUGMSG(D_INIT, "Stage 4: "); + numprint = 1; + } + BUGMSG2(D_INIT, "%lXh ", *shmem); } + BUGMSG2(D_INIT, "\n"); + + /* Stage 5: for any ports that have the correct status, can disable + * the RESET flag, and (if no irq is given) generate an autoirq, + * register an ARCnet device. + * + * Currently, we can only register one device per probe, so quit + * after the first one is found. + */ + BUGMSG(D_INIT, "Stage 5: "); + numprint = 0; + for (port = &ports[0]; port - ports < numports; port++) { + numprint++; + if (numprint > 8) { + BUGMSG2(D_INIT, "\n"); + BUGMSG(D_INIT, "Stage 5: "); + numprint = 1; + } + BUGMSG2(D_INIT, "%Xh ", *port); + + ioaddr = *port; + status = ARCSTATUS; + + if ((status & 0x9D) + != (NORXflag | RECONflag | TXFREEflag | RESETflag)) { + BUGMSG2(D_INIT_REASONS, "(status=%Xh)\n", status); + BUGMSG(D_INIT_REASONS, "Stage 5: "); + BUGLVL(D_INIT_REASONS) numprint = 0; + *port = ports[numports - 1]; + numports--; + port--; + continue; + } + ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); + status = ARCSTATUS; + if (status & RESETflag) { + BUGMSG2(D_INIT_REASONS, " (eternal reset, status=%Xh)\n", + status); + BUGMSG(D_INIT_REASONS, "Stage 5: "); + BUGLVL(D_INIT_REASONS) numprint = 0; + *port = ports[numports - 1]; + numports--; + port--; + continue; + } + /* skip this completely if an IRQ was given, because maybe + * we're on a machine that locks during autoirq! + */ + if (!dev->irq) { + /* if we do this, we're sure to get an IRQ since the + * card has just reset and the NORXflag is on until + * we tell it to start receiving. + */ + airqmask = probe_irq_on(); + AINTMASK(NORXflag); + udelay(1); + AINTMASK(0); + airq = probe_irq_off(airqmask); + + if (airq <= 0) { + BUGMSG2(D_INIT_REASONS, "(airq=%d)\n", airq); + BUGMSG(D_INIT_REASONS, "Stage 5: "); + BUGLVL(D_INIT_REASONS) numprint = 0; + *port = ports[numports - 1]; + numports--; + port--; + continue; + } + } else { + airq = dev->irq; + } + + BUGMSG2(D_INIT, "(%d,", airq); + openparen = 1; + + /* Everything seems okay. But which shmem, if any, puts + * back its signature byte when the card is reset? + * + * If there are multiple cards installed, there might be + * multiple shmems still in the list. + */ +#ifdef FAST_PROBE + if (numports > 1 || numshmems > 1) { + ARCRESET; + JIFFER(RESETtime); + } else { + /* just one shmem and port, assume they match */ + writeb(TESTvalue, shmems[0]); + } #else - ARCRESET; - JIFFER(RESETtime); + ARCRESET; + JIFFER(RESETtime); #endif - for (shmem = &shmems[0]; shmem-shmems 1) - probe_more = numshmems - 1; - else - probe_more = 0; - retval=arc90xx_found(dev,*port,airq,*shmem,probe_more); - if (retval) openparen=0; - - /* remove shmem from the list */ - *shmem=shmems[numshmems-1]; - numshmems--; - - break; - } - else - { - BUGMSG2(D_INIT_REASONS,"%Xh-", readb(ptr)); - } - } - - if (openparen) - { - BUGMSG2(D_INIT,"no matching shmem)\n"); - BUGMSG(D_INIT_REASONS,"Stage 5: "); - BUGLVL(D_INIT_REASONS) numprint=0; - } - - *port=ports[numports-1]; - numports--; - port--; - - if (!retval) break; - } - BUGMSG(D_INIT_REASONS,"\n"); - - /* Now put back TESTvalue on all leftover shmems. - */ - for (shmem = &shmems[0]; shmem-shmems 1) + probe_more = numshmems - 1; + else + probe_more = 0; + retval = arc90xx_found(dev, *port, airq, *shmem, probe_more); + if (retval) + openparen = 0; + + /* remove shmem from the list */ + *shmem = shmems[numshmems - 1]; + numshmems--; + + break; + } else { + BUGMSG2(D_INIT_REASONS, "%Xh-", readb(ptr)); + } + } - if (retval) BUGMSG(D_NORMAL,"Stage 5: No ARCnet cards found.\n"); - return retval; + if (openparen) { + BUGMSG2(D_INIT, "no matching shmem)\n"); + BUGMSG(D_INIT_REASONS, "Stage 5: "); + BUGLVL(D_INIT_REASONS) numprint = 0; + } + *port = ports[numports - 1]; + numports--; + port--; + + if (!retval) + break; + } + BUGMSG(D_INIT_REASONS, "\n"); + + /* Now put back TESTvalue on all leftover shmems. + */ + for (shmem = &shmems[0]; shmem - shmems < numshmems; shmem++) + writeb(TESTvalue, *shmem); + + if (retval) + BUGMSG(D_NORMAL, "Stage 5: No ARCnet cards found.\n"); + return retval; } /* Set up the struct device associated with this card. Called after * probing succeeds. */ -__initfunc(static int arc90xx_found(struct device *dev,int ioaddr,int airq, u_long shmem, int more)) +__initfunc(static int arc90xx_found(struct device *dev, int ioaddr, int airq, u_long shmem, int more)) { - struct arcnet_local *lp; - u_long first_mirror,last_mirror; - int mirror_size; - - /* reserve the irq */ - if (request_irq(airq,&arcnet_interrupt,0,"arcnet (90xx)",dev)) - { - BUGMSG(D_NORMAL,"Can't get IRQ %d!\n",airq); - return -ENODEV; - } - dev->irq=airq; - - /* reserve the I/O region - guaranteed to work by check_region */ - request_region(ioaddr,ARCNET_TOTAL_SIZE,"arcnet (90xx)"); - dev->base_addr=ioaddr; + struct arcnet_local *lp; + u_long first_mirror, last_mirror; + int mirror_size; + + /* reserve the irq */ + if (request_irq(airq, &arcnet_interrupt, 0, "arcnet (90xx)", dev)) { + BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", airq); + return -ENODEV; + } + dev->irq = airq; + + /* reserve the I/O region - guaranteed to work by check_region */ + request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (90xx)"); + dev->base_addr = ioaddr; - /* find the real shared memory start/end points, including mirrors */ + /* find the real shared memory start/end points, including mirrors */ #define BUFFER_SIZE (512) #define MIRROR_SIZE (BUFFER_SIZE*4) - /* guess the actual size of one "memory mirror" - the number of - * bytes between copies of the shared memory. On most cards, it's - * 2k (or there are no mirrors at all) but on some, it's 4k. - */ - mirror_size=MIRROR_SIZE; - if (readb(shmem)==TESTvalue - && readb(shmem-mirror_size)!=TESTvalue - && readb(shmem-2*mirror_size)==TESTvalue) - mirror_size*=2; - - first_mirror=last_mirror=shmem; - while (readb(first_mirror)==TESTvalue) first_mirror-=mirror_size; - first_mirror+=mirror_size; - - while (readb(last_mirror)==TESTvalue) last_mirror+=mirror_size; - last_mirror-=mirror_size; - - dev->mem_start=first_mirror; - dev->mem_end=last_mirror+MIRROR_SIZE-1; - dev->rmem_start=dev->mem_start+BUFFER_SIZE*0; - dev->rmem_end=dev->mem_start+BUFFER_SIZE*2-1; - - /* Initialize the rest of the device structure. */ - - dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); - if (dev->priv == NULL) - { - free_irq(airq,dev); - release_region(ioaddr,ARCNET_TOTAL_SIZE); - return -ENOMEM; - } - memset(dev->priv,0,sizeof(struct arcnet_local)); - lp=(struct arcnet_local *)(dev->priv); - lp->card_type = ARC_90xx; - lp->card_type_str = "COM 90xx"; - lp->arcnet_reset=arc90xx_reset; - lp->asetmask=arc90xx_setmask; - lp->astatus=arc90xx_status; - lp->acommand=arc90xx_command; - lp->openclose_device=arc90xx_openclose; - lp->prepare_tx=arc90xx_prepare_tx; - lp->inthandler=arc90xx_inthandler; - - /* Fill in the fields of the device structure with generic - * values. - */ - arcnet_setup(dev); - - /* And now fill particular fields with arcnet values */ - dev->mtu=1500; /* completely arbitrary - agrees with ether, though */ - dev->hard_header_len=sizeof(struct ClientData); - lp->sequence=1; - lp->recbuf=0; - - BUGMSG(D_DURING,"ClientData header size is %d.\n", - sizeof(struct ClientData)); - BUGMSG(D_DURING,"HardHeader size is %d.\n", - sizeof(struct archdr)); - - /* get and check the station ID from offset 1 in shmem */ - lp->stationid = readb(first_mirror+1); - - if (lp->stationid==0) - BUGMSG(D_NORMAL,"WARNING! Station address 00 is reserved " - "for broadcasts!\n"); - else if (lp->stationid==255) - BUGMSG(D_NORMAL,"WARNING! Station address FF may confuse " - "DOS networking programs!\n"); - dev->dev_addr[0]=lp->stationid; - - BUGMSG(D_NORMAL,"ARCnet COM90xx: station %02Xh found at %03lXh, IRQ %d, " - "ShMem %lXh (%ld*%xh).\n", - lp->stationid, - dev->base_addr, dev->irq, dev->mem_start, - (dev->mem_end-dev->mem_start+1)/mirror_size,mirror_size); - - /* OK. We're finished. If there are probably other cards, add other - * COM90xx drivers to the device chain, so they get probed later. - */ + /* guess the actual size of one "memory mirror" - the number of + * bytes between copies of the shared memory. On most cards, it's + * 2k (or there are no mirrors at all) but on some, it's 4k. + */ + mirror_size = MIRROR_SIZE; + if (readb(shmem) == TESTvalue + && readb(shmem - mirror_size) != TESTvalue + && readb(shmem - 2 * mirror_size) == TESTvalue) + mirror_size *= 2; + + first_mirror = last_mirror = shmem; + while (readb(first_mirror) == TESTvalue) + first_mirror -= mirror_size; + first_mirror += mirror_size; + + while (readb(last_mirror) == TESTvalue) + last_mirror += mirror_size; + last_mirror -= mirror_size; + + dev->mem_start = first_mirror; + dev->mem_end = last_mirror + MIRROR_SIZE - 1; + dev->rmem_start = dev->mem_start + BUFFER_SIZE * 0; + dev->rmem_end = dev->mem_start + BUFFER_SIZE * 2 - 1; + + /* Initialize the rest of the device structure. */ + + dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); + if (dev->priv == NULL) { + free_irq(airq, dev); + release_region(ioaddr, ARCNET_TOTAL_SIZE); + return -ENOMEM; + } + memset(dev->priv, 0, sizeof(struct arcnet_local)); + lp = (struct arcnet_local *) (dev->priv); + lp->card_type = ARC_90xx; + lp->card_type_str = "COM 90xx"; + lp->arcnet_reset = arc90xx_reset; + lp->asetmask = arc90xx_setmask; + lp->astatus = arc90xx_status; + lp->acommand = arc90xx_command; + lp->openclose_device = arc90xx_openclose; + lp->prepare_tx = arc90xx_prepare_tx; + lp->inthandler = arc90xx_inthandler; + + /* Fill in the fields of the device structure with generic + * values. + */ + arcnet_setup(dev); + + /* And now fill particular fields with arcnet values */ + dev->mtu = 1500; /* completely arbitrary - agrees with ether, though */ + dev->hard_header_len = sizeof(struct ClientData); + lp->sequence = 1; + lp->recbuf = 0; + + BUGMSG(D_DURING, "ClientData header size is %d.\n", + sizeof(struct ClientData)); + BUGMSG(D_DURING, "HardHeader size is %d.\n", + sizeof(struct archdr)); + + /* get and check the station ID from offset 1 in shmem */ + lp->stationid = readb(first_mirror + 1); + + if (lp->stationid == 0) + BUGMSG(D_NORMAL, "WARNING! Station address 00 is reserved " + "for broadcasts!\n"); + else if (lp->stationid == 255) + BUGMSG(D_NORMAL, "WARNING! Station address FF may confuse " + "DOS networking programs!\n"); + dev->dev_addr[0] = lp->stationid; + + BUGMSG(D_NORMAL, "ARCnet COM90xx: station %02Xh found at %03lXh, IRQ %d, " + "ShMem %lXh (%ld*%xh).\n", + lp->stationid, + dev->base_addr, dev->irq, dev->mem_start, + (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size); + + /* OK. We're finished. If there are probably other cards, add other + * COM90xx drivers to the device chain, so they get probed later. + */ #ifndef MODULE - while (!com90xx_explicit && more--) - { - if (arcnet_num_devs < MAX_ARCNET_DEVS) - { - arcnet_devs[arcnet_num_devs].next=dev->next; - dev->next=&arcnet_devs[arcnet_num_devs]; - dev=dev->next; - dev->name=(char *)&arcnet_dev_names[arcnet_num_devs]; - arcnet_num_devs++; - } - else - { - BUGMSG(D_NORMAL, "Too many arcnet devices - no more will be probed for.\n"); - return 0; - } - arcnet_makename(dev->name); - dev->init=arc90xx_probe; - } + while (!com90xx_explicit && more--) { + if (arcnet_num_devs < MAX_ARCNET_DEVS) { + arcnet_devs[arcnet_num_devs].next = dev->next; + dev->next = &arcnet_devs[arcnet_num_devs]; + dev = dev->next; + dev->name = (char *) &arcnet_dev_names[arcnet_num_devs]; + arcnet_num_devs++; + } else { + BUGMSG(D_NORMAL, "Too many arcnet devices - no more will be probed for.\n"); + return 0; + } + arcnet_makename(dev->name); + dev->init = arc90xx_probe; + } #endif - return 0; + return 0; } /* Do a hardware reset on the card, and set up necessary registers. - * + * This should be called as little as possible, because it disrupts the * token on the network (causes a RECON) and requires a significant delay. * * However, it does make sure the card is in a defined state. */ -int arc90xx_reset(struct device *dev,int reset_delay) +int arc90xx_reset(struct device *dev, int reset_delay) { - struct arcnet_local *lp=(struct arcnet_local *)dev->priv; - short ioaddr=dev->base_addr; - int delayval,recbuf=lp->recbuf; - - if (reset_delay==3) - { - ARCRESET; - return 0; - } - - /* no IRQ's, please! */ - lp->intmask=0; - SETMASK; - - BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n", - dev->name,ARCSTATUS); - - if (reset_delay) - { - /* reset the card */ - ARCRESET; - JIFFER(RESETtime); - } - - ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */ - ACOMMAND(CFLAGScmd|CONFIGclear); - - /* verify that the ARCnet signature byte is present */ - if (readb(dev->mem_start) != TESTvalue) - { - BUGMSG(D_NORMAL,"reset failed: TESTvalue not present.\n"); - return 1; - } - - /* clear out status variables */ - recbuf=lp->recbuf=0; - lp->txbuf=2; + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + short ioaddr = dev->base_addr; + int delayval, recbuf = lp->recbuf; + + if (reset_delay == 3) { + ARCRESET; + return 0; + } + /* no IRQ's, please! */ + lp->intmask = 0; + SETMASK; + + BUGMSG(D_INIT, "Resetting %s (status=%Xh)\n", + dev->name, ARCSTATUS); + + if (reset_delay) { + /* reset the card */ + ARCRESET; + JIFFER(RESETtime); + } + ACOMMAND(CFLAGScmd | RESETclear); /* clear flags & end reset */ + ACOMMAND(CFLAGScmd | CONFIGclear); + + /* verify that the ARCnet signature byte is present */ + if (readb(dev->mem_start) != TESTvalue) { + BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); + return 1; + } + /* clear out status variables */ + recbuf = lp->recbuf = 0; + lp->txbuf = 2; - /* enable extended (512-byte) packets */ - ACOMMAND(CONFIGcmd|EXTconf); + /* enable extended (512-byte) packets */ + ACOMMAND(CONFIGcmd | EXTconf); #ifndef SLOW_XMIT_COPY - /* clean out all the memory to make debugging make more sense :) */ - BUGLVL(D_DURING) - memset_io(dev->mem_start,0x42,2048); + /* clean out all the memory to make debugging make more sense :) */ + BUGLVL(D_DURING) + memset_io(dev->mem_start, 0x42, 2048); #endif - /* and enable receive of our first packet to the first buffer */ - EnableReceiver(); + /* and enable receive of our first packet to the first buffer */ + EnableReceiver(); - /* re-enable interrupts */ - lp->intmask|=NORXflag; + /* re-enable interrupts */ + lp->intmask |= NORXflag; #ifdef DETECT_RECONFIGS - lp->intmask|=RECONflag; + lp->intmask |= RECONflag; #endif - SETMASK; + SETMASK; - /* done! return success. */ - return 0; + /* done! return success. */ + return 0; } static void arc90xx_openclose(int open) { - if (open) - MOD_INC_USE_COUNT; - else - MOD_DEC_USE_COUNT; + if (open) + MOD_INC_USE_COUNT; + else + MOD_DEC_USE_COUNT; } static void arc90xx_setmask(struct device *dev, u_char mask) { - short ioaddr=dev->base_addr; + short ioaddr = dev->base_addr; - AINTMASK(mask); + AINTMASK(mask); } static u_char arc90xx_status(struct device *dev) { - short ioaddr=dev->base_addr; + short ioaddr = dev->base_addr; - return ARCSTATUS; + return ARCSTATUS; } static void arc90xx_command(struct device *dev, u_char cmd) { - short ioaddr=dev->base_addr; + short ioaddr = dev->base_addr; - ACOMMAND(cmd); + ACOMMAND(cmd); } /* The actual interrupt handler routine - handle various IRQ's generated * by the card. */ -static void -arc90xx_inthandler(struct device *dev) +static void arc90xx_inthandler(struct device *dev) { - struct arcnet_local *lp=(struct arcnet_local *)dev->priv; - int ioaddr=dev->base_addr, status, boguscount = 3, didsomething; - - AINTMASK(0); + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + int ioaddr = dev->base_addr, status, boguscount = 3, didsomething; - BUGMSG(D_DURING,"in arcnet_inthandler (status=%Xh, intmask=%Xh)\n", - ARCSTATUS,lp->intmask); + AINTMASK(0); - do - { - status = ARCSTATUS; - didsomething=0; + BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n", + ARCSTATUS, lp->intmask); - /* RESET flag was enabled - card is resetting and if RX - * is disabled, it's NOT because we just got a packet. - */ - if (status & RESETflag) - { - BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n", - status); - arc90xx_reset(dev,0); + do { + status = ARCSTATUS; + didsomething = 0; + + /* RESET flag was enabled - card is resetting and if RX + * is disabled, it's NOT because we just got a packet. + */ + if (status & RESETflag) { + BUGMSG(D_NORMAL, "spurious reset (status=%Xh)\n", + status); + arc90xx_reset(dev, 0); - /* all other flag values are just garbage */ - break; - } - - /* RX is inhibited - we must have received something. */ - if (status & lp->intmask & NORXflag) - { - int recbuf=lp->recbuf=!lp->recbuf; - - BUGMSG(D_DURING,"receive irq (status=%Xh)\n", - status); - - /* enable receive of our next packet */ - EnableReceiver(); - - /* Got a packet. */ - arc90xx_rx(dev,!recbuf); - - didsomething++; - } - - /* it can only be an xmit-done irq if we're xmitting :) */ - /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/ - if (status & lp->intmask & TXFREEflag) - { - struct Outgoing *out=&(lp->outgoing); - int was_sending=lp->sending; + /* all other flag values are just garbage */ + break; + } + /* RX is inhibited - we must have received something. */ + if (status & lp->intmask & NORXflag) { + int recbuf = lp->recbuf = !lp->recbuf; - lp->intmask &= ~TXFREEflag; + BUGMSG(D_DURING, "receive irq (status=%Xh)\n", + status); - lp->in_txhandler++; - if (was_sending) lp->sending--; + /* enable receive of our next packet */ + EnableReceiver(); - BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n", - status,out->numsegs,out->segnum,out->skb); + /* Got a packet. */ + arc90xx_rx(dev, !recbuf); - if (was_sending && !(status&TXACKflag)) - { - if (lp->lasttrans_dest != 0) - { - BUGMSG(D_EXTRA,"transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n", - status,lp->lasttrans_dest); - lp->stats.tx_errors++; - lp->stats.tx_carrier_errors++; + didsomething++; } - else - { - BUGMSG(D_DURING,"broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n", - status, - lp->lasttrans_dest); + /* it can only be an xmit-done irq if we're xmitting :) */ + /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending) */ + if (status & lp->intmask & TXFREEflag) { + struct Outgoing *out = &(lp->outgoing); + int was_sending = lp->sending; + + lp->intmask &= ~TXFREEflag; + + lp->in_txhandler++; + if (was_sending) + lp->sending--; + + BUGMSG(D_DURING, "TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n", + status, out->numsegs, out->segnum, out->skb); + + if (was_sending && !(status & TXACKflag)) { + if (lp->lasttrans_dest != 0) { + BUGMSG(D_EXTRA, "transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n", + status, lp->lasttrans_dest); + lp->stats.tx_errors++; + lp->stats.tx_carrier_errors++; + } else { + BUGMSG(D_DURING, "broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n", + status, + lp->lasttrans_dest); + } + } + /* send packet if there is one */ + arcnet_go_tx(dev, 0); + didsomething++; + + if (lp->intx) { + BUGMSG(D_DURING, "TXDONE while intx! (status=%Xh, intx=%d)\n", + ARCSTATUS, lp->intx); + lp->in_txhandler--; + continue; + } + if (!lp->outgoing.skb) { + BUGMSG(D_DURING, "TX IRQ done: no split to continue.\n"); + + /* inform upper layers */ + if (!lp->txready) + arcnet_tx_done(dev, lp); + lp->in_txhandler--; + continue; + } + /* if more than one segment, and not all segments + * are done, then continue xmit. + */ + if (out->segnum < out->numsegs) + arcnetA_continue_tx(dev); + arcnet_go_tx(dev, 0); + + /* if segnum==numsegs, the transmission is finished; + * free the skb. + */ + if (out->segnum >= out->numsegs) { + /* transmit completed */ + out->segnum++; + if (out->skb) { + lp->stats.tx_bytes += out->skb->len; + dev_kfree_skb(out->skb); + } + out->skb = NULL; + + /* inform upper layers */ + if (!lp->txready) + arcnet_tx_done(dev, lp); + } + didsomething++; + + lp->in_txhandler--; + } else if (lp->txready && !lp->sending && !lp->intx) { + BUGMSG(D_NORMAL, "recovery from silent TX (status=%Xh)\n", + status); + arcnet_go_tx(dev, 0); + didsomething++; } - } - - /* send packet if there is one */ - arcnet_go_tx(dev,0); - didsomething++; - - if (lp->intx) - { - BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n", - ARCSTATUS,lp->intx); - lp->in_txhandler--; - continue; - } - - if (!lp->outgoing.skb) - { - BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n"); - - /* inform upper layers */ - if (!lp->txready) arcnet_tx_done(dev, lp); - lp->in_txhandler--; - continue; - } - - /* if more than one segment, and not all segments - * are done, then continue xmit. - */ - if (out->segnumnumsegs) - arcnetA_continue_tx(dev); - arcnet_go_tx(dev,0); - - /* if segnum==numsegs, the transmission is finished; - * free the skb. - */ - if (out->segnum>=out->numsegs) - { - /* transmit completed */ - out->segnum++; - if (out->skb) - { - lp->stats.tx_bytes += out->skb->len; - dev_kfree_skb(out->skb); - } - out->skb=NULL; - - /* inform upper layers */ - if (!lp->txready) arcnet_tx_done(dev, lp); - } - didsomething++; - - lp->in_txhandler--; - } - else if (lp->txready && !lp->sending && !lp->intx) - { - BUGMSG(D_NORMAL,"recovery from silent TX (status=%Xh)\n", - status); - arcnet_go_tx(dev,0); - didsomething++; - } - #ifdef DETECT_RECONFIGS - if (status & (lp->intmask) & RECONflag) - { - ACOMMAND(CFLAGScmd|CONFIGclear); - lp->stats.tx_carrier_errors++; + if (status & (lp->intmask) & RECONflag) { + ACOMMAND(CFLAGScmd | CONFIGclear); + lp->stats.tx_carrier_errors++; #ifdef SHOW_RECONFIGS - BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh)\n", - status); -#endif /* SHOW_RECONFIGS */ + BUGMSG(D_NORMAL, "Network reconfiguration detected (status=%Xh)\n", + status); +#endif /* SHOW_RECONFIGS */ #ifdef RECON_THRESHOLD - /* is the RECON info empty or old? */ - if (!lp->first_recon || !lp->last_recon || - jiffies-lp->last_recon > HZ*10) - { - if (lp->network_down) - BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n"); - lp->first_recon=lp->last_recon=jiffies; - lp->num_recons=lp->network_down=0; - - BUGMSG(D_DURING,"recon: clearing counters.\n"); - } - else /* add to current RECON counter */ - { - lp->last_recon=jiffies; - lp->num_recons++; - - BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n", - lp->num_recons, - (lp->last_recon-lp->first_recon)/HZ, - lp->network_down); - - /* if network is marked up; - * and first_recon and last_recon are 60+ sec - * apart; - * and the average no. of recons counted is - * > RECON_THRESHOLD/min; - * then print a warning message. - */ - if (!lp->network_down - && (lp->last_recon-lp->first_recon)<=HZ*60 - && lp->num_recons >= RECON_THRESHOLD) - { - lp->network_down=1; - BUGMSG(D_NORMAL,"many reconfigurations detected: cabling problem?\n"); - } - else if (!lp->network_down - && lp->last_recon-lp->first_recon > HZ*60) - { - /* reset counters if we've gone for - * over a minute. - */ - lp->first_recon=lp->last_recon; - lp->num_recons=1; - } - } - } - else if (lp->network_down && jiffies-lp->last_recon > HZ*10) - { - if (lp->network_down) - BUGMSG(D_NORMAL,"cabling restored?\n"); - lp->first_recon=lp->last_recon=0; - lp->num_recons=lp->network_down=0; + /* is the RECON info empty or old? */ + if (!lp->first_recon || !lp->last_recon || + jiffies - lp->last_recon > HZ * 10) { + if (lp->network_down) + BUGMSG(D_NORMAL, "reconfiguration detected: cabling restored?\n"); + lp->first_recon = lp->last_recon = jiffies; + lp->num_recons = lp->network_down = 0; + + BUGMSG(D_DURING, "recon: clearing counters.\n"); + } else { /* add to current RECON counter */ + lp->last_recon = jiffies; + lp->num_recons++; + + BUGMSG(D_DURING, "recon: counter=%d, time=%lds, net=%d\n", + lp->num_recons, + (lp->last_recon - lp->first_recon) / HZ, + lp->network_down); + + /* if network is marked up; + * and first_recon and last_recon are 60+ sec + * apart; + * and the average no. of recons counted is + * > RECON_THRESHOLD/min; + * then print a warning message. + */ + if (!lp->network_down + && (lp->last_recon - lp->first_recon) <= HZ * 60 + && lp->num_recons >= RECON_THRESHOLD) { + lp->network_down = 1; + BUGMSG(D_NORMAL, "many reconfigurations detected: cabling problem?\n"); + } else if (!lp->network_down + && lp->last_recon - lp->first_recon > HZ * 60) { + /* reset counters if we've gone for + * over a minute. + */ + lp->first_recon = lp->last_recon; + lp->num_recons = 1; + } + } + } else if (lp->network_down && jiffies - lp->last_recon > HZ * 10) { + if (lp->network_down) + BUGMSG(D_NORMAL, "cabling restored?\n"); + lp->first_recon = lp->last_recon = 0; + lp->num_recons = lp->network_down = 0; - BUGMSG(D_DURING,"not recon: clearing counters anyway.\n"); + BUGMSG(D_DURING, "not recon: clearing counters anyway.\n"); #endif - } -#endif /* DETECT_RECONFIGS */ - } while (--boguscount && didsomething); + } +#endif /* DETECT_RECONFIGS */ + } while (--boguscount && didsomething); - BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n", - ARCSTATUS,boguscount); - BUGMSG(D_DURING,"\n"); + BUGMSG(D_DURING, "net_interrupt complete (status=%Xh, count=%d)\n", + ARCSTATUS, boguscount); + BUGMSG(D_DURING, "\n"); - SETMASK; /* put back interrupt mask */ + SETMASK; /* put back interrupt mask */ } @@ -987,57 +912,52 @@ * arcnet_rx routing to deal with it. */ -static void -arc90xx_rx(struct device *dev,int recbuf) +static void arc90xx_rx(struct device *dev, int recbuf) { - struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - int ioaddr=dev->base_addr; - union ArcPacket *arcpacket= - (union ArcPacket *)phys_to_virt(dev->mem_start+recbuf*512); - u_char *arcsoft; - short length,offset; - u_char daddr,saddr; - - lp->stats.rx_packets++; - - saddr=arcpacket->hardheader.source; - - /* if source is 0, it's a "used" packet! */ - if (saddr==0) - { - BUGMSG(D_NORMAL,"discarding old packet. (status=%Xh)\n", - ARCSTATUS); - lp->stats.rx_errors++; - return; - } - /* Set source address to zero to mark it as old */ - - arcpacket->hardheader.source=0; - - daddr=arcpacket->hardheader.destination; - - if (arcpacket->hardheader.offset1) /* Normal Packet */ - { - offset=arcpacket->hardheader.offset1; - arcsoft=&arcpacket->raw[offset]; - length=256-offset; - } - else /* ExtendedPacket or ExceptionPacket */ - { - offset=arcpacket->hardheader.offset2; - arcsoft=&arcpacket->raw[offset]; + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + int ioaddr = dev->base_addr; + union ArcPacket *arcpacket = + (union ArcPacket *) phys_to_virt(dev->mem_start + recbuf * 512); + u_char *arcsoft; + short length, offset; + u_char daddr, saddr; - length=512-offset; - } + lp->stats.rx_packets++; - arcnet_rx(lp, arcsoft, length, saddr, daddr); + saddr = arcpacket->hardheader.source; - BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx"); + /* if source is 0, it's a "used" packet! */ + if (saddr == 0) { + BUGMSG(D_NORMAL, "discarding old packet. (status=%Xh)\n", + ARCSTATUS); + lp->stats.rx_errors++; + return; + } + /* Set source address to zero to mark it as old */ + + arcpacket->hardheader.source = 0; + + daddr = arcpacket->hardheader.destination; + + if (arcpacket->hardheader.offset1) { /* Normal Packet */ + offset = arcpacket->hardheader.offset1; + arcsoft = &arcpacket->raw[offset]; + length = 256 - offset; + } else { /* ExtendedPacket or ExceptionPacket */ + offset = arcpacket->hardheader.offset2; + arcsoft = &arcpacket->raw[offset]; + + length = 512 - offset; + } + + arcnet_rx(lp, arcsoft, length, saddr, daddr); + + BUGLVL(D_RX) arcnet_dump_packet(lp->adev, arcpacket->raw, length > 240, "rx"); #ifndef SLOW_XMIT_COPY - /* clean out the page to make debugging make more sense :) */ - BUGLVL(D_DURING) - memset((void *)arcpacket->raw,0x42,512); + /* clean out the page to make debugging make more sense :) */ + BUGLVL(D_DURING) + memset((void *) arcpacket->raw, 0x42, 512); #endif } @@ -1045,91 +965,84 @@ /* Given an skb, copy a packet into the ARCnet buffers for later transmission * by arcnet_go_tx. */ -static void -arc90xx_prepare_tx(struct device *dev,u_char *hdr,int hdrlen, - char *data,int length,int daddr,int exceptA, int offset) +static void arc90xx_prepare_tx(struct device *dev, u_char * hdr, int hdrlen, + char *data, int length, int daddr, int exceptA, int offset) { - struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - union ArcPacket *arcpacket = - (union ArcPacket *)phys_to_virt(dev->mem_start+512*(lp->txbuf^1)); + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + union ArcPacket *arcpacket = + (union ArcPacket *) phys_to_virt(dev->mem_start + 512 * (lp->txbuf ^ 1)); #ifdef SLOW_XMIT_COPY - char *iptr,*iend,*optr; + char *iptr, *iend, *optr; #endif - lp->txbuf=lp->txbuf^1; /* XOR with 1 to alternate between 2 and 3 */ + lp->txbuf = lp->txbuf ^ 1; /* XOR with 1 to alternate between 2 and 3 */ - length+=hdrlen; + length += hdrlen; - BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n", - hdr,length,data); + BUGMSG(D_TX, "arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n", + hdr, length, data); #ifndef SLOW_XMIT_COPY - /* clean out the page to make debugging make more sense :) */ - BUGLVL(D_DURING) - memset_io(dev->mem_start+lp->txbuf*512,0x42,512); + /* clean out the page to make debugging make more sense :) */ + BUGLVL(D_DURING) + memset_io(dev->mem_start + lp->txbuf * 512, 0x42, 512); #endif - arcpacket->hardheader.destination=daddr; + arcpacket->hardheader.destination = daddr; - /* load packet into shared memory */ - if (length<=MTU) /* Normal (256-byte) Packet */ - arcpacket->hardheader.offset1=offset=offset?offset:256-length; - - else if (length>=MinTU || offset) /* Extended (512-byte) Packet */ - { - arcpacket->hardheader.offset1=0; - arcpacket->hardheader.offset2=offset=offset?offset:512-length; - } - else if (exceptA) /* RFC1201 Exception Packet */ - { - arcpacket->hardheader.offset1=0; - arcpacket->hardheader.offset2=offset=512-length-4; - - /* exception-specific stuff - these four bytes - * make the packet long enough to fit in a 512-byte - * frame. - */ - - arcpacket->raw[offset+0]=hdr[0]; - arcpacket->raw[offset+1]=0xFF; /* FF flag */ - arcpacket->raw[offset+2]=0xFF; /* FF padding */ - arcpacket->raw[offset+3]=0xFF; /* FF padding */ - offset+=4; - } - else /* "other" Exception packet */ - { - /* RFC1051 - set 4 trailing bytes to 0 */ - memset(&arcpacket->raw[508],0,4); - - /* now round up to MinTU */ - arcpacket->hardheader.offset1=0; - arcpacket->hardheader.offset2=offset=512-MinTU; - } - - /* copy the packet into ARCnet shmem - * - the first bytes of ClientData header are skipped - */ + /* load packet into shared memory */ + if (length <= MTU) /* Normal (256-byte) Packet */ + arcpacket->hardheader.offset1 = offset = offset ? offset : 256 - length; + + else if (length >= MinTU || offset) { /* Extended (512-byte) Packet */ + arcpacket->hardheader.offset1 = 0; + arcpacket->hardheader.offset2 = offset = offset ? offset : 512 - length; + } else if (exceptA) { /* RFC1201 Exception Packet */ + arcpacket->hardheader.offset1 = 0; + arcpacket->hardheader.offset2 = offset = 512 - length - 4; + + /* exception-specific stuff - these four bytes + * make the packet long enough to fit in a 512-byte + * frame. + */ + + arcpacket->raw[offset + 0] = hdr[0]; + arcpacket->raw[offset + 1] = 0xFF; /* FF flag */ + arcpacket->raw[offset + 2] = 0xFF; /* FF padding */ + arcpacket->raw[offset + 3] = 0xFF; /* FF padding */ + offset += 4; + } else { /* "other" Exception packet */ + /* RFC1051 - set 4 trailing bytes to 0 */ + memset(&arcpacket->raw[508], 0, 4); + + /* now round up to MinTU */ + arcpacket->hardheader.offset1 = 0; + arcpacket->hardheader.offset2 = offset = 512 - MinTU; + } + + /* copy the packet into ARCnet shmem + * - the first bytes of ClientData header are skipped + */ - memcpy((u_char*)arcpacket+offset, (u_char*)hdr,hdrlen); + memcpy((u_char *) arcpacket + offset, (u_char *) hdr, hdrlen); #ifdef SLOW_XMIT_COPY - for (iptr=data,iend=iptr+length-hdrlen,optr=(char *)arcpacket+offset+hdrlen; - iptrraw,length>MTU,"tx"); + BUGLVL(D_TX) arcnet_dump_packet(dev, arcpacket->raw, length > MTU, "tx"); - lp->lastload_dest=daddr; - lp->txready=lp->txbuf; /* packet is ready for sending */ + lp->lastload_dest = daddr; + lp->txready = lp->txbuf; /* packet is ready for sending */ } @@ -1143,118 +1056,112 @@ #ifdef MODULE static char devicename[9] = ""; -static struct device thiscard = { - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0, 0, /* I/O address, IRQ */ - 0, 0, 0, NULL, arc90xx_probe +static struct device thiscard = +{ + devicename, /* device name is inserted by linux/drivers/net/net_init.c */ + 0, 0, 0, 0, + 0, 0, /* I/O address, IRQ */ + 0, 0, 0, NULL, arc90xx_probe }; int init_module(void) { - struct device *dev=&thiscard; - if (device) - strcpy(dev->name,device); - else arcnet_makename(dev->name); - - dev->base_addr=io; - - dev->irq=irq; - if (dev->irq==2) dev->irq=9; - - if (shmem) - { - dev->mem_start=shmem; - dev->mem_end=thiscard.mem_start+512*4-1; - dev->rmem_start=thiscard.mem_start+512*0; - dev->rmem_end=thiscard.mem_start+512*2-1; - } - - if (register_netdev(dev) != 0) - return -EIO; - arcnet_use_count(1); - return 0; + struct device *dev = &thiscard; + if (device) + strcpy(dev->name, device); + else + arcnet_makename(dev->name); + + dev->base_addr = io; + + dev->irq = irq; + if (dev->irq == 2) + dev->irq = 9; + + if (shmem) { + dev->mem_start = shmem; + dev->mem_end = thiscard.mem_start + 512 * 4 - 1; + dev->rmem_start = thiscard.mem_start + 512 * 0; + dev->rmem_end = thiscard.mem_start + 512 * 2 - 1; + } + if (register_netdev(dev) != 0) + return -EIO; + arcnet_use_count(1); + return 0; } void cleanup_module(void) { - struct device *dev=&thiscard; - int ioaddr=dev->mem_start; + struct device *dev = &thiscard; + int ioaddr = dev->mem_start; - if (dev->start) (*dev->stop)(dev); + if (dev->start) + (*dev->stop) (dev); - /* Flush TX and disable RX */ - if (ioaddr) - { - AINTMASK(0); /* disable IRQ's */ - ACOMMAND(NOTXcmd); /* stop transmit */ - ACOMMAND(NORXcmd); /* disable receive */ + /* Flush TX and disable RX */ + if (ioaddr) { + AINTMASK(0); /* disable IRQ's */ + ACOMMAND(NOTXcmd); /* stop transmit */ + ACOMMAND(NORXcmd); /* disable receive */ #if defined(IO_MAPPED_BUFFERS) && !defined(COM20020) - /* Set the thing back to MMAP mode, in case the old - driver is loaded later */ - outb( (inb(_CONFIG)&~IOMAPflag),_CONFIG); + /* Set the thing back to MMAP mode, in case the old + driver is loaded later */ + outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG); #endif - } - - if (dev->irq) - { - free_irq(dev->irq,dev); - } - - if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE); - unregister_netdev(dev); - kfree(dev->priv); - dev->priv = NULL; - arcnet_use_count(0); + } + if (dev->irq) { + free_irq(dev->irq, dev); + } + if (dev->base_addr) + release_region(dev->base_addr, ARCNET_TOTAL_SIZE); + unregister_netdev(dev); + kfree(dev->priv); + dev->priv = NULL; + arcnet_use_count(0); } #else -__initfunc(void com90xx_setup (char *str, int *ints)) +__initfunc(void com90xx_setup(char *str, int *ints)) { - struct device *dev; - - if (arcnet_num_devs == MAX_ARCNET_DEVS) - { - printk("com90xx: Too many ARCnet devices registered (max %d).\n", - MAX_ARCNET_DEVS); - return; - } + struct device *dev; - if (!ints[0] && (!str || !*str)) - { - printk("com90xx: Disabled.\n"); - com90xx_explicit++; - return; - } - - dev=&arcnet_devs[arcnet_num_devs]; + if (arcnet_num_devs == MAX_ARCNET_DEVS) { + printk("com90xx: Too many ARCnet devices registered (max %d).\n", + MAX_ARCNET_DEVS); + return; + } + if (!ints[0] && (!str || !*str)) { + printk("com90xx: Disabled.\n"); + com90xx_explicit++; + return; + } + dev = &arcnet_devs[arcnet_num_devs]; - dev->dev_addr[3]=3; - dev->init=arc90xx_probe; + dev->dev_addr[3] = 3; + dev->init = arc90xx_probe; - switch(ints[0]) - { - case 4: /* ERROR */ - printk("com20020: Too many arguments.\n"); + switch (ints[0]) { + case 4: /* ERROR */ + printk("com20020: Too many arguments.\n"); - case 3: /* Mem address */ - dev->mem_start=ints[3]; + case 3: /* Mem address */ + dev->mem_start = ints[3]; - case 2: /* IRQ */ - dev->irq=ints[2]; + case 2: /* IRQ */ + dev->irq = ints[2]; - case 1: /* IO address */ - dev->base_addr=ints[1]; - } + case 1: /* IO address */ + dev->base_addr = ints[1]; + } - dev->name = (char *)&arcnet_dev_names[arcnet_num_devs]; + dev->name = (char *) &arcnet_dev_names[arcnet_num_devs]; - if (str) - strncpy(dev->name, str, 9); + if (str) + strncpy(dev->name, str, 9); - arcnet_num_devs++; + arcnet_num_devs++; } -#endif /* MODULE */ +#endif /* MODULE */ diff -u --recursive --new-file v2.1.100/linux/drivers/net/defxx.c linux/drivers/net/defxx.c --- v2.1.100/linux/drivers/net/defxx.c Mon Apr 6 17:41:00 1998 +++ linux/drivers/net/defxx.c Fri May 8 00:08:02 1998 @@ -2013,6 +2013,8 @@ bp->stats.rx_packets = bp->rcv_total_frames; bp->stats.tx_packets = bp->xmt_total_frames; + bp->stats.rx_bytes = bp->rcv_total_bytes; + bp->stats.tx_bytes = bp->xmt_total_bytes; bp->stats.rx_errors = (u32)(bp->rcv_crc_errors + bp->rcv_frame_status_errors + bp->rcv_length_errors); bp->stats.tx_errors = bp->xmt_length_errors; bp->stats.rx_dropped = bp->rcv_discards; @@ -3099,6 +3101,8 @@ bp->rcv_total_frames++; if (*(p_buff + RCV_BUFF_K_DA) & 0x01) bp->rcv_multicast_frames++; + + bp->rcv_total_bytes += skb->len; } } } @@ -3375,13 +3379,14 @@ p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[bp->rcv_xmt_reg.index.xmt_comp]); - /* Return skb to operating system */ - - dev_kfree_skb(p_xmt_drv_descr->p_skb); - /* Increment transmit counters */ bp->xmt_total_frames++; + bp->xmt_total_bytes += p_xmt_drv_descr->p_skb->len; + + /* Return skb to operating system */ + + dev_kfree_skb(p_xmt_drv_descr->p_skb); /* * Move to start of next packet by updating completion index diff -u --recursive --new-file v2.1.100/linux/drivers/net/defxx.h linux/drivers/net/defxx.h --- v2.1.100/linux/drivers/net/defxx.h Mon Apr 6 17:41:00 1998 +++ linux/drivers/net/defxx.h Fri May 8 00:08:02 1998 @@ -1771,9 +1771,12 @@ u32 rcv_length_errors; u32 rcv_total_frames; u32 rcv_multicast_frames; + u32 rcv_total_bytes; + u32 xmt_discards; u32 xmt_length_errors; u32 xmt_total_frames; + u32 xmt_total_bytes; } DFX_board_t; #endif /* #ifndef _DEFXX_H_ */ diff -u --recursive --new-file v2.1.100/linux/drivers/net/epic100.c linux/drivers/net/epic100.c --- v2.1.100/linux/drivers/net/epic100.c Wed Apr 8 19:36:27 1998 +++ linux/drivers/net/epic100.c Fri May 8 00:20:47 1998 @@ -69,7 +69,6 @@ #include #include #include -#include #include /* Processor type for cache alignment. */ #include #include @@ -124,6 +123,7 @@ #if (LINUX_VERSION_CODE < 0x20123) #define test_and_set_bit(val, addr) set_bit(val, addr) +#include #else #ifdef MODULE MODULE_AUTHOR("Donald Becker "); @@ -258,7 +258,7 @@ #endif static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq, - int chip_id, int options, int card_idx); + int chip_id, int options, int card_idx); static int epic_open(struct device *dev); static int read_eeprom(int ioaddr, int location); static int mii_read(int ioaddr, int phy_id, int location); @@ -293,11 +293,17 @@ well with the current structure. So instead we detect just the Epic cards in slot order. */ - if (pcibios_present()) { + if (pci_present()) { unsigned char pci_bus, pci_device_fn; for (;pci_index < 0xff; pci_index++) { - unsigned char pci_irq_line, pci_latency; +#if LINUX_VERSION_CODE >= 0x20155 + unsigned int pci_irq_line; + struct pci_dev *pdev; +#else + unsigned char pci_irq_line; +#endif + unsigned char pci_latency; unsigned short pci_command, vendor, device; unsigned int pci_ioaddr, chip_idx = 0; @@ -317,10 +323,16 @@ pcibios_read_config_word(pci_bus, pci_device_fn, PCI_DEVICE_ID, &device); +#if LINUX_VERSION_CODE >= 0x20155 + pdev = pci_find_slot(pci_bus, pci_device_fn); + pci_irq_line = pdev->irq; + pci_ioaddr = pdev->base_address[0]; +#else pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_irq_line); pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0, &pci_ioaddr); +#endif /* Remove I/O space marker in bit 0. */ pci_ioaddr &= ~3; @@ -730,6 +742,17 @@ struct epic_private *tp = (struct epic_private *)dev->priv; int entry; u32 flag; + +#ifndef final_version + if (skb == NULL || skb->len <= 0) { + printk("%s: Obsolete driver layer request made: skbuff==NULL.\n", + dev->name); +#if 0 + dev_tint(dev); +#endif + return 0; + } +#endif /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ diff -u --recursive --new-file v2.1.100/linux/drivers/net/myri_sbus.h linux/drivers/net/myri_sbus.h --- v2.1.100/linux/drivers/net/myri_sbus.h Thu Mar 27 14:40:04 1997 +++ linux/drivers/net/myri_sbus.h Fri May 8 00:20:47 1998 @@ -171,7 +171,7 @@ #define MYRINET_MTU 8432 #define RX_ALLOC_SIZE 8448 #define MYRI_PAD_LEN 2 -#define RX_COPY_THRESHOLD 128 +#define RX_COPY_THRESHOLD 256 /* These numbers are cast in stone, new firmware is needed if * you want to change them. diff -u --recursive --new-file v2.1.100/linux/drivers/net/net_init.c linux/drivers/net/net_init.c --- v2.1.100/linux/drivers/net/net_init.c Sun Nov 30 14:00:38 1997 +++ linux/drivers/net/net_init.c Fri May 8 00:20:47 1998 @@ -35,9 +35,10 @@ #include #include #include +#include +#include #include #include -#include #include #include @@ -162,6 +163,63 @@ #endif +#ifdef CONFIG_HIPPI +static int hippi_change_mtu(struct device *dev, int new_mtu) +{ + /* + * HIPPI's got these nice large MTUs. + */ + if ((new_mtu < 68) || (new_mtu > 65280)) + return -EINVAL; + dev->mtu = new_mtu; + return(0); +} + + +/* + * For HIPPI we will actually use the lower 4 bytes of the hardware + * address as the I-FIELD rather than the actual hardware address. + */ +static int hippi_mac_addr(struct device *dev, void *p) +{ + struct sockaddr *addr = p; + if(dev->start) + return -EBUSY; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + return 0; +} + + +struct device *init_hippi_dev(struct device *dev, int sizeof_priv) +{ + struct device *tmp_dev; /* pointer to a device structure */ + + /* Find next free HIPPI entry */ + + for (tmp_dev = dev; tmp_dev != NULL; tmp_dev = tmp_dev->next) + if ((strncmp(tmp_dev->name, "hip", 3) == 0) && + (tmp_dev->base_addr == 0)) + break; + + if (tmp_dev == NULL) + { + printk("Could not find free HIPPI device structure.\n"); + return NULL; + } + + tmp_dev->init = NULL; + sizeof_priv = (sizeof_priv + 3) & ~3; + tmp_dev->priv = sizeof_priv ? kmalloc(sizeof_priv, GFP_KERNEL) : NULL; + + if (tmp_dev->priv) + memset(dev->priv, 0, sizeof_priv); + + /* Initialize remaining device structure information */ + + hippi_setup(tmp_dev); + return tmp_dev; +} +#endif void ether_setup(struct device *dev) { @@ -233,6 +291,40 @@ return; } +#endif + +#ifdef CONFIG_HIPPI +void hippi_setup(struct device *dev) +{ + dev->set_multicast_list = NULL; + dev->change_mtu = hippi_change_mtu; + dev->hard_header = hippi_header; + dev->rebuild_header = hippi_rebuild_header; + dev->set_mac_address = hippi_mac_addr; + dev->hard_header_parse = NULL; + dev->hard_header_cache = NULL; + dev->header_cache_update = NULL; + + /* + * We don't support HIPPI `ARP' for the time being, and probably + * never will unless someone else implements it. However we + * still need a fake ARPHRD to make ifconfig and friends play ball. + */ + dev->type = ARPHRD_HIPPI; + dev->hard_header_len = HIPPI_HLEN; + dev->mtu = 65280; + dev->addr_len = HIPPI_ALEN; + dev->tx_queue_len = 25 /* 5 */; + memset(dev->broadcast, 0xFF, HIPPI_ALEN); + + /* New-style flags. */ + dev->flags = IFF_NODYNARP; /* + * HIPPI doesn't support + * broadcast+multicast and we only + * use static ARP tables. + */ + dev_init_buffers(dev); +} #endif #if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE) diff -u --recursive --new-file v2.1.100/linux/drivers/net/rtl8139.c linux/drivers/net/rtl8139.c --- v2.1.100/linux/drivers/net/rtl8139.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/rtl8139.c Fri May 8 00:20:47 1998 @@ -0,0 +1,1356 @@ +/* rtl8139.c: A RealTek RTL8129/8139 Fast Ethernet driver for Linux. */ +/* + Written 1997 by Donald Becker. + + This software may be used and distributed according to the terms + of the GNU Public License, incorporated herein by reference. + All other rights reserved. + + This driver is for boards based on the RTL8129 and RTL8139 PCI ethernet + chips. + + The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O + Center of Excellence in Space Data and Information Sciences + Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 + + Support and updates available at + http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html +*/ + +static const char *version = +"rtl8139.c:v0.14 12/9/97 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n"; + +/* A few user-configurable values. */ +/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ +static int max_interrupt_work = 10; + +/* Size of the in-memory receive ring. */ +#define RX_BUF_LEN_IDX 3 /* 0==8K, 1==16K, 2==32K, 3==64K */ +#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX) +/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ +#define TX_BUF_SIZE 1536 + +/* PCI Tuning Parameters + Threshold is bytes transferred to chip before transmission starts. */ +#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ + +/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024. */ +#define RX_FIFO_THRESH 4 /* Rx buffer level before first PCI xfer. */ +#define RX_DMA_BURST 4 /* Maximum PCI burst, '4' is 256 bytes */ +#define TX_DMA_BURST 4 + +/* Operational parameters that usually are not changed. */ +/* Time in jiffies before concluding the transmitter is hung. */ +#define TX_TIMEOUT ((4000*HZ)/1000) + +#include +#ifdef MODULE +#ifdef MODVERSIONS +#include +#endif +#include +#include +#else +#define MOD_INC_USE_COUNT +#define MOD_DEC_USE_COUNT +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* Processor type for cache alignment. */ +#include +#include +#include + +#include +#include +#include + +/* Kernel compatibility defines, common to David Hind's PCMCIA package. + This is only in the support-all-kernels source code. */ +#include /* Evil, but neccessary */ + +#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10300 +#define RUN_AT(x) (x) /* What to put in timer->expires. */ +#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC) +#define virt_to_bus(addr) ((unsigned long)addr) +#define bus_to_virt(addr) ((void*)addr) + +#else /* 1.3.0 and later */ +#define RUN_AT(x) (jiffies + (x)) +#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2) +#endif + +#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10338 +#ifdef MODULE +#if !defined(CONFIG_MODVERSIONS) && !defined(__NO_VERSION__) +char kernel_version[] = UTS_RELEASE; +#endif +#else +#undef MOD_INC_USE_COUNT +#define MOD_INC_USE_COUNT +#undef MOD_DEC_USE_COUNT +#define MOD_DEC_USE_COUNT +#endif +#endif /* 1.3.38 */ + +#if (LINUX_VERSION_CODE >= 0x10344) +#define NEW_MULTICAST +#include +#endif + +#ifdef SA_SHIRQ +#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev) +#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance) +#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs) +#else +#define FREE_IRQ(irqnum, dev) free_irq(irqnum) +#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n) +#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs) +#endif + +#if (LINUX_VERSION_CODE < 0x20123) +#define test_and_set_bit(val, addr) set_bit(val, addr) +#include +#endif + +/* The I/O extent. */ +#define RTL8129_TOTAL_SIZE 0x80 + +#ifdef HAVE_DEVLIST +struct netdev_entry rtl8139_drv = +{"RTL8139", rtl8139_probe, RTL8129_TOTAL_SIZE, NULL}; +#endif + +static int rtl8129_debug = 1; + +/* + Theory of Operation + +I. Board Compatibility + +This device driver is designed for the RealTek RTL8129, the RealTek Fast +Ethernet controllers for PCI. This chip is used on a few clone boards. + + +II. Board-specific settings + +PCI bus devices are configured by the system at boot time, so no jumpers +need to be set on the board. The system BIOS will assign the +PCI INTA signal to a (preferably otherwise unused) system IRQ line. +Note: Kernel versions earlier than 1.3.73 do not support shared PCI +interrupt lines. + +III. Driver operation + +IIIa. Rx Ring buffers + +The receive unit uses a single linear ring buffer rather than the more +common (and more efficient) descriptor-based architecture. Incoming frames +are sequentially stored into the Rx region, and the host copies them into +skbuffs. + +Comment: While it is theoretically possible to process many frames in place, +any delay in Rx processing would cause us to drop frames. More importantly, +the Linux protocol stack is not designed to operate in this manner. + +IIIb. Tx operation + +The RTL8129 uses a fixed set of four Tx descriptors in register space. +In a stunningly bad design choice, Tx frames must be 32 bit aligned. Linux +aligns the IP header on word boundaries, and 14 byte ethernet header means +that almost all frames will need to be copied to an alignment buffer. + +IVb. References + +http://www.realtek.com.tw/cn/cn.html +http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html + +IVc. Errata + +*/ + +#ifndef PCI_VENDOR_ID_REALTEK +#define PCI_VENDOR_ID_REALTEK 0x10ec +#endif +#ifndef PCI_DEVICE_ID_REALTEK_8129 +#define PCI_DEVICE_ID_REALTEK_8129 0x8129 +#endif +#ifndef PCI_DEVICE_ID_REALTEK_8139 +#define PCI_DEVICE_ID_REALTEK_8139 0x8139 +#endif + +/* The rest of these values should never change. */ +#define NUM_TX_DESC 4 /* Number of Tx descriptor registers. */ + +/* Symbolic offsets to registers. */ +enum RTL8129_registers { + MAC0=0, /* Ethernet hardware address. */ + MAR0=8, /* Multicast filter. */ + TxStat0=0x10, /* Transmit status (Four 32bit registers). */ + TxAddr0=0x20, /* Tx descriptors (also four 32bit). */ + RxBuf=0x30, RxEarlyCnt=0x34, RxEarlyStatus=0x36, + ChipCmd=0x37, RxBufPtr=0x38, RxBufAddr=0x3A, + IntrMask=0x3C, IntrStatus=0x3E, + TxConfig=0x40, RxConfig=0x44, + Timer=0x48, /* A general-purpose counter. */ + RxMissed=0x4C, /* 24 bits valid, write clears. */ + Cfg9346=0x50, Config0=0x51, Config1=0x52, + FlashReg=0x54, GPPinData=0x58, GPPinDir=0x59, MII_SMI=0x5A, HltClk=0x5B, + MultiIntr=0x5C, TxSummary=0x60, + BMCR=0x62, BMSR=0x64, NWayAdvert=0x66, NWayLPAR=0x68, NWayExpansion=0x6A, +}; + +enum ChipCmdBits { + CmdReset=0x10, CmdRxEnb=0x08, CmdTxEnb=0x04, RxBufEmpty=0x01, }; + +/* Interrupt register bits, using my own meaningful names. */ +enum IntrStatusBits { + PCIErr=0x8000, PCSTimeout=0x4000, + RxFIFOOver=0x40, RxUnderrun=0x20, RxOverflow=0x10, + TxErr=0x08, TxOK=0x04, RxErr=0x02, RxOK=0x01, +}; +enum TxStatusBits { + TxHostOwns=0x2000, TxUnderrun=0x4000, TxStatOK=0x8000, + TxOutOfWindow=0x20000000, TxAborted=0x40000000, TxCarrierLost=0x80000000, +}; +enum RxStatusBits { + RxMulticast=0x8000, RxPhysical=0x4000, RxBroadcast=0x2000, + RxBadSymbol=0x0020, RxRunt=0x0010, RxTooLong=0x0008, RxCRCErr=0x0004, + RxBadAlign=0x0002, RxStatusOK=0x0001, +}; + +struct rtl8129_private { + char devname[8]; /* Used only for kernel debugging. */ + const char *product_name; + struct device *next_module; + int chip_id; + int chip_revision; + struct enet_statistics stats; + struct timer_list timer; /* Media selection timer. */ + unsigned int cur_rx, cur_tx; /* The next free and used entries */ + unsigned int dirty_rx, dirty_tx; + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ + struct sk_buff* tx_skbuff[NUM_TX_DESC]; + unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ + unsigned char *rx_ring; + unsigned char *tx_bufs; /* Tx bounce buffer region. */ + unsigned char mc_filter[8]; /* Current multicast filter. */ + char phys[4]; /* MII device addresses. */ + unsigned int tx_full:1; /* The Tx queue is full. */ + unsigned int full_duplex:1; /* Full-duplex operation requested. */ + unsigned int default_port:4; /* Last dev->if_port value. */ + unsigned int media2:4; /* Secondary monitored media port. */ + unsigned int medialock:1; /* Don't sense media type. */ + unsigned int mediasense:1; /* Media sensing in progress. */ +}; + +#ifdef MODULE +/* Used to pass the full-duplex flag, etc. */ +static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1}; +static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1}; +#if LINUX_VERSION_CODE > 0x20118 +MODULE_AUTHOR("Donald Becker "); +MODULE_DESCRIPTION("RealTek RTL8129/8139 Fast Ethernet driver"); +MODULE_PARM(debug, "i"); +MODULE_PARM(options, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(max_interrupt_work, "i"); +#endif +#endif + +static struct device *rtl8129_probe1(struct device *dev, int ioaddr, int irq, + int chip_id, int options, int card_idx); +static int rtl8129_open(struct device *dev); +static int read_eeprom(int ioaddr, int location); +static int mdio_read(int ioaddr, int phy_id, int location); +static void rtl8129_timer(unsigned long data); +static void rtl8129_tx_timeout(struct device *dev); +static void rtl8129_init_ring(struct device *dev); +static int rtl8129_start_xmit(struct sk_buff *skb, struct device *dev); +static int rtl8129_rx(struct device *dev); +static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +static int rtl8129_close(struct device *dev); +static struct enet_statistics *rtl8129_get_stats(struct device *dev); +#ifdef NEW_MULTICAST +static void set_rx_mode(struct device *dev); +#else +static void set_rx_mode(struct device *dev, int num_addrs, void *addrs); +#endif + + + +#ifdef MODULE +/* A list of all installed RTL8129 devices, for removing the driver module. */ +static struct device *root_rtl8129_dev = NULL; +#endif + +int rtl8139_probe(struct device *dev) +{ + int cards_found = 0; + static int pci_index = 0; /* Static, for multiple probe calls. */ + + /* Ideally we would detect all network cards in slot order. That would + be best done a central PCI probe dispatch, which wouldn't work + well with the current structure. So instead we detect just the + Rtl81*9 cards in slot order. */ + + if (pci_present()) { + unsigned char pci_bus, pci_device_fn; + + for (;pci_index < 0xff; pci_index++) { + unsigned char pci_latency; +#if LINUX_VERSION_CODE >= 0x20155 + unsigned int pci_irq_line; + struct pci_dev *pdev; +#else + unsigned char pci_irq_line; +#endif + unsigned short pci_command, new_command, vendor, device; + unsigned int pci_ioaddr; + + if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, +#ifdef REVERSE_PROBE_ORDER + 0xff - pci_index, +#else + pci_index, +#endif + &pci_bus, &pci_device_fn) + != PCIBIOS_SUCCESSFUL) + break; + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_VENDOR_ID, &vendor); + if (vendor != PCI_VENDOR_ID_REALTEK) + continue; + + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_DEVICE_ID, &device); +#if LINUX_VERSION_CODE >= 0x20155 + pdev = pci_find_slot(pci_bus, pci_device_fn); + pci_irq_line = pdev->irq; + pci_ioaddr = pdev->base_address[0]; +#else + pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_INTERRUPT_LINE, &pci_irq_line); + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_0, &pci_ioaddr); +#endif + /* Remove I/O space marker in bit 0. */ + pci_ioaddr &= ~3; + + if (device != PCI_DEVICE_ID_REALTEK_8129 + && device != PCI_DEVICE_ID_REALTEK_8139) { + printk(KERN_NOTICE"Unknown RealTek PCI ethernet chip type " + "%4.4x detected: not configured.\n", device); + continue; + } + if (check_region(pci_ioaddr, RTL8129_TOTAL_SIZE)) + continue; + + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_COMMAND, &pci_command); + new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO; + if (pci_command != new_command) { + printk(KERN_INFO " The PCI BIOS has not enabled this" + " device! Updating PCI config %4.4x->%4.4x.\n", + pci_command, new_command); + pcibios_write_config_word(pci_bus, pci_device_fn, + PCI_COMMAND, new_command); + } + +#ifdef MODULE + dev = rtl8129_probe1(dev, pci_ioaddr, pci_irq_line, device, + options[cards_found], cards_found); +#else + dev = rtl8129_probe1(dev, pci_ioaddr, pci_irq_line, device, + dev ? dev->mem_start : 0, -1); +#endif + + if (dev) { + pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_LATENCY_TIMER, &pci_latency); + if (pci_latency < 32) { + printk(KERN_NOTICE" PCI latency timer (CFLT) is " + "unreasonably low at %d. Setting to 64 clocks.\n", + pci_latency); + pcibios_write_config_byte(pci_bus, pci_device_fn, + PCI_LATENCY_TIMER, 64); + } else if (rtl8129_debug > 1) + printk(KERN_INFO" PCI latency timer (CFLT) is %#x.\n", + pci_latency); + dev = 0; + cards_found++; + } + } + } + +#if defined (MODULE) + return cards_found; +#else + return cards_found ? 0 : -ENODEV; +#endif +} + +static struct device *rtl8129_probe1(struct device *dev, int ioaddr, int irq, + int chip_id, int options, int card_idx) +{ + static int did_version = 0; /* Already printed version info. */ + struct rtl8129_private *tp; + int i; + + if (rtl8129_debug > 0 && did_version++ == 0) + printk(KERN_INFO "%s", version); + + dev = init_etherdev(dev, 0); + + printk(KERN_INFO "%s: RealTek RTL%x at %#3x, IRQ %d, ", + dev->name, chip_id, ioaddr, irq); + + /* Bring the chip out of low-power mode. */ + outb(0x00, ioaddr + Config1); + + /* Perhaps this should be read from the EEPROM? */ + for (i = 0; i < 6; i++) + dev->dev_addr[i] = inb(ioaddr + MAC0 + i); + + for (i = 0; i < 5; i++) + printk("%2.2x:", dev->dev_addr[i]); + printk("%2.2x.\n", dev->dev_addr[i]); + + if (rtl8129_debug > 1) { + printk(KERN_INFO "%s: EEPROM contents\n", dev->name); + for (i = 0; i < 64; i++) + printk(" %4.4x%s", read_eeprom(ioaddr, i), + i%16 == 15 ? "\n"KERN_INFO : ""); + } + + /* We do a request_region() to register /proc/ioports info. */ + request_region(ioaddr, RTL8129_TOTAL_SIZE, "RealTek RTL8129/39 Fast Ethernet"); + + dev->base_addr = ioaddr; + dev->irq = irq; + + /* Some data structures must be quadword aligned. */ + tp = kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA); + memset(tp, 0, sizeof(*tp)); + dev->priv = tp; + +#ifdef MODULE + tp->next_module = root_rtl8129_dev; + root_rtl8129_dev = dev; +#endif + + tp->chip_id = chip_id; + + /* Find the connected MII xcvrs. + Doing this in open() would allow detecting external xcvrs later, but + takes too much time. */ + if (chip_id == 0x8129) { + int phy, phy_idx; + for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys); + phy++) { + int mii_status = mdio_read(ioaddr, phy, 1); + + if (mii_status != 0xffff && mii_status != 0x0000) { + tp->phys[phy_idx++] = phy; + printk(KERN_INFO "%s: MII transceiver found at address %d.\n", + dev->name, phy); + } + } + if (phy_idx == 0) { + printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " + "transceiver.\n", + dev->name); + tp->phys[0] = -1; + } + } else { + tp->phys[0] = -1; + } + + /* Put the chip into low-power mode. */ + outb(0xC0, ioaddr + Cfg9346); + outb(0x03, ioaddr + Config1); + outb('H', ioaddr + HltClk); /* 'R' would leave the clock running. */ + + /* The lower four bits are the media type. */ + if (options > 0) { + tp->full_duplex = (options & 16) ? 1 : 0; + tp->default_port = options & 15; + if (tp->default_port) + tp->medialock = 1; + } +#ifdef MODULE + if (card_idx >= 0) { + if (full_duplex[card_idx] >= 0) + tp->full_duplex = full_duplex[card_idx]; + } +#endif + + /* The Rtl8129-specific entries in the device structure. */ + dev->open = &rtl8129_open; + dev->hard_start_xmit = &rtl8129_start_xmit; + dev->stop = &rtl8129_close; + dev->get_stats = &rtl8129_get_stats; + dev->set_multicast_list = &set_rx_mode; + + return dev; +} + +/* Serial EEPROM section. */ + +/* EEPROM_Ctrl bits. */ +#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ +#define EE_CS 0x08 /* EEPROM chip select. */ +#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ +#define EE_WRITE_0 0x00 +#define EE_WRITE_1 0x02 +#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ +#define EE_ENB (0x80 | EE_CS) + +/* Delay between EEPROM clock transitions. + The 1.2 code is a "nasty" timing loop, but PC compatible machines are + *supposed* to delay an ISA-compatible period for the SLOW_DOWN_IO macro. */ +#ifdef _LINUX_DELAY_H +#define eeprom_delay(nanosec) udelay((nanosec + 999)/1000) +#else +#define eeprom_delay(nanosec) do { int _i = 3; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0) +#endif + +/* The EEPROM commands include the alway-set leading bit. */ +#define EE_WRITE_CMD (5 << 6) +#define EE_READ_CMD (6 << 6) +#define EE_ERASE_CMD (7 << 6) + +static int read_eeprom(int ioaddr, int location) +{ + int i; + unsigned short retval = 0; + short ee_addr = ioaddr + Cfg9346; + int read_cmd = location | EE_READ_CMD; + + outb(EE_ENB & ~EE_CS, ee_addr); + outb(EE_ENB, ee_addr); + + /* Shift the read command bits out. */ + for (i = 10; i >= 0; i--) { + short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + outb(EE_ENB | dataval, ee_addr); + eeprom_delay(100); + outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); + eeprom_delay(150); + outb(EE_ENB | dataval, ee_addr); /* Finish EEPROM a clock tick. */ + eeprom_delay(250); + } + outb(EE_ENB, ee_addr); + + for (i = 16; i > 0; i--) { + outb(EE_ENB | EE_SHIFT_CLK, ee_addr); + eeprom_delay(100); + retval = (retval << 1) | ((inb(ee_addr) & EE_DATA_READ) ? 1 : 0); + outb(EE_ENB, ee_addr); + eeprom_delay(100); + } + + /* Terminate the EEPROM access. */ + outb(~EE_CS, ee_addr); + return retval; +} + +/* MII serial management: mostly bogus for now. */ +/* Read and write the MII management registers using software-generated + serial MDIO protocol. The maxium data clock rate is 2.5 Mhz. */ +#define MDIO_DIR 0x80 +#define MDIO_DATA_OUT 0x04 +#define MDIO_DATA_IN 0x02 +#define MDIO_CLK 0x01 +#ifdef _LINUX_DELAY_H +#define mdio_delay() udelay(1) /* Really 400ns. */ +#else +#define mdio_delay() __SLOW_DOWN_IO; +#endif + +/* Syncronize the MII management interface by shifting 32 one bits out. */ +static void mdio_sync(int ioaddr) +{ + int i; + int mdio_addr = ioaddr + MII_SMI; + + for (i = 32; i >= 0; i--) { + outb(MDIO_DIR | MDIO_DATA_OUT, mdio_addr); + mdio_delay(); + outb(MDIO_DIR | MDIO_DATA_OUT | MDIO_CLK, mdio_addr); + mdio_delay(); + } + return; +} +static int mdio_read(int ioaddr, int phy_id, int location) +{ + int i; + int read_cmd = (0xf6 << 10) | (phy_id << 5) | location; + int retval = 0; + int mdio_addr = ioaddr + MII_SMI; + + mdio_sync(ioaddr); + /* Shift the read command bits out. */ + for (i = 15; i >= 0; i--) { + int dataval = + (read_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; + + outb(MDIO_DIR | dataval, mdio_addr); + mdio_delay(); + outb(MDIO_DIR | dataval | MDIO_CLK, mdio_addr); + mdio_delay(); + } + + /* Read the two transition, 16 data, and wire-idle bits. */ + for (i = 19; i > 0; i--) { + outb(0, mdio_addr); + mdio_delay(); + retval = (retval << 1) | ((inb(mdio_addr) & MDIO_DATA_IN) ? 1 : 0); + outb(MDIO_CLK, mdio_addr); + mdio_delay(); + } + return (retval>>1) & 0xffff; +} + +static int +rtl8129_open(struct device *dev) +{ + struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; + int ioaddr = dev->base_addr; + int i; + int full_duplex = 0; + + /* Soft reset the chip. */ + outb(CmdReset, ioaddr + ChipCmd); + +#ifdef SA_SHIRQ + if (request_irq(dev->irq, &rtl8129_interrupt, SA_SHIRQ, + "RealTek RTL8129/39 Fast Ethernet", dev)) { + return -EAGAIN; + } +#else + if (irq2dev_map[dev->irq] != NULL + || (irq2dev_map[dev->irq] = dev) == NULL + || dev->irq == 0 + || request_irq(dev->irq, &rtl8129_interrupt, 0, "RTL8129")) { + return -EAGAIN; + } +#endif + + MOD_INC_USE_COUNT; + + tp->tx_bufs = kmalloc(TX_BUF_SIZE * NUM_TX_DESC, GFP_KERNEL); + tp->rx_ring = kmalloc(RX_BUF_LEN + 16, GFP_KERNEL); + if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { + if (tp->tx_bufs) + kfree(tp->tx_bufs); + if (rtl8129_debug > 0) + printk(KERN_ERR "%s: Couldn't allocate a %d byte receive ring.\n", + dev->name, RX_BUF_LEN); + return -ENOMEM; + } + rtl8129_init_ring(dev); + +#ifndef final_version + /* Used to monitor rx ring overflow. */ + memset(tp->rx_ring + RX_BUF_LEN, 0xcc, 16); +#endif + + /* Check that the chip has finished the reset. */ + for (i = 1000; i > 0; i--) + if ((inb(ioaddr + ChipCmd) & CmdReset) == 0) + break; +#ifndef final_version + if (rtl8129_debug > 2) + printk(KERN_DEBUG"%s: reset finished with status %2.2x after %d loops.\n", + dev->name, inb(ioaddr + ChipCmd), 1000-i); +#endif + + for (i = 0; i < 6; i++) + outb(dev->dev_addr[i], ioaddr + MAC0 + i); + + /* Must enable Tx/Rx before setting transfer thresholds! */ + outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); + outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) | (RX_DMA_BURST<<8), + ioaddr + RxConfig); + outl((TX_DMA_BURST<<8)|0x03000000, ioaddr + TxConfig); + + full_duplex = tp->full_duplex; + if (tp->phys[0] >= 0 || tp->chip_id == 0x8139) { + u16 mii_reg5; + if (tp->chip_id == 0x8139) + mii_reg5 = inw(ioaddr + NWayLPAR); + else + mii_reg5 = mdio_read(ioaddr, tp->phys[0], 5); + if (mii_reg5 == 0xffff) + ; /* Not there */ + else if ((mii_reg5 & 0x0100) == 0x0100 + || (mii_reg5 & 0x00C0) == 0x0040) + full_duplex = 1; + if (rtl8129_debug > 1) + printk(KERN_INFO"%s: Setting %s%s-duplex based on" + " auto-negotiated partner ability %4.4x.\n", dev->name, + mii_reg5 == 0 ? "" : + (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ", + full_duplex ? "full" : "half", mii_reg5); + } + + outb(0xC0, ioaddr + Cfg9346); + outb(full_duplex ? 0x60 : 0x20, ioaddr + Config1); + outb(0x00, ioaddr + Cfg9346); + + outl(virt_to_bus(tp->rx_ring), ioaddr + RxBuf); + + /* Start the chip's Tx and Rx process. */ + outl(0, ioaddr + RxMissed); + set_rx_mode(dev); + + outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); +#ifndef final_version + if (rtl8129_debug > 1) + printk(KERN_DEBUG"%s: In rtl8129_open() Tx/Rx Config %8.8x/%8.8x" + " Chip Config %2.2x/%2.2x.\n", + dev->name, inl(ioaddr + TxConfig), inl(ioaddr + RxConfig), + inb(ioaddr + Config0), inb(ioaddr + Config1)); +#endif + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + /* Enable all known interrupts by setting the interrupt mask. */ + outw(PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver + | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask); + + if (rtl8129_debug > 1) + printk(KERN_DEBUG"%s: rtl8129_open() ioaddr %4.4x IRQ %d" + " GP Pins %2.2x %s-duplex.\n", + dev->name, ioaddr, dev->irq, inb(ioaddr + GPPinData), + full_duplex ? "full" : "half"); + + /* Set the timer to switch to check for link beat and perhaps switch + to an alternate media type. */ + init_timer(&tp->timer); + tp->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */ + tp->timer.data = (unsigned long)dev; + tp->timer.function = &rtl8129_timer; /* timer handler */ + add_timer(&tp->timer); + + return 0; +} + +static void rtl8129_timer(unsigned long data) +{ + struct device *dev = (struct device *)data; + struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; + int ioaddr = dev->base_addr; + int next_tick = 0; + + if (tp->chip_id == 0x8139) { + u16 mii_reg5 = inw(ioaddr + NWayLPAR); + if ((mii_reg5 & 0x0100) == 0x0100 + || (mii_reg5 & 0x00C0) == 0x0040) + if ( ! tp->full_duplex) { + tp->full_duplex = 1; + if (rtl8129_debug > 0) + printk(KERN_INFO "%s: Switching to full-duplex based on " + "link partner ability of %4.4x.\n", + dev->name, mii_reg5); + outb(0xC0, ioaddr + Cfg9346); + outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1); + outb(0x00, ioaddr + Cfg9346); + } + } + if (rtl8129_debug > 2) { + if (tp->chip_id == 0x8129) + printk(KERN_DEBUG"%s: Media selection tick, GP pins %2.2x.\n", + dev->name, inb(ioaddr + GPPinData)); + else + printk(KERN_DEBUG"%s: Media selection tick, Link partner %4.4x.\n", + dev->name, inw(ioaddr + NWayLPAR)); + printk(KERN_DEBUG"%s: Other registers are IntMask %4.4x IntStatus %4.4x" + " RxStatus %4.4x.\n", + dev->name, inw(ioaddr + IntrMask), inw(ioaddr + IntrStatus), + inl(ioaddr + RxEarlyStatus)); + printk(KERN_DEBUG"%s: Chip config %2.2x %2.2x.\n", + dev->name, inb(ioaddr + Config0), inb(ioaddr + Config1)); + } + + if (next_tick) { + tp->timer.expires = RUN_AT(next_tick); + add_timer(&tp->timer); + } +} + +static void rtl8129_tx_timeout(struct device *dev) +{ + struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; + int ioaddr = dev->base_addr; + int i; + + if (rtl8129_debug > 0) + printk(KERN_WARNING "%s: Transmit timeout, status %2.2x %4.4x.\n", + dev->name, inb(ioaddr + ChipCmd), inw(ioaddr + IntrStatus)); + for (i = 0; i < NUM_TX_DESC; i++) + printk(KERN_DEBUG"%s: Tx descriptor %d is %8.8x.%s\n", + dev->name, i, inl(ioaddr + TxStat0 + i*4), + i == tp->dirty_tx % NUM_TX_DESC ? " (queue head)" : ""); + if (tp->chip_id == 0x8129) { + int mii_reg; + printk(KERN_DEBUG"%s: MII #%d registers are:", dev->name, tp->phys[0]); + for (mii_reg = 0; mii_reg < 8; mii_reg++) + printk(" %4.4x", mdio_read(ioaddr, tp->phys[0], mii_reg)); + printk(".\n"); + } else { + printk(KERN_DEBUG"%s: MII status register is %4.4x.\n", + dev->name, inw(ioaddr + BMSR)); + } + /* Restart the chip Tx process. */ + outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); + /* Continue from any transmit abort. */ + outl((TX_DMA_BURST<<8) || 0x03000001, ioaddr + TxConfig); + + dev->trans_start = jiffies; + tp->stats.tx_errors++; + return; +} + + +/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ +static void +rtl8129_init_ring(struct device *dev) +{ + struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; + int i; + + tp->tx_full = 0; + tp->cur_rx = tp->cur_tx = 0; + tp->dirty_rx = tp->dirty_tx = 0; + + for (i = 0; i < NUM_TX_DESC; i++) { + tp->tx_skbuff[i] = 0; + tp->tx_buf[i] = &tp->tx_bufs[i*TX_BUF_SIZE]; + } +} + +static int +rtl8129_start_xmit(struct sk_buff *skb, struct device *dev) +{ + struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; + int ioaddr = dev->base_addr; + int entry; + +#ifndef final_version + if (skb == NULL || skb->len <= 0) { + printk(KERN_ERR"%s: Obsolete driver Tx request made: skbuff==NULL.\n", + dev->name); +#if 0 + dev_tint(dev); +#endif + return 0; + } +#endif + + /* Block a timer-based transmit from overlapping. This could better be + done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ + if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { + if (jiffies - dev->trans_start < TX_TIMEOUT) + return 1; + rtl8129_tx_timeout(dev); + return 1; + } + + /* Calculate the next Tx descriptor entry. */ + entry = tp->cur_tx % NUM_TX_DESC; + + tp->tx_skbuff[entry] = skb; + if ((long)skb->data & 3) { /* Must use alignment buffer. */ + memcpy(tp->tx_buf[entry], skb->data, skb->len); + outl(virt_to_bus(tp->tx_buf[entry]), ioaddr + TxAddr0 + entry*4); + } else + outl(virt_to_bus(skb->data), ioaddr + TxAddr0 + entry*4); + /* Note: the chip doesn't have auto-pad! */ + outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | + (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN), + ioaddr + TxStat0 + entry*4); + + if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */ + dev->tbusy = 0; + } else { + tp->tx_full = 1; + } + + dev->trans_start = jiffies; + if (rtl8129_debug > 4) + printk(KERN_DEBUG"%s: Queued Tx packet at %p size %d to slot %d.\n", + dev->name, skb->data, skb->len, entry); + + return 0; +} + +/* The interrupt handler does all of the Rx thread work and cleans up + after the Tx thread. */ +static void rtl8129_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs) +{ +#ifdef SA_SHIRQ + struct device *dev = (struct device *)dev_instance; +#else + struct device *dev = (struct device *)(irq2dev_map[irq]); +#endif + struct rtl8129_private *tp; + int ioaddr, boguscnt = max_interrupt_work; + int status; + + if (dev == NULL) { + printk (KERN_ERR"rtl8139_interrupt(): IRQ %d for unknown device.\n", + irq); + return; + } + + ioaddr = dev->base_addr; + tp = (struct rtl8129_private *)dev->priv; + if (test_and_set_bit(0, (void*)&dev->interrupt)) { + printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name); + return; + } + + do { + status = inw(ioaddr + IntrStatus); + /* Acknowledge all of the current interrupt sources ASAP. */ + outw(status, ioaddr + IntrStatus); + + if (rtl8129_debug > 4) + printk(KERN_DEBUG"%s: interrupt status=%#4.4x new intstat=%#4.4x.\n", + dev->name, status, inw(ioaddr + IntrStatus)); + + if ((status & (PCIErr|PCSTimeout|RxUnderrun|RxOverflow|RxFIFOOver + |TxErr|TxOK|RxErr|RxOK)) == 0) + break; + + if (status & (RxOK|RxUnderrun|RxOverflow|RxFIFOOver))/* Rx interrupt */ + rtl8129_rx(dev); + + if (status & (TxOK | TxErr)) { + unsigned int dirty_tx; + + for (dirty_tx = tp->dirty_tx; dirty_tx < tp->cur_tx; dirty_tx++) { + int entry = dirty_tx % NUM_TX_DESC; + int txstatus = inl(ioaddr + TxStat0 + entry*4); + + if ( ! (txstatus & TxHostOwns)) + break; /* It still hasn't been Txed */ + + /* Note: TxCarrierLost is always asserted at 100mbps. */ + if (txstatus & (TxOutOfWindow | TxAborted)) { + /* There was an major error, log it. */ +#ifndef final_version + if (rtl8129_debug > 1) + printk(KERN_NOTICE"%s: Transmit error, Tx status %8.8x.\n", + dev->name, txstatus); +#endif + tp->stats.tx_errors++; + if (txstatus&TxAborted) { + tp->stats.tx_aborted_errors++; + outl((TX_DMA_BURST<<8)|0x03000001, ioaddr + TxConfig); + } + if (txstatus&TxCarrierLost) tp->stats.tx_carrier_errors++; + if (txstatus&TxOutOfWindow) tp->stats.tx_window_errors++; +#ifdef ETHER_STATS + if ((txstatus & 0x0f000000) == 0x0f000000) + tp->stats.collisions16++; +#endif + } else { +#ifdef ETHER_STATS + /* No count for tp->stats.tx_deferred */ +#endif + if (txstatus & TxUnderrun) { + /* Todo: increase the Tx FIFO threshold. */ + tp->stats.tx_fifo_errors++; + } + tp->stats.collisions += (txstatus >> 24) & 15; + tp->stats.tx_packets++; + } + + /* Free the original skb. */ + dev_kfree_skb(tp->tx_skbuff[entry]); + tp->tx_skbuff[entry] = 0; + } + +#ifndef final_version + if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { + printk(KERN_ERR"%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", + dev->name, dirty_tx, tp->cur_tx, tp->tx_full); + dirty_tx += NUM_TX_DESC; + } +#endif + + if (tp->tx_full && dev->tbusy + && dirty_tx > tp->cur_tx - NUM_TX_DESC) { + /* The ring is no longer full, clear tbusy. */ + tp->tx_full = 0; + dev->tbusy = 0; + mark_bh(NET_BH); + } + + tp->dirty_tx = dirty_tx; + } + + /* Check uncommon events with one test. */ + if (status & (PCIErr|PCSTimeout |RxUnderrun|RxOverflow|RxFIFOOver + |TxErr|RxErr)) { + +#ifndef final_version + if (rtl8129_debug > 0) + printk(KERN_DEBUG"%s: Unusual error, status %4.4x.\n", + dev->name, status); +#endif + + /* Update the error count. */ + tp->stats.rx_missed_errors += inl(ioaddr + RxMissed); + outl(0, ioaddr + RxMissed); + + if (status & (RxUnderrun | RxOverflow | RxErr | RxFIFOOver)) + tp->stats.rx_errors++; + + if (status & (PCSTimeout)) tp->stats.rx_length_errors++; + if (status & (RxUnderrun|RxFIFOOver)) tp->stats.rx_fifo_errors++; + if (status & RxOverflow) { + tp->stats.rx_over_errors++; + tp->cur_rx = inw(ioaddr + RxBufAddr) % RX_BUF_LEN; + outw(tp->cur_rx - 16, ioaddr + RxBufPtr); + } + /* Error sources cleared above. */ + } + if (--boguscnt < 0) { + printk(KERN_WARNING"%s: Too much work at interrupt, " + "IntrStatus=0x%4.4x.\n", + dev->name, status); + /* Clear all interrupt sources. */ + outw(0xffff, ioaddr + IntrStatus); + break; + } + } while (1); + + if (rtl8129_debug > 3) + printk(KERN_DEBUG"%s: exiting interrupt, intr_status=%#4.4x.\n", + dev->name, inl(ioaddr + IntrStatus)); + +#ifndef final_version + /* Code that should never be run! Perhaps remove after testing.. */ + { + static int stopit = 10; + if (dev->start == 0 && --stopit < 0) { + printk(KERN_ERR"%s: Emergency stop, looping startup interrupt.\n", + dev->name); + FREE_IRQ(irq, dev); + } + } +#endif + + dev->interrupt = 0; + return; +} + +/* Todo: The data sheet doesn't describe the Rx ring at all, so I'm winging + it here until I have a chip to play with. 8/30/97 */ +static int +rtl8129_rx(struct device *dev) +{ + struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; + int ioaddr = dev->base_addr; + unsigned char *rx_ring = tp->rx_ring; + u16 cur_rx = tp->cur_rx; + + if (rtl8129_debug > 4) + printk(KERN_DEBUG"%s: In rtl8129_rx(), current %4.4x BufAddr %4.4x," + " free to %4.4x, Cmd %2.2x.\n", + dev->name, cur_rx, inw(ioaddr + RxBufAddr), + inw(ioaddr + RxBufPtr), inb(ioaddr + ChipCmd)); + + while ((inb(ioaddr + ChipCmd) & 1) == 0) { + u16 ring_offset = cur_rx % RX_BUF_LEN; + u32 rx_status = *(u32*)(rx_ring + ring_offset); + u16 rx_size = rx_status >> 16; + + if (rtl8129_debug > 4) { + int i; + printk(KERN_DEBUG"%s: rtl8129_rx() status %4.4x, size %4.4x, cur %4.4x.\n", + dev->name, rx_status, rx_size, cur_rx); + printk(KERN_DEBUG"%s: Frame contents ", dev->name); + for (i = 0; i < 70; i++) + printk(" %2.2x", rx_ring[ring_offset + i]); + printk(".\n"); + } + if (rx_status & RxTooLong) { + if (rtl8129_debug > 0) + printk(KERN_NOTICE"%s: Oversized Ethernet frame, status %4.4x!\n", + dev->name, rx_status); + tp->stats.rx_length_errors++; + } else if (rx_status & + (RxBadSymbol|RxRunt|RxTooLong|RxCRCErr|RxBadAlign)) { + if (rtl8129_debug > 1) + printk(KERN_DEBUG"%s: Ethernet frame had errors," + " status %4.4x.\n", dev->name, rx_status); + tp->stats.rx_errors++; + if (rx_status & (RxBadSymbol|RxBadAlign)) + tp->stats.rx_frame_errors++; + if (rx_status & (RxRunt|RxTooLong)) tp->stats.rx_length_errors++; + if (rx_status & RxCRCErr) tp->stats.rx_crc_errors++; + } else { + /* Malloc up new buffer, compatible with net-2e. */ + /* Omit the four octet CRC from the length. */ + struct sk_buff *skb; + + skb = DEV_ALLOC_SKB(rx_size + 2); + if (skb == NULL) { + printk(KERN_WARNING"%s: Memory squeeze, deferring packet.\n", + dev->name); + /* We should check that some rx space is free. + If not, free one and mark stats->rx_dropped++. */ + tp->stats.rx_dropped++; + break; + } + skb->dev = dev; + skb_reserve(skb, 2); /* 16 byte align the IP fields. */ + if (ring_offset+rx_size+4 > RX_BUF_LEN) { + int semi_count = RX_BUF_LEN - ring_offset - 4; + memcpy(skb_put(skb, semi_count), &rx_ring[ring_offset + 4], + semi_count); + memcpy(skb_put(skb, rx_size-semi_count), rx_ring, + rx_size-semi_count); + if (rtl8129_debug > 4) { + int i; + printk(KERN_DEBUG"%s: Frame wrap @%d", dev->name, semi_count); + for (i = 0; i < 16; i++) + printk(" %2.2x", rx_ring[i]); + printk(".\n"); + memset(rx_ring, 0xcc, 16); + } + } else + memcpy(skb_put(skb, rx_size), &rx_ring[ring_offset + 4], + rx_size); +#if LINUX_VERSION_CODE >= 0x10300 + skb->protocol = eth_type_trans(skb, dev); +#else + skb->len = rx_size; +#endif + netif_rx(skb); + tp->stats.rx_packets++; + } + + cur_rx += rx_size + 4; + cur_rx = (cur_rx + 3) & ~3; + outw(cur_rx - 16, ioaddr + RxBufPtr); + } + if (rtl8129_debug > 4) + printk(KERN_DEBUG"%s: Done rtl8129_rx(), current %4.4x BufAddr %4.4x," + " free to %4.4x, Cmd %2.2x.\n", + dev->name, cur_rx, inw(ioaddr + RxBufAddr), + inw(ioaddr + RxBufPtr), inb(ioaddr + ChipCmd)); + tp->cur_rx = cur_rx; + return 0; +} + +static int +rtl8129_close(struct device *dev) +{ + int ioaddr = dev->base_addr; + struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; + int i; + + dev->start = 0; + dev->tbusy = 1; + + if (rtl8129_debug > 1) + printk(KERN_DEBUG"%s: Shutting down ethercard, status was 0x%4.4x.\n", + dev->name, inw(ioaddr + IntrStatus)); + + /* Disable interrupts by clearing the interrupt mask. */ + outw(0x0000, ioaddr + IntrMask); + + /* Stop the chip's Tx and Rx DMA processes. */ + outb(0x00, ioaddr + ChipCmd); + + /* Update the error counts. */ + tp->stats.rx_missed_errors += inl(ioaddr + RxMissed); + outl(0, ioaddr + RxMissed); + + del_timer(&tp->timer); + +#ifdef SA_SHIRQ + free_irq(dev->irq, dev); +#else + free_irq(dev->irq); + irq2dev_map[dev->irq] = 0; +#endif + +#ifndef final_version + /* Used to monitor rx ring overflow. */ + for (i = 0; i < 16; i++) + if (tp->rx_ring[RX_BUF_LEN+i] != 0xcc) { + printk(KERN_WARNING"%s: Rx ring overflowed! Values are ", + dev->name); + for (i = 0; i < 16; i++) + printk(" %2.2x", tp->rx_ring[RX_BUF_LEN + i]); + printk(".\n"); + break; + } +#endif + + for (i = 0; i < NUM_TX_DESC; i++) { + if (tp->tx_skbuff[i]) + dev_kfree_skb(tp->tx_skbuff[i]); + tp->tx_skbuff[i] = 0; + } + kfree(tp->rx_ring); + kfree(tp->tx_bufs); + + /* Green! Put the chip in low-power mode. */ + outb(0xC0, ioaddr + Cfg9346); + outb(0x03, ioaddr + Config1); + outb('H', ioaddr + HltClk); /* 'R' would leave the clock running. */ + + MOD_DEC_USE_COUNT; + + return 0; +} + +static struct enet_statistics * +rtl8129_get_stats(struct device *dev) +{ + struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; + int ioaddr = dev->base_addr; + + if (dev->start) { + tp->stats.rx_missed_errors += inl(ioaddr + RxMissed); + outl(0, ioaddr + RxMissed); + } + + return &tp->stats; +} + +/* Set or clear the multicast filter for this adaptor. + Note that we only use exclusion around actually queueing the + new frame, not around filling tp->setup_frame. This is non-deterministic + when re-entered but still correct. */ + +/* The little-endian AUTODIN II ethernet CRC calculation. + N.B. Do not use for bulk data, use a table-based routine instead. + This is common code and should be moved to net/core/crc.c */ +static unsigned const ethernet_polynomial_le = 0xedb88320U; +static inline unsigned ether_crc_le(int length, unsigned char *data) +{ + unsigned int crc = 0xffffffff; /* Initial value. */ + while(--length >= 0) { + unsigned char current_octet = *data++; + int bit; + for (bit = 8; --bit >= 0; current_octet >>= 1) { + if ((crc ^ current_octet) & 1) { + crc >>= 1; + crc ^= ethernet_polynomial_le; + } else + crc >>= 1; + } + } + return crc; +} + + +static void +#ifdef NEW_MULTICAST +set_rx_mode(struct device *dev) +#else +static void set_rx_mode(struct device *dev, int num_addrs, void *addrs); +#endif +{ + int ioaddr = dev->base_addr; + struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; + unsigned char mc_filter[8]; /* Multicast hash filter */ + int i; + + if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ + /* Unconditionally log net taps. */ + printk(KERN_NOTICE"%s: Promiscuous mode enabled.\n", dev->name); + memset(mc_filter, 0xff, sizeof(mc_filter)); + outb(0x0F, ioaddr + RxConfig); + } else if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) { + /* Too many to filter perfectly -- accept all multicasts. */ + memset(mc_filter, 0xff, sizeof(mc_filter)); + outb(0x0E, ioaddr + RxConfig); + } else if (dev->mc_count == 0) { + outb(0x0A, ioaddr + RxConfig); + return; + } else { + struct dev_mc_list *mclist; + + memset(mc_filter, 0, sizeof(mc_filter)); + for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + i++, mclist = mclist->next) + set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f, + mc_filter); + } + /* ToDo: perhaps we need to stop the Tx and Rx process here? */ + if (memcmp(mc_filter, tp->mc_filter, sizeof(mc_filter))) { + for (i = 0; i < 2; i++) + outl(((u32 *)mc_filter)[i], ioaddr + MAR0 + i*4); + memcpy(tp->mc_filter, mc_filter, sizeof(mc_filter)); + } + if (rtl8129_debug > 3) + printk(KERN_DEBUG"%s: set_rx_mode(%4.4x) done -- Rx config %8.8x.\n", + dev->name, dev->flags, inl(ioaddr + RxConfig)); + return; +} + +#ifdef MODULE + +/* An additional parameter that may be passed in... */ +static int debug = -1; + +int +init_module(void) +{ + int cards_found; + + if (debug >= 0) + rtl8129_debug = debug; + + root_rtl8129_dev = NULL; + cards_found = rtl8139_probe(0); + + return cards_found ? 0 : -ENODEV; +} + +void +cleanup_module(void) +{ + struct device *next_dev; + + /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ + while (root_rtl8129_dev) { + next_dev = ((struct rtl8129_private *)root_rtl8129_dev->priv)->next_module; + unregister_netdev(root_rtl8129_dev); + release_region(root_rtl8129_dev->base_addr, RTL8129_TOTAL_SIZE); + kfree(root_rtl8129_dev); + root_rtl8129_dev = next_dev; + } +} + +#endif /* MODULE */ + +/* + * Local variables: + * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c" + * c-indent-level: 4 + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff -u --recursive --new-file v2.1.100/linux/drivers/net/sgiseeq.c linux/drivers/net/sgiseeq.c --- v2.1.100/linux/drivers/net/sgiseeq.c Thu Feb 12 20:56:09 1998 +++ linux/drivers/net/sgiseeq.c Fri May 8 00:20:47 1998 @@ -1,7 +1,9 @@ -/* $Id: sgiseeq.c,v 1.3 1997/11/16 13:57:45 alan Exp $ +/* * sgiseeq.c: Seeq8003 ethernet driver for SGI machines. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: sgiseeq.c,v 1.5 1998/05/01 01:35:40 ralf Exp $ */ #include @@ -15,6 +17,7 @@ #include #include +#include #include #include #include @@ -173,7 +176,7 @@ buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL); ib->tx_desc[i].buf_vaddr = KSEG1ADDR(buffer); ib->tx_desc[i].tdma.pbuf = PHYSADDR(buffer); - flush_cache_all(); +// flush_cache_all(); } ib->tx_desc[i].tdma.cntinfo = (TCNTINFO_INIT); } @@ -186,7 +189,7 @@ buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL); ib->rx_desc[i].buf_vaddr = KSEG1ADDR(buffer); ib->rx_desc[i].rdma.pbuf = PHYSADDR(buffer); - flush_cache_all(); +// flush_cache_all(); } ib->rx_desc[i].rdma.cntinfo = (RCNTINFO_INIT); } @@ -351,6 +354,25 @@ } } +static inline void kick_tx(struct sgiseeq_tx_desc *td, + volatile struct hpc3_ethregs *hregs) +{ + /* If the HPC aint doin nothin, and there are more packets + * with ETXD cleared and XIU set we must make very certain + * that we restart the HPC else we risk locking up the + * adapter. The following code is only safe iff the HPCDMA + * is not active! + */ + while((td->tdma.cntinfo & (HPCDMA_XIU | HPCDMA_ETXD)) == + (HPCDMA_XIU | HPCDMA_ETXD)) + td = (struct sgiseeq_tx_desc *) + KSEG1ADDR(td->tdma.pnext); + if(td->tdma.cntinfo & HPCDMA_XIU) { + hregs->tx_ndptr = PHYSADDR(td); + hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE; + } +} + static inline void sgiseeq_tx(struct device *dev, struct sgiseeq_private *sp, volatile struct hpc3_ethregs *hregs, volatile struct sgiseeq_regs *sregs) @@ -361,32 +383,14 @@ tx_maybe_reset_collisions(sp, sregs); - if(!(status & HPC3_ETXCTRL_ACTIVE)) { - if(!(status & SEEQ_TSTAT_PTRANS)) { - /* Oops, HPC detected some sort of error. */ - if(status & SEEQ_TSTAT_R16) - sp->stats.tx_aborted_errors++; - if(status & SEEQ_TSTAT_UFLOW) - sp->stats.tx_fifo_errors++; - if(status & SEEQ_TSTAT_LCLS) - sp->stats.collisions++; - } - /* If the HPC aint doin nothin, and there are more packets - * with ETXD cleared and XIU set we must make very certain - * that we restart the HPC else we risk locking up the - * adapter. The following read of tx_ndptr is only safe - * iff the HPCDMA is not active! - */ - td = (struct sgiseeq_tx_desc *) - KSEG1ADDR(((hregs->tx_ndptr) & ~0xf)); - while((td->tdma.cntinfo & (HPCDMA_XIU | HPCDMA_ETXD)) == - (HPCDMA_XIU | HPCDMA_ETXD)) - td = (struct sgiseeq_tx_desc *) - KSEG1ADDR(td->tdma.pnext); - if(td->tdma.cntinfo & HPCDMA_XIU) { - hregs->tx_ndptr = PHYSADDR(td); - hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE; - } + if(!(status & (HPC3_ETXCTRL_ACTIVE | SEEQ_TSTAT_PTRANS))) { + /* Oops, HPC detected some sort of error. */ + if(status & SEEQ_TSTAT_R16) + sp->stats.tx_aborted_errors++; + if(status & SEEQ_TSTAT_UFLOW) + sp->stats.tx_fifo_errors++; + if(status & SEEQ_TSTAT_LCLS) + sp->stats.collisions++; } /* Ack 'em... */ @@ -395,8 +399,13 @@ if(!(td->tdma.cntinfo & (HPCDMA_XIU))) break; - if(!(td->tdma.cntinfo & (HPCDMA_ETXD))) + if(!(td->tdma.cntinfo & (HPCDMA_ETXD))) { + if(!(status & HPC3_ETXCTRL_ACTIVE)) { + hregs->tx_ndptr = PHYSADDR(td); + hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE; + } break; + } sp->stats.tx_packets++; sp->tx_old = NEXT_TX(sp->tx_old); td->tdma.cntinfo &= ~(HPCDMA_XIU | HPCDMA_XIE); @@ -501,13 +510,14 @@ /* Are we bolixed? */ if(dev->tbusy) { int tickssofar = jiffies - dev->trans_start; + if (tickssofar < 20) + return 1; printk("%s: transmit timed out, ticks=%d resetting\n", dev->name, tickssofar); sgiseeq_reset(dev); return 0; } - /* Are we getting in someone else's way? */ if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) { printk("%s: Transmitter access conflict.\n", dev->name); @@ -565,10 +575,9 @@ sp->tx_new = NEXT_TX(sp->tx_new); /* Advance. */ /* Maybe kick the HPC back into motion. */ - if(!(hregs->tx_ctrl & HPC3_ETXCTRL_ACTIVE)) { - hregs->tx_ndptr = PHYSADDR(&sp->srings.tx_desc[sp->tx_old]); - hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE; - } + if(!(hregs->tx_ctrl & HPC3_ETXCTRL_ACTIVE)) + kick_tx(&sp->srings.tx_desc[sp->tx_old], hregs); + dev->trans_start = jiffies; dev_kfree_skb(skb); @@ -656,15 +665,17 @@ sp->name = sgiseeqstr; sp->srings.rx_desc = (struct sgiseeq_rx_desc *) - (KSEG1ADDR(ALIGNED(&sp->srings.rxvector[0]))); + (KSEG1ADDR(ALIGNED(&sp->srings.rxvector[0]))); + dma_cache_wback_inv((unsigned long)&sp->srings.rxvector, + sizeof(sp->srings.rxvector)); sp->srings.tx_desc = (struct sgiseeq_tx_desc *) - (KSEG1ADDR(ALIGNED(&sp->srings.txvector[0]))); - flush_cache_all(); + (KSEG1ADDR(ALIGNED(&sp->srings.txvector[0]))); + dma_cache_wback_inv((unsigned long)&sp->srings.txvector, + sizeof(sp->srings.txvector)); /* A couple calculations now, saves many cycles later. */ setup_rx_ring(sp->srings.rx_desc, SEEQ_RX_BUFFERS); setup_tx_ring(sp->srings.tx_desc, SEEQ_TX_BUFFERS); - flush_cache_all(); /* Reset the chip. */ hpc3_eth_reset((volatile struct hpc3_ethregs *) hregs); diff -u --recursive --new-file v2.1.100/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c --- v2.1.100/linux/drivers/net/sunhme.c Thu Apr 23 20:21:33 1998 +++ linux/drivers/net/sunhme.c Fri May 8 00:20:47 1998 @@ -58,6 +58,70 @@ #undef SXDEBUG #undef RXDEBUG #undef TXDEBUG +#undef TXLOGGING + +#ifdef TXLOGGING +struct hme_tx_logent { + unsigned int tstamp; + int tx_new, tx_old; + unsigned int action; +#define TXLOG_ACTION_IRQ 0x01 +#define TXLOG_ACTION_TXMIT 0x02 +#define TXLOG_ACTION_TBUSY 0x04 +#define TXLOG_ACTION_NBUFS 0x08 + unsigned int status; +}; +#define TX_LOG_LEN 128 +static struct hme_tx_logent tx_log[TX_LOG_LEN]; +static int txlog_cur_entry = 0; +static __inline__ void tx_add_log(struct happy_meal *hp, unsigned int a, unsigned int s) +{ + struct hme_tx_logent *tlp; + unsigned long flags; + + save_and_cli(flags); + tlp = &tx_log[txlog_cur_entry]; + tlp->tstamp = (unsigned int)jiffies; + tlp->tx_new = hp->tx_new; + tlp->tx_old = hp->tx_old; + tlp->action = a; + tlp->status = s; + txlog_cur_entry = (txlog_cur_entry + 1) & (TX_LOG_LEN - 1); + restore_flags(flags); +} +static __inline__ void tx_dump_log(void) +{ + int i, this; + + this = txlog_cur_entry; + for(i = 0; i < TX_LOG_LEN; i++) { + printk("TXLOG[%d]: j[%08x] tx[N(%d)O(%d)] action[%08x] stat[%08x]\n", i, + tx_log[this].tstamp, + tx_log[this].tx_new, tx_log[this].tx_old, + tx_log[this].action, tx_log[this].status); + this = (this + 1) & (TX_LOG_LEN - 1); + } +} +static __inline__ void tx_dump_ring(struct happy_meal *hp) +{ + struct hmeal_init_block *hb = hp->happy_block; + struct happy_meal_txd *tp = &hb->happy_meal_txd[0]; + int i; + + for(i = 0; i < TX_RING_SIZE; i+=4) { + printk("TXD[%d..%d]: [%08x:%08x] [%08x:%08x] [%08x:%08x] [%08x:%08x]\n", + i, i + 4, + le32_to_cpu(tp[i].tx_flags), le32_to_cpu(tp[i].tx_addr), + le32_to_cpu(tp[i + 1].tx_flags), le32_to_cpu(tp[i + 1].tx_addr), + le32_to_cpu(tp[i + 2].tx_flags), le32_to_cpu(tp[i + 2].tx_addr), + le32_to_cpu(tp[i + 3].tx_flags), le32_to_cpu(tp[i + 3].tx_addr)); + } +} +#else +#define tx_add_log(hp, a, s) do { } while(0) +#define tx_dump_log() do { } while(0) +#define tx_dump_ring(hp) do { } while(0) +#endif #ifdef HMEDEBUG #define HMD(x) printk x @@ -73,7 +137,7 @@ #define ASD(x) #endif -#define DEFAULT_IPG0 32 /* For lance-mode only */ +#define DEFAULT_IPG0 16 /* For lance-mode only */ #define DEFAULT_IPG1 8 /* For all modes */ #define DEFAULT_IPG2 4 /* For all modes */ #define DEFAULT_JAMSIZE 4 /* Toe jam */ @@ -376,18 +440,33 @@ full = 0; } - /* XXX This may not be enough, we may need to reinit the entire - * XXX Happy Meal front end for this to work every time. + /* Before changing other bits in the tx_cfg register, and in + * general any of other the TX config registers too, you + * must: + * 1) Clear Enable + * 2) Poll with reads until that bit reads back as zero + * 3) Make TX configuration changes + * 4) Set Enable once more */ - if(full) + hme_write32(hp, &hp->bigmacregs->tx_cfg, + hme_read32(hp, &hp->bigmacregs->tx_cfg) & + ~(BIGMAC_TXCFG_ENABLE)); + while(hme_read32(hp, &hp->bigmacregs->tx_cfg) & BIGMAC_TXCFG_ENABLE) + barrier(); + if(full) { + hp->happy_flags |= HFLAG_FULL; hme_write32(hp, &hp->bigmacregs->tx_cfg, hme_read32(hp, &hp->bigmacregs->tx_cfg) | BIGMAC_TXCFG_FULLDPLX); - else + } else { + hp->happy_flags &= ~(HFLAG_FULL); hme_write32(hp, &hp->bigmacregs->tx_cfg, hme_read32(hp, &hp->bigmacregs->tx_cfg) & ~(BIGMAC_TXCFG_FULLDPLX)); - + } + hme_write32(hp, &hp->bigmacregs->tx_cfg, + hme_read32(hp, &hp->bigmacregs->tx_cfg) | + BIGMAC_TXCFG_ENABLE); return 0; no_response: return 1; @@ -1220,8 +1299,8 @@ /* Load up the MAC address and random seed. */ HMD(("rseed/macaddr, ")); - /* XXX use something less deterministic... */ - hme_write32(hp, &bregs->rand_seed, 0xbd); + /* The docs recommend to use the 10LSB of our MAC here. */ + hme_write32(hp, &bregs->rand_seed, ((e[5] | e[4]<<8)&0x3ff)); hme_write32(hp, &bregs->mac_addr2, ((e[4] << 8) | e[5])); hme_write32(hp, &bregs->mac_addr1, ((e[2] << 8) | e[3])); @@ -2013,7 +2092,7 @@ hp->dev->tbusy = 0; mark_bh(NET_BH); } - + tx_add_log(hp, TXLOG_ACTION_IRQ, happy_status); dev->interrupt = 0; HMD(("done\n")); } @@ -2154,29 +2233,29 @@ struct happy_meal *hp = (struct happy_meal *) dev->priv; int len, entry; - if(dev->tbusy) { + if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) { int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 40) { - return 1; - } else { + if (tickssofar >= 40) { printk ("%s: transmit timed out, resetting\n", dev->name); hp->net_stats.tx_errors++; + tx_dump_log(); + printk ("%s: Happy Status %08x TX[%08x:%08x]\n", dev->name, + hme_read32(hp, &hp->gregs->stat), + hme_read32(hp, &hp->etxregs->cfg), + hme_read32(hp, &hp->bigmacregs->tx_cfg)); happy_meal_init(hp, 0); dev->tbusy = 0; dev->trans_start = jiffies; - return 0; - } - } - - if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) { - printk("happy meal: Transmitter access conflict.\n"); + } else + tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_TBUSY, 0); return 1; } - if(!TX_BUFFS_AVAIL(hp)) + if(!TX_BUFFS_AVAIL(hp)) { + tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_NBUFS, 0); return 1; - + } len = skb->len; entry = hp->tx_new; @@ -2194,6 +2273,7 @@ if(TX_BUFFS_AVAIL(hp)) dev->tbusy = 0; + tx_add_log(hp, TXLOG_ACTION_TXMIT, 0); return 0; } @@ -2203,29 +2283,32 @@ struct happy_meal *hp = (struct happy_meal *) dev->priv; int len, entry; - if(dev->tbusy) { + if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) { int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 40) { - return 1; - } else { + if (tickssofar >= 40) { + unsigned long flags; + printk ("%s: transmit timed out, resetting\n", dev->name); + + save_and_cli(flags); + tx_dump_log(); + tx_dump_ring(hp); + restore_flags(flags); + hp->net_stats.tx_errors++; happy_meal_init(hp, 0); dev->tbusy = 0; dev->trans_start = jiffies; - return 0; - } - } - - if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) { - printk("happy meal: Transmitter access conflict.\n"); + } else + tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_TBUSY, 0); return 1; } - if(!TX_BUFFS_AVAIL(hp)) + if(!TX_BUFFS_AVAIL(hp)) { + tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_NBUFS, 0); return 1; - + } len = skb->len; entry = hp->tx_new; @@ -2243,6 +2326,7 @@ if(TX_BUFFS_AVAIL(hp)) dev->tbusy = 0; + tx_add_log(hp, TXLOG_ACTION_TXMIT, 0); return 0; } #endif @@ -2629,6 +2713,11 @@ pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_COMMAND, pci_command); + + /* Set the latency timer as well, PROM leaves it at zero. */ + pcibios_write_config_byte(pdev->bus->number, + pdev->devfn, + PCI_LATENCY_TIMER, 240); #ifdef MODULE /* We are home free at this point, link us in to the happy diff -u --recursive --new-file v2.1.100/linux/drivers/net/sunhme.h linux/drivers/net/sunhme.h --- v2.1.100/linux/drivers/net/sunhme.h Thu Sep 4 13:25:28 1997 +++ linux/drivers/net/sunhme.h Fri May 8 00:20:47 1998 @@ -468,9 +468,9 @@ (hp)->tx_old - (hp)->tx_new - 1) #define RX_OFFSET 2 -#define RX_BUF_ALLOC_SIZE (ETH_FRAME_LEN + RX_OFFSET + (64 * 3)) +#define RX_BUF_ALLOC_SIZE (1546 + RX_OFFSET + 64) -#define RX_COPY_THRESHOLD 128 +#define RX_COPY_THRESHOLD 256 struct hmeal_init_block { struct happy_meal_rxd happy_meal_rxd[RX_RING_MAXSIZE]; diff -u --recursive --new-file v2.1.100/linux/drivers/net/sunlance.c linux/drivers/net/sunlance.c --- v2.1.100/linux/drivers/net/sunlance.c Sat Apr 25 18:13:11 1998 +++ linux/drivers/net/sunlance.c Fri May 8 00:20:48 1998 @@ -1,4 +1,4 @@ -/* $Id: sunlance.c,v 1.74 1998/02/12 07:37:25 davem Exp $ +/* $Id: sunlance.c,v 1.75 1998/04/24 12:29:50 davem Exp $ * lance.c: Linux/Sparc/Lance driver * * Written 1995, 1996 by Miguel de Icaza diff -u --recursive --new-file v2.1.100/linux/drivers/net/sunqe.h linux/drivers/net/sunqe.h --- v2.1.100/linux/drivers/net/sunqe.h Mon Apr 14 16:28:12 1997 +++ linux/drivers/net/sunqe.h Fri May 8 00:20:48 1998 @@ -309,8 +309,8 @@ (qp)->tx_old - (qp)->tx_new - (TX_RING_SIZE - SUN4C_TX_RING_SIZE)) -#define RX_COPY_THRESHOLD 128 -#define RX_BUF_ALLOC_SIZE (ETH_FRAME_LEN + (64 * 3)) +#define RX_COPY_THRESHOLD 256 +#define RX_BUF_ALLOC_SIZE (1546 + 64) struct qe_init_block { struct qe_rxd qe_rxd[RX_RING_MAXSIZE]; diff -u --recursive --new-file v2.1.100/linux/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c --- v2.1.100/linux/drivers/net/yellowfin.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/yellowfin.c Fri May 8 00:20:48 1998 @@ -0,0 +1,1309 @@ +/* yellowfin.c: A Packet Engines G-NIC ethernet driver for linux. */ +/* + Written 1997 by Donald Becker. + + This software may be used and distributed according to the terms + of the GNU Public License, incorporated herein by reference. + + This driver is for the Packet Engines G-NIC PCI Gigabit Ethernet adapter. + + The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O + Center of Excellence in Space Data and Information Sciences + Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 + + Support and updates available at + http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html +*/ + +static const char *version = "yellowfin.c:v0.10 12/5/97 becker@cesdis.gsfc.nasa.gov\n"; + +/* A few user-configurable values. */ + +static int max_interrupt_work = 20; +static int min_pci_latency = 64; +static int mtu = 0; +#ifdef YF_PROTOTYPE /* Support for prototype hardware errata. */ +/* System-wide count of bogus-rx frames. */ +static int bogus_rx = 0; +static int dma_ctrl = 0x004A0263; /* Constrained by errata */ +static int fifo_cfg = 0x0020; /* Bypass external Tx FIFO. */ +#elif YF_NEW +static int dma_ctrl = 0x00CAC277; /* Override when loading module! */ +static int fifo_cfg = 0x0028; +#else +static int dma_ctrl = 0x004A0263; /* Constrained by errata */ +static int fifo_cfg = 0x0020; /* Bypass external Tx FIFO. */ +#endif + +/* Set the copy breakpoint for the copy-only-tiny-frames scheme. + Setting to > 1518 effectively disables this feature. */ +static const rx_copybreak = 100; + +/* Keep the ring sizes a power of two for efficiency. + Making the Tx ring too large decreases the effectiveness of channel + bonding and packet priority. + There are no ill effects from too-large receive rings. */ +#define TX_RING_SIZE 16 +#define RX_RING_SIZE 32 + +/* Operational parameters that usually are not changed. */ +/* Time in jiffies before concluding the transmitter is hung. */ +#define TX_TIMEOUT ((2000*HZ)/1000) + +#include +#ifdef MODULE +#ifdef MODVERSIONS +#include +#endif +#include +#include +#else +#define MOD_INC_USE_COUNT +#define MOD_DEC_USE_COUNT +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* Processor type for cache alignment. */ +#include +#include + +#include +#include +#include + +/* Kernel compatibility defines, common to David Hind's PCMCIA package. + This is only in the support-all-kernels source code. */ +#include /* Evil, but neccessary */ + +#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10300 +#define RUN_AT(x) (x) /* What to put in timer->expires. */ +#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC) +#define virt_to_bus(addr) ((unsigned long)addr) +#define bus_to_virt(addr) ((void*)addr) + +#else /* 1.3.0 and later */ +#define RUN_AT(x) (jiffies + (x)) +#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2) +#endif + +#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10338 +#ifdef MODULE +#if !defined(CONFIG_MODVERSIONS) && !defined(__NO_VERSION__) +char kernel_version[] = UTS_RELEASE; +#endif +#else +#undef MOD_INC_USE_COUNT +#define MOD_INC_USE_COUNT +#undef MOD_DEC_USE_COUNT +#define MOD_DEC_USE_COUNT +#endif +#endif /* 1.3.38 */ + +#if (LINUX_VERSION_CODE >= 0x10344) +#define NEW_MULTICAST +#include +#endif +#if (LINUX_VERSION_CODE >= 0x20100) +#ifdef MODULE +char kernel_version[] = UTS_RELEASE; +#endif +#endif +#ifdef SA_SHIRQ +#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs) +#else +#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs) +#endif +#if (LINUX_VERSION_CODE < 0x20123) +#define test_and_set_bit(val, addr) set_bit(val, addr) +#include +#endif + +static const char *card_name = "Yellowfin G-NIC Gbit Ethernet"; + +/* The PCI I/O space extent. */ +#define YELLOWFIN_TOTAL_SIZE 0x100 + +#ifdef HAVE_DEVLIST +struct netdev_entry yellowfin_drv = +{card_name, yellowfin_pci_probe, YELLOWFIN_TOTAL_SIZE, NULL}; +#endif + +#ifdef YELLOWFIN_DEBUG +int yellowfin_debug = YELLOWFIN_DEBUG; +#else +int yellowfin_debug = 1; +#endif + +/* + Theory of Operation + +I. Board Compatibility + +This device driver is designed for the Packet Engines "Yellowfin" Gigabit +Ethernet adapter. The only PCA currently supported is the G-NIC 64-bit +PCI card. + +II. Board-specific settings + +PCI bus devices are configured by the system at boot time, so no jumpers +need to be set on the board. The system BIOS preferably should assign the +PCI INTA signal to an otherwise unused system IRQ line. +Note: Kernel versions earlier than 1.3.73 do not support shared PCI +interrupt lines. + +III. Driver operation + +IIIa. Ring buffers + +The Yellowfin uses the Descriptor Based DMA Architecture specified by Apple. +This is a descriptor list scheme similar to that used by the EEPro100 and +Tulip. This driver uses two statically allocated fixed-size descriptor lists +formed into rings by a branch from the final descriptor to the beginning of +the list. The ring sizes are set at compile time by RX/TX_RING_SIZE. + +The driver allocates full frame size skbuffs for the Rx ring buffers at +open() time and passes the skb->data field to the Yellowfin as receive data +buffers. When an incoming frame is less than RX_COPYBREAK bytes long, +a fresh skbuff is allocated and the frame is copied to the new skbuff. +When the incoming frame is larger, the skbuff is passed directly up the +protocol stack and replaced by a newly allocated skbuff. + +The RX_COPYBREAK value is chosen to trade-off the memory wasted by +using a full-sized skbuff for small frames vs. the copying costs of larger +frames. For small frames the copying cost is negligible (esp. considering +that we are pre-loading the cache with immediately useful header +information). For large frames the copying cost is non-trivial, and the +larger copy might flush the cache of useful data. + +IIIC. Synchronization + +The driver runs as two independent, single-threaded flows of control. One +is the send-packet routine, which enforces single-threaded use by the +dev->tbusy flag. The other thread is the interrupt handler, which is single +threaded by the hardware and other software. + +The send packet thread has partial control over the Tx ring and 'dev->tbusy' +flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next +queue slot is empty, it clears the tbusy flag when finished otherwise it sets +the 'yp->tx_full' flag. + +The interrupt handler has exclusive control over the Rx ring and records stats +from the Tx ring. After reaping the stats, it marks the Tx queue entry as +empty by incrementing the dirty_tx mark. Iff the 'yp->tx_full' flag is set, it +clears both the tx_full and tbusy flags. + +IV. Notes + +Thanks to Kim Stearns of Packet Engines for providing a pair of G-NIC boards. + +IVb. References + +Yellowfin Engineering Design Specification, 4/23/97 Preliminary/Confidential +http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html + +IVc. Errata + +See Packet Engines confidential appendix. + +*/ + +/* A few values that may be tweaked. */ +#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ + +#ifndef PCI_VENDOR_ID_PKT_ENG /* To be defined in linux/pci.h */ +#define PCI_VENDOR_ID_PKT_ENG 0x1000 /* Hmm, likely number.. */ +#define PCI_DEVICE_ID_YELLOWFIN 0x0702 +#endif + +/* The rest of these values should never change. */ + +static void yellowfin_timer(unsigned long data); + +/* Offsets to the Yellowfin registers. Various sizes and alignments. */ +enum yellowfin_offsets { + TxCtrl=0x00, TxStatus=0x04, TxPtr=0x0C, + TxIntrSel=0x10, TxBranchSel=0x14, TxWaitSel=0x18, + RxCtrl=0x40, RxStatus=0x44, RxPtr=0x4C, + RxIntrSel=0x50, RxBranchSel=0x54, RxWaitSel=0x58, + EventStatus=0x80, IntrEnb=0x82, IntrClear=0x84, IntrStatus=0x86, + ChipRev=0x8C, DMACtrl=0x90, Cnfg=0xA0, RxDepth=0xB8, FlowCtrl=0xBC, + AddrMode=0xD0, StnAddr=0xD2, HashTbl=0xD8, FIFOcfg=0xF8, +}; + +/* The Yellowfin Rx and Tx buffer descriptors. */ +struct yellowfin_desc { + u16 request_cnt; + u16 cmd; + u32 addr; + u32 branch_addr; + u16 result_cnt; + u16 status; +}; + +struct tx_status_words { + u16 tx_cnt; + u16 tx_errs; + u16 total_tx_cnt; + u16 paused; +}; + +/* Bits in yellowfin_desc.cmd */ +enum desc_cmd_bits { + CMD_TX_PKT=0x1000, CMD_RX_BUF=0x2000, CMD_TXSTATUS=0x3000, + CMD_NOP=0x6000, CMD_STOP=0x7000, + BRANCH_ALWAYS=0x0C, INTR_ALWAYS=0x30, WAIT_ALWAYS=0x03, + BRANCH_IFTRUE=0x04, +}; + +/* Bits in yellowfin_desc.status */ +enum desc_status_bits { RX_EOP=0x0040, }; + +/* Bits in the interrupt status/mask registers. */ +enum intr_status_bits { + IntrRxDone=0x01, IntrRxInvalid=0x02, IntrRxPCIFault=0x04,IntrRxPCIErr=0x08, + IntrTxDone=0x10, IntrTxInvalid=0x20, IntrTxPCIFault=0x40,IntrTxPCIErr=0x80, + IntrEarlyRx=0x100, IntrWakeup=0x200, }; + +struct yellowfin_private { + /* Descriptor rings first for alignment. Tx requires a second descriptor + for status. */ + struct yellowfin_desc rx_ring[RX_RING_SIZE]; + struct yellowfin_desc tx_ring[TX_RING_SIZE*2]; + const char *product_name; + struct device *next_module; + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ + struct sk_buff* tx_skbuff[TX_RING_SIZE]; + struct tx_status_words tx_status[TX_RING_SIZE]; + /* The addresses of receive-in-place skbuffs. */ + struct sk_buff* rx_skbuff[RX_RING_SIZE]; + int chip_id; + struct enet_statistics stats; + struct timer_list timer; /* Media selection timer. */ + unsigned int cur_rx, cur_tx; /* The next free ring entry */ + unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ + unsigned int tx_full:1; /* The Tx queue is full. */ + unsigned int full_duplex:1; /* Full-duplex operation requested. */ + unsigned int medialock:1; /* Do not sense media. */ + unsigned int default_port:4; /* Last dev->if_port value. */ + u32 pad[4]; /* Used for 32-byte alignment */ +}; + +#ifdef MODULE +/* Used to pass the media type, etc. */ +#define MAX_UNITS 8 /* More are supported, limit only on options */ +static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; + +#if LINUX_VERSION_CODE > 0x20115 +MODULE_AUTHOR("Donald Becker "); +MODULE_DESCRIPTION("Packet Engines Yellowfin G-NIC Gigabit Ethernet driver"); +MODULE_PARM(max_interrupt_work, "i"); +MODULE_PARM(min_pci_latency, "i"); +MODULE_PARM(mtu, "i"); +MODULE_PARM(debug, "i"); +MODULE_PARM(rx_copybreak, "i"); +MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); +#endif + +#endif + +static struct device *yellowfin_probe1(struct device *dev, int ioaddr, int irq, + int chip_id, int options); +static int yellowfin_open(struct device *dev); +static void yellowfin_timer(unsigned long data); +static void yellowfin_tx_timeout(struct device *dev); +static void yellowfin_init_ring(struct device *dev); +static int yellowfin_start_xmit(struct sk_buff *skb, struct device *dev); +static int yellowfin_rx(struct device *dev); +static void yellowfin_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs); +static int yellowfin_close(struct device *dev); +static struct enet_statistics *yellowfin_get_stats(struct device *dev); +#ifdef NEW_MULTICAST +static void set_rx_mode(struct device *dev); +#else +static void set_rx_mode(struct device *dev, int num_addrs, void *addrs); +#endif + + + +#ifdef MODULE +/* A list of all installed Yellowfin devices, for removing the driver module. */ +static struct device *root_yellowfin_dev = NULL; +#endif + +int yellowfin_probe(struct device *dev) +{ + int cards_found = 0; + static int pci_index = 0; /* Static, for multiple probe calls. */ + + /* Ideally we would detect all network cards in slot order. That would + be best done a central PCI probe dispatch, which wouldn't work + well with the current structure. So instead we detect just the + Yellowfin cards in slot order. */ + + if (pci_present()) { + unsigned char pci_bus, pci_device_fn; + + for (;pci_index < 0xff; pci_index++) { +#if LINUX_VERSION_CODE >= 0x20155 + unsigned int pci_irq_line; + struct pci_dev *pdev; +#else + unsigned char pci_irq_line; +#endif + unsigned char pci_latency; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr, chip_idx = 0; + +#ifdef REVERSE_PROBE_ORDER + if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, + 0xfe - pci_index, + &pci_bus, &pci_device_fn) + != PCIBIOS_SUCCESSFUL) + continue; +#else + if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, + pci_index, + &pci_bus, &pci_device_fn) + != PCIBIOS_SUCCESSFUL) + break; +#endif + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_VENDOR_ID, &vendor); + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_DEVICE_ID, &device); +#if LINUX_VERSION_CODE >= 0x20155 + pdev = pci_find_slot(pci_bus, pci_device_fn); + pci_irq_line = pdev->irq; + pci_ioaddr = pdev->base_address[0]; +#else + pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_INTERRUPT_LINE, &pci_irq_line); + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_0, &pci_ioaddr); +#endif + /* Remove I/O space marker in bit 0. */ + pci_ioaddr &= ~3; + + if (vendor != PCI_VENDOR_ID_PKT_ENG) + continue; + + if (device != PCI_DEVICE_ID_YELLOWFIN) + continue; + + if (yellowfin_debug > 2) + printk("Found Packet Engines Yellowfin G-NIC at I/O %#x, IRQ %d.\n", + pci_ioaddr, pci_irq_line); + + if (check_region(pci_ioaddr, YELLOWFIN_TOTAL_SIZE)) + continue; + +#ifdef MODULE + dev = yellowfin_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx, + cards_found < MAX_UNITS ? options[cards_found] : 0); +#else + dev = yellowfin_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx, + dev ? dev->mem_start : 0); +#endif + + if (dev) { + /* Get and check the bus-master and latency values. */ + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_COMMAND, &pci_command); + if ( ! (pci_command & PCI_COMMAND_MASTER)) { + printk(" PCI Master Bit has not been set! Setting...\n"); + pci_command |= PCI_COMMAND_MASTER; + pcibios_write_config_word(pci_bus, pci_device_fn, + PCI_COMMAND, pci_command); + } + pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_LATENCY_TIMER, &pci_latency); + if (pci_latency < min_pci_latency) { + printk(" PCI latency timer (CFLT) is unreasonably low at %d." + " Setting to %d clocks.\n", + pci_latency, min_pci_latency); + pcibios_write_config_byte(pci_bus, pci_device_fn, + PCI_LATENCY_TIMER, min_pci_latency); + } else if (yellowfin_debug > 1) + printk(" PCI latency timer (CFLT) is %#x.\n", pci_latency); + dev = 0; + cards_found++; + } + } + } + +#if defined (MODULE) + return cards_found; +#else + return 0; +#endif +} + +static struct device *yellowfin_probe1(struct device *dev, int ioaddr, int irq, + int chip_id, int options) +{ + static int did_version = 0; /* Already printed version info. */ + struct yellowfin_private *yp; + int i; + + if (yellowfin_debug > 0 && did_version++ == 0) + printk(version); + + dev = init_etherdev(dev, sizeof(struct yellowfin_private)); + + printk("%s: P-E Yellowfin type %8x at %#3x, ", + dev->name, inl(ioaddr + ChipRev), ioaddr); + + for (i = 0; i < 5; i++) + printk("%2.2x:", inb(ioaddr + StnAddr + i)); + printk("%2.2x, IRQ %d.\n", inb(ioaddr + StnAddr + i), irq); + for (i = 0; i < 6; i++) + dev->dev_addr[i] = inb(ioaddr + StnAddr + i); + + /* Reset the chip. */ + outl(0x80000000, ioaddr + DMACtrl); + + + /* We do a request_region() only to register /proc/ioports info. */ + request_region(ioaddr, YELLOWFIN_TOTAL_SIZE, card_name); + + dev->base_addr = ioaddr; + dev->irq = irq; + + /* Make certain the descriptor lists are aligned. */ + yp = (void *)(((long)kmalloc(sizeof(*yp), GFP_KERNEL) + 31) & ~31); + memset(yp, 0, sizeof(*yp)); + dev->priv = yp; + +#ifdef MODULE + yp->next_module = root_yellowfin_dev; + root_yellowfin_dev = dev; +#endif + + yp->chip_id = chip_id; + + yp->full_duplex = 1; +#ifdef YELLOWFIN_DEFAULT_MEDIA + yp->default_port = YELLOWFIN_DEFAULT_MEDIA; +#endif +#ifdef YELLOWFIN_NO_MEDIA_SWITCH + yp->medialock = 1; +#endif + + /* The lower four bits are the media type. */ + if (options > 0) { + yp->full_duplex = (options & 16) ? 1 : 0; + yp->default_port = options & 15; + if (yp->default_port) + yp->medialock = 1; + } + + /* The Yellowfin-specific entries in the device structure. */ + dev->open = &yellowfin_open; + dev->hard_start_xmit = &yellowfin_start_xmit; + dev->stop = &yellowfin_close; + dev->get_stats = &yellowfin_get_stats; + dev->set_multicast_list = &set_rx_mode; + if (mtu) + dev->mtu = mtu; + + /* todo: Reset the xcvr interface and turn on heartbeat. */ + + return dev; +} + + +static int +yellowfin_open(struct device *dev) +{ + struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; + int ioaddr = dev->base_addr; + + /* Reset the chip. */ + outl(0x80000000, ioaddr + DMACtrl); + +#ifdef SA_SHIRQ + if (request_irq(dev->irq, &yellowfin_interrupt, SA_SHIRQ, + card_name, dev)) { + return -EAGAIN; + } +#else + if (irq2dev_map[dev->irq] != NULL + || (irq2dev_map[dev->irq] = dev) == NULL + || dev->irq == 0 + || request_irq(dev->irq, &yellowfin_interrupt, 0, card_name)) { + return -EAGAIN; + } +#endif + + if (yellowfin_debug > 1) + printk("%s: yellowfin_open() irq %d.\n", dev->name, dev->irq); + + MOD_INC_USE_COUNT; + + yellowfin_init_ring(dev); + + outl(virt_to_bus(yp->rx_ring), ioaddr + RxPtr); + outl(virt_to_bus(yp->tx_ring), ioaddr + TxPtr); + + /* Set up various condition 'select' registers. + There are no options here. */ + outl(0x00800080, ioaddr + TxIntrSel); /* Interrupt on Tx abort */ + outl(0x00800080, ioaddr + TxBranchSel); /* Branch on Tx abort */ + outl(0x00400040, ioaddr + TxWaitSel); /* Wait on Tx status */ + outl(0x00400040, ioaddr + RxIntrSel); /* Interrupt on Rx done */ + outl(0x00400040, ioaddr + RxBranchSel); /* Branch on Rx error */ + outl(0x00400040, ioaddr + RxWaitSel); /* Wait on Rx done */ + + /* Initialize other registers: with so many this eventually this will + converted to an offset/value list. */ + outl(dma_ctrl, ioaddr + DMACtrl); + outw(fifo_cfg, ioaddr + FIFOcfg); + /* Enable automatic generation of flow control frames, period 0xffff. */ + outl(0x0030FFFF, ioaddr + FlowCtrl); + + if (dev->if_port == 0) + dev->if_port = yp->default_port; + + dev->tbusy = 0; + dev->interrupt = 0; + + /* We are always in full-duplex mode with the current chip! */ + yp->full_duplex = 1; + + /* Setting the Rx mode will start the Rx process. */ + outw(0x01CD | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg); +#ifdef NEW_MULTICAST + set_rx_mode(dev); +#else + set_rx_mode(dev, 0, 0); +#endif + + dev->start = 1; + + /* Enable interrupts by setting the interrupt mask. */ + outw(0x81ff, ioaddr + IntrEnb); /* See enum intr_status_bits */ + outw(0x0000, ioaddr + EventStatus); /* Clear non-interrupting events */ + outl(0x80008000, ioaddr + RxCtrl); /* Start Rx and Tx channels. */ + outl(0x80008000, ioaddr + TxCtrl); + + if (yellowfin_debug > 2) { + printk("%s: Done yellowfin_open().\n", + dev->name); + } + /* Set the timer to check for link beat. */ + init_timer(&yp->timer); + yp->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */ + yp->timer.data = (unsigned long)dev; + yp->timer.function = &yellowfin_timer; /* timer handler */ + add_timer(&yp->timer); + + return 0; +} + +static void yellowfin_timer(unsigned long data) +{ + struct device *dev = (struct device *)data; + struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; + int ioaddr = dev->base_addr; + int next_tick = 0; + + if (yellowfin_debug > 3) { + printk("%s: Yellowfin timer tick, status %8.8x.\n", + dev->name, inl(ioaddr + IntrStatus)); + } + if (next_tick) { + yp->timer.expires = RUN_AT(next_tick); + add_timer(&yp->timer); + } +} + +static void yellowfin_tx_timeout(struct device *dev) +{ + struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; + int ioaddr = dev->base_addr; + int i; + + printk("%s: Yellowfin transmit timed out, status %8.8x, resetting...\n", + dev->name, inl(ioaddr)); + +#ifndef __alpha__ + printk(" Rx ring %8.8x: ", (int)yp->rx_ring); + for (i = 0; i < RX_RING_SIZE; i++) + printk(" %8.8x", (unsigned int)yp->rx_ring[i].status); + printk("\n Tx ring %8.8x: ", (int)yp->tx_ring); + for (i = 0; i < TX_RING_SIZE; i++) + printk(" %4.4x /%4.4x", yp->tx_status[i].tx_errs, yp->tx_ring[i].status); + printk("\n"); +#endif + + /* Perhaps we should reinitialize the hardware here. */ + dev->if_port = 0; + /* Stop and restart the chip's Tx processes . */ + + /* Trigger an immediate transmit demand. */ + + dev->trans_start = jiffies; + yp->stats.tx_errors++; + return; +} + + +/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ +static void +yellowfin_init_ring(struct device *dev) +{ + struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; + int i; + + yp->tx_full = 0; + yp->cur_rx = yp->cur_tx = 0; + yp->dirty_rx = yp->dirty_tx = 0; + + for (i = 0; i < RX_RING_SIZE; i++) { + struct sk_buff *skb; + int pkt_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); + + yp->rx_ring[i].request_cnt = pkt_buf_sz; + yp->rx_ring[i].cmd = CMD_RX_BUF | INTR_ALWAYS; + + skb = DEV_ALLOC_SKB(pkt_buf_sz); + skb_reserve(skb, 2); /* 16 byte align the IP header. */ + yp->rx_skbuff[i] = skb; + if (skb == NULL) + break; /* Bad news! */ + skb->dev = dev; /* Mark as being used by this device. */ +#if LINUX_VERSION_CODE > 0x10300 + yp->rx_ring[i].addr = virt_to_bus(skb->tail); +#else + yp->rx_ring[i].addr = virt_to_bus(skb->data); +#endif + yp->rx_ring[i].branch_addr = virt_to_bus(&yp->rx_ring[i+1]); + } + /* Mark the last entry as wrapping the ring. */ + yp->rx_ring[i-1].cmd = CMD_RX_BUF | INTR_ALWAYS | BRANCH_ALWAYS; + yp->rx_ring[i-1].branch_addr = virt_to_bus(&yp->rx_ring[0]); + +/*#define NO_TXSTATS*/ +#ifdef NO_TXSTATS + /* In this mode the Tx ring needs only a single descriptor. */ + for (i = 0; i < TX_RING_SIZE; i++) { + yp->tx_skbuff[i] = 0; + yp->tx_ring[i].cmd = CMD_STOP; + yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[i+1]); + } + yp->tx_ring[--i].cmd = CMD_STOP | BRANCH_ALWAYS; /* Wrap ring */ + yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[0]); +#else + /* Tx ring needs a pair of descriptors, the second for the status. */ + for (i = 0; i < TX_RING_SIZE*2; i++) { + yp->tx_skbuff[i/2] = 0; + yp->tx_ring[i].cmd = CMD_STOP; /* Branch on Tx error. */ + yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[i+1]); + i++; + yp->tx_ring[i].cmd = CMD_TXSTATUS; /* Interrupt, no wait. */ + yp->tx_ring[i].request_cnt = sizeof(yp->tx_status[i]); + yp->tx_ring[i].addr = virt_to_bus(&yp->tx_status[i/2]); + yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[i+1]); + } + /* Wrap ring */ + yp->tx_ring[--i].cmd = CMD_TXSTATUS | BRANCH_ALWAYS | INTR_ALWAYS; + yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[0]); +#endif +} + +static int +yellowfin_start_xmit(struct sk_buff *skb, struct device *dev) +{ + struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; + unsigned entry; + + /* Block a timer-based transmit from overlapping. This could better be + done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ + if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { + if (jiffies - dev->trans_start < TX_TIMEOUT) + return 1; + yellowfin_tx_timeout(dev); + return 1; + } + + /* Caution: the write order is important here, set the base address + with the "ownership" bits last. */ + + /* Calculate the next Tx descriptor entry. */ + entry = yp->cur_tx % TX_RING_SIZE; + + yp->tx_skbuff[entry] = skb; + +#ifdef NO_TXSTATS + yp->tx_ring[entry].request_cnt = skb->len; + yp->tx_ring[entry].addr = virt_to_bus(skb->data); + yp->tx_ring[entry].status = 0; + if (entry >= TX_RING_SIZE-1) { + yp->tx_ring[0].cmd = CMD_STOP; /* New stop command. */ + yp->tx_ring[TX_RING_SIZE-1].cmd = CMD_TX_PKT | BRANCH_ALWAYS; + } else { + yp->tx_ring[entry+1].cmd = CMD_STOP; /* New stop command. */ + yp->tx_ring[entry].cmd = CMD_TX_PKT | BRANCH_IFTRUE; + } + yp->cur_tx++; +#else + yp->tx_ring[entry<<1].request_cnt = skb->len; + yp->tx_ring[entry<<1].addr = virt_to_bus(skb->data); + /* The input_last (status-write) command is constant, but we must rewrite + the subsequent 'stop' command. */ + + yp->cur_tx++; + { + unsigned next_entry = yp->cur_tx % TX_RING_SIZE; + yp->tx_ring[next_entry<<1].cmd = CMD_STOP; + } + /* Final step -- overwrite the old 'stop' command. */ + + yp->tx_ring[entry<<1].cmd = + (entry % 6) == 0 ? CMD_TX_PKT | INTR_ALWAYS | BRANCH_IFTRUE : + CMD_TX_PKT | BRANCH_IFTRUE; +#endif + + /* Todo: explicitly flush cache lines here. */ + + /* Wake the potentially-idle transmit channel. */ + outl(0x10001000, dev->base_addr + TxCtrl); + + if (yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 1) + dev->tbusy = 0; /* Typical path */ + else + yp->tx_full = 1; + dev->trans_start = jiffies; + + if (yellowfin_debug > 4) { + printk("%s: Yellowfin transmit frame #%d queued in slot %d.\n", + dev->name, yp->cur_tx, entry); + } + return 0; +} + +/* The interrupt handler does all of the Rx thread work and cleans up + after the Tx thread. */ +static void yellowfin_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs) +{ +#ifdef SA_SHIRQ /* Use the now-standard shared IRQ implementation. */ + struct device *dev = (struct device *)dev_instance; +#else + struct device *dev = (struct device *)(irq2dev_map[irq]); +#endif + + struct yellowfin_private *lp; + int ioaddr, boguscnt = max_interrupt_work; + + if (dev == NULL) { + printk ("yellowfin_interrupt(): irq %d for unknown device.\n", irq); + return; + } + + ioaddr = dev->base_addr; + lp = (struct yellowfin_private *)dev->priv; + if (test_and_set_bit(0, (void*)&dev->interrupt)) { + printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name); + return; + } + + do { + u16 intr_status = inw(ioaddr + IntrClear); + unsigned dirty_tx = lp->dirty_tx; + + if (yellowfin_debug > 4) + printk("%s: Yellowfin interrupt, status %4.4x.\n", + dev->name, intr_status); + + if (intr_status == 0) + break; + + if (intr_status & (IntrRxDone | IntrEarlyRx)) + yellowfin_rx(dev); + +#ifdef NO_TXSTATS + for (; dirty_tx < lp->cur_tx; dirty_tx++) { + int entry = dirty_tx % TX_RING_SIZE; + if (lp->tx_ring[entry].status == 0) + break; + /* Free the original skb. */ + dev_kfree_skb(lp->tx_skbuff[entry]); + lp->tx_skbuff[entry] = 0; + lp->stats.tx_packets++; + } + if (lp->tx_full && dev->tbusy + && dirty_tx > lp->cur_tx - TX_RING_SIZE + 4) { + /* The ring is no longer full, clear tbusy. */ + lp->tx_full = 0; + dev->tbusy = 0; + mark_bh(NET_BH); + } + lp->dirty_tx = dirty_tx; +#else + if (intr_status & IntrTxDone + || lp->tx_status[dirty_tx % TX_RING_SIZE].tx_errs) { + + for (dirty_tx = lp->dirty_tx; dirty_tx < lp->cur_tx; dirty_tx++) { + /* Todo: optimize this. */ + int entry = dirty_tx % TX_RING_SIZE; + u16 tx_errs = lp->tx_status[entry].tx_errs; + + if (tx_errs == 0) + break; /* It still hasn't been Txed */ + if (tx_errs & 0xF8100000) { + /* There was an major error, log it. */ +#ifndef final_version + if (yellowfin_debug > 1) + printk("%s: Transmit error, Tx status %4.4x.\n", + dev->name, tx_errs); +#endif + lp->stats.tx_errors++; + if (tx_errs & 0xF800) lp->stats.tx_aborted_errors++; + if (tx_errs & 0x0800) lp->stats.tx_carrier_errors++; + if (tx_errs & 0x2000) lp->stats.tx_window_errors++; + if (tx_errs & 0x8000) lp->stats.tx_fifo_errors++; +#ifdef ETHER_STATS + if (tx_errs & 0x1000) lp->stats.collisions16++; +#endif + } else { +#ifdef ETHER_STATS + if (status & 0x0400) lp->stats.tx_deferred++; +#endif + lp->stats.collisions += tx_errs & 15; + lp->stats.tx_packets++; + } + + /* Free the original skb. */ + dev_kfree_skb(lp->tx_skbuff[entry]); + lp->tx_skbuff[entry] = 0; + /* Mark status as empty. */ + lp->tx_status[entry].tx_errs = 0; + } + +#ifndef final_version + if (lp->cur_tx - dirty_tx > TX_RING_SIZE) { + printk("%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", + dev->name, dirty_tx, lp->cur_tx, lp->tx_full); + dirty_tx += TX_RING_SIZE; + } +#endif + + if (lp->tx_full && dev->tbusy + && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { + /* The ring is no longer full, clear tbusy. */ + lp->tx_full = 0; + dev->tbusy = 0; + mark_bh(NET_BH); + } + + lp->dirty_tx = dirty_tx; + } +#endif + + /* Log errors and other events. */ + if (intr_status & 0x2ee) { /* Abnormal error summary. */ + printk("%s: Something Wicked happened! %4.4x.\n", + dev->name, intr_status); + /* Hmmmmm, it's not clear what to do here. */ + if (intr_status & (IntrTxPCIErr | IntrTxPCIFault)) + lp->stats.tx_errors++; + if (intr_status & (IntrRxPCIErr | IntrRxPCIFault)) + lp->stats.rx_errors++; + } + if (--boguscnt < 0) { + printk("%s: Too much work at interrupt, status=0x%4.4x.\n", + dev->name, intr_status); + break; + } + } while (1); + + if (yellowfin_debug > 3) + printk("%s: exiting interrupt, status=%#4.4x.\n", + dev->name, inw(ioaddr + IntrStatus)); + + /* Code that should never be run! Perhaps remove after testing.. */ + { + static int stopit = 10; + if (dev->start == 0 && --stopit < 0) { + printk("%s: Emergency stop, looping startup interrupt.\n", + dev->name); +#ifdef SA_SHIRQ + free_irq(irq, dev); +#else + free_irq(irq); +#endif + } + } + + dev->interrupt = 0; + return; +} + +/* This routine is logically part of the interrupt handler, but seperated + for clarity and better register allocation. */ +static int +yellowfin_rx(struct device *dev) +{ + struct yellowfin_private *lp = (struct yellowfin_private *)dev->priv; + struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; + int entry = lp->cur_rx % RX_RING_SIZE; + int boguscnt = 20; + + if (yellowfin_debug > 4) { + printk(" In yellowfin_rx(), entry %d status %4.4x.\n", entry, + yp->rx_ring[entry].status); + printk(" #%d desc. %4.4x %4.4x %8.8x %4.4x %4.4x.\n", + entry, yp->rx_ring[entry].cmd, + yp->rx_ring[entry].request_cnt, yp->rx_ring[entry].addr, + yp->rx_ring[entry].result_cnt, yp->rx_ring[entry].status); + } + + + /* If EOP is set on the next entry, it's a new packet. Send it up. */ + while (yp->rx_ring[entry].status) { + /* Todo: optimize this mess. */ + u16 desc_status = yp->rx_ring[entry].status; + struct yellowfin_desc *desc = &lp->rx_ring[entry]; + int frm_size = desc->request_cnt - desc->result_cnt; + u8 *buf_addr = bus_to_virt(lp->rx_ring[entry].addr); + s16 frame_status = *(s16*)&(buf_addr[frm_size - 2]); + + if (yellowfin_debug > 4) + printk(" yellowfin_rx() status was %4.4x.\n", frame_status); + if (--boguscnt < 0) + break; + if ( ! (desc_status & RX_EOP)) { + printk("%s: Oversized Ethernet frame spanned multiple buffers," + " status %4.4x!\n", dev->name, desc_status); + lp->stats.rx_length_errors++; + } else if (frame_status & 0x0038) { + /* There was a error. */ + if (yellowfin_debug > 3) + printk(" yellowfin_rx() Rx error was %4.4x.\n", frame_status); + lp->stats.rx_errors++; + if (frame_status & 0x0060) lp->stats.rx_length_errors++; + if (frame_status & 0x0008) lp->stats.rx_frame_errors++; + if (frame_status & 0x0010) lp->stats.rx_crc_errors++; + if (frame_status < 0) lp->stats.rx_dropped++; +#ifdef YF_PROTOTYPE /* Support for prototype hardware errata. */ + } else if (memcmp(bus_to_virt(lp->rx_ring[entry].addr), + dev->dev_addr, 6) != 0 + && memcmp(bus_to_virt(lp->rx_ring[entry].addr), + "\0377\0377\0377\0377\0377\0377", 6) != 0) { + printk("%s: Bad frame to %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", + dev->name, + ((char *)bus_to_virt(lp->rx_ring[entry].addr))[0], + ((char *)bus_to_virt(lp->rx_ring[entry].addr))[1], + ((char *)bus_to_virt(lp->rx_ring[entry].addr))[2], + ((char *)bus_to_virt(lp->rx_ring[entry].addr))[3], + ((char *)bus_to_virt(lp->rx_ring[entry].addr))[4], + ((char *)bus_to_virt(lp->rx_ring[entry].addr))[5]); + bogus_rx++; +#endif + } else { + u8 bogus_cnt = buf_addr[frm_size - 8]; + short pkt_len = frm_size - 8 - bogus_cnt; + struct sk_buff *skb; + int rx_in_place = 0; + + /* Check if the packet is long enough to just accept without + copying to a properly sized skbuff. */ + if (pkt_len > rx_copybreak) { + struct sk_buff *newskb; + char *temp; + + /* Get a fresh skbuff to replace the filled one. */ + newskb = DEV_ALLOC_SKB(dev->mtu <= 1500 ? PKT_BUF_SZ + : dev->mtu + 32); + if (newskb == NULL) { + skb = 0; /* No memory, drop the packet. */ + goto memory_squeeze; + } + /* Pass up the skb already on the Rx ring. */ + skb = lp->rx_skbuff[entry]; + temp = skb_put(skb, pkt_len); + if (bus_to_virt(lp->rx_ring[entry].addr) != temp) + printk("%s: Warning -- the skbuff addresses do not match" + " in yellowfin_rx: %p vs. %p / %p.\n", dev->name, + bus_to_virt(lp->rx_ring[entry].addr), + skb->head, temp); + rx_in_place = 1; + lp->rx_skbuff[entry] = newskb; + newskb->dev = dev; + skb_reserve(newskb, 2); /* 16 byte align IP header */ + lp->rx_ring[entry].addr = virt_to_bus(newskb->tail); + } else + skb = DEV_ALLOC_SKB(pkt_len + 2); + memory_squeeze: + if (skb == NULL) { + printk("%s: Memory squeeze, deferring packet.\n", dev->name); + /* todo: Check that at least two ring entries are free. + If not, free one and mark stats->rx_dropped++. */ + break; + } + skb->dev = dev; + if (! rx_in_place) { + skb_reserve(skb, 2); /* 16 byte align the data fields */ + memcpy(skb_put(skb, pkt_len), + bus_to_virt(lp->rx_ring[entry].addr), pkt_len); + } +#if LINUX_VERSION_CODE > 0x10300 + skb->protocol = eth_type_trans(skb, dev); +#else + skb->len = pkt_len; +#endif + netif_rx(skb); + lp->stats.rx_packets++; + } + + /* Mark this entry as being the end-of-list, and the prior entry + as now valid. */ + lp->rx_ring[entry].cmd = CMD_STOP; + yp->rx_ring[entry].status = 0; + { + int prev_entry = entry - 1; + if (prev_entry < 0) + lp->rx_ring[RX_RING_SIZE - 1].cmd = + CMD_RX_BUF | INTR_ALWAYS | BRANCH_ALWAYS; + else + lp->rx_ring[prev_entry].cmd = CMD_RX_BUF | INTR_ALWAYS; + } + entry = (++lp->cur_rx) % RX_RING_SIZE; + } + /* todo: restart Rx engine if stopped. For now we just make the Rx ring + large enough to avoid this. */ + + return 0; +} + +static int +yellowfin_close(struct device *dev) +{ + int ioaddr = dev->base_addr; + struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; + int i; + + dev->start = 0; + dev->tbusy = 1; + + if (yellowfin_debug > 1) { + printk("%s: Shutting down ethercard, status was Tx %4.4x Rx %4.4x Int %2.2x.\n", + dev->name, inw(ioaddr + TxStatus), + inw(ioaddr + RxStatus), inl(ioaddr + IntrStatus)); + printk("%s: Queue pointers were Tx %d / %d, Rx %d / %d.\n", + dev->name, yp->cur_tx, yp->dirty_tx, yp->cur_rx, yp->dirty_rx); + } + + /* Disable interrupts by clearing the interrupt mask. */ + outw(0x0000, ioaddr + IntrEnb); + + /* Stop the chip's Tx and Rx processes. */ + outl(0x80000000, ioaddr + RxCtrl); + outl(0x80000000, ioaddr + TxCtrl); + + del_timer(&yp->timer); + + if (yellowfin_debug > 2) { + printk("\n Tx ring at %8.8x:\n", (int)virt_to_bus(yp->tx_ring)); + for (i = 0; i < TX_RING_SIZE*2; i++) + printk(" %c #%d desc. %4.4x %4.4x %8.8x %8.8x %4.4x %4.4x.\n", + inl(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ', + i, yp->tx_ring[i].cmd, + yp->tx_ring[i].request_cnt, yp->tx_ring[i].addr, + yp->tx_ring[i].branch_addr, + yp->tx_ring[i].result_cnt, yp->tx_ring[i].status); + printk(" Tx status %p:\n", yp->tx_status); + for (i = 0; i < TX_RING_SIZE; i++) + printk(" #%d status %4.4x %4.4x %4.4x %4.4x.\n", + i, yp->tx_status[i].tx_cnt, yp->tx_status[i].tx_errs, + yp->tx_status[i].total_tx_cnt, yp->tx_status[i].paused); + + printk("\n Rx ring %8.8x:\n", (int)virt_to_bus(yp->rx_ring)); + for (i = 0; i < RX_RING_SIZE; i++) { + printk(" %c #%d desc. %4.4x %4.4x %8.8x %4.4x %4.4x\n", + inl(ioaddr + RxPtr) == (long)&yp->rx_ring[i] ? '>' : ' ', + i, yp->rx_ring[i].cmd, + yp->rx_ring[i].request_cnt, yp->rx_ring[i].addr, + yp->rx_ring[i].result_cnt, yp->rx_ring[i].status); + if (yellowfin_debug > 5) { + if (*(u8*)yp->rx_ring[i].addr != 0x69) { + int j; + for (j = 0; j < 0x50; j++) + printk(" %4.4x", ((u16*)yp->rx_ring[i].addr)[j]); + printk("\n"); + } + } + } + } + +#ifdef SA_SHIRQ + free_irq(dev->irq, dev); +#else + free_irq(dev->irq); + irq2dev_map[dev->irq] = 0; +#endif + + /* Free all the skbuffs in the Rx queue. */ + for (i = 0; i < RX_RING_SIZE; i++) { + yp->rx_ring[i].cmd = CMD_STOP; + yp->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */ + if (yp->rx_skbuff[i]) { +#if LINUX_VERSION_CODE < 0x20100 + yp->rx_skbuff[i]->free = 1; +#endif + dev_kfree_skb(yp->rx_skbuff[i]); + } + yp->rx_skbuff[i] = 0; + } + for (i = 0; i < TX_RING_SIZE; i++) { + if (yp->tx_skbuff[i]) + dev_kfree_skb(yp->tx_skbuff[i]); + yp->tx_skbuff[i] = 0; + } + +#ifdef YF_PROTOTYPE /* Support for prototype hardware errata. */ + if (yellowfin_debug > 0) { + printk("%s: Received %d frames that we should not have.\n", + dev->name, bogus_rx); + } +#endif + MOD_DEC_USE_COUNT; + + return 0; +} + +static struct enet_statistics * +yellowfin_get_stats(struct device *dev) +{ + struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; + return &yp->stats; +} + +/* Set or clear the multicast filter for this adaptor. */ + +/* The little-endian AUTODIN32 ethernet CRC calculation. + N.B. Do not use for bulk data, use a table-based routine instead. + This is common code and should be moved to net/core/crc.c */ +static unsigned const ethernet_polynomial_le = 0xedb88320U; +static inline unsigned ether_crc_le(int length, unsigned char *data) +{ + unsigned int crc = 0xffffffff; /* Initial value. */ + while(--length >= 0) { + unsigned char current_octet = *data++; + int bit; + for (bit = 8; --bit >= 0; current_octet >>= 1) { + if ((crc ^ current_octet) & 1) { + crc >>= 1; + crc ^= ethernet_polynomial_le; + } else + crc >>= 1; + } + } + return crc; +} + + +static void +#ifdef NEW_MULTICAST +set_rx_mode(struct device *dev) +#else +static void set_rx_mode(struct device *dev, int num_addrs, void *addrs); +#endif +{ + int ioaddr = dev->base_addr; + u16 cfg_value = inw(ioaddr + Cnfg); + + /* Stop the Rx process to change any value. */ + outw(cfg_value & ~0x1000, ioaddr + Cnfg); + if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ + /* Unconditionally log net taps. */ + printk("%s: Promiscuous mode enabled.\n", dev->name); + outw(0x000F, ioaddr + AddrMode); + } else if ((dev->mc_count > 64) || (dev->flags & IFF_ALLMULTI)) { + /* Too many to filter well, or accept all multicasts. */ + printk("%s: Set all-multicast mode.\n", dev->name); + outw(0x000B, ioaddr + AddrMode); + } else if (dev->mc_count > 0) { /* Must use the multicast hash table. */ + struct dev_mc_list *mclist; + u16 hash_table[4]; + int i; + memset(hash_table, 0, sizeof(hash_table)); + for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + i++, mclist = mclist->next) { + /* Due to a bug in the early chip versions, multiple filter + slots must be set for each address. */ + set_bit((ether_crc_le(3, mclist->dmi_addr) >> 3) & 0x3f, + hash_table); + set_bit((ether_crc_le(4, mclist->dmi_addr) >> 3) & 0x3f, + hash_table); + set_bit((ether_crc_le(5, mclist->dmi_addr) >> 3) & 0x3f, + hash_table); + set_bit((ether_crc_le(6, mclist->dmi_addr) >> 3) & 0x3f, + hash_table); + } + /* Copy the hash table to the chip. */ + for (i = 0; i < 4; i++) + outw(hash_table[i], ioaddr + HashTbl + i*2); + printk("%s: Set multicast mode.\n", dev->name); + outw(0x0003, ioaddr + AddrMode); + } else { /* Normal, unicast/broadcast-only mode. */ + printk("%s: Set unicast mode.\n", dev->name); + outw(0x0001, ioaddr + AddrMode); + } + /* Restart the Rx process. */ + outw(cfg_value | 0x1000, ioaddr + Cnfg); +} + +#ifdef MODULE + +/* An additional parameter that may be passed in... */ +static int debug = -1; + +int +init_module(void) +{ + int cards_found; + + if (debug >= 0) + yellowfin_debug = debug; + + root_yellowfin_dev = NULL; + cards_found = yellowfin_probe(0); + + return cards_found ? 0 : -ENODEV; +} + +void +cleanup_module(void) +{ + struct device *next_dev; + + /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ + while (root_yellowfin_dev) { + next_dev = ((struct yellowfin_private *)root_yellowfin_dev->priv)->next_module; + unregister_netdev(root_yellowfin_dev); + release_region(root_yellowfin_dev->base_addr, YELLOWFIN_TOTAL_SIZE); + kfree(root_yellowfin_dev); + root_yellowfin_dev = next_dev; + } +} + +#endif /* MODULE */ + +/* + * Local variables: + * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c yellowfin.c" + * c-indent-level: 4 + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/audio/amd7930.c linux/drivers/sbus/audio/amd7930.c --- v2.1.100/linux/drivers/sbus/audio/amd7930.c Mon Feb 23 18:12:06 1998 +++ linux/drivers/sbus/audio/amd7930.c Fri May 8 00:23:41 1998 @@ -29,7 +29,7 @@ #include #include -#include "audio.h" +#include #include "amd7930.h" #define MAX_DRIVERS 1 @@ -342,7 +342,6 @@ static void transceive_Dchannel(struct amd7930_info *info) { __u8 dummy; - int lbrp=0; /* Last Byte of Received Packet (LBRP) */ #define D_XMIT_ERRORS (AMR_DER_COLLISION | AMR_DER_UNRN) #define D_RECV_ERRORS (AMR_DER_RABRT | AMR_DER_RFRAME | AMR_DER_FCS | \ @@ -433,7 +432,7 @@ channel->output_count = 0; if (channel->output_callback) (*channel->output_callback) - (channel->output_callback_arg); + (channel->output_callback_arg,1); } } else { *io_reg = channel->xmit_idle_char; @@ -631,9 +630,9 @@ static void amd7930_sunaudio_getdev(struct sparcaudio_driver *drv, audio_device_t * audinfo) { - strncpy(audinfo->name, "amd7930", sizeof(audinfo->name) - 1); - strncpy(audinfo->version, "x", sizeof(audinfo->version) - 1); - strncpy(audinfo->config, "audio", sizeof(audinfo->config) - 1); + strncpy(audinfo->name, "SUNW,am79c30", sizeof(audinfo->name) - 1); + strncpy(audinfo->version, "a", sizeof(audinfo->version) - 1); + strncpy(audinfo->config, "onboard1", sizeof(audinfo->config) - 1); } static int amd7930_sunaudio_getdev_sunos(struct sparcaudio_driver *drv) diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c --- v2.1.100/linux/drivers/sbus/audio/audio.c Mon Jan 12 15:15:45 1998 +++ linux/drivers/sbus/audio/audio.c Fri May 8 00:23:41 1998 @@ -2,6 +2,12 @@ * drivers/sbus/audio/audio.c * * Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu) + * Copyright (C) 1997 Derrick J. Brashear (shadow@dementia.org) + * Copyright (C) 1997 Brent Baccala (baccala@freesoft.org) + * + * Mixer code adapted from code contributed by and + * Copyright (C) 1998 Michael Mraka (michael@fi.muni.cz) + * * * This is the audio midlayer that sits between the VFS character * devices and the low-level audio hardware device drivers. @@ -22,7 +28,7 @@ #include #include -#include "audio.h" +#include /* @@ -58,6 +64,7 @@ */ drv->num_output_buffers = 32; + drv->playing_count = 0; drv->output_front = 0; drv->output_rear = 0; drv->output_count = 0; @@ -74,6 +81,7 @@ /* Setup the circular queue of input buffers. */ drv->num_input_buffers = 32; + drv->recording_count = 0; drv->input_front = 0; drv->input_rear = 0; drv->input_count = 0; @@ -143,28 +151,25 @@ return 0; } -static void sparcaudio_output_done_task(void * arg) +void sparcaudio_output_done(struct sparcaudio_driver * drv, int reclaim) { - struct sparcaudio_driver *drv = (struct sparcaudio_driver *)arg; - unsigned long flags; + /* Reclaim a buffer unless it's still in the DMA pipe */ + if (reclaim) { + if (drv->output_count > 0) + drv->output_count--; + else + if (drv->playing_count > 0) + drv->playing_count--; + } else + drv->playing_count++; - save_and_cli(flags); - drv->ops->start_output(drv, - drv->output_buffers[drv->output_front], - drv->output_sizes[drv->output_front]); - drv->output_active = 1; - restore_flags(flags); -} - -void sparcaudio_output_done(struct sparcaudio_driver * drv) -{ /* Point the queue after the "done" buffer. */ drv->output_size -= drv->output_sizes[drv->output_front]; drv->output_front = (drv->output_front + 1) % drv->num_output_buffers; - drv->output_count--; /* If the output queue is empty, shutdown the driver. */ if (drv->output_count == 0) { + if (drv->playing_count == 0) { /* Stop the lowlevel driver from outputing. */ drv->ops->stop_output(drv); drv->output_active = 0; @@ -173,19 +178,16 @@ wake_up_interruptible(&drv->output_write_wait); wake_up_interruptible(&drv->output_drain_wait); return; + } } - /* Otherwise, queue a task to give the driver the next buffer. */ - drv->tqueue.next = NULL; - drv->tqueue.sync = 0; - drv->tqueue.routine = sparcaudio_output_done_task; - drv->tqueue.data = drv; - - queue_task(&drv->tqueue, &tq_immediate); - mark_bh(IMMEDIATE_BH); - - /* Wake up any tasks that are waiting. */ - wake_up_interruptible(&drv->output_write_wait); + /* If we got back a buffer, see if anyone wants to write to it */ + if (reclaim || ((drv->output_count + drv->playing_count) + < drv->num_output_buffers)) + wake_up_interruptible(&drv->output_write_wait); + + drv->ops->start_output(drv, drv->output_buffers[drv->output_front], + drv->output_sizes[drv->output_front]); } void sparcaudio_input_done(struct sparcaudio_driver * drv) @@ -263,7 +265,7 @@ /* If the low-level driver is not active, activate it. */ save_and_cli(flags); - if (! driver->output_active) { + if ((!driver->output_active) && (driver->output_count > 0)) { driver->ops->start_output(driver, driver->output_buffers[driver->output_front], driver->output_sizes[driver->output_front]); @@ -277,59 +279,184 @@ { int bytes_written = 0, bytes_to_copy; - /* Ensure that we have something to write. */ - if (count < 1) { - sparcaudio_sync_output(driver); - return 0; - } + if (! file->f_mode & FMODE_WRITE) + return -EINVAL; /* Loop until all output is written to device. */ while (count > 0) { - /* Check to make sure that an output buffer is available. */ - /* If not, make valiant attempt */ - if (driver->output_count == driver->num_output_buffers) - sparcaudio_reorganize_buffers(driver); - - if (driver->output_count == driver->num_output_buffers) { - /* We need buffers, so... */ - sparcaudio_sync_output(driver); - interruptible_sleep_on(&driver->output_write_wait); - if (signal_pending(current)) - return bytes_written > 0 ? bytes_written : -EINTR; + /* Check to make sure that an output buffer is available. */ + /* If not, make valiant attempt */ + if (driver->num_output_buffers == + (driver->output_count + driver->playing_count)) + sparcaudio_reorganize_buffers(driver); + + if (driver->num_output_buffers == + (driver->output_count + driver->playing_count)) { + /* We need buffers, so... */ + sparcaudio_sync_output(driver); + interruptible_sleep_on(&driver->output_write_wait); + if (signal_pending(current)) + return bytes_written > 0 ? bytes_written : -EINTR; } - /* Determine how much we can copy in this iteration. */ - bytes_to_copy = count; - if (bytes_to_copy > PAGE_SIZE) - bytes_to_copy = PAGE_SIZE; + /* No buffers were freed. Go back to sleep */ + if (driver->num_output_buffers == + (driver->output_count + driver->playing_count)) + continue; + + /* Determine how much we can copy in this iteration. */ + bytes_to_copy = count; + if (bytes_to_copy > PAGE_SIZE) + bytes_to_copy = PAGE_SIZE; - copy_from_user_ret(driver->output_buffers[driver->output_rear], + copy_from_user_ret(driver->output_buffers[driver->output_rear], buf, bytes_to_copy, -EFAULT); - /* Update the queue pointers. */ - buf += bytes_to_copy; - count -= bytes_to_copy; - bytes_written += bytes_to_copy; - driver->output_sizes[driver->output_rear] = bytes_to_copy; - driver->output_rear = (driver->output_rear + 1) % driver->num_output_buffers; - driver->output_count++; - driver->output_size += bytes_to_copy; - - /* Activate the driver if more than page of data is waiting. */ - if (driver->output_size > 4096) - sparcaudio_sync_output(driver); + /* Update the queue pointers. */ + buf += bytes_to_copy; + count -= bytes_to_copy; + bytes_written += bytes_to_copy; + driver->output_sizes[driver->output_rear] = bytes_to_copy; + driver->output_rear = (driver->output_rear + 1) % driver->num_output_buffers; + driver->output_count++; + driver->output_size += bytes_to_copy; } + sparcaudio_sync_output(driver); /* Return the number of bytes written to the caller. */ return bytes_written; } +#define COPY_IN(arg, get) get_user(get, (int *)arg) +#define COPY_OUT(arg, ret) put_user(ret, (int *)arg) + +/* Add these in as new devices are supported. Belongs in audioio.h, actually */ +#define SUPPORTED_MIXER_DEVICES (SOUND_MASK_VOLUME) +#define MONO_DEVICES (SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_SPEAKER | SOUND_MASK_MIC) + +static inline int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) +{ + int i = 0, j = 0; + if (_IOC_DIR(cmd) & _IOC_WRITE) { + /* For any missing routines, pretend we changed things anyhow for now */ + switch (cmd & 0xff) { + case SOUND_MIXER_VOLUME: + if (driver->ops->get_output_channels) + j = driver->ops->get_output_channels(driver); + COPY_IN(arg, i); + if (j == 1) { + i = s_to_m(i); + if (driver->ops->set_output_volume) + driver->ops->set_output_volume(driver, i * 255/100); + if (driver->ops->get_output_volume) + i = driver->ops->get_output_volume(driver); + i = m_to_s(i); + } else { + /* there should be stuff here which calculates balance and + volume on a stereo device. will do it eventually */ + i = s_to_g(i); + if (driver->ops->set_output_volume) + driver->ops->set_output_volume(driver, i * 255/100); + if (driver->ops->get_output_volume) + i = driver->ops->get_output_volume(driver); + j = s_to_b(i); + if (driver->ops->set_output_balance) + driver->ops->set_output_balance(driver, j); + if (driver->ops->get_output_balance) + j = driver->ops->get_output_balance(driver); + i = b_to_s(i,j); + } + return COPY_OUT(arg, i); + default: + /* Play like we support other things */ + return COPY_OUT(arg, i); + } + } else { + switch (cmd & 0xff) { + case SOUND_MIXER_RECSRC: + if (driver->ops->get_input_port) + i = driver->ops->get_input_port(driver); + /* only one should ever be selected */ + if (i & AUDIO_ANALOG_LOOPBACK) j = SOUND_MASK_IMIX; /* ? */ + if (i & AUDIO_CD) j = SOUND_MASK_CD; + if (i & AUDIO_LINE_IN) j = SOUND_MASK_LINE; + if (i & AUDIO_MICROPHONE) j = SOUND_MASK_MIC; + + return COPY_OUT(arg, j); + + case SOUND_MIXER_RECMASK: + if (driver->ops->get_input_ports) + i = driver->ops->get_input_ports(driver); + /* what do we support? */ + if (i & AUDIO_MICROPHONE) j |= SOUND_MASK_MIC; + if (i & AUDIO_LINE_IN) j |= SOUND_MASK_LINE; + if (i & AUDIO_CD) j |= SOUND_MASK_CD; + if (i & AUDIO_ANALOG_LOOPBACK) j |= SOUND_MASK_IMIX; /* ? */ + + return COPY_OUT(arg, j); + + case SOUND_MIXER_CAPS: /* mixer capabilities */ + i = SOUND_CAP_EXCL_INPUT; + return COPY_OUT(arg, i); + + case SOUND_MIXER_DEVMASK: /* all supported devices */ + case SOUND_MIXER_STEREODEVS: /* what supports stereo */ + if (driver->ops->get_input_ports) + i = driver->ops->get_input_ports(driver); + /* what do we support? */ + if (i & AUDIO_MICROPHONE) j |= SOUND_MASK_MIC; + if (i & AUDIO_LINE_IN) j |= SOUND_MASK_LINE; + if (i & AUDIO_CD) j |= SOUND_MASK_CD; + if (i & AUDIO_ANALOG_LOOPBACK) j |= SOUND_MASK_IMIX; /* ? */ + + if (driver->ops->get_output_ports) + i = driver->ops->get_output_ports(driver); + if (i & AUDIO_SPEAKER) j |= SOUND_MASK_SPEAKER; + if (i & AUDIO_HEADPHONE) j |= SOUND_MASK_LINE; /* ? */ + if (i & AUDIO_LINE_OUT) j |= SOUND_MASK_LINE; + + j |= SOUND_MASK_VOLUME; + + if ((cmd & 0xff) == SOUND_MIXER_STEREODEVS) + j &= ~(MONO_DEVICES); + return COPY_OUT(arg, j); + + case SOUND_MIXER_VOLUME: + if (driver->ops->get_output_channels) + j = driver->ops->get_output_channels(driver); + if (j == 1) { + if (driver->ops->get_output_volume) + i = driver->ops->get_output_volume(driver); + i = m_to_s(i); + } else { + /* there should be stuff here which calculates balance and + volume on a stereo device. will do it eventually */ + if (driver->ops->get_output_volume) + i = driver->ops->get_output_volume(driver); + if (driver->ops->get_output_balance) + j = driver->ops->get_output_balance(driver); + i = b_to_s(i,j); + } + return COPY_OUT(arg, i); + + default: + /* Play like we support other things */ + return COPY_OUT(arg, i); + } + } +} + static int sparcaudio_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { int retval = 0; struct audio_info ainfo; + if (((cmd >> 8) & 0xff) == 'M') { + return sparcaudio_mixer_ioctl(inode, file, cmd, arg); + } + switch (cmd) { case SNDCTL_DSP_SYNC: case AUDIO_DRAIN: @@ -339,6 +466,40 @@ } break; + case AUDIO_FLUSH: + if (driver->output_active && (file->f_mode & FMODE_WRITE)) { + wake_up_interruptible(&driver->output_write_wait); + driver->ops->stop_output(driver); + driver->output_active = 0; + driver->output_front = 0; + driver->output_rear = 0; + driver->output_count = 0; + driver->output_size = 0; + driver->playing_count = 0; + } + if (driver->input_active && (file->f_mode & FMODE_READ)) { + wake_up_interruptible(&driver->input_read_wait); + driver->ops->stop_input(driver); + driver->input_active = 0; + driver->input_front = 0; + driver->input_rear = 0; + driver->input_count = 0; + driver->recording_count = 0; + } + if ((file->f_mode & FMODE_READ) && + !(driver->flags & SDF_OPEN_READ)) { + driver->ops->start_input(driver, + driver->input_buffers[driver->input_front], + PAGE_SIZE); + driver->input_active = 1; + } + if ((file->f_mode & FMODE_WRITE) && + !(driver->flags & SDF_OPEN_WRITE)) { + sparcaudio_sync_output(driver); + } + break; + + case AUDIO_GETDEV: if (driver->ops->sunaudio_getdev) { audio_device_t tmp; @@ -686,6 +847,19 @@ } } + /* Maybe this should be a routine instead of a macro */ +#define IF_SET_DO(x,y) if ((x) && Modify(y)) x(driver, y) +#define IF_SETC_DO(x,y) if ((x) && Modifyc(y)) x(driver, y) + IF_SETC_DO(driver->ops->set_input_balance, (int)ainfo.record.balance); + IF_SETC_DO(driver->ops->set_output_balance, (int)ainfo.play.balance); + IF_SET_DO(driver->ops->set_input_volume, ainfo.record.gain); + IF_SET_DO(driver->ops->set_output_volume, ainfo.play.gain); + IF_SET_DO(driver->ops->set_input_port, ainfo.record.port); + IF_SET_DO(driver->ops->set_output_port, ainfo.play.port); + IF_SET_DO(driver->ops->set_monitor_volume, ainfo.monitor_gain); + IF_SET_DO(driver->ops->set_output_muted, ainfo.output_muted); +#undef IF_SET_DO +#undef IF_SETC_DO printk("sparcaudio_ioctl: AUDIO_SETINFO\n"); break; @@ -725,77 +899,83 @@ static int sparcaudio_open(struct inode * inode, struct file * file) { - int err; - - /* A low-level audio driver must exist. */ - if (!driver) - return -ENODEV; - - if (MINOR(inode->i_rdev) == 5) { + int minor = MINOR(inode->i_rdev); + int err; - file->f_op = &sparcaudioctl_fops; - - MOD_INC_USE_COUNT; - - return 0; - } - - /* We only support minor #4 (/dev/audio) right now. */ - if (MINOR(inode->i_rdev) != 4) - return -ENXIO; - - /* If the driver is busy, then wait to get through. */ - retry_open: + /* A low-level audio driver must exist. */ + if (!driver) + return -ENODEV; + + switch (minor) { + case SPARCAUDIO_AUDIOCTL_MINOR: + file->f_op = &sparcaudioctl_fops; + break; + + case SPARCAUDIO_DSP16_MINOR: + case SPARCAUDIO_DSP_MINOR: + case SPARCAUDIO_AUDIO_MINOR: + /* If the driver is busy, then wait to get through. */ + retry_open: if (file->f_mode & FMODE_READ && driver->flags & SDF_OPEN_READ) { - if (file->f_flags & O_NONBLOCK) - return -EBUSY; - - interruptible_sleep_on(&driver->open_wait); - if (signal_pending(current)) - return -EINTR; - goto retry_open; + if (file->f_flags & O_NONBLOCK) + return -EBUSY; + + interruptible_sleep_on(&driver->open_wait); + if (signal_pending(current)) + return -EINTR; + goto retry_open; } if (file->f_mode & FMODE_WRITE && driver->flags & SDF_OPEN_WRITE) { - if (file->f_flags & O_NONBLOCK) - return -EBUSY; - - interruptible_sleep_on(&driver->open_wait); - if (signal_pending(current)) - return -EINTR; - goto retry_open; + if (file->f_flags & O_NONBLOCK) + return -EBUSY; + + interruptible_sleep_on(&driver->open_wait); + if (signal_pending(current)) + return -EINTR; + goto retry_open; } + /* Allow the low-level driver to initialize itself. */ + if (driver->ops->open) { + err = driver->ops->open(inode,file,driver); + if (err < 0) + return err; + } + /* Mark the driver as locked for read and/or write. */ if (file->f_mode & FMODE_READ) { - driver->input_offset = 0; - driver->input_front = 0; - driver->input_rear = 0; - driver->input_count = 0; - driver->ops->start_input(driver, driver->input_buffers[driver->input_front], - PAGE_SIZE); - driver->input_active = 1; - driver->flags |= SDF_OPEN_READ; + driver->input_offset = 0; + driver->input_front = 0; + driver->input_rear = 0; + driver->input_count = 0; + driver->recording_count = 0; + driver->ops->start_input(driver, driver->input_buffers[driver->input_front], + PAGE_SIZE); + driver->input_active = 1; + driver->flags |= SDF_OPEN_READ; } if (file->f_mode & FMODE_WRITE) { - driver->output_size = 0; - driver->output_front = 0; - driver->output_rear = 0; - driver->output_count = 0; - driver->output_active = 0; - driver->flags |= SDF_OPEN_WRITE; + driver->playing_count = 0; + driver->output_size = 0; + driver->output_front = 0; + driver->output_rear = 0; + driver->output_count = 0; + driver->output_active = 0; + driver->flags |= SDF_OPEN_WRITE; } - - /* Allow the low-level driver to initialize itself. */ - if (driver->ops->open) { - err = driver->ops->open(inode,file,driver); - if (err < 0) - return err; - } - - MOD_INC_USE_COUNT; - - /* Success! */ - return 0; + break; + case SPARCAUDIO_MIXER_MINOR: + file->f_op = &sparcaudioctl_fops; + break; + + default: + return -ENXIO; + } + + MOD_INC_USE_COUNT; + + /* Success! */ + return 0; } static int sparcaudio_release(struct inode * inode, struct file * file) @@ -876,3 +1056,22 @@ unregister_chrdev(SOUND_MAJOR, "sparcaudio"); } #endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 4 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -4 + * c-argdecl-indent: 4 + * c-label-offset: -4 + * c-continued-statement-offset: 4 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/audio/audio.h linux/drivers/sbus/audio/audio.h --- v2.1.100/linux/drivers/sbus/audio/audio.h Mon Jan 12 15:15:45 1998 +++ linux/drivers/sbus/audio/audio.h Wed Dec 31 16:00:00 1969 @@ -1,384 +0,0 @@ -/* - * drivers/sbus/audio/audio.h - * - * Sparc Audio Midlayer - * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) - */ - -#ifndef _AUDIO_H_ -#define _AUDIO_H_ - -/* - * SunOS/Solaris /dev/audio interface - */ - -#include -#include -#include - -/* - * This structure contains state information for audio device IO streams. - */ -typedef struct audio_prinfo { - /* - * The following values describe the audio data encoding. - */ - unsigned int sample_rate; /* samples per second */ - unsigned int channels; /* number of interleaved channels */ - unsigned int precision; /* bit-width of each sample */ - unsigned int encoding; /* data encoding method */ - - /* - * The following values control audio device configuration - */ - unsigned int gain; /* gain level: 0 - 255 */ - unsigned int port; /* selected I/O port (see below) */ - unsigned int avail_ports; /* available I/O ports (see below) */ - unsigned int _xxx[2]; /* Reserved for future use */ - - unsigned int buffer_size; /* I/O buffer size */ - - /* - * The following values describe driver state - */ - unsigned int samples; /* number of samples converted */ - unsigned int eof; /* End Of File counter (play only) */ - - unsigned char pause; /* non-zero for pause, zero to resume */ - unsigned char error; /* non-zero if overflow/underflow */ - unsigned char waiting; /* non-zero if a process wants access */ - unsigned char balance; /* stereo channel balance */ - - unsigned short minordev; - - /* - * The following values are read-only state flags - */ - unsigned char open; /* non-zero if open access permitted */ - unsigned char active; /* non-zero if I/O is active */ -} audio_prinfo_t; - - -/* - * This structure describes the current state of the audio device. - */ -typedef struct audio_info { - /* - * Per-stream information - */ - audio_prinfo_t play; /* output status information */ - audio_prinfo_t record; /* input status information */ - - /* - * Per-unit/channel information - */ - unsigned int monitor_gain; /* input to output mix: 0 - 255 */ - unsigned char output_muted; /* non-zero if output is muted */ - unsigned char _xxx[3]; /* Reserved for future use */ - unsigned int _yyy[3]; /* Reserved for future use */ -} audio_info_t; - - -/* - * Audio encoding types - */ -#define AUDIO_ENCODING_NONE (0) /* no encoding assigned */ -#define AUDIO_ENCODING_ULAW (1) /* u-law encoding */ -#define AUDIO_ENCODING_ALAW (2) /* A-law encoding */ -#define AUDIO_ENCODING_LINEAR (3) /* Linear PCM encoding */ -#define AUDIO_ENCODING_DVI (104) /* DVI ADPCM */ -#define AUDIO_ENCODING_LINEAR8 (105) /* 8 bit UNSIGNED */ -#define AUDIO_ENCODING_LINEARLE (106) /* Linear PCM LE encoding */ - -/* - * These ranges apply to record, play, and monitor gain values - */ -#define AUDIO_MIN_GAIN (0) /* minimum gain value */ -#define AUDIO_MAX_GAIN (255) /* maximum gain value */ - -/* - * These values apply to the balance field to adjust channel gain values - */ -#define AUDIO_LEFT_BALANCE (0) /* left channel only */ -#define AUDIO_MID_BALANCE (32) /* equal left/right channel */ -#define AUDIO_RIGHT_BALANCE (64) /* right channel only */ -#define AUDIO_BALANCE_SHIFT (3) - -/* - * Generic minimum/maximum limits for number of channels, both modes - */ -#define AUDIO_MIN_PLAY_CHANNELS (1) -#define AUDIO_MAX_PLAY_CHANNELS (4) -#define AUDIO_MIN_REC_CHANNELS (1) -#define AUDIO_MAX_REC_CHANNELS (4) - -/* - * Generic minimum/maximum limits for sample precision - */ -#define AUDIO_MIN_PLAY_PRECISION (8) -#define AUDIO_MAX_PLAY_PRECISION (32) -#define AUDIO_MIN_REC_PRECISION (8) -#define AUDIO_MAX_REC_PRECISION (32) - -/* - * Define some convenient names for typical audio ports - */ -/* - * output ports (several may be enabled simultaneously) - */ -#define AUDIO_SPEAKER 0x01 /* output to built-in speaker */ -#define AUDIO_HEADPHONE 0x02 /* output to headphone jack */ -#define AUDIO_LINE_OUT 0x04 /* output to line out */ - -/* - * input ports (usually only one at a time) - */ -#define AUDIO_MICROPHONE 0x01 /* input from microphone */ -#define AUDIO_LINE_IN 0x02 /* input from line in */ -#define AUDIO_CD 0x04 /* input from on-board CD inputs */ -#define AUDIO_INTERNAL_CD_IN AUDIO_CD /* input from internal CDROM */ -/* Supposedly an undocumented feature of the 4231 */ -#define AUDIO_ANALOG_LOOPBACK 0x40 - - -/* - * This macro initializes an audio_info structure to 'harmless' values. - * Note that (~0) might not be a harmless value for a flag that was - * a signed int. - */ -#define AUDIO_INITINFO(i) { \ - unsigned int *__x__; \ - for (__x__ = (unsigned int *)(i); \ - (char *) __x__ < (((char *)(i)) + sizeof (audio_info_t)); \ - *__x__++ = ~0); \ -} - - -/* - * These allow testing for what the user wants to set - */ -#define AUD_INITVALUE (~0) -#define Modify(X) ((unsigned int)(X) != AUD_INITVALUE) -#define Modifys(X) ((X) != (unsigned short)AUD_INITVALUE) -#define Modifyc(X) ((X) != (unsigned char)AUD_INITVALUE) - -/* - * Parameter for the AUDIO_GETDEV ioctl to determine current - * audio devices. - */ -#define MAX_AUDIO_DEV_LEN (16) -typedef struct audio_device { - char name[MAX_AUDIO_DEV_LEN]; - char version[MAX_AUDIO_DEV_LEN]; - char config[MAX_AUDIO_DEV_LEN]; -} audio_device_t; - - -/* - * Ioctl calls for the audio device. - */ - -/* - * AUDIO_GETINFO retrieves the current state of the audio device. - * - * AUDIO_SETINFO copies all fields of the audio_info structure whose - * values are not set to the initialized value (-1) to the device state. - * It performs an implicit AUDIO_GETINFO to return the new state of the - * device. Note that the record.samples and play.samples fields are set - * to the last value before the AUDIO_SETINFO took effect. This allows - * an application to reset the counters while atomically retrieving the - * last value. - * - * AUDIO_DRAIN suspends the calling process until the write buffers are - * empty. - * - * AUDIO_GETDEV returns a structure of type audio_device_t which contains - * three strings. The string "name" is a short identifying string (for - * example, the SBus Fcode name string), the string "version" identifies - * the current version of the device, and the "config" string identifies - * the specific configuration of the audio stream. All fields are - * device-dependent -- see the device specific manual pages for details. - */ -#define AUDIO_GETINFO _IOR('A', 1, audio_info_t) -#define AUDIO_SETINFO _IOWR('A', 2, audio_info_t) -#define AUDIO_DRAIN _IO('A', 3) -#define AUDIO_GETDEV _IOR('A', 4, audio_device_t) -#define AUDIO_GETDEV_SUNOS _IOR('A', 4, int) - -/* Define possible audio hardware configurations for - * old SunOS-style AUDIO_GETDEV ioctl */ - -#define AUDIO_DEV_UNKNOWN (0) /* not defined */ -#define AUDIO_DEV_AMD (1) /* audioamd device */ -#define AUDIO_DEV_SPEAKERBOX (2) /* dbri device with speakerbox */ -#define AUDIO_DEV_CODEC (3) /* dbri device (internal speaker) */ -#define AUDIO_DEV_CS4231 (5) /* cs4231 device */ - -/* - * The following ioctl sets the audio device into an internal loopback mode, - * if the hardware supports this. The argument is TRUE to set loopback, - * FALSE to reset to normal operation. If the hardware does not support - * internal loopback, the ioctl should fail with EINVAL. - */ -#define AUDIO_DIAG_LOOPBACK _IOW('A', 101, int) - -#ifdef notneeded -/* - * Structure sent up as a M_PROTO message on trace streams - */ -typedef struct audtrace_hdr audtrace_hdr_t; -struct audtrace_hdr { - unsigned int seq; /* Sequence number (per-aud_stream) */ - int type; /* device-dependent */ - struct timeval timestamp; - char _f[8]; /* filler */ -}; -#endif - -/* - * Linux kernel internal implementation. - */ - -#ifdef __KERNEL__ - -#include -#include -#include -#include - -#define SDF_OPEN_WRITE 0x00000001 -#define SDF_OPEN_READ 0x00000002 - -struct sparcaudio_driver -{ - const char * name; - struct sparcaudio_operations *ops; - void *private; - unsigned long flags; - - /* Processes blocked on open() sit here. */ - struct wait_queue *open_wait; - - /* Task queue for this driver's bottom half. */ - struct tq_struct tqueue; - - /* Support for a circular queue of output buffers. */ - __u8 **output_buffers; - size_t *output_sizes, output_size; - int num_output_buffers, output_front, output_rear; - int output_count, output_active; - struct wait_queue *output_write_wait, *output_drain_wait; - - /* Support for a circular queue of input buffers. */ - __u8 **input_buffers; - int input_offset; - int num_input_buffers, input_front, input_rear; - int input_count, input_active; - struct wait_queue *input_read_wait; -}; - -struct sparcaudio_operations -{ - int (*open)(struct inode *, struct file *, struct sparcaudio_driver *); - void (*release)(struct inode *, struct file *, struct sparcaudio_driver *); - int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long, - struct sparcaudio_driver *); - - /* Ask driver to begin playing a buffer. */ - void (*start_output)(struct sparcaudio_driver *, __u8 *, unsigned long); - - /* Ask driver to stop playing a buffer. */ - void (*stop_output)(struct sparcaudio_driver *); - - /* Ask driver to begin recording into a buffer. */ - void (*start_input)(struct sparcaudio_driver *, __u8 *, unsigned long); - - /* Ask driver to stop recording. */ - void (*stop_input)(struct sparcaudio_driver *); - - /* Return driver name/version to caller. (/dev/audio specific) */ - void (*sunaudio_getdev)(struct sparcaudio_driver *, audio_device_t *); - - /* Get and set the output volume. (0-255) */ - int (*set_output_volume)(struct sparcaudio_driver *, int); - int (*get_output_volume)(struct sparcaudio_driver *); - - /* Get and set the input volume. (0-255) */ - int (*set_input_volume)(struct sparcaudio_driver *, int); - int (*get_input_volume)(struct sparcaudio_driver *); - - /* Get and set the monitor volume. (0-255) */ - int (*set_monitor_volume)(struct sparcaudio_driver *, int); - int (*get_monitor_volume)(struct sparcaudio_driver *); - - /* Get and set the output balance. (0-64) */ - int (*set_output_balance)(struct sparcaudio_driver *, int); - int (*get_output_balance)(struct sparcaudio_driver *); - - /* Get and set the input balance. (0-64) */ - int (*set_input_balance)(struct sparcaudio_driver *, int); - int (*get_input_balance)(struct sparcaudio_driver *); - - /* Get and set the output channels. (1-4) */ - int (*set_output_channels)(struct sparcaudio_driver *, int); - int (*get_output_channels)(struct sparcaudio_driver *); - - /* Get and set the input channels. (1-4) */ - int (*set_input_channels)(struct sparcaudio_driver *, int); - int (*get_input_channels)(struct sparcaudio_driver *); - - /* Get and set the output precision. (8-32) */ - int (*set_output_precision)(struct sparcaudio_driver *, int); - int (*get_output_precision)(struct sparcaudio_driver *); - - /* Get and set the input precision. (8-32) */ - int (*set_input_precision)(struct sparcaudio_driver *, int); - int (*get_input_precision)(struct sparcaudio_driver *); - - /* Get and set the output port. () */ - int (*set_output_port)(struct sparcaudio_driver *, int); - int (*get_output_port)(struct sparcaudio_driver *); - - /* Get and set the input port. () */ - int (*set_input_port)(struct sparcaudio_driver *, int); - int (*get_input_port)(struct sparcaudio_driver *); - - /* Get and set the output encoding. () */ - int (*set_output_encoding)(struct sparcaudio_driver *, int); - int (*get_output_encoding)(struct sparcaudio_driver *); - - /* Get and set the input encoding. () */ - int (*set_input_encoding)(struct sparcaudio_driver *, int); - int (*get_input_encoding)(struct sparcaudio_driver *); - - /* Get and set the output rate. () */ - int (*set_output_rate)(struct sparcaudio_driver *, int); - int (*get_output_rate)(struct sparcaudio_driver *); - - /* Get and set the input rate. () */ - int (*set_input_rate)(struct sparcaudio_driver *, int); - int (*get_input_rate)(struct sparcaudio_driver *); - - /* Return driver number to caller. (SunOS /dev/audio specific) */ - int (*sunaudio_getdev_sunos)(struct sparcaudio_driver *); - - /* Get available ports */ - int (*get_output_ports)(struct sparcaudio_driver *); - int (*get_input_ports)(struct sparcaudio_driver *); - - /* Get and set output mute */ - int (*set_output_muted)(struct sparcaudio_driver *, int); - int (*get_output_muted)(struct sparcaudio_driver *); -}; - -extern int register_sparcaudio_driver(struct sparcaudio_driver *); -extern int unregister_sparcaudio_driver(struct sparcaudio_driver *); -extern void sparcaudio_output_done(struct sparcaudio_driver *); -extern void sparcaudio_input_done(struct sparcaudio_driver *); -extern int sparcaudio_init(void); -extern int amd7930_init(void); -extern int cs4231_init(void); - -#endif /* __KERNEL__ */ - -#endif /* _AUDIO_H */ diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/audio/cs4231.c linux/drivers/sbus/audio/cs4231.c --- v2.1.100/linux/drivers/sbus/audio/cs4231.c Mon Feb 23 18:12:06 1998 +++ linux/drivers/sbus/audio/cs4231.c Fri May 8 00:23:41 1998 @@ -1,13 +1,20 @@ /* - * drivers/sbus/audio/cs4231.c + * Drivers/sbus/audio/cs4231.c * + * Copyright (C) 1996, 1997 Derrick J Brashear (shadow@andrew.cmu.edu) + * + * Based on the AMD7930 driver: * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) - * Copyright (C) 1996 Derrick J Brashear (shadow@andrew.cmu.edu) * * This is the lowlevel driver for the CS4231 audio chip found on some - * sun4m machines. + * sun4m and sun4u machines. + * + * This was culled from the Crystal docs on the 4231a, and the addendum they + * faxed me on the 4231. + * The APC DMA controller support unfortunately is not documented. Thanks, Sun */ +#include #include #include #include @@ -15,15 +22,15 @@ #include #include #include +#include #include #include #include #include #include -#include #include -#include "audio.h" +#include #include "cs4231.h" /* Stolen for now from compat.h */ @@ -34,194 +41,700 @@ #define MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) #endif +#undef __CS4231_DEBUG +#undef __CS4231_TRACE +#undef __CS4231_ERROR +#ifdef __CS4231_ERROR +#define eprintk(x) printk x +#else +#define eprintk(x) +#endif +#ifdef __CS4231_TRACE +#define tprintk(x) printk x +#else +#define tprintk(x) +#endif +#ifdef __CS4231_DEBUG +#define dprintk(x) printk x +#else +#define dprintk(x) +#endif + #define MAX_DRIVERS 1 static struct sparcaudio_driver drivers[MAX_DRIVERS]; static int num_drivers; -static int cs4231_playintr(struct sparcaudio_driver *drv); +static int cs4231_record_gain(struct sparcaudio_driver *drv, int value, unsigned char balance); +static int cs4231_play_gain(struct sparcaudio_driver *drv, int value, unsigned char balance); +static void cs4231_ready(struct sparcaudio_driver *drv); +static void cs4231_playintr(struct sparcaudio_driver *drv); static int cs4231_recintr(struct sparcaudio_driver *drv); -static void cs4231_output_muted(struct sparcaudio_driver *drv, unsigned int value); -static void cs4231_mute(struct sparcaudio_driver *drv); +static int cs4231_output_muted(struct sparcaudio_driver *drv, int value); static void cs4231_pollinput(struct sparcaudio_driver *drv); +static int cs4231_length_to_samplecount(struct audio_prinfo *thisdir, unsigned int length); +static void cs4231_getsamplecount(struct sparcaudio_driver *drv, unsigned int length, unsigned int value); -#define CHIP_BUG udelay(100); cs4231_ready(drv); udelay(1000); +#define CHIP_READY udelay(100); cs4231_ready(drv); udelay(1000); -/* Disable mode change, let chip auto-calibrate */ -static void cs4231_ready(struct sparcaudio_driver *drv) +/* Enable cs4231 interrupts atomically. */ +static __inline__ void cs4231_enable_interrupts(struct sparcaudio_driver *drv) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - unsigned int x = 0; + register unsigned long flags; - cs4231_chip->pioregs->iar = (u_char)IAR_AUTOCAL_END; - while (cs4231_chip->pioregs->iar == IAR_NOT_READY && x <= CS_TIMEOUT) { - x++; + if (cs4231_chip->status & CS_STATUS_INTS_ON) + return; + + tprintk(("enabling interrupts\n")); + save_flags(flags); + cli(); + cs4231_chip->regs->iar = 0xa; + cs4231_chip->regs->idr = INTR_ON; + restore_flags(flags); + + cs4231_chip->status |= CS_STATUS_INTS_ON; +} + +/* Disable cs4231 interrupts atomically. */ +static __inline__ void cs4231_disable_interrupts(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + register unsigned long flags; + + if (!(cs4231_chip->status & CS_STATUS_INTS_ON)) + return; + + tprintk(("disabling interrupts\n")); + save_flags(flags); + cli(); + cs4231_chip->regs->iar = 0xa; + cs4231_chip->regs->idr = INTR_OFF; + restore_flags(flags); + + cs4231_chip->status &= ~CS_STATUS_INTS_ON; +} + +static __inline__ void cs4231_enable_play(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + register unsigned long flags; + + tprintk(("enabling play\n")); + save_flags(flags); + cli(); + cs4231_chip->regs->iar = 0x9; + cs4231_chip->regs->idr |= PEN_ENABLE; + restore_flags(flags); +} + +static __inline__ void cs4231_disable_play(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + register unsigned long flags; + + tprintk(("disabling play\n")); + save_flags(flags); + cli(); + cs4231_chip->regs->iar = 0x9; + cs4231_chip->regs->idr &= PEN_DISABLE; + restore_flags(flags); +} + +static __inline__ void cs4231_enable_rec(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + register unsigned long flags; + + tprintk(("enabling rec\n")); + save_flags(flags); + cli(); + cs4231_chip->regs->iar = 0x9; + cs4231_chip->regs->idr |= CEN_ENABLE; + restore_flags(flags); +} + +static __inline__ void cs4231_disable_rec(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + register unsigned long flags; + + tprintk(("disabling rec\n")); + save_flags(flags); + cli(); + cs4231_chip->regs->iar = 0x9; + cs4231_chip->regs->idr &= CEN_DISABLE; + restore_flags(flags); +} + +static int +cs4231_rate_to_bits(struct sparcaudio_driver *drv, int value) +{ + int set_bits; + + switch (value) { + case 5512: + set_bits = CS4231_DFR_5512; + break; + case 6615: + set_bits = CS4231_DFR_6615; + break; + case 8000: + set_bits = CS4231_DFR_8000; + break; + case 9600: + set_bits = CS4231_DFR_9600; + break; + case 11025: + set_bits = CS4231_DFR_11025; + break; + case 16000: + set_bits = CS4231_DFR_16000; + break; + case 18900: + set_bits = CS4231_DFR_18900; + break; + case 22050: + set_bits = CS4231_DFR_22050; + break; + case 27429: + set_bits = CS4231_DFR_27429; + break; + case 32000: + set_bits = CS4231_DFR_32000; + break; + case 33075: + set_bits = CS4231_DFR_33075; + break; + case 37800: + set_bits = CS4231_DFR_37800; + break; + case 44100: + set_bits = CS4231_DFR_44100; + break; + case 48000: + set_bits = CS4231_DFR_48000; + break; + default: + set_bits = -(EINVAL); + break; } + return set_bits; +} - x = 0; - cs4231_chip->pioregs->iar = 0x0b; - while (cs4231_chip->pioregs->idr == AUTOCAL_IN_PROGRESS && x <= CS_TIMEOUT) { - x++; +static int +cs4231_encoding_to_bits(struct sparcaudio_driver *drv, int value) +{ + int set_bits; + + switch (value) { + case AUDIO_ENCODING_ULAW: + set_bits = CS4231_DFR_ULAW; + break; + case AUDIO_ENCODING_ALAW: + set_bits = CS4231_DFR_ALAW; + break; + case AUDIO_ENCODING_DVI: + set_bits = CS4231_DFR_ADPCM; + break; + case AUDIO_ENCODING_LINEARLE: + set_bits = CS4231_DFR_LINEARLE; + break; + case AUDIO_ENCODING_LINEAR: + set_bits = CS4231_DFR_LINEARBE; + break; + case AUDIO_ENCODING_LINEAR8: + set_bits = CS4231_DFR_LINEAR8; + break; + default: + set_bits = -(EINVAL); + break; } + + return set_bits; } -/* Audio interrupt handler. */ -static void cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static int +cs4231_set_output_encoding(struct sparcaudio_driver *drv, int value) { - struct sparcaudio_driver *drv = (struct sparcaudio_driver *)dev_id; struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - __u8 dummy; - int ic = 1; - - /* Clear the interrupt. */ - dummy = cs4231_chip->dmaregs.dmacsr; - cs4231_chip->dmaregs.dmacsr = dummy; + int tmp_bits, set_bits; - /* now go through and figure out what gets to claim the interrupt */ - if (dummy & CS_PLAY_INT) { - if (dummy & CS_XINT_PNVA) { - /* recalculate number of samples */ - cs4231_playintr(drv); + tprintk(("output encoding %d\n", value)); + if (value != 0) { + set_bits = cs4231_encoding_to_bits(drv, value); + if (set_bits >= 0) { + cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x8; + tmp_bits = cs4231_chip->regs->idr; + cs4231_chip->regs->idr = CHANGE_ENCODING(tmp_bits, set_bits); + + CHIP_READY + + cs4231_chip->perchip_info.play.encoding = value; + return 0; } - ic = 0; } - if (dummy & CS_CAPT_INT) { - if (dummy & CS_XINT_CNVA) { - /* recalculate number of samples */ - cs4231_recintr(drv); + eprintk(("output enc failed\n")); + return -EINVAL; +} + +static int cs4231_get_output_encoding(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + return cs4231_chip->perchip_info.play.encoding; +} + +static int +cs4231_set_input_encoding(struct sparcaudio_driver *drv, int value) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + int tmp_bits, set_bits; + + dprintk(("input encoding %d\n", value)); + if (value != 0) { + set_bits = cs4231_encoding_to_bits(drv, value); + if (set_bits >= 0) { + cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1c; + tmp_bits = cs4231_chip->regs->idr; + cs4231_chip->regs->idr = CHANGE_ENCODING(tmp_bits, set_bits); + + CHIP_READY + + cs4231_chip->perchip_info.record.encoding = value; + return 0; } - ic = 0; } - if ((dummy & CS_XINT_CEMP) - && (cs4231_chip->perchip_info.record.active == 0)) - { - ic = 0; + eprintk(("input enc failed\n")); + return -EINVAL; +} + +static int cs4231_get_input_encoding(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + return cs4231_chip->perchip_info.record.encoding; +} + +static int +cs4231_set_output_rate(struct sparcaudio_driver *drv, int value) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + int tmp_bits, set_bits; + + tprintk(("output rate %d\n", value)); + if (value != 0) { + set_bits = cs4231_rate_to_bits(drv, value); + if (set_bits >= 0) { + cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x8; + tmp_bits = cs4231_chip->regs->idr; + cs4231_chip->regs->idr = CHANGE_DFR(tmp_bits, set_bits); + + CHIP_READY + + cs4231_chip->perchip_info.play.sample_rate = value; + return 0; } - if ((dummy & CS_XINT_EMPT) && (cs4231_chip->perchip_info.play.active == 0)) { - cs4231_chip->dmaregs.dmacsr |= (CS_PPAUSE); - cs4231_chip->pioregs->iar = 0x9; - cs4231_chip->pioregs->idr &= PEN_DISABLE; - - cs4231_mute(drv); + } + eprintk(("output rate failed\n")); + return -EINVAL; +} + +static int cs4231_get_output_rate(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + return cs4231_chip->perchip_info.play.sample_rate; +} + +static int +cs4231_set_input_rate(struct sparcaudio_driver *drv, int value) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + int tmp_bits, set_bits; + + dprintk(("input rate %d\n", value)); + if (value != 0) { + set_bits = cs4231_rate_to_bits(drv, value); + if (set_bits >= 0) { + cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1c; + tmp_bits = cs4231_chip->regs->idr; + cs4231_chip->regs->idr = CHANGE_DFR(tmp_bits, set_bits); + + CHIP_READY + + cs4231_chip->perchip_info.record.sample_rate = value; + return 0; + } + } + eprintk(("input rate failed\n")); + return -EINVAL; +} + +static int cs4231_get_input_rate(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + return cs4231_chip->perchip_info.record.sample_rate; +} + +/* Generically we support 4 channels. This hardware does 2 */ +static int +cs4231_set_input_channels(struct sparcaudio_driver *drv, int value) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + int tmp_bits; + + dprintk(("input channels %d\n", value)); + cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1c; + tmp_bits = cs4231_chip->regs->idr; + switch (value) { + case 1: + cs4231_chip->regs->idr = CS4231_MONO_ON(tmp_bits); + break; + case 2: + cs4231_chip->regs->idr = CS4231_STEREO_ON(tmp_bits); + break; + default: + eprintk(("input chan failed\n")); + return -(EINVAL); + } + + CHIP_READY + + cs4231_chip->perchip_info.record.channels = value; + return 0; +} + +static int cs4231_get_input_channels(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + return cs4231_chip->perchip_info.record.channels; +} + +/* Generically we support 4 channels. This hardware does 2 */ +static int +cs4231_set_output_channels(struct sparcaudio_driver *drv, int value) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + int tmp_bits; + + tprintk(("output channels %d\n", value)); + cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x8; + tmp_bits = cs4231_chip->regs->idr; + switch (value) { + case 1: + cs4231_chip->regs->idr = CS4231_MONO_ON(tmp_bits); + break; + case 2: + cs4231_chip->regs->idr = CS4231_STEREO_ON(tmp_bits); + break; + default: + eprintk(("output chan failed\n")); + return -(EINVAL); + } + + CHIP_READY - /* recalculate number of samples */ - /* cleanup DMA */ - ic = 0; + cs4231_chip->perchip_info.play.channels = value; + return 0; +} + +static int cs4231_get_output_channels(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + return cs4231_chip->perchip_info.play.channels; +} + +static int cs4231_set_input_precision(struct sparcaudio_driver *drv, int value) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + cs4231_chip->perchip_info.record.precision = value; + return 0; +} + +static int cs4231_get_input_precision(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + return cs4231_chip->perchip_info.record.precision; +} + +static int cs4231_set_output_precision(struct sparcaudio_driver *drv, int value) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + cs4231_chip->perchip_info.play.precision = value; + return 0; +} + +static int cs4231_get_output_precision(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + return cs4231_chip->perchip_info.play.precision; +} + +/* Wait until the auto calibration process has finished */ +static void +cs4231_ready(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + unsigned int x = 0; + + cs4231_chip->regs->iar = IAR_AUTOCAL_END; + while (cs4231_chip->regs->iar == IAR_NOT_READY && x <= CS_TIMEOUT) { + x++; } - if (dummy & CS_GENL_INT) { - ic = 0; + + x = 0; + cs4231_chip->regs->iar = 0x0b; + while (cs4231_chip->regs->idr == AUTOCAL_IN_PROGRESS && x <= CS_TIMEOUT) { + x++; } } /* Set output mute */ -static void cs4231_output_muted(struct sparcaudio_driver *drv, unsigned int value) +static int cs4231_output_muted(struct sparcaudio_driver *drv, int value) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + tprintk(("in cs4231_output_muted: %d\n", value)); if (!value) { - cs4231_chip->pioregs->iar = 0x7; - cs4231_chip->pioregs->idr &= OUTCR_UNMUTE; - cs4231_chip->pioregs->iar = 0x6; - cs4231_chip->pioregs->idr &= OUTCR_UNMUTE; + cs4231_chip->regs->iar = 0x7; + cs4231_chip->regs->idr &= OUTCR_UNMUTE; + cs4231_chip->regs->iar = 0x6; + cs4231_chip->regs->idr &= OUTCR_UNMUTE; cs4231_chip->perchip_info.output_muted = 0; } else { - cs4231_chip->pioregs->iar = 0x7; - cs4231_chip->pioregs->idr |= OUTCR_MUTE; - cs4231_chip->pioregs->iar = 0x6; - cs4231_chip->pioregs->idr |= OUTCR_MUTE; + cs4231_chip->regs->iar = 0x7; + cs4231_chip->regs->idr |= OUTCR_MUTE; + cs4231_chip->regs->iar = 0x6; + cs4231_chip->regs->idr |= OUTCR_MUTE; cs4231_chip->perchip_info.output_muted = 1; } - return /*(cs4231_chip->perchip_info.output_muted)*/; + return 0; } -/* Set chip "output" port */ -static unsigned int cs4231_out_port(struct sparcaudio_driver *drv, unsigned int value) +static int cs4231_get_output_muted(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + return cs4231_chip->perchip_info.output_muted; +} + +static int cs4231_get_output_ports(struct sparcaudio_driver *drv) +{ + return (AUDIO_LINE_OUT | AUDIO_SPEAKER | AUDIO_HEADPHONE); +} + +static int cs4231_get_input_ports(struct sparcaudio_driver *drv) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - unsigned int r = 0; + if (cs4231_chip->status & CS_STATUS_IS_ULTRA) + return (AUDIO_LINE_IN | AUDIO_MICROPHONE | AUDIO_ANALOG_LOOPBACK); + else + return (AUDIO_INTERNAL_CD_IN | AUDIO_LINE_IN | AUDIO_MICROPHONE | + AUDIO_ANALOG_LOOPBACK); +} - /* You can have any combo you want. Just don't tell anyone. */ +/* Set chip "output" port */ +static int cs4231_set_output_port(struct sparcaudio_driver *drv, int value) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + int retval = 0; - cs4231_chip->pioregs->iar = 0x1a; - cs4231_chip->pioregs->idr |= MONO_IOCR_MUTE; - cs4231_chip->pioregs->iar = 0x0a; - cs4231_chip->pioregs->idr |= PINCR_LINE_MUTE; - cs4231_chip->pioregs->idr |= PINCR_HDPH_MUTE; + tprintk(("output port: %d\n", value)); + /* Aaaaaah! It's all coming so fast! Turn it all off, then selectively + * enable things. + */ + cs4231_chip->regs->iar = 0x1a; + cs4231_chip->regs->idr |= MONO_IOCR_MUTE; + cs4231_chip->regs->iar = 0x0a; + cs4231_chip->regs->idr |= PINCR_LINE_MUTE; + cs4231_chip->regs->idr |= PINCR_HDPH_MUTE; if (value & AUDIO_SPEAKER) { - cs4231_chip->pioregs->iar = 0x1a; - cs4231_chip->pioregs->idr &= ~MONO_IOCR_MUTE; - r |= AUDIO_SPEAKER; + cs4231_chip->regs->iar = 0x1a; + cs4231_chip->regs->idr &= ~MONO_IOCR_MUTE; + retval |= AUDIO_SPEAKER; } if (value & AUDIO_HEADPHONE) { - cs4231_chip->pioregs->iar = 0x0a; - cs4231_chip->pioregs->idr &= ~PINCR_HDPH_MUTE; - r |= AUDIO_HEADPHONE; + cs4231_chip->regs->iar = 0x0a; + cs4231_chip->regs->idr &= ~PINCR_HDPH_MUTE; + retval |= AUDIO_HEADPHONE; } if (value & AUDIO_LINE_OUT) { - cs4231_chip->pioregs->iar = 0x0a; - cs4231_chip->pioregs->idr &= ~PINCR_LINE_MUTE; - r |= AUDIO_LINE_OUT; + cs4231_chip->regs->iar = 0x0a; + cs4231_chip->regs->idr &= ~PINCR_LINE_MUTE; + retval |= AUDIO_LINE_OUT; } - return (r); + cs4231_chip->perchip_info.play.port = retval; + + return (retval); +} + +static int cs4231_get_output_port(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + return cs4231_chip->perchip_info.play.port; } /* Set chip "input" port */ -static unsigned int cs4231_in_port(struct sparcaudio_driver *drv, unsigned int value) +static int cs4231_set_input_port(struct sparcaudio_driver *drv, int value) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - unsigned int r = 0; + int retval = 0; - /* The order of these seems to matter. Can't tell yet why. */ - if (value & AUDIO_INTERNAL_CD_IN) { - cs4231_chip->pioregs->iar = 0x1; - cs4231_chip->pioregs->idr = CDROM_ENABLE(cs4231_chip->pioregs->idr); - cs4231_chip->pioregs->iar = 0x0; - cs4231_chip->pioregs->idr = CDROM_ENABLE(cs4231_chip->pioregs->idr); - r = AUDIO_INTERNAL_CD_IN; + dprintk(("input port: %d\n", value)); + + /* You can have one and only one. This is probably wrong, but + * appears to be how SunOS is doing it. Should be able to mix. + * More work to be done. + */ + + /* Ultra systems do not support AUDIO_INTERNAL_CD_IN */ + if (!cs4231_chip->status & CS_STATUS_IS_ULTRA) { + if (value & AUDIO_INTERNAL_CD_IN) { + cs4231_chip->regs->iar = 0x1; + cs4231_chip->regs->idr = CDROM_ENABLE(cs4231_chip->regs->idr); + cs4231_chip->regs->iar = 0x0; + cs4231_chip->regs->idr = CDROM_ENABLE(cs4231_chip->regs->idr); + retval = AUDIO_INTERNAL_CD_IN; + } } if ((value & AUDIO_LINE_IN)) { - cs4231_chip->pioregs->iar = 0x1; - cs4231_chip->pioregs->idr = LINE_ENABLE(cs4231_chip->pioregs->idr); - cs4231_chip->pioregs->iar = 0x0; - cs4231_chip->pioregs->idr = LINE_ENABLE(cs4231_chip->pioregs->idr); - r = AUDIO_LINE_IN; + cs4231_chip->regs->iar = 0x1; + cs4231_chip->regs->idr = LINE_ENABLE(cs4231_chip->regs->idr); + cs4231_chip->regs->iar = 0x0; + cs4231_chip->regs->idr = LINE_ENABLE(cs4231_chip->regs->idr); + retval = AUDIO_LINE_IN; } else if (value & AUDIO_MICROPHONE) { - cs4231_chip->pioregs->iar = 0x1; - cs4231_chip->pioregs->idr = MIC_ENABLE(cs4231_chip->pioregs->idr); - cs4231_chip->pioregs->iar = 0x0; - cs4231_chip->pioregs->idr = MIC_ENABLE(cs4231_chip->pioregs->idr); - r = AUDIO_MICROPHONE; + cs4231_chip->regs->iar = 0x1; + cs4231_chip->regs->idr = MIC_ENABLE(cs4231_chip->regs->idr); + cs4231_chip->regs->iar = 0x0; + cs4231_chip->regs->idr = MIC_ENABLE(cs4231_chip->regs->idr); + retval = AUDIO_MICROPHONE; + } else if (value & AUDIO_ANALOG_LOOPBACK) { + cs4231_chip->regs->iar = 0x1; + cs4231_chip->regs->idr = OUTPUTLOOP_ENABLE(cs4231_chip->regs->idr); + cs4231_chip->regs->iar = 0x0; + cs4231_chip->regs->idr = OUTPUTLOOP_ENABLE(cs4231_chip->regs->idr); + retval = AUDIO_ANALOG_LOOPBACK; } - return (r); + cs4231_chip->perchip_info.record.port = retval; + + return (retval); +} + +static int cs4231_get_input_port(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + return cs4231_chip->perchip_info.record.port; } /* Set chip "monitor" gain */ -static unsigned int cs4231_monitor_gain(struct sparcaudio_driver *drv, unsigned int value) +static int cs4231_set_monitor_volume(struct sparcaudio_driver *drv, int value) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; int a = 0; + tprintk(("monitor gain: %d\n", value)); + + /* This interpolation really sucks. The question is, be compatible + * with ScumOS/Sloaris or not? + */ a = CS4231_MON_MAX_ATEN - (value * (CS4231_MON_MAX_ATEN + 1) / (AUDIO_MAX_GAIN + 1)); - cs4231_chip->pioregs->iar = 0x0d; + cs4231_chip->regs->iar = 0x0d; if (a >= CS4231_MON_MAX_ATEN) - cs4231_chip->pioregs->idr = LOOPB_OFF; + cs4231_chip->regs->idr = LOOPB_OFF; + else + cs4231_chip->regs->idr = ((a << 2) | LOOPB_ON); + + if (value == AUDIO_MAX_GAIN) + cs4231_chip->perchip_info.monitor_gain = AUDIO_MAX_GAIN; else - cs4231_chip->pioregs->idr = ((a << 2) | LOOPB_ON); + cs4231_chip->perchip_info.monitor_gain = ((CS4231_MAX_DEV_ATEN - a) * (AUDIO_MAX_GAIN + 1) / (CS4231_MAX_DEV_ATEN + 1)); + + return 0; +} + +static int cs4231_get_monitor_volume(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + + return (int)cs4231_chip->perchip_info.monitor_gain; +} + +/* But for play/record we have these cheesy jacket routines because of + * how this crap gets set */ +static int cs4231_set_input_volume(struct sparcaudio_driver *drv, int value) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + + cs4231_record_gain(drv, value, cs4231_chip->perchip_info.record.balance); + + return 0; +} + +static int cs4231_get_input_volume(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + + return (int)cs4231_chip->perchip_info.record.gain; +} + +static int cs4231_set_output_volume(struct sparcaudio_driver *drv, int value) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + + cs4231_play_gain(drv, value, cs4231_chip->perchip_info.play.balance); + + return 0; +} + +static int cs4231_get_output_volume(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + + return cs4231_chip->perchip_info.play.gain; +} + +/* Likewise for balance */ +static int cs4231_set_input_balance(struct sparcaudio_driver *drv, int value) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + + cs4231_chip->perchip_info.record.balance = value; + cs4231_record_gain(drv, cs4231_chip->perchip_info.record.gain, cs4231_chip->perchip_info.record.balance); + + return 0; +} + +static int cs4231_get_input_balance(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + + return (int)cs4231_chip->perchip_info.record.balance; +} + +static int cs4231_set_output_balance(struct sparcaudio_driver *drv, int value) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - if (value == AUDIO_MAX_GAIN) return AUDIO_MAX_GAIN; + cs4231_chip->perchip_info.play.balance = value; + cs4231_play_gain(drv, cs4231_chip->perchip_info.play.gain, cs4231_chip->perchip_info.play.balance); + + return 0; +} + +static int cs4231_get_output_balance(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - return ((CS4231_MAX_DEV_ATEN - a) * (AUDIO_MAX_GAIN + 1) / (CS4231_MAX_DEV_ATEN + 1)); + return (int)cs4231_chip->perchip_info.play.balance; } /* Set chip record gain */ -static unsigned int cs4231_record_gain(struct sparcaudio_driver *drv, unsigned int value, unsigned char balance) +static int cs4231_record_gain(struct sparcaudio_driver *drv, int value, unsigned char balance) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - unsigned int tmp = 0, r, l, ra, la; + int tmp = 0, r, l, r_adj, l_adj; unsigned char old_gain; r = l = value; @@ -232,31 +745,33 @@ l = MAX(0, (int)(value - ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT))); } - la = l * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1); - ra = r * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1); + l_adj = l * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1); + r_adj = r * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1); - cs4231_chip->pioregs->iar = 0x0; - old_gain = cs4231_chip->pioregs->idr; - cs4231_chip->pioregs->idr = RECGAIN_SET(old_gain, la); - cs4231_chip->pioregs->iar = 0x1; - old_gain = cs4231_chip->pioregs->idr; - cs4231_chip->pioregs->idr = RECGAIN_SET(old_gain, ra); + cs4231_chip->regs->iar = 0x0; + old_gain = cs4231_chip->regs->idr; + cs4231_chip->regs->idr = RECGAIN_SET(old_gain, l_adj); + cs4231_chip->regs->iar = 0x1; + old_gain = cs4231_chip->regs->idr; + cs4231_chip->regs->idr = RECGAIN_SET(old_gain, r_adj); if (l == value) { - (l == 0) ? (tmp = 0) : (tmp = ((la + 1) * AUDIO_MAX_GAIN) / (CS4231_MAX_GAIN + 1)); + (l == 0) ? (tmp = 0) : (tmp = ((l_adj + 1) * AUDIO_MAX_GAIN) / (CS4231_MAX_GAIN + 1)); } else if (r == value) { - (r == 0) ? (tmp = 0) : (tmp = ((ra + 1) * AUDIO_MAX_GAIN) / (CS4231_MAX_GAIN + 1)); + (r == 0) ? (tmp = 0) : (tmp = ((r_adj + 1) * AUDIO_MAX_GAIN) / (CS4231_MAX_GAIN + 1)); } - return (tmp); + cs4231_chip->perchip_info.record.gain = tmp; + return 0; } /* Set chip play gain */ -static unsigned int cs4231_play_gain(struct sparcaudio_driver *drv, unsigned int value, unsigned char balance) +static int cs4231_play_gain(struct sparcaudio_driver *drv, int value, unsigned char balance) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - unsigned int tmp = 0, r, l, ra, la; + int tmp = 0, r, l, r_adj, l_adj; unsigned char old_gain; + tprintk(("in play_gain: %d %c\n", value, balance)); r = l = value; if (balance < AUDIO_MID_BALANCE) { r = MAX(0, (int)(value - ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT))); @@ -264,156 +779,179 @@ l = MAX(0, (int)(value - ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT))); } - if (l == 0) { - la = CS4231_MAX_DEV_ATEN; - } else { - la = CS4231_MAX_ATEN - (l * (CS4231_MAX_ATEN + 1) / (AUDIO_MAX_GAIN + 1)); - } - if (r == 0) { - ra = CS4231_MAX_DEV_ATEN; - } else { - ra = CS4231_MAX_ATEN - (r * (CS4231_MAX_ATEN + 1) / (AUDIO_MAX_GAIN + 1)); - } + (l == 0) ? (l_adj = CS4231_MAX_DEV_ATEN) : (l_adj = CS4231_MAX_ATEN - (l * (CS4231_MAX_ATEN + 1) / (AUDIO_MAX_GAIN + 1))); + (r == 0) ? (r_adj = CS4231_MAX_DEV_ATEN) : (r_adj = CS4231_MAX_ATEN - (r * (CS4231_MAX_ATEN + 1) / (AUDIO_MAX_GAIN + 1))); - cs4231_chip->pioregs->iar = 0x6; - old_gain = cs4231_chip->pioregs->idr; - cs4231_chip->pioregs->idr = GAIN_SET(old_gain, la); - cs4231_chip->pioregs->iar = 0x7; - old_gain = cs4231_chip->pioregs->idr; - cs4231_chip->pioregs->idr = GAIN_SET(old_gain, ra); + cs4231_chip->regs->iar = 0x6; + old_gain = cs4231_chip->regs->idr; + cs4231_chip->regs->idr = GAIN_SET(old_gain, l_adj); + cs4231_chip->regs->iar = 0x7; + old_gain = cs4231_chip->regs->idr; + cs4231_chip->regs->idr = GAIN_SET(old_gain, r_adj); if ((value == 0) || (value == AUDIO_MAX_GAIN)) { tmp = value; } else { if (l == value) { - tmp = ((CS4231_MAX_ATEN - la) * (AUDIO_MAX_GAIN + 1) / (CS4231_MAX_ATEN + 1)); + tmp = ((CS4231_MAX_ATEN - l_adj) * (AUDIO_MAX_GAIN + 1) / (CS4231_MAX_ATEN + 1)); } else if (r == value) { - tmp = ((CS4231_MAX_ATEN - ra) * (AUDIO_MAX_GAIN + 1) / (CS4231_MAX_ATEN + 1)); + tmp = ((CS4231_MAX_ATEN - r_adj) * (AUDIO_MAX_GAIN + 1) / (CS4231_MAX_ATEN + 1)); } } - return (tmp); + cs4231_chip->perchip_info.play.gain = tmp; + + return 0; } /* Reset the audio chip to a sane state. */ -static void cs4231_reset(struct sparcaudio_driver *drv) +static void cs4231_chip_reset(struct sparcaudio_driver *drv) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - cs4231_chip->dmaregs.dmacsr = CS_CHIP_RESET; - cs4231_chip->dmaregs.dmacsr = 0x00; - cs4231_chip->dmaregs.dmacsr |= CS_CDC_RESET; - - udelay(100); - - cs4231_chip->dmaregs.dmacsr &= ~(CS_CDC_RESET); - cs4231_chip->pioregs->iar |= IAR_AUTOCAL_BEGIN; + tprintk(("in cs4231_chip_reset\n")); + + cs4231_chip->regs->dmacsr = CS_CHIP_RESET; + cs4231_chip->regs->dmacsr = 0x00; + cs4231_chip->regs->dmacsr |= CS_CDC_RESET; - CHIP_BUG - - cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x0c; - cs4231_chip->pioregs->idr = MISC_IR_MODE2; - cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x08; - cs4231_chip->pioregs->idr = DEFAULT_DATA_FMAT; /* Ulaw */ + udelay(20); - CHIP_BUG - - cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x1c; - cs4231_chip->pioregs->idr = DEFAULT_DATA_FMAT; /* Ulaw */ + cs4231_chip->regs->dmacsr &= ~(CS_CDC_RESET); + cs4231_chip->regs->iar |= IAR_AUTOCAL_BEGIN; - CHIP_BUG + CHIP_READY - cs4231_chip->pioregs->iar = 0x19; - + cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x0c; + cs4231_chip->regs->idr = MISC_IR_MODE2; + + /* This is the equivalent of DEFAULT_DATA_FMAT */ + cs4231_set_input_encoding(drv, AUDIO_ENCODING_ULAW); + cs4231_set_input_rate(drv, CS4231_RATE); + cs4231_set_input_channels(drv, CS4231_CHANNELS); + cs4231_set_input_precision(drv, CS4231_PRECISION); + + cs4231_set_output_encoding(drv, AUDIO_ENCODING_ULAW); + cs4231_set_output_rate(drv, CS4231_RATE); + cs4231_set_output_channels(drv, CS4231_CHANNELS); + cs4231_set_output_precision(drv, CS4231_PRECISION); + + cs4231_chip->regs->iar = 0x19; /* see what we can turn on */ - if (cs4231_chip->pioregs->idr & CS4231A) + if (cs4231_chip->regs->idr & CS4231A) { + tprintk(("This is a CS4231A\n")); cs4231_chip->status |= CS_STATUS_REV_A; - else + } else cs4231_chip->status &= ~CS_STATUS_REV_A; - cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x10; - cs4231_chip->pioregs->idr = OLB_ENABLE; + cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x10; + cs4231_chip->regs->idr = OLB_ENABLE; - cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x11; + cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x11; if (cs4231_chip->status & CS_STATUS_REV_A) - cs4231_chip->pioregs->idr = (HPF_ON | XTALE_ON); + cs4231_chip->regs->idr = (HPF_ON | XTALE_ON); else - cs4231_chip->pioregs->idr = (HPF_ON); + cs4231_chip->regs->idr = (HPF_ON); - cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x1a; - cs4231_chip->pioregs->idr = 0x00; + cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1a; + cs4231_chip->regs->idr = 0x00; /* Now set things up for defaults */ - cs4231_chip->perchip_info.play.port = cs4231_out_port(drv, AUDIO_SPEAKER); - cs4231_chip->perchip_info.record.port = cs4231_in_port(drv, AUDIO_MICROPHONE); - cs4231_chip->perchip_info.play.gain = cs4231_play_gain(drv, CS4231_DEFAULT_PLAYGAIN, AUDIO_MID_BALANCE); - cs4231_chip->perchip_info.record.gain = cs4231_record_gain(drv, CS4231_DEFAULT_RECGAIN, AUDIO_MID_BALANCE); - cs4231_chip->perchip_info.monitor_gain = cs4231_monitor_gain(drv, LOOPB_OFF); + cs4231_set_input_balance(drv, AUDIO_MID_BALANCE); + cs4231_set_output_balance(drv, AUDIO_MID_BALANCE); + + cs4231_set_input_volume(drv, CS4231_DEFAULT_RECGAIN); + cs4231_set_output_volume(drv, CS4231_DEFAULT_PLAYGAIN); + + cs4231_set_input_port(drv, AUDIO_MICROPHONE); + cs4231_set_output_port(drv, AUDIO_SPEAKER); + + cs4231_set_monitor_volume(drv, LOOPB_OFF); - cs4231_chip->pioregs->iar = (u_char)IAR_AUTOCAL_END; + cs4231_chip->regs->iar = IAR_AUTOCAL_END; cs4231_ready(drv); - cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x09; - cs4231_chip->pioregs->idr &= ACAL_DISABLE; - cs4231_chip->pioregs->iar = (u_char)IAR_AUTOCAL_END; + cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x09; + cs4231_chip->regs->idr &= ACAL_DISABLE; + cs4231_chip->regs->iar = IAR_AUTOCAL_END; cs4231_ready(drv); cs4231_output_muted(drv, 0); + + cs4231_chip->recording_count = 0; + cs4231_chip->playing_count = 0; } -static void cs4231_mute(struct sparcaudio_driver *drv) +static int +cs4231_length_to_samplecount(struct audio_prinfo *thisdir, unsigned int length) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + unsigned int count; - if (!(cs4231_chip->status & CS_STATUS_REV_A)) { - cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN; - udelay(100); - cs4231_chip->pioregs->iar = IAR_AUTOCAL_END; - CHIP_BUG - } + if (thisdir->channels == 2) + count = (length/2); + else + count = length; + + if (thisdir->encoding == AUDIO_ENCODING_LINEAR) + count = (count/2); + else if (thisdir->encoding == AUDIO_ENCODING_DVI) + count = (count/4); + + return count; } -/* Not yet useful */ -#if 0 -static int cs4231_len_to_sample(struct sparcaudio_driver *drv, int length, int direction) +static void cs4231_getsamplecount(struct sparcaudio_driver *drv, unsigned int length, unsigned int direction) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int sample; + struct audio_prinfo *thisdir; + unsigned int count, nextcount, curcount; - if (/* number of channels == 2*/0) { - sample = (length/2); - } else { - sample = length; - } - if (/*encoding == AUDIO_ENCODING_LINEAR*/0) { - sample = sample/2; - } - return (sample); + if (direction == 1) /* record */ + { + thisdir = &cs4231_chip->perchip_info.record; + curcount = + cs4231_length_to_samplecount(thisdir, cs4231_chip->regs->dmacc); + nextcount = + cs4231_length_to_samplecount(thisdir, cs4231_chip->regs->dmacnc); + } + else /* play */ + { + thisdir = &cs4231_chip->perchip_info.play; + curcount = + cs4231_length_to_samplecount(thisdir, cs4231_chip->regs->dmapc); + nextcount = + cs4231_length_to_samplecount(thisdir, cs4231_chip->regs->dmapnc); + } + count = thisdir->samples; + length = cs4231_length_to_samplecount(thisdir, length); + thisdir->samples = ((count - nextcount) + (length - curcount)); } -#endif static int cs4231_open(struct inode * inode, struct file * file, struct sparcaudio_driver *drv) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - /* Set the default audio parameters. */ - - cs4231_chip->perchip_info.play.sample_rate = CS4231_RATE; - cs4231_chip->perchip_info.play.channels = CS4231_CHANNELS; - cs4231_chip->perchip_info.play.precision = CS4231_PRECISION; - cs4231_chip->perchip_info.play.encoding = AUDIO_ENCODING_ULAW; - - cs4231_chip->perchip_info.record.sample_rate = CS4231_RATE; - cs4231_chip->perchip_info.record.channels = CS4231_CHANNELS; - cs4231_chip->perchip_info.record.precision = CS4231_PRECISION; - cs4231_chip->perchip_info.record.encoding = AUDIO_ENCODING_ULAW; - + /* Set the default audio parameters if not already in use. */ + if (file->f_mode & FMODE_WRITE) { + if (!(drv->flags & SDF_OPEN_WRITE) && + (cs4231_chip->perchip_info.play.active == 0)) { + cs4231_chip->perchip_info.play.open = 1; + cs4231_set_output_port(drv, AUDIO_SPEAKER); + } + } + + if (file->f_mode & FMODE_READ) { + if (!(drv->flags & SDF_OPEN_READ) && + (cs4231_chip->perchip_info.record.active == 0)) { + cs4231_chip->perchip_info.record.open = 1; + cs4231_set_input_port(drv, AUDIO_MICROPHONE); + } + } + cs4231_ready(drv); - cs4231_chip->status |= CS_STATUS_NEED_INIT; - - CHIP_BUG + CHIP_READY MOD_INC_USE_COUNT; @@ -422,31 +960,48 @@ static void cs4231_release(struct inode * inode, struct file * file, struct sparcaudio_driver *drv) { + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + /* zero out any info about what data we have as well */ - /* should insert init on close variable optionally calling cs4231_reset() */ + + if (file->f_mode & FMODE_READ) + cs4231_chip->perchip_info.record.open = 0; + + if (file->f_mode & FMODE_WRITE) + cs4231_chip->perchip_info.play.open = 0; + + if (!cs4231_chip->perchip_info.play.open && !cs4231_chip->perchip_info.record.open && (cs4231_chip->status & CS_STATUS_INIT_ON_CLOSE)) { + cs4231_chip_reset(drv); + cs4231_chip->status &= ~CS_STATUS_INIT_ON_CLOSE; + } + MOD_DEC_USE_COUNT; } -static int cs4231_playintr(struct sparcaudio_driver *drv) +static void cs4231_playintr(struct sparcaudio_driver *drv) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - /* Send the next byte of outgoing data. */ -#if 0 - if (cs4231_chip->output_ptr && cs4231_chip->output_count > 0) { - cs4231_chip->dmaregs.dmapnva = dma_handle; - cs4231_chip->dmaregs.dmapnc = length; - cs4231_chip->output_ptr++; - cs4231_chip->output_count--; - - /* Done with the buffer? Notify the midlevel driver. */ - if (cs4231_chip->output_count == 0) { - cs4231_chip->output_ptr = NULL; - cs4231_chip->output_count = 0; - sparcaudio_output_done(drv); - } + if (cs4231_chip->playlen == 0) + cs4231_chip->playlen = cs4231_chip->output_size; + + if (cs4231_chip->output_ptr && cs4231_chip->output_size > 0) { + cs4231_chip->regs->dmapnva = (__u32) cs4231_chip->output_ptr; + cs4231_chip->regs->dmapnc = cs4231_chip->output_size; + cs4231_chip->output_size = 0; + cs4231_chip->output_ptr = NULL; + cs4231_chip->playing_count++; + } + + /* Get two buffers into the pipe, then chain... */ + if (cs4231_chip->playing_count < 3) + sparcaudio_output_done(drv, 0); + else { + cs4231_chip->playing_count--; + sparcaudio_output_done(drv, 1); } -#endif + + return; } static void cs4231_recmute(int fmt) @@ -468,72 +1023,55 @@ { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - cs4231_recmute(cs4231_chip->perchip_info.record.encoding); - if (cs4231_chip->perchip_info.record.active == 0) { cs4231_pollinput(drv); - cs4231_chip->pioregs->iar = 0x9; - cs4231_chip->pioregs->idr &= CEN_DISABLE; + cs4231_recmute(cs4231_chip->perchip_info.record.encoding); + cs4231_disable_rec(drv); } - /* Read the next byte of incoming data. */ -#if 0 - if (cs4231_chip->input_ptr && cs4231_chip->input_count > 0) { - cs4231_chip->dmaregs.dmacnva = dma_handle; - cs4231_chip->dmaregs.dmacnc = length; - cs4231_chip->input_ptr++; - cs4231_chip->input_count--; - - /* Done with the buffer? Notify the midlevel driver. */ - if (cs4231_chip->input_count == 0) { - cs4231_chip->input_ptr = NULL; - cs4231_chip->input_count = 0; - sparcaudio_input_done(drv); - } + if (cs4231_chip->input_ptr) { + cs4231_chip->regs->dmacnva = (__u32) cs4231_chip->input_ptr; + cs4231_chip->regs->dmacnc = cs4231_chip->input_size; + cs4231_chip->input_ptr = NULL; + cs4231_chip->input_size = 0; + sparcaudio_input_done(drv); } -#endif + return 1; } static void cs4231_start_output(struct sparcaudio_driver *drv, __u8 * buffer, unsigned long count) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + cs4231_chip->output_ptr = buffer; + cs4231_chip->output_size = count; + if (cs4231_chip->perchip_info.play.active || (cs4231_chip->perchip_info.play.pause)) return; cs4231_ready(drv); - if (cs4231_chip->status & CS_STATUS_NEED_INIT) - { - cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x08; - cs4231_chip->pioregs->idr = DEFAULT_DATA_FMAT; - cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x1c; - cs4231_chip->pioregs->idr = DEFAULT_DATA_FMAT; - - CHIP_BUG - - cs4231_chip->status &= ~CS_STATUS_NEED_INIT; - } - - if (!cs4231_chip->perchip_info.play.pause) - { - /* init dma foo here */ - cs4231_chip->dmaregs.dmacsr &= ~CS_XINT_PLAY; - cs4231_chip->dmaregs.dmacsr &= ~CS_PPAUSE; - if (cs4231_playintr(drv)) { - cs4231_chip->dmaregs.dmacsr |= CS_PLAY_SETUP; - cs4231_chip->pioregs->iar = 0x9; - cs4231_chip->pioregs->idr |= PEN_ENABLE; - } - } cs4231_chip->perchip_info.play.active = 1; + + cs4231_chip->playing_count = 0; + cs4231_disable_play(drv); + cs4231_chip->regs->dmacsr &= ~CS_XINT_PLAY; + cs4231_chip->regs->dmacsr &= ~CS_PPAUSE; + cs4231_playintr(drv); + cs4231_enable_play(drv); + cs4231_chip->regs->dmacsr |= CS_PLAY_SETUP; + cs4231_output_muted(drv, 0); + cs4231_ready(drv); } static void cs4231_stop_output(struct sparcaudio_driver *drv) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + tprintk(("in cs4231_stop_output\n")); + cs4231_chip->output_ptr = NULL; + cs4231_chip->output_size = 0; cs4231_chip->perchip_info.play.active = 0; - cs4231_chip->dmaregs.dmacsr |= (CS_PPAUSE); + cs4231_chip->regs->dmacsr |= (CS_PPAUSE); } static void cs4231_pollinput(struct sparcaudio_driver *drv) @@ -541,10 +1079,10 @@ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; int x = 0; - while (!(cs4231_chip->dmaregs.dmacsr & CS_XINT_COVF) && x <= CS_TIMEOUT) { + while (!(cs4231_chip->regs->dmacsr & CS_XINT_COVF) && x <= CS_TIMEOUT) { x++; } - cs4231_chip->dmaregs.dmacsr |= CS_XINT_CEMP; + cs4231_chip->regs->dmacsr |= CS_XINT_CEMP; } static void cs4231_start_input(struct sparcaudio_driver *drv, __u8 * buffer, unsigned long count) @@ -556,29 +1094,14 @@ cs4231_ready(drv); - if (cs4231_chip->status & CS_STATUS_NEED_INIT) - { - cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x08; - cs4231_chip->pioregs->idr = DEFAULT_DATA_FMAT; - cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x1c; - cs4231_chip->pioregs->idr = DEFAULT_DATA_FMAT; - - CHIP_BUG - - cs4231_chip->status &= ~CS_STATUS_NEED_INIT; - } - - if (!cs4231_chip->perchip_info.record.pause) - { - /* init dma foo here */ - cs4231_chip->dmaregs.dmacsr &= ~CS_XINT_CAPT; - cs4231_chip->dmaregs.dmacsr &= ~CS_CPAUSE; - cs4231_recintr(drv); - cs4231_chip->dmaregs.dmacsr |= CS_CAPT_SETUP; - cs4231_chip->pioregs->iar = 0x9; - cs4231_chip->pioregs->idr |= CEN_ENABLE; - } cs4231_chip->perchip_info.record.active = 1; + cs4231_chip->recording_count = 0; + /* init dma foo here */ + cs4231_chip->regs->dmacsr &= ~CS_XINT_CAPT; + cs4231_chip->regs->dmacsr &= ~CS_CPAUSE; + cs4231_recintr(drv); + cs4231_chip->regs->dmacsr |= CS_CAPT_SETUP; + cs4231_enable_rec(drv); } static void cs4231_stop_input(struct sparcaudio_driver *drv) @@ -586,43 +1109,166 @@ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; cs4231_chip->perchip_info.record.active = 0; - cs4231_chip->dmaregs.dmacsr |= (CS_CPAUSE); + cs4231_chip->regs->dmacsr |= (CS_CPAUSE); cs4231_pollinput(drv); /* need adjust the end pointer, process the input, and clean up the dma */ - cs4231_chip->pioregs->iar = 0x09; - cs4231_chip->pioregs->idr &= CEN_DISABLE; + cs4231_disable_rec(drv); } static void cs4231_audio_getdev(struct sparcaudio_driver *drv, audio_device_t * audinfo) { - strncpy(audinfo->name, "cs4231", sizeof(audinfo->name) - 1); - strncpy(audinfo->version, "x", sizeof(audinfo->version) - 1); - strncpy(audinfo->config, "audio", sizeof(audinfo->config) - 1); + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + + strncpy(audinfo->name, "SUNW,CS4231", sizeof(audinfo->name) - 1); + /* versions: SPARCstation 4/5=a, Ultra=b */ + if (cs4231_chip->status & CS_STATUS_IS_ULTRA) + strncpy(audinfo->version, "b", sizeof(audinfo->version) - 1); + else + strncpy(audinfo->version, "a", sizeof(audinfo->version) - 1); + strncpy(audinfo->config, "onboard1", sizeof(audinfo->config) - 1); +} + + +static int cs4231_audio_getdev_sunos(struct sparcaudio_driver *drv) +{ + return AUDIO_DEV_CS4231; } +static void cs4231_loopback(struct sparcaudio_driver *drv, unsigned int value) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + + cs4231_chip->regs->iar = 0x0d; + cs4231_chip->regs->idr = (value ? LOOPB_ON : 0); +} + +static int cs4231_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg, + struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + int retval = 0; + + switch (cmd) { + case AUDIO_DIAG_LOOPBACK: + cs4231_chip->status |= CS_STATUS_INIT_ON_CLOSE; + cs4231_loopback(drv, (unsigned int)arg); + break; + default: + retval = -EINVAL; + } + + return retval; +} -/* The ioctl handler should be expected to identify itself and handle loopback - mode */ -/* There will also be a handler for getinfo and setinfo */ + +/* Audio interrupt handler. */ +void cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct sparcaudio_driver *drv = (struct sparcaudio_driver *)dev_id; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + __u32 dummy; + + tprintk(("in cs4231_interrupt\n")); + + /* Clear the interrupt. */ + dummy = cs4231_chip->regs->dmacsr; + cs4231_chip->regs->dmacsr = dummy; + + /* now go through and figure out what gets to claim the interrupt + * if anything since we may be doing shared interrupts + */ + + if (dummy & CS_PLAY_INT) { + if (dummy & CS_XINT_PNVA) { + cs4231_chip->perchip_info.play.samples += + cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play), + cs4231_chip->playlen); + cs4231_playintr(drv); + } + } + + if (dummy & CS_CAPT_INT) { + if (dummy & CS_XINT_CNVA) { + cs4231_chip->perchip_info.record.samples += + cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), + cs4231_chip->reclen); + cs4231_recintr(drv); + } + } + if ((dummy & CS_XINT_CEMP) + && (cs4231_chip->perchip_info.record.active == 0)) + { + cs4231_chip->perchip_info.record.active = 0; + } + if ((dummy & CS_XINT_EMPT) && (cs4231_chip->perchip_info.play.active == 0)) { + cs4231_chip->regs->dmacsr |= (CS_PPAUSE); + cs4231_disable_play(drv); + cs4231_output_muted(drv, 1); + + cs4231_getsamplecount(drv, cs4231_chip->playlen, 0); + } + + if (dummy & CS_GENL_INT) { + /* If we get here we must be sharing an interrupt, but I haven't code + to handle this right now */ + } + +} static struct sparcaudio_operations cs4231_ops = { cs4231_open, cs4231_release, - NULL, /* cs4231_ioctl */ + cs4231_ioctl, cs4231_start_output, cs4231_stop_output, cs4231_start_input, cs4231_stop_input, cs4231_audio_getdev, + cs4231_set_output_volume, + cs4231_get_output_volume, + cs4231_set_input_volume, + cs4231_get_input_volume, + cs4231_set_monitor_volume, + cs4231_get_monitor_volume, + cs4231_set_output_balance, + cs4231_get_output_balance, + cs4231_set_input_balance, + cs4231_get_input_balance, + cs4231_set_output_channels, + cs4231_get_output_channels, + cs4231_set_input_channels, + cs4231_get_input_channels, + cs4231_set_output_precision, + cs4231_get_output_precision, + cs4231_set_input_precision, + cs4231_get_input_precision, + cs4231_set_output_port, + cs4231_get_output_port, + cs4231_set_input_port, + cs4231_get_input_port, + cs4231_set_output_encoding, + cs4231_get_output_encoding, + cs4231_set_input_encoding, + cs4231_get_input_encoding, + cs4231_set_output_rate, + cs4231_get_output_rate, + cs4231_set_input_rate, + cs4231_get_input_rate, + cs4231_audio_getdev_sunos, + cs4231_get_output_ports, + cs4231_get_input_ports, + cs4231_output_muted, + cs4231_get_output_muted, }; /* Attach to an cs4231 chip given its PROM node. */ -static inline int -cs4231_attach(struct sparcaudio_driver *drv, struct linux_sbus_device *sdev) +static int cs4231_attach(struct sparcaudio_driver *drv, + struct linux_sbus_device *sdev) { struct cs4231_chip *cs4231_chip; int err; @@ -639,57 +1285,76 @@ /* Point at the information structure and initialize it. */ drv->ops = &cs4231_ops; cs4231_chip = (struct cs4231_chip *)drv->private; -#if 0 - cs4231_chip->input_ptr = NULL; - cs4231_chip->input_count = 0; - cs4231_chip->output_ptr = NULL; - cs4231_chip->output_count = 0; -#endif + cs4231_chip->input_ptr = cs4231_chip->output_ptr = NULL; + cs4231_chip->input_size = cs4231_chip->output_size = 0; + cs4231_chip->status = 0; /* Map the registers into memory. */ prom_apply_sbus_ranges(sbus, sdev->reg_addrs, 1, sdev); cs4231_chip->regs_size = sdev->reg_addrs[0].reg_size; - cs4231_chip->pioregs = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, - sdev->reg_addrs[0].reg_size, - "cs4231", sdev->reg_addrs[0].which_io, 0); - if (!cs4231_chip->pioregs) { + cs4231_chip->regs = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, + sdev->reg_addrs[0].reg_size, + "cs4231", sdev->reg_addrs[0].which_io, + 0); + + if (!cs4231_chip->regs) { printk(KERN_ERR "cs4231: could not allocate registers\n"); kfree(drv->private); return -EIO; } - /* Reset the audio chip. */ - cs4231_reset(drv); - /* Attach the interrupt handler to the audio interrupt. */ cs4231_chip->irq = sdev->irqs[0].pri; #ifndef __sparc_v9__ request_irq(cs4231_chip->irq, cs4231_interrupt, SA_SHIRQ, "cs4231", drv); #else - dcookie.real_dev_id = s; + dcookie.real_dev_id = drv; dcookie.imap = dcookie.iclr = 0; dcookie.pil = -1; dcookie.bus_cookie = sdev->my_bus; - request_irq (cs4231_chip->irq, cs4231_interrupt, (SA_SHIRQ | SA_SBUS | SA_DCOOKIE), "cs4231", drv); + request_irq (cs4231_chip->irq, cs4231_interrupt, (SA_SHIRQ | SA_SBUS | SA_DCOOKIE), "cs4231", &dcookie); cs4231_chip->irq = dcookie.ret_ino; #endif enable_irq(cs4231_chip->irq); + cs4231_enable_interrupts(drv); + + /* Reset the audio chip. */ + cs4231_chip_reset(drv); + /* Register ourselves with the midlevel audio driver. */ err = register_sparcaudio_driver(drv); + if (err < 0) { printk(KERN_ERR "cs4231: unable to register\n"); + cs4231_disable_interrupts(drv); disable_irq(cs4231_chip->irq); free_irq(cs4231_chip->irq, drv); - sparc_free_io(cs4231_chip->pioregs, cs4231_chip->regs_size); + sparc_free_io(cs4231_chip->regs, cs4231_chip->regs_size); kfree(drv->private); return -EIO; } + cs4231_chip->perchip_info.play.active = + cs4231_chip->perchip_info.play.pause = 0; + + cs4231_chip->perchip_info.record.active = + cs4231_chip->perchip_info.record.pause = 0; + + cs4231_chip->perchip_info.play.avail_ports = (AUDIO_HEADPHONE | + AUDIO_SPEAKER | + AUDIO_LINE_OUT); + + cs4231_chip->perchip_info.record.avail_ports = (AUDIO_INTERNAL_CD_IN | + AUDIO_LINE_IN | + AUDIO_MICROPHONE | + AUDIO_ANALOG_LOOPBACK); + /* Announce the hardware to the user. */ - printk(KERN_INFO "cs4231 at 0x%lx irq %d\n", - (unsigned long)cs4231_chip->pioregs, cs4231_chip->irq); + printk(KERN_INFO "cs4231%c at 0x%lx irq %d\n", + (cs4231_chip->status & CS_STATUS_REV_A) ? 'a' : ' ', + (unsigned long)cs4231_chip->regs, cs4231_chip->irq); /* Success! */ return 0; @@ -705,6 +1370,8 @@ struct linux_sbus *bus; struct linux_sbus_device *sdev; + num_drivers = 0; + /* Probe each SBUS for cs4231 chips. */ for_all_sbusdev(sdev,bus) { if (!strcmp(sdev->prom_name, "SUNW,CS4231")) { @@ -727,10 +1394,11 @@ { struct cs4231_chip *info = (struct cs4231_chip *)drv->private; + cs4231_disable_interrupts(drv); unregister_sparcaudio_driver(drv); disable_irq(info->irq); free_irq(info->irq, drv); - sparc_free_io(info->pioregs, info->regs_size); + sparc_free_io(info->regs, info->regs_size); kfree(drv->private); } @@ -745,3 +1413,21 @@ } #endif +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 4 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -4 + * c-argdecl-indent: 4 + * c-label-offset: -4 + * c-continued-statement-offset: 4 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/audio/cs4231.h linux/drivers/sbus/audio/cs4231.h --- v2.1.100/linux/drivers/sbus/audio/cs4231.h Mon Mar 17 14:54:28 1997 +++ linux/drivers/sbus/audio/cs4231.h Fri May 8 00:23:41 1998 @@ -10,65 +10,83 @@ #include +/* According to the CS4231A data provided on CS web site and sun's includes */ + struct cs4231_regs { - u_char iar; /* Index Address Register */ - u_char pad0[3]; - u_char idr; /* Indexed Data Register */ - u_char pad1[3]; - u_char statr; /* Status Register */ - u_char pad2[3]; - u_char piodr; /* PIO Data Register I/O */ - u_char pad3[3]; + __volatile__ __u8 iar; /* Index Address Register */ + __volatile__ __u8 pad0[3]; + __volatile__ __u8 idr; /* Indexed Data Register */ + __volatile__ __u8 pad1[3]; + __volatile__ __u8 statr; /* Status Register */ + __volatile__ __u8 pad2[3]; + __volatile__ __u8 piodr; /* PIO Data Register */ + __volatile__ __u8 pad3[3]; + __volatile__ __u32 dmacsr; /* APC CSR */ + __volatile__ __u32 dmapad[3]; + __volatile__ __u32 dmacva; /* Capture Virtual Address */ + __volatile__ __u32 dmacc; /* Capture Count */ + __volatile__ __u32 dmacnva; /* Capture Next Virtual Address */ + __volatile__ __u32 dmacnc; /* Capture Next Count */ + __volatile__ __u32 dmapva; /* Playback Virtual Address */ + __volatile__ __u32 dmapc; /* Playback Count */ + __volatile__ __u32 dmapnva; /* Playback Next Virtual Address */ + __volatile__ __u32 dmapnc; /* Playback Next Count */ }; -struct cs4231_dma { - u_long dmacsr; /* APC CSR */ - u_long dmapad[3]; - u_long dmacva; /* Capture Virtual Address */ - u_long dmacc; /* Capture Count */ - u_long dmacnva; /* Capture Next Virtual Address */ - u_long dmacnc; /* Capture Next Count */ - u_long dmapva; /* Playback Virtual Address */ - u_long dmapc; /* Playback Count */ - u_long dmapnva; /* Playback Next Virtual Address */ - u_long dmapnc; /* Playback Next Count */ -}; +/* Our structure for each chip */ struct cs4231_chip { - struct cs4231_regs *pioregs; - struct cs4231_dma dmaregs; - struct audio_info perchip_info; - int irq; - unsigned long regs_size; - - /* Keep track of various info */ - volatile unsigned int status; - - int dma; - int dma2; + struct cs4231_regs *regs; + struct audio_info perchip_info; + unsigned int playlen, reclen; + int irq; + unsigned long regs_size; + + /* Keep track of various info */ + volatile unsigned int status; + + /* Current buffer that the driver is playing. */ + volatile __u8 * output_ptr; + volatile unsigned long output_size; + + /* Current record buffer. */ + volatile __u8 * input_ptr; + volatile unsigned long input_size; + + /* Number of buffers in the pipe. */ + volatile unsigned long playing_count; + volatile unsigned long recording_count; }; -/* Status bits */ +/* Local status bits */ #define CS_STATUS_NEED_INIT 0x01 #define CS_STATUS_INIT_ON_CLOSE 0x02 #define CS_STATUS_REV_A 0x04 +#define CS_STATUS_INTS_ON 0x08 +#define CS_STATUS_IS_ULTRA 0x10 #define CS_TIMEOUT 9000000 #define GAIN_SET(var, gain) ((var & ~(0x3f)) | gain) #define RECGAIN_SET(var, gain) ((var & ~(0x1f)) | gain) -#define IAR_AUTOCAL_BEGIN 0x40 /* IAR_MCE */ -#define IAR_AUTOCAL_END ~(0x40) /* IAR_MCD */ -#define IAR_NOT_READY 0x80 /* 80h not ready CODEC state */ +/* bits 0-3 set address of register accessed by idr register */ +/* bit 4 allows access to idr registers 16-31 in mode 2 only */ +/* bit 5 if set causes dma transfers to cease if the int bit of status set */ +#define IAR_AUTOCAL_BEGIN 0x40 /* MCE */ +#define IAR_NOT_READY 0x80 /* INIT */ -/* Each register assumed mode 1 and 2 unless noted */ +#define IAR_AUTOCAL_END ~(IAR_AUTOCAL_BEGIN) /* MCD */ + +/* Registers 1-15 modes 1 and 2. Registers 16-31 mode 2 only */ +/* Registers assumed to be same in both modes unless noted */ /* 0 - Left Input Control */ /* 1 - Right Input Control */ #define MIC_ENABLE(var) ((var & 0x2f) | 0x80) #define LINE_ENABLE(var) (var & 0x2f) #define CDROM_ENABLE(var) ((var & 0x2f) | 0x40) +#define OUTPUTLOOP_ENABLE(var) ((var & 0x2f) | 0xC0) #define INPUTCR_AUX1 0x40 /* 2 - Left Aux 1 Input Control */ @@ -85,31 +103,41 @@ #define CHANGE_DFR(var, val) ((var & ~(0xF)) | val) #define CHANGE_ENCODING(var, val) ((var & ~(0xe0)) | val) #define DEFAULT_DATA_FMAT CS4231_DFR_ULAW +#define CS4231_DFR_5512 0x01 +#define CS4231_DFR_6615 0x0f #define CS4231_DFR_8000 0x00 #define CS4231_DFR_9600 0x0e #define CS4231_DFR_11025 0x03 #define CS4231_DFR_16000 0x02 #define CS4231_DFR_18900 0x05 #define CS4231_DFR_22050 0x07 +#define CS4231_DFR_27429 0x04 #define CS4231_DFR_32000 0x06 +#define CS4231_DFR_33075 0x0d #define CS4231_DFR_37800 0x09 #define CS4231_DFR_44100 0x0b #define CS4231_DFR_48000 0x0c #define CS4231_DFR_LINEAR8 0x00 #define CS4231_DFR_ULAW 0x20 +#define CS4231_DFR_LINEARLE 0x40 #define CS4231_DFR_ALAW 0x60 -#define CS4231_DFR_ADPCM 0xa0 -#define CS4231_DFR_LINEARBE 0xc0 +#define CS4231_DFR_ADPCM 0xa0 /* N/A in mode 1 */ +#define CS4231_DFR_LINEARBE 0xc0 /* N/A in mode 1 */ #define CS4231_STEREO_ON(val) (val | 0x10) #define CS4231_MONO_ON(val) (val & ~0x10) /* 9 - Interface Config. Register */ -#define CHIP_INACTIVE 0x08 -#define PEN_ENABLE (0x01) +#define PEN_ENABLE (0x01) /* Playback Enable */ #define PEN_DISABLE (~0x01) -#define CEN_ENABLE (0x02) +#define CEN_ENABLE (0x02) /* Capture Enable */ #define CEN_DISABLE (~0x02) -#define ACAL_DISABLE (~0x08) +#define SDC_ENABLE (0x04) /* Turn on single DMA Channel mode */ +#define ACAL_CONV 0x08 /* Turn on converter autocal */ +#define ACAL_DISABLE (~0x08) +#define ACAL_DAC 0x10 /* Turn on DAC autocal */ +#define ACAL_FULL (ACAL_DAC|ACAL_CONV) /* Turn on full autocal */ +#define PPIO 0x20 /* do playback via PIO rather than DMA */ +#define CPIO 0x40 /* do capture via PIO rather than DMA */ #define ICR_AUTOCAL_INIT 0x01 /* 10 - Pin Control Register */ @@ -129,8 +157,8 @@ #define LOOPB_ON 0x01 #define LOOPB_OFF 0x00 -/* 14 - Unused (mode 1) */ -/* 15 - Unused (mode 1) */ +/* 14 - shared play/capture upper (mode 1) */ +/* 15 - shared play/capture lower (mode 1) */ /* 14 - Playback Upper (mode 2) */ /* 15 - Playback Lower (mode 2) */ @@ -138,11 +166,16 @@ /* The rest are mode 2 only */ /* 16 - Alternate Feature 1 Enable */ -#define OLB_ENABLE 0x80 +#define DAC_ZERO 0x01 +#define PLAY_MCE 0x10 +#define CAPTURE_MCE 0x20 +#define TIMER_ENABLE 0x40 +#define OLB_ENABLE 0x80 /* go to 2.88 vpp analog output */ /* 17 - Alternate Feature 2 Enable */ -#define HPF_ON 0x01 -#define XTALE_ON 0x20 +#define HPF_ON 0x01 /* High Pass Filter */ +#define XTALE_ON 0x02 /* Enable both crystals */ +#define APAR_OFF 0x04 /* ADPCM playback accum reset */ /* 18 - Left Line Input Gain */ /* 19 - Right Line Input Gain */ @@ -151,11 +184,18 @@ /* 21 - Timer Low */ /* 22 - unused */ -/* 23 - unused */ + +/* 23 - Alt. Fea. Ena 3 */ +#define ACF 0x01 /* 24 - Alternate Feature Status */ #define CS_PU 0x01 /* Underrun */ -#define CS_PO 0x20 /* Overrun */ +#define CS_PO 0x02 /* Overrun */ +#define CS_CU 0x04 /* Underrun */ +#define CS_CO 0x08 /* Overrun */ +#define CS_PI 0x10 +#define CS_CI 0x20 +#define CS_TI 0x40 /* 25 - Version */ #define CS4231A 0x20 @@ -163,7 +203,9 @@ /* 26 - Mono I/O Control */ #define CHANGE_MONO_GAIN(val) ((val & ~(0xFF)) | val) +#define MONO_IOCR_BYPASS 0x20 #define MONO_IOCR_MUTE 0x40 +#define MONO_IOCR_INMUTE 0x80 /* 27 - Unused */ @@ -176,29 +218,29 @@ /* 31 - Capture Lower */ /* Following are CSR register definitions for the Sparc */ -/* Also list "Solaris" equivs for now, not really useful tho */ -#define CS_INT_PENDING 0x800000 /* APC_IP */ /* Interrupt Pending */ -#define CS_PLAY_INT 0x400000 /* APC_PI */ /* Playback interrupt */ -#define CS_CAPT_INT 0x200000 /* APC_CI */ /* Capture interrupt */ -#define CS_GENL_INT 0x100000 /* APC_EI */ /* General interrupt */ -#define CS_XINT_ENA 0x80000 /* APC_IE */ /* General ext int. enable */ -#define CS_XINT_PLAY 0x40000 /* APC_PIE */ /* Playback ext intr */ -#define CS_XINT_CAPT 0x20000 /* APC_CIE */ /* Capture ext intr */ -#define CS_XINT_GENL 0x10000 /* APC_EIE */ /* Error ext intr */ -#define CS_XINT_EMPT 0x8000 /* APC_PMI */ /* Pipe empty interrupt */ -#define CS_XINT_PEMP 0x4000 /* APC_PM */ /* Play pipe empty */ -#define CS_XINT_PNVA 0x2000 /* APC_PD */ /* Playback NVA dirty */ -#define CS_XINT_PENA 0x1000 /* APC_PMIE */ /* play pipe empty Int enable */ -#define CS_XINT_COVF 0x800 /* APC_CM */ /* Cap data dropped on floor */ -#define CS_XINT_CNVA 0x400 /* APC_CD */ /* Capture NVA dirty */ -#define CS_XINT_CEMP 0x200 /* APC_CMI */ /* Capture pipe empty interrupt */ -#define CS_XINT_CENA 0x100 /* APC_CMIE */ /* Cap. pipe empty int enable */ -#define CS_PPAUSE 0x80 /* APC_PPAUSE */ /* Pause the play DMA */ -#define CS_CPAUSE 0x40 /* APC_CPAUSE */ /* Pause the capture DMA */ -#define CS_CDC_RESET 0x20 /* APC_CODEC_PDN */ /* CODEC RESET */ -#define PDMA_READY 0x08 /* PDMA_GO */ -#define CDMA_READY 0x04 /* CDMA_GO */ -#define CS_CHIP_RESET 0x01 /* APC_RESET */ /* Reset the chip */ + +#define CS_INT_PENDING 0x800000 /* Interrupt Pending */ +#define CS_PLAY_INT 0x400000 /* Playback interrupt */ +#define CS_CAPT_INT 0x200000 /* Capture interrupt */ +#define CS_GENL_INT 0x100000 /* General interrupt */ +#define CS_XINT_ENA 0x80000 /* General ext int. enable */ +#define CS_XINT_PLAY 0x40000 /* Playback ext intr */ +#define CS_XINT_CAPT 0x20000 /* Capture ext intr */ +#define CS_XINT_GENL 0x10000 /* Error ext intr */ +#define CS_XINT_EMPT 0x8000 /* Pipe empty interrupt */ +#define CS_XINT_PEMP 0x4000 /* Play pipe empty */ +#define CS_XINT_PNVA 0x2000 /* Playback NVA dirty */ +#define CS_XINT_PENA 0x1000 /* play pipe empty Int enable */ +#define CS_XINT_COVF 0x800 /* Cap data dropped on floor */ +#define CS_XINT_CNVA 0x400 /* Capture NVA dirty */ +#define CS_XINT_CEMP 0x200 /* Capture pipe empty interrupt */ +#define CS_XINT_CENA 0x100 /* Cap. pipe empty int enable */ +#define CS_PPAUSE 0x80 /* Pause the play DMA */ +#define CS_CPAUSE 0x40 /* Pause the capture DMA */ +#define CS_CDC_RESET 0x20 /* CODEC RESET */ +#define PDMA_READY 0x08 /* Play DMA Go */ +#define CDMA_READY 0x04 /* Capture DMA Go */ +#define CS_CHIP_RESET 0x01 /* Reset the chip */ #define CS_INIT_SETUP (CDMA_READY | PDMA_READY | CS_XINT_ENA | CS_XINT_PLAY | CS_XINT_GENL | CS_INT_PENDING | CS_PLAY_INT | CS_CAPT_INT | CS_GENL_INT) @@ -223,8 +265,5 @@ #define CS4231_CHANNELS (1) /* channels/sample */ #define CS4231_RATE (8000) /* default sample rate */ -/* Other rates supported are: - * 9600, 11025, 16000, 18900, 22050, 32000, 37800, 44100, 48000 - */ #endif diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/bwtwo.c linux/drivers/sbus/char/bwtwo.c --- v2.1.100/linux/drivers/sbus/char/bwtwo.c Sat Apr 25 18:13:11 1998 +++ linux/drivers/sbus/char/bwtwo.c Fri May 8 00:23:41 1998 @@ -1,4 +1,4 @@ -/* $Id: bwtwo.c,v 1.20 1998/03/10 20:18:22 jj Exp $ +/* $Id: bwtwo.c,v 1.21 1998/04/24 12:29:53 davem Exp $ * bwtwo.c: bwtwo console driver * * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/creator.c linux/drivers/sbus/char/creator.c --- v2.1.100/linux/drivers/sbus/char/creator.c Thu Apr 23 20:21:34 1998 +++ linux/drivers/sbus/char/creator.c Fri May 8 00:23:41 1998 @@ -1,4 +1,4 @@ -/* $Id: creator.c,v 1.14 1998/03/10 20:18:32 jj Exp $ +/* $Id: creator.c,v 1.15 1998/04/13 07:26:55 davem Exp $ * creator.c: Creator/Creator3D frame buffer driver * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -507,11 +507,10 @@ sbus_hw_hide_cursor (); } -__initfunc(static unsigned long ffb_postsetup (fbinfo_t *fb, unsigned long memory_start)) +__initfunc(static void ffb_postsetup (fbinfo_t *fb)) { - fb->info.ffb.clut = (u32 *)(memory_start); - fb->color_map = (u8 *)(memory_start+256*4); - return memory_start + 256*4 + 256*3; + fb->info.ffb.clut = kmalloc(256 * 4, GFP_ATOMIC); + fb->color_map = kmalloc(256 * 3, GFP_ATOMIC); } __initfunc(void creator_setup (fbinfo_t *fb, int slot, int ffb_node, unsigned long ffb, int ffb_io)) diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/fb.h linux/drivers/sbus/char/fb.h --- v2.1.100/linux/drivers/sbus/char/fb.h Thu Sep 4 12:54:48 1997 +++ linux/drivers/sbus/char/fb.h Fri May 8 00:23:41 1998 @@ -1,4 +1,4 @@ -/* $Id: fb.h,v 1.33 1997/08/25 07:50:29 jj Exp $ +/* $Id: fb.h,v 1.34 1998/04/13 07:26:55 davem Exp $ * fb.h: contains the definitions of the structures that various sun * frame buffer can use to do console driver stuff. * @@ -150,7 +150,7 @@ void (*setcurshape)(struct fbinfo *); void (*setcursormap)(struct fbinfo *, unsigned char *, unsigned char *, unsigned char *); - unsigned long (*postsetup)(struct fbinfo *, unsigned long); + void (*postsetup)(struct fbinfo *); void (*clear_fb)(int); void (*set_other_palette)(int); void (*blitc)(unsigned short, int, int); @@ -208,7 +208,7 @@ extern int sbus_hw_cursor_shown; extern int sun_prom_console_id; -extern unsigned long cg_postsetup(fbinfo_t *, unsigned long); +extern void cg_postsetup(fbinfo_t *); #define FB_DEV(x) (MINOR(x) / 32) diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/leo.c linux/drivers/sbus/char/leo.c --- v2.1.100/linux/drivers/sbus/char/leo.c Thu Apr 23 20:21:34 1998 +++ linux/drivers/sbus/char/leo.c Fri May 8 00:23:41 1998 @@ -1,4 +1,4 @@ -/* $Id: leo.c,v 1.26 1998/03/10 20:18:29 jj Exp $ +/* $Id: leo.c,v 1.27 1998/04/13 07:26:57 davem Exp $ * leo.c: SUNW,leo 24/8bit frame buffer driver * * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -503,14 +503,13 @@ } -__initfunc(static unsigned long leo_postsetup (fbinfo_t *fb, unsigned long memory_start)) +__initfunc(static void leo_postsetup (fbinfo_t *fb)) { - fb->info.leo.cluts[0] = (u32 *)(memory_start); - fb->info.leo.cluts[1] = (u32 *)(memory_start+256*4); - fb->info.leo.cluts[2] = (u32 *)(memory_start+256*4*2); - fb->info.leo.xlut = (u8 *)(memory_start+256*4*3); - fb->color_map = (u8 *)(memory_start+256*4*3+256); - return memory_start + (256*4*3) + 256 + 256*3; + fb->info.leo.cluts[0] = kmalloc(256 * 4, GFP_ATOMIC); + fb->info.leo.cluts[1] = kmalloc(256 * 4, GFP_ATOMIC); + fb->info.leo.cluts[2] = kmalloc(256 * 4, GFP_ATOMIC); + fb->info.leo.xlut = kmalloc(256, GFP_ATOMIC); + fb->color_map = kmalloc(256 * 3, GFP_ATOMIC); } __initfunc(void leo_setup (fbinfo_t *fb, int slot, u32 leo, int leo_io)) diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/mach64.c linux/drivers/sbus/char/mach64.c --- v2.1.100/linux/drivers/sbus/char/mach64.c Thu Apr 23 20:21:34 1998 +++ linux/drivers/sbus/char/mach64.c Fri May 8 00:23:41 1998 @@ -1,4 +1,4 @@ -/* $Id: mach64.c,v 1.17 1998/04/06 06:42:23 davem Exp $ +/* $Id: mach64.c,v 1.18 1998/05/03 21:56:07 davem Exp $ * mach64.c: Ultra/PCI Mach64 console driver. * * Just about all of this is from the PPC/mac driver, see that for @@ -28,7 +28,7 @@ #include "mach64.h" #include "fb.h" -static unsigned int mach64_pci_membase; +static unsigned int mach64_pci_membase, mach64_pci_membase2; static unsigned int mach64_pci_iobase; #define MACH64_LE_FBOFF 0x000000 @@ -83,6 +83,9 @@ if (vma->vm_offset == (mach64_pci_iobase & PAGE_MASK)) { addr = __pa((pcivga_iobase & PAGE_MASK)); size = PAGE_SIZE; + } else if(mach64_pci_membase2 && + (vma->vm_offset == (mach64_pci_membase2 & PAGE_MASK))) { + addr = __pa((pcivga_membase2 & PAGE_MASK)); } else if (vma->vm_offset >= (mach64_pci_membase + 0x800000)) { addr = __pa(pcivga_membase) - mach64_pci_membase + vma->vm_offset; @@ -194,6 +197,9 @@ else pcivga_membase = addr & PCI_BASE_ADDRESS_MEM_MASK; + pcivga_membase2 = (pdev->base_address[2] & + PCI_BASE_ADDRESS_MEM_MASK); + if(!pcivga_iobase || !pcivga_membase) { prom_printf("mach64_init: I/O or MEM baseaddr is missing\n"); prom_printf("mach64_init: ba[0]=%016lx ba[1]=%016lx\n", @@ -209,8 +215,12 @@ PCI_BASE_ADDRESS_1, &mach64_pci_iobase); mach64_pci_iobase &= PCI_BASE_ADDRESS_IO_MASK; - printk("mach64_init: IOBASE[%016lx] MEMBASE[%016lx]\n", - pcivga_iobase, pcivga_membase); + pcibios_read_config_dword(pdev->bus->number, pdev->devfn, + PCI_BASE_ADDRESS_2, &mach64_pci_membase2); + mach64_pci_membase2 &= PCI_BASE_ADDRESS_MEM_MASK; + + printk("mach64_init: IOBASE[%016lx] M1[%016lx] M2[%016lx]\n", + pcivga_iobase, pcivga_membase, pcivga_membase2); cookie = pdev->sysdata; pbm = cookie->pbm; diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/pcicons.c linux/drivers/sbus/char/pcicons.c --- v2.1.100/linux/drivers/sbus/char/pcicons.c Thu Apr 23 20:21:34 1998 +++ linux/drivers/sbus/char/pcicons.c Fri May 8 00:23:41 1998 @@ -1,4 +1,4 @@ -/* $Id: pcicons.c,v 1.13 1998/04/01 06:55:11 ecd Exp $ +/* $Id: pcicons.c,v 1.17 1998/05/03 21:56:10 davem Exp $ * pcicons.c: PCI specific probing and console operations layer. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,13 @@ static void pci_install_consops(void); static int (*fbuf_offset)(int); +static int color_fbuf_offset_1280_144 (int cindex) +{ + register int i = (cindex/144); + /* (1280 * CHAR_HEIGHT) == 101.0000.0000.0000 */ + return skip_bytes + (i << 14) + (i << 12) + ((cindex % 144) << 3); +} + static int color_fbuf_offset_1152_128(int cindex) { register int i = (cindex >> 7); @@ -61,6 +69,30 @@ return skip_bytes + (i << 14) + ((cindex & 127) << 3); } +static int color_fbuf_offset_800_96 (int cindex) +{ + register int i = (cindex / 96); + /* (800 * CHAR_HEIGHT) == 11.0010.0000.0000 */ + return skip_bytes + (i<<13) + (i<<12) + (i<<9) + ((cindex % 96)<<3); +} + +static int color_fbuf_offset_640_80 (int cindex) +{ + register int i = (cindex/80); + /* (640 * CHAR_HEIGHT) == 10.1000.0000.0000 */ + return skip_bytes + (i << 13) + (i << 11) + ((cindex % 80) << 3); +} + +static int color_fbuf_offset_generic (int cindex) +{ +#if 0 + /* XXX Implement me -DaveM */ + return skip_bytes + (cindex / video_num_columns) * bytes_per_row + ((cindex % video_num_columns) << 3); +#else + return 0; +#endif +} + static __u32 expand_bits_8[16] = { 0x00000000, 0x000000ff, @@ -349,7 +381,7 @@ for (i = 0; i < 256; i++) { for (line = 0; line < CHAR_HEIGHT; line++) { unsigned char value; - __get_user_ret(value, (arg + (i + 32 + line)), -EFAULT); + __get_user_ret(value, (arg + (i * 32 + line)), -EFAULT); vga_font[i * CHAR_HEIGHT + line] = value; } } @@ -478,16 +510,13 @@ fb->switch_from_graph(); } -static unsigned long -pci_postsetup(fbinfo_t *fb, unsigned long memory_start) +static void pci_postsetup(fbinfo_t *fb) { - fb->color_map = (char *)memory_start; + fb->color_map = kmalloc(fb->type.fb_cmsize * 3, GFP_ATOMIC); pci_set_palette(); - return memory_start + fb->type.fb_cmsize * 3; } -__initfunc(static unsigned long -pci_con_type_init(unsigned long kmem_start, const char **display_desc)) +__initfunc(static void pci_con_type_init(const char **display_desc)) { can_do_color = 1; @@ -505,12 +534,9 @@ /* * Fake the screen memory with some CPU memory */ - video_mem_base = kmem_start; - kmem_start += video_screen_size; - video_mem_term = kmem_start; + video_mem_base = (unsigned long)kmalloc(video_screen_size, GFP_ATOMIC); + video_mem_term = (video_mem_base + video_screen_size); } - - return kmem_start; } __initfunc(static void pci_con_type_init_finish(void)) @@ -573,14 +599,19 @@ unsigned long pcivga_iobase = 0; unsigned long pcivga_membase = 0; +unsigned long pcivga_membase2 = 0; static struct { int depth; int resx, resy; int x_margin, y_margin; } scr_def[] = { + { 8, 1280, 1024, 64, 80 }, + { 8, 1152, 1024, 64, 80 }, { 8, 1152, 900, 64, 18 }, { 8, 1024, 768, 0, 0 }, + { 8, 800, 600, 16, 12 }, + { 8, 640, 480, 0, 0 }, { 0 } }; @@ -626,6 +657,9 @@ x_margin = scr_def[i].x_margin; y_margin = scr_def[i].y_margin; skip_bytes = y_margin * fb->linebytes + x_margin; + + /* XXX Check that ORIG_VIDEO_COLS match -DaveM */ + fbuf_offset = color_fbuf_offset_generic; switch (fb->type.fb_width) { case 1152: fbuf_offset = color_fbuf_offset_1152_128; @@ -633,11 +667,26 @@ case 1024: fbuf_offset = color_fbuf_offset_1024_128; break; + case 1280: + fbuf_offset = color_fbuf_offset_1280_144; + break; + case 800: + fbuf_offset = color_fbuf_offset_800_96; + break; + case 640: + fbuf_offset = color_fbuf_offset_640_80; + break; default: prom_printf("can't handle console width %d\n", fb->type.fb_width); prom_halt(); } + break; + } + if(scr_def[i].depth == 0) { + prom_printf("can't support console resolution %dX%d\n", + fb->type.fb_width, fb->type.fb_height); + prom_halt(); } pci_install_consops(); diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/pcicons.h linux/drivers/sbus/char/pcicons.h --- v2.1.100/linux/drivers/sbus/char/pcicons.h Thu Sep 4 12:54:48 1997 +++ linux/drivers/sbus/char/pcicons.h Fri May 8 00:23:41 1998 @@ -1,4 +1,4 @@ -/* $Id: pcicons.h,v 1.2 1997/08/24 12:13:11 ecd Exp $ +/* $Id: pcicons.h,v 1.3 1998/05/03 21:56:12 davem Exp $ * pcicons.h: Stuff which is generic across all PCI console drivers. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -13,6 +13,7 @@ extern unsigned long pcivga_iobase; extern unsigned long pcivga_membase; +extern unsigned long pcivga_membase2; extern unsigned char vga_font[8192]; diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/sbuscons.c linux/drivers/sbus/char/sbuscons.c --- v2.1.100/linux/drivers/sbus/char/sbuscons.c Sat Apr 25 18:13:11 1998 +++ linux/drivers/sbus/char/sbuscons.c Fri May 8 00:23:41 1998 @@ -1,4 +1,4 @@ -/* $Id: sbuscons.c,v 1.15 1998/03/31 01:49:50 davem Exp $ +/* $Id: sbuscons.c,v 1.17 1998/04/24 12:29:54 davem Exp $ * sbuscons.c: Routines specific to SBUS frame buffer consoles. * * Copyright (C) 1995 Peter Zaitcev (zaitcev@lab.ipmce.su) @@ -366,8 +366,7 @@ sbus_blitc (*contents, (unsigned long) contents); } -__initfunc(static unsigned long -sbus_con_type_init(unsigned long kmem_start, const char **display_desc)) +__initfunc(static void sbus_con_type_init(const char **display_desc)) { can_do_color = (con_type != FBTYPE_SUN2BW); @@ -381,11 +380,9 @@ /* * fake the screen memory with some CPU memory */ - video_mem_base = kmem_start; - kmem_start += video_screen_size; - video_mem_term = kmem_start; + video_mem_base = (unsigned long)kmalloc(video_screen_size, GFP_ATOMIC); + video_mem_term = (video_mem_base + video_screen_size); } - return kmem_start; } __initfunc(static void sbus_con_type_init_finish(void)) @@ -694,10 +691,9 @@ (*fb_restore_palette) (&fbinfo[0]); } -__initfunc(unsigned long cg_postsetup(fbinfo_t *fb, unsigned long start_mem)) +__initfunc(void cg_postsetup(fbinfo_t *fb)) { - fb->color_map = (char *)start_mem; - return start_mem + 256*3; + fb->color_map = kmalloc(256 * 3, GFP_ATOMIC); } static char *known_cards [] __initdata = { diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/suncons.c linux/drivers/sbus/char/suncons.c --- v2.1.100/linux/drivers/sbus/char/suncons.c Thu Apr 23 20:21:34 1998 +++ linux/drivers/sbus/char/suncons.c Fri May 8 00:23:41 1998 @@ -1,4 +1,4 @@ -/* $Id: suncons.c,v 1.79 1998/01/30 10:59:23 jj Exp $ +/* $Id: suncons.c,v 1.80 1998/04/13 07:27:01 davem Exp $ * suncons.c: Sparc platform console generic layer. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -100,10 +101,8 @@ { } -static unsigned long nop_con_type_init(unsigned long mem_start, - const char **display_desc) +static void nop_con_type_init(const char **display_desc) { - return mem_start; } static void nop_con_type_init_finish(void) @@ -222,9 +221,9 @@ suncons_ops.console_restore_palette(); } -unsigned long con_type_init(unsigned long mem_start, const char **disp_desc) +void con_type_init(const char **disp_desc) { - return suncons_ops.con_type_init(mem_start, disp_desc); + return suncons_ops.con_type_init(disp_desc); } void con_type_init_finish(void) @@ -283,14 +282,14 @@ extern int sbus_console_probe(void); extern int serial_console; -__initfunc(static unsigned long finish_console_init(unsigned long memory_start)) +__initfunc(static void finish_console_init(void)) { static int confinish_has_run = 0; int i, j; if(confinish_has_run != 0) { printk("finish_console_init: Someone tries to run me twice.\n"); - return memory_start; + return; } for(i = FRAME_BUFFERS; i > 1; i--) if(fbinfo[i - 1].type.fb_type != FBTYPE_NOTYPE) @@ -299,7 +298,7 @@ for(j = 0; j < i; j++) if (fbinfo[j].postsetup) - memory_start = (*fbinfo[j].postsetup)(fbinfo+j, memory_start); + (*fbinfo[j].postsetup)(fbinfo+j); suncons_ops.clear_screen(); @@ -316,30 +315,50 @@ #endif confinish_has_run = 1; +} - return memory_start; +__initfunc(int con_is_present(void)) +{ + return serial_console ? 0 : 1; } #ifdef CONFIG_PCI +extern int pci_console_probe(void); extern void pci_console_inithook(void); -#endif -__initfunc(int con_is_present(void)) +__initfunc(void pci_console_init(void)) { - return serial_console ? 0 : 1; + /* Nothing to do in this case. */ + if (!con_is_present()) + return; + + if (!cons_type) { + /* Some console was already found on SBUS or UPA */ + return; + } + + if(pci_console_probe()) { + prom_printf("Could not probe PCI console, bailing out...\n"); + prom_halt(); + } + + finish_console_init(); + + con_type_init_finish(); } -__initfunc(unsigned long sun_console_init(unsigned long memory_start)) +#endif /* CONFIG_PCI */ + +__initfunc(void sun_console_init(void)) { int i; /* Nothing to do in this case. */ if (!con_is_present()) - return memory_start; + return; - fbinfo = (fbinfo_t *)memory_start; + fbinfo = kmalloc(sizeof(fbinfo_t) * FRAME_BUFFERS, GFP_ATOMIC); memset(fbinfo, 0, FRAME_BUFFERS * sizeof(fbinfo_t)); - memory_start += (FRAME_BUFFERS * sizeof(fbinfo_t)); fbinfos = 0; for (i = 0; i < FRAME_BUFFERS; i++) @@ -348,39 +367,12 @@ if(sbus_console_probe()) { #ifdef CONFIG_PCI cons_type = 1; - pci_console_inithook(); - return memory_start; + return pci_console_inithook(); #else /* XXX We need to write PROM console fallback driver... */ prom_printf("Could not probe SBUS console, bailing out...\n"); prom_halt(); #endif } - return finish_console_init(memory_start); -} - -#ifdef CONFIG_PCI -extern int pci_console_probe(void); - -__initfunc(unsigned long pci_console_init(unsigned long memory_start)) -{ - /* Nothing to do in this case. */ - if (!con_is_present()) - return memory_start; - - if (!cons_type) { - /* Some console was already found on SBUS or UPA */ - return memory_start; - } - - if(pci_console_probe()) { - prom_printf("Could not probe PCI console, bailing out...\n"); - prom_halt(); - } - - memory_start = finish_console_init(memory_start); - - con_type_init_finish(); - return memory_start; + return finish_console_init(); } -#endif diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c --- v2.1.100/linux/drivers/sbus/char/sunkbd.c Thu Apr 23 20:21:34 1998 +++ linux/drivers/sbus/char/sunkbd.c Fri May 8 00:23:41 1998 @@ -79,6 +79,11 @@ struct l1a_kbd_state l1a_state = { 0, 0 }; +/* Dummy function for now, we need it to link. -DaveM */ +void kbd_reset_setup(char *str, int *ints) +{ +} + #ifndef CONFIG_PCI struct wait_queue * keypress_wait = NULL; #endif diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/sunserial.c linux/drivers/sbus/char/sunserial.c --- v2.1.100/linux/drivers/sbus/char/sunserial.c Mon Jan 12 15:15:45 1998 +++ linux/drivers/sbus/char/sunserial.c Fri May 8 00:23:41 1998 @@ -1,4 +1,4 @@ -/* $Id: sunserial.c,v 1.56 1997/12/19 07:33:07 ecd Exp $ +/* $Id: sunserial.c,v 1.57 1998/04/13 07:27:02 davem Exp $ * serial.c: Serial port driver infrastructure for the Sparc. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -77,11 +77,9 @@ printk(buffer); } -__initfunc(long -serial_console_init(long kmem_start, long kmem_end)) +__initfunc(void serial_console_init(void)) { sun_serial_finish_init(); - return kmem_start; } void rs_change_mouse_baud(int baud) diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/dvma.c linux/drivers/sbus/dvma.c --- v2.1.100/linux/drivers/sbus/dvma.c Sat Apr 25 18:13:11 1998 +++ linux/drivers/sbus/dvma.c Fri May 8 00:23:41 1998 @@ -74,8 +74,8 @@ } /* Probe this SBus DMA module(s) */ -__initfunc(unsigned long -dvma_init(struct linux_sbus *sbus, unsigned long memory_start)) +__initfunc(void +dvma_init(struct linux_sbus *sbus)) { struct linux_sbus_device *this_dev; struct Linux_SBus_DMA *dma; @@ -93,8 +93,7 @@ continue; /* Found one... */ - dma = (struct Linux_SBus_DMA *) memory_start; - memory_start += sizeof(struct Linux_SBus_DMA); + dma = kmalloc(sizeof(struct Linux_SBus_DMA), GFP_ATOMIC); dma->SBus_dev = this_dev; @@ -127,22 +126,18 @@ init_one_dvma(dma, num_dma++); }; /* while(this_dev) */ - - return memory_start; } #ifdef CONFIG_SUN4 #include -__initfunc(unsigned long -sun4_dvma_init(unsigned long memory_start)) +__initfunc(void sun4_dvma_init(void)) { struct Linux_SBus_DMA *dma; struct Linux_SBus_DMA *dchain; - dma = (struct Linux_SBus_DMA *) memory_start; - memory_start += sizeof(struct Linux_SBus_DMA); + dma = kmalloc(sizeof(struct Linux_SBus_DMA), GFP_ATOMIC); /* No SBUS */ dma->SBus_dev = 0x0; @@ -158,7 +153,6 @@ dma->node = 0x0; init_one_dvma(dma, 0); - return memory_start; } #endif diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c --- v2.1.100/linux/drivers/sbus/sbus.c Thu Apr 23 20:21:34 1998 +++ linux/drivers/sbus/sbus.c Fri May 8 00:23:41 1998 @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -181,12 +182,10 @@ * devices. */ -extern unsigned long sun_console_init(unsigned long); -extern unsigned long iommu_init(int iommu_node, unsigned long memstart, - unsigned long memend, struct linux_sbus *sbus); -extern unsigned long iounit_init(int sbi_node, int iounit_node, unsigned long memstart, - unsigned long memend, struct linux_sbus *sbus); -unsigned long sun4_init(unsigned long memory_start, unsigned long memory_end); +extern void sun_console_init(void); +extern void iommu_init(int iommu_node, struct linux_sbus *sbus); +extern void iounit_init(int sbi_node, int iounit_node, struct linux_sbus *sbus); +void sun4_init(void); #ifdef CONFIG_SUN_OPENPROMIO extern int openprom_init(void); #endif @@ -197,9 +196,8 @@ extern int flash_init(void); #endif -__initfunc(static unsigned long -sbus_do_child_siblings(unsigned long memory_start, int start_node, - struct linux_sbus_device *child, +__initfunc(static void +sbus_do_child_siblings(int start_node, struct linux_sbus_device *child, struct linux_sbus *sbus)) { struct linux_sbus_device *this_dev = child; @@ -208,8 +206,7 @@ /* Child already filled in, just need to traverse siblings. */ child->child = 0; while((this_node = prom_getsibling(this_node)) != 0) { - this_dev->next = (struct linux_sbus_device *) memory_start; - memory_start += sizeof(struct linux_sbus_device); + this_dev->next = kmalloc(sizeof(struct linux_sbus_device), GFP_ATOMIC); this_dev = this_dev->next; this_dev->next = 0; @@ -217,23 +214,19 @@ this_dev->my_bus = sbus; if(prom_getchild(this_node)) { - this_dev->child = (struct linux_sbus_device *) memory_start; - memory_start += sizeof(struct linux_sbus_device); + this_dev->child = kmalloc(sizeof(struct linux_sbus_device), + GFP_ATOMIC); fill_sbus_device(prom_getchild(this_node), this_dev->child); this_dev->child->my_bus = sbus; - memory_start = sbus_do_child_siblings(memory_start, - prom_getchild(this_node), - this_dev->child, - sbus); + sbus_do_child_siblings(prom_getchild(this_node), + this_dev->child, sbus); } else { this_dev->child = 0; } } - return memory_start; } -__initfunc(unsigned long -sbus_init(unsigned long memory_start, unsigned long memory_end)) +__initfunc(void sbus_init(void)) { register int nd, this_sbus, sbus_devs, topnd, iommund; unsigned int sbus_clock; @@ -242,11 +235,9 @@ int num_sbus = 0; /* How many did we find? */ #ifdef CONFIG_SUN4 - return sun4_init(memory_start, memory_end); + return sun4_init(); #endif - memory_start = ((memory_start + 7) & (~7)); - topnd = prom_getchild(prom_root_node); /* Finding the first sbus is a special case... */ @@ -256,7 +247,7 @@ if(nd == 0) { #ifdef CONFIG_PCI printk("SBUS: No SBUS's found.\n"); - return sun_console_init(memory_start); + return sun_console_init(); #else prom_printf("YEEE, UltraSparc sbus not found\n"); prom_halt(); @@ -280,28 +271,21 @@ /* Ok, we've found the first one, allocate first SBus struct * and place in chain. */ - sbus = SBus_chain = (struct linux_sbus *) memory_start; - memory_start += sizeof(struct linux_sbus); + sbus = SBus_chain = kmalloc(sizeof(struct linux_sbus), GFP_ATOMIC); sbus->next = 0; this_sbus=nd; if(iommund && sparc_cpu_model != sun4u && sparc_cpu_model != sun4d) - memory_start = iommu_init(iommund, - memory_start, memory_end, - sbus); + iommu_init(iommund, sbus); /* Loop until we find no more SBUS's */ while(this_sbus) { /* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */ if(sparc_cpu_model == sun4u) - memory_start = iommu_init(this_sbus, - memory_start, memory_end, - sbus); + iommu_init(this_sbus, sbus); #ifndef __sparc_v9__ else if (sparc_cpu_model == sun4d) - memory_start = iounit_init(this_sbus, iommund, - memory_start, memory_end, - sbus); + iounit_init(this_sbus, iommund, sbus); #endif printk("sbus%d: ", num_sbus); sbus_clock = prom_getint(this_sbus, "clock-frequency"); @@ -326,8 +310,7 @@ sbus_devs = prom_getchild(this_sbus); - sbus->devices = (struct linux_sbus_device *) memory_start; - memory_start += sizeof(struct linux_sbus_device); + sbus->devices = kmalloc(sizeof(struct linux_sbus_device), GFP_ATOMIC); this_dev = sbus->devices; this_dev->next = 0; @@ -338,24 +321,21 @@ /* Should we traverse for children? */ if(prom_getchild(sbus_devs)) { /* Allocate device node */ - this_dev->child = (struct linux_sbus_device *) memory_start; - memory_start += sizeof(struct linux_sbus_device); + this_dev->child = kmalloc(sizeof(struct linux_sbus_device), + GFP_ATOMIC); /* Fill it */ - fill_sbus_device(prom_getchild(sbus_devs), this_dev->child); this_dev->child->my_bus = sbus; - memory_start = sbus_do_child_siblings(memory_start, - prom_getchild(sbus_devs), - this_dev->child, - sbus); + sbus_do_child_siblings(prom_getchild(sbus_devs), + this_dev->child, sbus); } else { this_dev->child = 0; } while((sbus_devs = prom_getsibling(sbus_devs)) != 0) { /* Allocate device node */ - this_dev->next = (struct linux_sbus_device *) memory_start; - memory_start += sizeof(struct linux_sbus_device); + this_dev->next = kmalloc(sizeof(struct linux_sbus_device), + GFP_ATOMIC); this_dev=this_dev->next; this_dev->next=0; @@ -367,24 +347,20 @@ if(prom_getchild(sbus_devs)) { /* Get new device struct */ this_dev->child = - (struct linux_sbus_device *) memory_start; - memory_start += sizeof(struct linux_sbus_device); - + kmalloc(sizeof(struct linux_sbus_device), + GFP_ATOMIC); /* Fill it */ fill_sbus_device(prom_getchild(sbus_devs), this_dev->child); this_dev->child->my_bus = sbus; - memory_start = sbus_do_child_siblings( - memory_start, - prom_getchild(sbus_devs), - this_dev->child, - sbus); + sbus_do_child_siblings(prom_getchild(sbus_devs), + this_dev->child, sbus); } else { this_dev->child = 0; } } - memory_start = dvma_init(sbus, memory_start); + dvma_init(sbus); num_sbus++; if(sparc_cpu_model == sun4u) { @@ -404,8 +380,7 @@ this_sbus = prom_searchsiblings(this_sbus, "sbus"); } if(this_sbus) { - sbus->next = (struct linux_sbus *) memory_start; - memory_start += sizeof(struct linux_sbus); + sbus->next = kmalloc(sizeof(struct linux_sbus), GFP_ATOMIC); sbus = sbus->next; sbus->next = 0; } else { @@ -413,12 +388,11 @@ } } /* while(this_sbus) */ if (sparc_cpu_model == sun4d) { - extern unsigned long sun4d_init_sbi_irq(unsigned long); - - memory_start = sun4d_init_sbi_irq(memory_start); + extern void sun4d_init_sbi_irq(void); + sun4d_init_sbi_irq(); } - memory_start = sun_console_init(memory_start); /* whee... */ + sun_console_init(); /* whee... */ #ifdef CONFIG_SUN_OPENPROMIO openprom_init(); #endif @@ -441,22 +415,15 @@ clock_probe(); } #endif - return memory_start; } #ifdef CONFIG_SUN4 -extern unsigned long sun4_dvma_init(unsigned long); +extern void sun4_dvma_init(void); -__initfunc(unsigned long -sun4_init(unsigned long memory_start, unsigned long memory_end)) +__initfunc(void sun4_init(void)) { - memory_start = ((memory_start + 7) & (~7)); - - memory_start = sun_console_init(memory_start); - - memory_start = sun4_dvma_init(memory_start); - - return memory_start; + sun_console_init(); + sun4_dvma_init(); } #endif diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile --- v2.1.100/linux/drivers/scsi/Makefile Tue Feb 17 13:12:47 1998 +++ linux/drivers/scsi/Makefile Fri May 8 00:22:11 1998 @@ -163,6 +163,54 @@ endif endif +ifeq ($(CONFIG_SCSI_SGIWD93),y) +L_OBJS += sgiwd93.o wd33c93.o +else + ifeq ($(CONFIG_SCSI_SGIWD93),m) + M_OBJS += sgiwd93.o wd33c93.o + endif +endif + +ifeq ($(CONFIG_CYBERSTORM_SCSI),y) +L_OBJS += NCR53C9x.o cyberstorm.o +else + ifeq ($(CONFIG_CYBERSTORM_SCSI),m) + M_OBJS += NCR53C9x.o cyberstorm.o + endif +endif + +ifeq ($(CONFIG_CYBERSTORMII_SCSI),y) +L_OBJS += NCR53C9x.o cyberstormII.o +else + ifeq ($(CONFIG_CYBERSTORMII_SCSI),m) + M_OBJS += NCR53C9x.o cyberstormII.o + endif +endif + +ifeq ($(CONFIG_BLZ2060_SCSI),y) +L_OBJS += NCR53C9x.o blz2060.o +else + ifeq ($(CONFIG_BLZ2060_SCSI),m) + M_OBJS += NCR53C9x.o blz2060.o + endif +endif + +ifeq ($(CONFIG_BLZ1230_SCSI),y) +L_OBJS += NCR53C9x.o blz1230.o +else + ifeq ($(CONFIG_BLZ1230_SCSI),m) + M_OBJS += NCR53C9x.o blz1230.o + endif +endif + +ifeq ($(CONFIG_FASTLANE_SCSI),y) +L_OBJS += NCR53C9x.o fastlane.o +else + ifeq ($(CONFIG_FASTLANE_SCSI),m) + M_OBJS += NCR53C9x.o fastlane.o + endif +endif + ifeq ($(CONFIG_ATARI_SCSI),y) L_OBJS += atari_scsi.o else @@ -464,19 +512,26 @@ include $(TOPDIR)/Rules.make -53c8xx_d.h 53c8xx_u.h : 53c7,8xx.scr script_asm.pl - ln -sf 53c7,8xx.scr fake.c - $(CPP) -traditional -DCHIP=810 fake.c | grep -v '^#' | perl script_asm.pl +53c8xx_d.h: 53c7,8xx.scr script_asm.pl + ln -sf 53c7,8xx.scr fake8.c + $(CPP) -traditional -DCHIP=810 fake8.c | grep -v '^#' | perl script_asm.pl mv script.h 53c8xx_d.h mv scriptu.h 53c8xx_u.h - rm fake.c + rm fake8.c -53c7xx_d.h 53c7xx_u.h : 53c7xx.scr script_asm.pl - ln -sf 53c7xx.scr fake.c - $(CPP) -traditional -DCHIP=710 fake.c | grep -v '^#' | perl -s script_asm.pl -ncr7x0_family +53c8xx_u.h: 53c8xx_d.h + +53c7xx_d.h: 53c7xx.scr script_asm.pl + ln -sf 53c7xx.scr fake7.c + $(CPP) -traditional -DCHIP=710 fake7.c | grep -v '^#' | perl -s script_asm.pl -ncr7x0_family mv script.h 53c7xx_d.h mv scriptu.h 53c7xx_u.h - rm fake.c + rm fake7.c + +53c7xx_u.h: 53c7xx_d.h + +53c7xx.o : 53c7xx_d.h 53c7xx.c + $(CC) $(CFLAGS) -c 53c7xx.c scsi_mod.o: $(MIX_OBJS) hosts.o scsi.o scsi_ioctl.o constants.o \ scsicam.o scsi_proc.o scsi_error.o scsi_obsolete.o scsi_queue.o diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c --- v2.1.100/linux/drivers/scsi/advansys.c Thu Apr 23 20:21:35 1998 +++ linux/drivers/scsi/advansys.c Fri May 8 17:46:24 1998 @@ -1,5 +1,5 @@ -/* $Id: advansys.c,v 1.49 1998/01/22 20:19:25 bobf Exp bobf $ */ -#define ASC_VERSION "3.1D" /* AdvanSys Driver Version */ +/* $Id: advansys.c,v 1.50 1998/05/08 23:39:15 bobf Exp bobf $ */ +#define ASC_VERSION "3.1E" /* AdvanSys Driver Version */ /* * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters @@ -571,7 +571,7 @@ be page aligned. 3.1C (1/10/98): - 1. Update latest BIOS version to 3.1E. + 1. Update latest BIOS version checked for from the /proc file. 2. Don't set microcode SDTR variable at initialization. Instead wait until device capabilities have been detected from an Inquiry command. @@ -580,6 +580,18 @@ 1. Improve performance when the driver is compiled as module by allowing up to 64 scatter-gather elements instead of 8. + 3.1E (5/1/98): + 1. Set time delay in AscWaitTixISRDone() to 1000 ms. + 2. Include SMP locking changes. + 3. For v2.1.93 and newer kernels use CONFIG_PCI and new PCI BIOS + access functions. + 4. Update board serial number printing. + 5. Try allocating an IRQ both with and without the SA_INTERRUPT + flag set to allow IRQ sharing with drivers that do not set + the SA_INTERRUPT flag. Also display a more descriptive error + message if request_irq() fails. + 5. Update to latest Asc and Adv Libraries. + J. Known Problems or Issues 1. Remove conditional constants (ASC_QUEUE_FLOW_CONTROL) around @@ -598,7 +610,7 @@ Erik Ratcliffe has done testing of the AdvanSys driver in the Caldera releases. - Rik van Riel provided a patch to + Rik van Riel provided a patch to AscWaitTixISRDone() which he found necessary to make the driver work with a SCSI-1 disk. @@ -639,6 +651,7 @@ * --- Linux Include Files */ +#include #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) #ifdef MODULE #include @@ -670,13 +683,23 @@ #endif /* version >= v1.3.0 */ #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,95) #include -#endif +#endif /* version >= 2.1.95 */ #include "scsi.h" #include "hosts.h" #include "sd.h" #include "advansys.h" - -#include +#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,93) +#ifdef CONFIG_PCI +#include +#endif /* CONFIG_PCI */ +#else /* version < v2.1.93 */ +/* + * For earlier than v2.1.93 the driver has its own PCI configuration. + * If PCI is not needed in a kernel before v2.1.93 this define can be + * turned-off to make the driver object smaller. + */ +#define ASC_CONFIG_PCI +#endif /* version < v2.1.93 */ /* * If Linux eventually defines a DID_UNDERRUN, the constant here can be @@ -694,7 +717,7 @@ #define ADVANSYS_ASSERT /* Enable driver tracing. */ -/*#define ADVANSYS_DEBUG*/ +/* #define ADVANSYS_DEBUG */ /* * Because of no /proc to display them, statistics are disabled @@ -724,7 +747,7 @@ #define ASC_LIB_VERSION_MAJOR 1 #define ASC_LIB_VERSION_MINOR 22 -#define ASC_LIB_SERIAL_NUMBER 111 +#define ASC_LIB_SERIAL_NUMBER 113 typedef unsigned char uchar; @@ -1489,7 +1512,7 @@ ASC_SCSI_BIT_ID_TYPE can_tagged_qng; ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled; ASC_SCSI_BIT_ID_TYPE disc_enable; - uchar res; + ASC_SCSI_BIT_ID_TYPE sdtr_enable; uchar chip_scsi_id:4; uchar isa_dma_speed:4; uchar isa_dma_channel; @@ -1952,8 +1975,6 @@ STATIC ushort AscInitFromEEP(ASC_DVC_VAR asc_ptr_type *); STATIC ushort AscInitFromAscDvcVar(ASC_DVC_VAR asc_ptr_type *); STATIC ushort AscInitMicroCodeVar(ASC_DVC_VAR asc_ptr_type * asc_dvc); -STATIC void AscInitPollIsrCallBack(ASC_DVC_VAR asc_ptr_type *, - ASC_QDONE_INFO *); STATIC int AscTestExternalLram(ASC_DVC_VAR asc_ptr_type *); STATIC uchar AscMsgOutSDTR(ASC_DVC_VAR asc_ptr_type *, uchar, uchar); STATIC uchar AscCalSDTRData(ASC_DVC_VAR asc_ptr_type *, uchar, uchar); @@ -1996,31 +2017,6 @@ STATIC uchar _AscCopyLramScsiDoneQ(PortAddr, ushort, ASC_QDONE_INFO *, ulong); STATIC int AscIsrQDone(ASC_DVC_VAR asc_ptr_type *); -STATIC int AscScsiSetupCmdQ(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q *, uchar *, ulong); -STATIC int AscScsiInquiry(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q *, uchar *, int); -STATIC int AscScsiTestUnitReady(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q *); -STATIC int AscScsiStartStopUnit(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q *, uchar); -STATIC int AscScsiReadCapacity(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q *, uchar *); -STATIC ulong *swapfarbuf4(uchar *); -STATIC int PollQueueDone(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q *, int); -STATIC int PollScsiReadCapacity(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q *, ASC_CAP_INFO *); -STATIC int PollScsiInquiry(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q *, uchar *, int); -STATIC int PollScsiTestUnitReady(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q *); -STATIC int PollScsiStartUnit(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q *); -STATIC int InitTestUnitReady(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q *); -STATIC int AscPollQDone(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q *, int); STATIC int AscCompareString(uchar *, uchar *, int); STATIC ushort AscGetEisaChipCfg(PortAddr); STATIC ulong AscGetEisaProductID(PortAddr); @@ -2056,10 +2052,11 @@ STATIC ushort AscInitGetConfig(ASC_DVC_VAR asc_ptr_type *); STATIC ushort AscInitSetConfig(ASC_DVC_VAR asc_ptr_type *); STATIC ushort AscInitAsc1000Driver(ASC_DVC_VAR asc_ptr_type *); -STATIC int AscInitPollBegin(ASC_DVC_VAR asc_ptr_type *); -STATIC int AscInitPollEnd(ASC_DVC_VAR asc_ptr_type *); -STATIC int AscInitPollTarget(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q *, ASC_SCSI_INQUIRY *, ASC_CAP_INFO *); +STATIC void AscAsyncFix(ASC_DVC_VAR asc_ptr_type *, uchar, + ASC_SCSI_INQUIRY *); +STATIC int AscTagQueuingSafe(ASC_SCSI_INQUIRY *); +STATIC void AscInquiryHandling(ASC_DVC_VAR asc_ptr_type *, + uchar, ASC_SCSI_INQUIRY *); STATIC int AscExeScsiQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q *); STATIC int AscISR(ASC_DVC_VAR asc_ptr_type *); STATIC uint AscGetNumOfFreeQueue(ASC_DVC_VAR asc_ptr_type *, uchar, @@ -2079,7 +2076,7 @@ */ #define ADV_LIB_VERSION_MAJOR 3 -#define ADV_LIB_VERSION_MINOR 34 +#define ADV_LIB_VERSION_MINOR 45 /* d_os_dep.h */ #define ADV_OS_LINUX @@ -3150,10 +3147,6 @@ #define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */ #define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */ -/* 'IS_SCSIQ_FLAG is now obsolete; Instead use ADV_IS_SCSIQ_FLAG. */ -#define IS_SCSIQ_FLAG ADV_IS_SCSIQ_FLAQ - - /* Return the address that is aligned at the next doubleword >= to 'addr'. */ #define ADV_DWALIGN(addr) (((ulong) (addr) + 0x3) & ~0x3) @@ -3360,6 +3353,7 @@ #define PCI_MAX_BUS 0xFF #define PCI_IOADDRESS_MASK 0xFFFE #define ASC_PCI_VENDORID 0x10CD +#define ASC_PCI_DEVICE_ID_CNT 4 /* PCI Device ID count. */ #define ASC_PCI_DEVICE_ID_1100 0x1100 #define ASC_PCI_DEVICE_ID_1200 0x1200 #define ASC_PCI_DEVICE_ID_1300 0x1300 @@ -3797,7 +3791,11 @@ ASC_IS_PCI, }; +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) +#ifdef ASC_CONFIG_PCI STATIC int pci_scan_method ASC_INITDATA = -1; +#endif /* ASC_CONFIG_PCI */ +#endif /* version < v2.1.93 */ /* * Used with the LILO 'advansys' option to eliminate or @@ -3844,11 +3842,8 @@ #endif /* version >= v1.3.0 */ #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70) STATIC void advansys_interrupt(int, struct pt_regs *); -#elif LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95) -STATIC void advansys_interrupt(int, void *, struct pt_regs *); -#else /* version >= 2.1.95 */ +#else /* version >= v1.3.70 */ STATIC void advansys_interrupt(int, void *, struct pt_regs *); -STATIC void do_advansys_interrupt(int, void *, struct pt_regs *); #endif /* version >= v1.3.70 */ #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) STATIC void advansys_select_queue_depths(struct Scsi_Host *, @@ -3862,7 +3857,8 @@ STATIC int adv_get_sglist(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *, Scsi_Cmnd *); STATIC void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *); STATIC void adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); -STATIC int asc_init_dev(ASC_DVC_VAR *, Scsi_Cmnd *); +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) +#ifdef ASC_CONFIG_PCI STATIC int asc_srch_pci_dev(PCI_DEVICE *); STATIC uchar asc_scan_method(void); STATIC int asc_pci_find_dev(PCI_DEVICE *); @@ -3870,6 +3866,8 @@ STATIC ushort asc_get_cfg_word(PCI_DATA *); STATIC uchar asc_get_cfg_byte(PCI_DATA *); STATIC void asc_put_cfg_byte(PCI_DATA *, uchar); +#endif /* ASC_CONFIG_PCI */ +#endif /* version < v2.1.93 */ STATIC void asc_enqueue(asc_queue_t *, REQP, int); STATIC REQP asc_dequeue(asc_queue_t *, int); STATIC REQP asc_dequeue_list(asc_queue_t *, REQP *, int); @@ -4180,8 +4178,27 @@ ADV_DVC_VAR *adv_dvc_varp = NULL; int ioport = 0; int share_irq = FALSE; +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) +#ifdef ASC_CONFIG_PCI PCI_DEVICE pciDevice; PCI_CONFIG_SPACE pciConfig; +#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) + unsigned long pci_memory_address; +#endif /* version >= v1,3,0 */ +#endif /* ASC_CONFIG_PCI */ +#else /* version >= v2.1.93 */ +#ifdef CONFIG_PCI + struct pci_dev *pci_devp = NULL; + int pci_device_id_cnt = 0; + unsigned int pci_device_id[ASC_PCI_DEVICE_ID_CNT] = { + ASC_PCI_DEVICE_ID_1100, + ASC_PCI_DEVICE_ID_1200, + ASC_PCI_DEVICE_ID_1300, + ASC_PCI_DEVICE_ID_2300 + }; + unsigned long pci_memory_address; +#endif /* CONFIG_PCI */ +#endif /* version >= v2.1.93 */ int warn_code, err_code; int ret; @@ -4225,10 +4242,14 @@ ioport = 0; } +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) +#ifdef ASC_CONFIG_PCI memset(&pciDevice, 0, sizeof(PCI_DEVICE)); memset(&pciConfig, 0, sizeof(PCI_CONFIG_SPACE)); pciDevice.maxBusNumber = PCI_MAX_BUS; pciDevice.endSlot = PCI_MAX_SLOT; +#endif /* ASC_CONFIG_PCI */ +#endif /* version < v2.1.93 */ for (bus = 0; bus < ASC_NUM_BUS; bus++) { @@ -4309,22 +4330,52 @@ iop = AscSearchIOPortAddr(iop, asc_bus[bus]); break; +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) +#ifdef ASC_CONFIG_PCI + case ASC_IS_PCI: + if (asc_srch_pci_dev(&pciDevice) != PCI_DEVICE_FOUND) { + iop = 0; + } else { + ASC_DBG2(2, + "advansys_detect: slotFound %d, busNumber %d\n", + pciDevice.slotFound, pciDevice.busNumber); + asc_get_pci_cfg(&pciDevice, &pciConfig); + iop = pciConfig.baseAddress[0] & PCI_IOADDRESS_MASK; + ASC_DBG2(1, + "advansys_detect: vendorID %X, deviceID %X\n", + pciConfig.vendorID, pciConfig.deviceID); + ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n", + iop, pciConfig.irqLine); + } + break; +#endif /* ASC_CONFIG_PCI */ +#else /* version >= v2.1.93 */ +#ifdef CONFIG_PCI case ASC_IS_PCI: - if (asc_srch_pci_dev(&pciDevice) != PCI_DEVICE_FOUND) { - iop = 0; + while (pci_device_id_cnt < ASC_PCI_DEVICE_ID_CNT) { + if ((pci_devp = pci_find_device(ASC_PCI_VENDORID, + pci_device_id[pci_device_id_cnt], pci_devp)) == NULL) { + pci_device_id_cnt++; } else { - ASC_DBG2(2, - "advansys_detect: slotFound %d, busNumber %d\n", - pciDevice.slotFound, pciDevice.busNumber); - asc_get_pci_cfg(&pciDevice, &pciConfig); - iop = pciConfig.baseAddress[0] & PCI_IOADDRESS_MASK; - ASC_DBG2(1, - "advansys_detect: vendorID %X, deviceID %X\n", - pciConfig.vendorID, pciConfig.deviceID); - ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n", - iop, pciConfig.irqLine); + break; } + } + if (pci_devp == NULL) { + iop = 0; + } else { + ASC_DBG2(2, + "advansys_detect: devfn %d, bus number %d\n", + pci_devp->devfn, pci_devp->bus->number); + iop = pci_devp->base_address[0] & PCI_IOADDRESS_MASK; + ASC_DBG2(1, + "advansys_detect: vendorID %X, deviceID %X\n", + pci_devp->vendor, pci_devp->device); + ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n", + iop, pci_devp->irq); + } break; +#endif /* CONFIG_PCI */ +#endif /* version >= v2.1.93 */ default: ASC_PRINT1("advansys_detect: unknown bus type: %d\n", @@ -4358,14 +4409,29 @@ boardp->id = asc_board_count - 1; /* - * Handle both narrow and wide PCI boards. + * Handle both narrow and wide boards. * * If a Wide board was detected, set the board structure * wide board flag. Set-up the board structure based on * the board type. */ - if ((asc_bus[bus] == ASC_IS_PCI && - pciConfig.deviceID == ASC_PCI_DEVICE_ID_2300) == 0) { +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) +#ifdef ASC_CONFIG_PCI + if (asc_bus[bus] == ASC_IS_PCI && + pciConfig.deviceID == ASC_PCI_DEVICE_ID_2300) { + boardp->flags |= ASC_IS_WIDE_BOARD; + } +#endif /* ASC_CONFIG_PCI */ +#else /* version >= v2.1.93 */ +#ifdef CONFIG_PCI + if (asc_bus[bus] == ASC_IS_PCI && + pci_devp->device == ASC_PCI_DEVICE_ID_2300) { + boardp->flags |= ASC_IS_WIDE_BOARD; + } +#endif /* CONFIG_PCI */ +#endif /* version >= v2.1.93 */ + + if (ASC_NARROW_BOARD(boardp)) { ASC_DBG(1, "advansys_detect: narrow board\n"); asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; asc_dvc_varp->bus_type = asc_bus[bus]; @@ -4376,7 +4442,6 @@ asc_dvc_varp->isr_callback = (Ptr2Func) asc_isr_callback; } else { ASC_DBG(1, "advansys_detect: wide board\n"); - boardp->flags |= ASC_IS_WIDE_BOARD; adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; adv_dvc_varp->drv_ptr = (ulong) boardp; adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg; @@ -4396,20 +4461,41 @@ * PCI register base address will not cross a page * boundary. */ +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) +#ifdef ASC_CONFIG_PCI + pci_memory_address = pciConfig.baseAddress[1]; if ((boardp->ioremap_addr = - ioremap(pciConfig.baseAddress[1] & PAGE_MASK, + ioremap(pci_memory_address & PAGE_MASK, PAGE_SIZE)) == 0) { ASC_PRINT3( "advansys_detect: board %d: ioremap(%lx, %d) returned NULL\n", - boardp->id, pciConfig.baseAddress[1], ADV_CONDOR_IOLEN); + boardp->id, pci_memory_address, ADV_CONDOR_IOLEN); scsi_unregister(shp); asc_board_count--; continue; } adv_dvc_varp->iop_base = (AdvPortAddr) (boardp->ioremap_addr + - (pciConfig.baseAddress[1] - - (pciConfig.baseAddress[1] & PAGE_MASK))); + (pci_memory_address - (pci_memory_address & PAGE_MASK))); +#endif /* ASC_CONFIG_PCI */ +#else /* version >= v2.1.93 */ +#ifdef CONFIG_PCI + pci_memory_address = pci_devp->base_address[1]; + if ((boardp->ioremap_addr = + ioremap(pci_memory_address & PAGE_MASK, + PAGE_SIZE)) == 0) { + ASC_PRINT3( +"advansys_detect: board %d: ioremap(%lx, %d) returned NULL\n", + boardp->id, pci_memory_address, ADV_CONDOR_IOLEN); + scsi_unregister(shp); + asc_board_count--; + continue; + } + adv_dvc_varp->iop_base = (AdvPortAddr) + (boardp->ioremap_addr + + (pci_memory_address - (pci_memory_address & PAGE_MASK))); +#endif /* CONFIG_PCI */ +#endif /* version >= v2.1.93 */ #endif /* version >= v1,3,0 */ /* @@ -4455,16 +4541,33 @@ shp->unchecked_isa_dma = FALSE; share_irq = TRUE; break; +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) +#ifdef ASC_CONFIG_PCI case ASC_IS_PCI: shp->irq = asc_dvc_varp->irq_no = pciConfig.irqLine; - shp->unchecked_isa_dma = FALSE; - share_irq = TRUE; asc_dvc_varp->cfg->pci_device_id = pciConfig.deviceID; asc_dvc_varp->cfg->pci_slot_info = ASC_PCI_MKID(pciDevice.busNumber, pciDevice.slotFound, pciDevice.devFunc); + shp->unchecked_isa_dma = FALSE; + share_irq = TRUE; break; +#endif /* ASC_CONFIG_PCI */ +#else /* version >= v2.1.93 */ +#ifdef CONFIG_PCI + case ASC_IS_PCI: + shp->irq = asc_dvc_varp->irq_no = pci_devp->irq; + asc_dvc_varp->cfg->pci_device_id = pci_devp->device; + asc_dvc_varp->cfg->pci_slot_info = + ASC_PCI_MKID(pci_devp->bus->number, + PCI_SLOT(pci_devp->devfn), + PCI_FUNC(pci_devp->devfn)); + shp->unchecked_isa_dma = FALSE; + share_irq = TRUE; + break; +#endif /* CONFIG_PCI */ +#endif /* version >= v2.1.93 */ default: ASC_PRINT2( "advansys_detect: board %d: unknown adapter type: %d\n", @@ -4478,14 +4581,29 @@ * For Wide boards set PCI information before calling * AdvInitGetConfig(). */ +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) +#ifdef ASC_CONFIG_PCI shp->irq = adv_dvc_varp->irq_no = pciConfig.irqLine; + adv_dvc_varp->cfg->pci_device_id = pciConfig.deviceID; + adv_dvc_varp->cfg->pci_slot_info = + ASC_PCI_MKID(pciDevice.busNumber, + pciDevice.slotFound, + pciDevice.devFunc); shp->unchecked_isa_dma = FALSE; share_irq = TRUE; - adv_dvc_varp->cfg->pci_device_id = pciConfig.deviceID; +#endif /* ASC_CONFIG_PCI */ +#else /* version >= v2.1.93 */ +#ifdef CONFIG_PCI + shp->irq = adv_dvc_varp->irq_no = pci_devp->irq; + adv_dvc_varp->cfg->pci_device_id = pci_devp->device; adv_dvc_varp->cfg->pci_slot_info = - ASC_PCI_MKID(pciDevice.busNumber, - pciDevice.slotFound, - pciDevice.devFunc); + ASC_PCI_MKID(pci_devp->bus->number, + PCI_SLOT(pci_devp->devfn), + PCI_FUNC(pci_devp->devfn)); + shp->unchecked_isa_dma = FALSE; + share_irq = TRUE; +#endif /* CONFIG_PCI */ +#endif /* version >= v2.1.93 */ } /* @@ -4580,7 +4698,7 @@ */ ep = &boardp->eep_config.asc_eep; - ep->init_sdtr = asc_dvc_varp->init_sdtr; + ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable; ep->disc_enable = asc_dvc_varp->cfg->disc_enable; ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled; ep->isa_dma_speed = asc_dvc_varp->cfg->isa_dma_speed; @@ -4886,19 +5004,37 @@ #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70) if ((ret = request_irq(shp->irq, advansys_interrupt, SA_INTERRUPT, "advansys")) != 0) -#elif LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95) - if ((ret = request_irq(shp->irq, advansys_interrupt, - SA_INTERRUPT | (share_irq == TRUE ? SA_SHIRQ : 0), - "advansys", boardp)) != 0) -#else /* version >= 2.1.95 */ - if ((ret = request_irq(shp->irq, do_advansys_interrupt, +#else /* version >= v1.3.70 */ + /* + * If request_irq() fails with the SA_INTERRUPT flag set, + * then try again without the SA_INTERRUPT flag set. This + * allows IRQ sharing to work even with other drivers that + * do not set the SA_INTERRUPT flag. + * + * If SA_INTERRUPT is not set, then interrupts are enabled + * before the driver interrupt function is called. + */ + if (((ret = request_irq(shp->irq, advansys_interrupt, SA_INTERRUPT | (share_irq == TRUE ? SA_SHIRQ : 0), - "advansys", boardp)) != 0) + "advansys", boardp)) != 0) && + ((ret = request_irq(shp->irq, advansys_interrupt, + (share_irq == TRUE ? SA_SHIRQ : 0), + "advansys", boardp)) != 0)) #endif /* version >= v1.3.70 */ { - ASC_PRINT2( -"advansys_detect: board %d: request_irq() failed %d\n", - boardp->id, ret); + if (ret == -EBUSY) { + ASC_PRINT2( +"advansys_detect: board %d: request_irq(): IRQ %d already in use.\n", + boardp->id, shp->irq); + } else if (ret == -EINVAL) { + ASC_PRINT2( +"advansys_detect: board %d: request_irq(): IRQ %d not valid.\n", + boardp->id, shp->irq); + } else { + ASC_PRINT3( +"advansys_detect: board %d: request_irq(): IRQ %d failed with %d\n", + boardp->id, shp->irq, ret); + } release_region(shp->io_port, shp->n_io_port); #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) iounmap(boardp->ioremap_addr); @@ -5152,7 +5288,11 @@ busname = "ISA"; } sprintf(info, +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92) "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X/%X, IRQ %u, DMA %u", +#else /* version >= v2.1.92 */ +"AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %lX/%X, IRQ %u, DMA %u", +#endif /* version >= v2.1.92 */ ASC_VERSION, busname, asc_dvc_varp->max_total_qng, (unsigned) shp->base, shp->io_port, shp->n_io_port - 1, @@ -5165,7 +5305,11 @@ busname = "PCI"; } sprintf(info, +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92) "AdvanSys SCSI %s: %s %u CDB: IO %X/%X, IRQ %u", +#else /* version >= v2.1.92 */ + "AdvanSys SCSI %s: %s %u CDB: IO %lX/%X, IRQ %u", +#endif /* version >= v2.1.92 */ ASC_VERSION, busname, asc_dvc_varp->max_total_qng, shp->io_port, shp->n_io_port - 1, shp->irq); } else { @@ -5180,7 +5324,11 @@ boardp->id, asc_dvc_varp->bus_type); } sprintf(info, +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92) "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X/%X, IRQ %u", +#else /* version >= v2.1.92 */ + "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %lX/%X, IRQ %u", +#endif /* version >= v2.1.92 */ ASC_VERSION, busname, asc_dvc_varp->max_total_qng, (unsigned) shp->base, shp->io_port - 1, shp->n_io_port, shp->irq); @@ -5730,13 +5878,6 @@ status = AscResetDevice(asc_dvc_varp, scp->target); cli(); - /* - * If the device has been reset, try to initialize it. - */ - if (status == ASC_TRUE) { - status = asc_init_dev(asc_dvc_varp, scp); - } - switch (status) { case ASC_TRUE: ASC_DBG(1, "advansys_reset: AscResetDevice() success\n"); @@ -5957,7 +6098,7 @@ asc_scsi_done_list(done_scp); } - ASC_DBG1(1, "advansys_reset: ret %d", ret); + ASC_DBG1(1, "advansys_reset: ret %d\n", ret); /* Re-enable interrupts, if they were enabled on entry. */ restore_flags(flags); @@ -6121,15 +6262,27 @@ advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs) #endif /* version >= v1.3.70 */ { +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95) int flags; +#else /* version >= v2.1.95 */ + unsigned long flags; +#endif /* version >= v2.1.95 */ int i; asc_board_t *boardp; Scsi_Cmnd *done_scp = NULL, *last_scp = NULL; Scsi_Cmnd *new_last_scp; +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95) /* Disable interrupts, if they aren't already disabled. */ save_flags(flags); cli(); +#else /* version >= v2.1.95 */ + /* + * Disable interrupts, if they aren't already disabled and acquire + * the I/O spinlock. + */ + spin_lock_irqsave(&io_request_lock, flags); +#endif /* version >= v2.1.95 */ ASC_DBG(1, "advansys_interrupt: begin\n"); @@ -6203,30 +6356,31 @@ /* * It is possible for the request done function to re-enable - * interrupts without confusing the driver. But here interrupts - * aren't enabled until all requests have been completed. + * interrupts without confusing the driver. But here the + * original flags aren't restored until all requests have been + * completed. */ asc_scsi_done_list(done_scp); - /* Re-enable interrupts, if they were enabled on entry. */ +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95) + /* + * Restore the original flags which will enable interrupts + * if and only if they were enabled on entry. + */ restore_flags(flags); +#else /* version >= v2.1.95 */ + /* + * Release the I/O spinlock and restore the original flags + * which will enable interrupts if and only if they were + * enabled on entry. + */ + spin_unlock_irqrestore(&io_request_lock, flags); +#endif /* version >= v2.1.95 */ ASC_DBG(1, "advansys_interrupt: end\n"); return; } -#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,95) -static void -do_advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - advansys_interrupt(irq, dev_id, regs); - spin_unlock_irqrestore(&io_request_lock, flags); -} -#endif - #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) /* * Set the number of commands to queue per device for the @@ -6366,21 +6520,6 @@ asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; /* - * Narrow Board - Asc Library requires special device initialization. - * - * If this is the first command, then initialize the device. If - * no device is found set 'DID_BAD_TARGET' and return. - */ - if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0) { - if (asc_init_dev(asc_dvc_varp, scp) == ASC_FALSE) { - scp->result = HOST_BYTE(DID_BAD_TARGET); - asc_enqueue(&boardp->done, scp, ASC_BACK); - return ASC_ERROR; - } - boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->target); - } - - /* * Build Asc Library request structure using the * global structures 'asc_scsi_req' and 'asc_sg_head'. * @@ -6925,7 +7064,7 @@ asc_board_t *boardp; Scsi_Cmnd *scp; struct Scsi_Host *shp; - int underrun = ASC_FALSE; + int underrun = ASC_FALSE; int i; ASC_ASSERT(interrupts_enabled() == ASC_FALSE); @@ -6971,6 +7110,7 @@ * Display a message and return. */ boardp = ASC_BOARDP(shp); + ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var); if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) { ASC_PRINT2("asc_isr_callback: board %d: scp %x not on active queue\n", boardp->id, (unsigned) scp); @@ -6981,7 +7121,7 @@ * Check for an underrun condition. */ if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 && - qdonep->remain_bytes <= scp->request_bufflen != 0) { + qdonep->remain_bytes <= scp->request_bufflen != 0) { ASC_DBG1(1, "asc_isr_callback: underrun condition %u bytes\n", (unsigned) qdonep->remain_bytes); underrun = ASC_TRUE; @@ -7002,13 +7142,28 @@ scp->result = HOST_BYTE(DID_ERROR); break; } - /* - * If there was an underrun without any other error, - * set DID_ERROR to indicate the underrun error. - */ - if (scp->result == 0 && underrun == ASC_TRUE) { + + /* + * If an INQUIRY command completed successfully, then call + * the AscInquiryHandling() function to set-up the device. + */ + if (scp->cmnd[0] == SCSICMD_Inquiry && scp->lun == 0 && + (scp->request_bufflen - qdonep->remain_bytes) >= 8) + { + AscInquiryHandling(asc_dvc_varp, scp->target & 0x7, + (ASC_SCSI_INQUIRY *) scp->request_buffer); + } + + /* + * If there was an underrun without any other error, + * set DID_ERROR to indicate the underrun error. + * + * Note: There is no way yet to indicate the number + * of underrun bytes. + */ + if (scp->result == 0 && underrun == ASC_TRUE) { scp->result = HOST_BYTE(DID_UNDERRUN); - } + } break; case QD_WITH_ERROR: @@ -7038,10 +7193,9 @@ default: /* QHSTA error occurred */ - ASC_DBG1(2, "asc_isr_callback: host_stat %x\n", + ASC_DBG1(1, "asc_isr_callback: host_stat %x\n", qdonep->d3.host_stat); - scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) | - STATUS_BYTE(qdonep->d3.scsi_stat); + scp->result = HOST_BYTE(DID_BAD_TARGET); break; } break; @@ -7053,12 +7207,23 @@ break; default: - ASC_PRINT1("asc_isr_callback: done_stat %x\n", qdonep->d3.done_stat); + ASC_DBG1(1, "asc_isr_callback: done_stat %x\n", qdonep->d3.done_stat); scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) | STATUS_BYTE(qdonep->d3.scsi_stat); break; } + /* + * If the 'init_tidmask' bit isn't already set for the target and the + * current request finished normally, then set the bit for the target + * to indicate that a device is present. + */ + if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0 && + qdonep->d3.done_stat == QD_NO_ERROR && + qdonep->d3.host_stat == QHSTA_NO_ERROR) { + boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->target); + } + /* * Because interrupts may be enabled by the 'Scsi_Cmnd' done * function, add the command to the end of the board's done queue. @@ -7082,7 +7247,7 @@ adv_req_t *reqp; Scsi_Cmnd *scp; struct Scsi_Host *shp; - int underrun = ASC_FALSE; + int underrun = ASC_FALSE; int i; ASC_ASSERT(interrupts_enabled() == ASC_FALSE); @@ -7150,6 +7315,7 @@ * to free the adv_req_t and adv_sgblk_t, if any, structures. */ boardp = ASC_BOARDP(shp); + ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var); if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) { ASC_PRINT2("adv_isr_callback: board %d: scp %x not on active queue\n", boardp->id, (unsigned) scp); @@ -7182,13 +7348,16 @@ scp->result = HOST_BYTE(DID_ERROR); break; } - /* - * If there was an underrun without any other error, - * set DID_ERROR to indicate the underrun error. - */ - if (scp->result == 0 && underrun == ASC_TRUE) { - scp->result = HOST_BYTE(DID_UNDERRUN); - } + /* + * If there was an underrun without any other error, + * set DID_ERROR to indicate the underrun error. + * + * Note: There is no way yet to indicate the number + * of underrun bytes. + */ + if (scp->result == 0 && underrun == ASC_TRUE) { + scp->result = HOST_BYTE(DID_UNDERRUN); + } break; case QD_WITH_ERROR: @@ -7218,7 +7387,7 @@ default: /* Some other QHSTA error occurred. */ - ASC_DBG1(2, "adv_isr_callback: host_status %x\n", + ASC_DBG1(1, "adv_isr_callback: host_status %x\n", scsiqp->host_status); scp->result = HOST_BYTE(DID_BAD_TARGET); break; @@ -7231,15 +7400,15 @@ break; default: - ASC_PRINT1("adv_isr_callback: done_status %x\n", scsiqp->done_status); + ASC_DBG1(1, "adv_isr_callback: done_status %x\n", scsiqp->done_status); scp->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status); break; } /* * If the 'init_tidmask' bit isn't already set for the target and the - * current request did not finish with a Selection Timeout, then set - * the bit for the target to indicate that a device is present. + * current request finished normally, then set the bit for the target + * to indicate that a device is present. */ if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0 && scsiqp->done_status == QD_NO_ERROR && @@ -7276,119 +7445,8 @@ return; } -/* - * asc_init_dev() - Narrow Board initialization function. - * - * Perform one-time initialization of a device for Asc Library - */ -STATIC int -asc_init_dev(ASC_DVC_VAR *asc_dvc_varp, Scsi_Cmnd *scp) -{ - asc_board_t *boardp; - ASC_SCSI_REQ_Q *scsireqq; - ASC_CAP_INFO *cap_info; - ASC_SCSI_INQUIRY *inquiry; - int found; - ASC_SCSI_BIT_ID_TYPE save_use_tagged_qng; - ASC_SCSI_BIT_ID_TYPE save_can_tagged_qng; - int ret; -#ifdef ADVANSYS_DEBUG - ASC_SCSI_BIT_ID_TYPE tidmask; /* target id bit mask: 1 - 128 */ -#endif /* ADVANSYS_DEBUG */ - - ASC_DBG1(1, "asc_init_dev: target %d\n", (unsigned) scp->target); - - /* The host's target id is set in init_tidmask during initialization. */ - ASC_ASSERT(asc_dvc_varp->cfg->chip_scsi_id != scp->target); - - boardp = ASC_BOARDP(scp->host); - - /* Set-up AscInitPollTarget() arguments. */ - scsireqq = &boardp->scsireqq; - memset(scsireqq, 0, sizeof(ASC_SCSI_REQ_Q)); - cap_info = &boardp->cap_info; - memset(cap_info, 0, sizeof(ASC_CAP_INFO)); - inquiry = &boardp->inquiry; - memset(inquiry, 0, sizeof(ASC_SCSI_INQUIRY)); - - /* - * AscInitPollBegin() re-initializes these bitmask fields to zero. - * Save the current bitmask value and 'or' them back in after calling - * AscInitPollEnd() below.. - */ - save_use_tagged_qng = asc_dvc_varp->use_tagged_qng; - save_can_tagged_qng = asc_dvc_varp->cfg->can_tagged_qng; - - ASC_DBG(2, "asc_init_dev: AscInitPollBegin()\n"); - if (AscInitPollBegin(asc_dvc_varp)) { - ASC_PRINT1("asc_init_dev: board %d: AscInitPollBegin() failed\n", - boardp->id); - return ASC_FALSE; - } - - scsireqq->sense_ptr = &scsireqq->sense[0]; - scsireqq->r1.sense_len = ASC_MIN_SENSE_LEN; - scsireqq->r1.target_id = ASC_TID_TO_TARGET_ID(scp->target); - scsireqq->r1.target_lun = 0; - scsireqq->r2.target_ix = ASC_TIDLUN_TO_IX(scp->target, 0); - - found = ASC_FALSE; - ASC_DBG(2, "asc_init_dev: AscInitPollTarget()\n"); - switch (ret = AscInitPollTarget(asc_dvc_varp, scsireqq, inquiry, - cap_info)) { - case ASC_TRUE: - found = ASC_TRUE; -#ifdef ADVANSYS_DEBUG - tidmask = ADV_TID_TO_TIDMASK(scp->target); - ASC_DBG2(1, "asc_init_dev: lba %lu, blk_size %lu\n", - cap_info->lba, cap_info->blk_size); - ASC_DBG1(1, "asc_init_dev: peri_dvc_type %x\n", - inquiry->byte0.peri_dvc_type); - if (asc_dvc_varp->use_tagged_qng & tidmask) { - ASC_DBG1(1, "asc_init_dev: command queuing enabled: %d\n", - asc_dvc_varp->max_dvc_qng[scp->target]); - } else { - ASC_DBG(1, "asc_init_dev: command queuing disabled\n"); - } - if (asc_dvc_varp->init_sdtr & tidmask) { - ASC_DBG(1, "asc_init_dev: synchronous transfers enabled\n"); - } else { - ASC_DBG(1, "asc_init_dev: synchronous transfers disabled\n"); - } - /* Set bit means fix disabled. */ - if (asc_dvc_varp->pci_fix_asyn_xfer & tidmask) { - ASC_DBG(1, "asc_init_dev: synchronous transfer fix disabled\n"); - } else { - ASC_DBG(1, "asc_init_dev: synchronous transfer fix enabled\n"); - } -#endif /* ADVANSYS_DEBUG */ - break; - case ASC_FALSE: - ASC_DBG(1, "asc_init_dev: no device found\n"); - break; - case ASC_ERROR: - ASC_PRINT1("asc_init_dev: board %d: AscInitPollTarget() ASC_ERROR\n", - boardp->id); - break; - default: - ASC_PRINT2( -"asc_init_dev: board %d: AscInitPollTarget() unknown ret %d\n", - boardp->id, ret); - break; - } - - /* Restore previously set bits in the bitmask fields. */ - asc_dvc_varp->use_tagged_qng |= save_use_tagged_qng; - asc_dvc_varp->cfg->can_tagged_qng |= save_can_tagged_qng; - - ASC_DBG(2, "asc_init_dev: AscInitPollEnd()\n"); - AscInitPollEnd(asc_dvc_varp); - - ASC_DBG1(1, "asc_init_dev: found %d\n", found); - - return found; -} - +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) +#ifdef ASC_CONFIG_PCI /* * Search for an AdvanSys PCI device in the PCI configuration space. */ @@ -7397,7 +7455,7 @@ asc_srch_pci_dev(PCI_DEVICE *pciDevice) ) { - int ret; + int ret = PCI_DEVICE_NOT_FOUND; ASC_DBG(2, "asc_srch_pci_dev: begin\n"); @@ -7424,6 +7482,7 @@ ASC_DBG1(2, "asc_srch_pci_dev: recursive call return %d\n", ret); } } + ASC_DBG1(2, "asc_srch_pci_dev: return %d\n", ret); return ret; } @@ -7524,7 +7583,7 @@ uchar counter; uchar *localConfig; - ASC_DBG1(4, "asc_get_pci_cfg: slot found - %d\n ", + ASC_DBG1(4, "asc_get_pci_cfg: slotFound %d\n ", pciDevice->slotFound); pciData.type = pciDevice->type; @@ -7636,8 +7695,74 @@ ) { uchar tmp; + ulong address; + ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func; + uchar t2CFA, t2CF8; + ulong t1CF8, t1CFC; + + ASC_DBG1(4, "asc_get_cfg_byte: type: %d\n", pciData->type); - pcibios_read_config_byte(pciData->bus, pciData->slot * 8 + pciData->func, pciData->offset, &tmp); + /* + * Check type of configuration mechanism. + */ + if (pciData->type == 2) { + /* + * Save registers to be restored later. + */ + t2CFA = inp(0xCFA); /* save PCI bus register */ + t2CF8 = inp(0xCF8); /* save config space enable register */ + + /* + * Write the bus and enable registers. + */ + /* set for type 1 cycle, if needed */ + outp(0xCFA, pciData->bus); + /* set the function number */ + outp(0xCF8, 0x10 | (pciData->func << 1)); + + /* + * Read configuration space type 2 locations. + */ + tmp = inp(0xC000 | ((pciData->slot << 8) + pciData->offset)); + + /* + * Restore registers. + */ + outp(0xCF8, t2CF8); /* restore the enable register */ + outp(0xCFA, t2CFA); /* restore PCI bus register */ + } else { + /* + * Type 1 or 3 configuration mechanism. + * + * Save CONFIG_ADDRESS and CONFIG_DATA register values. + */ + t1CF8 = inpl(0xCF8); + t1CFC = inpl(0xCFC); + + /* + * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>, + * reg = <7:2> + */ + address = (ulong) ((lbus << 16) | (lslot << 11) | + (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L); + + /* + * Write out address to CONFIG_ADDRESS. + */ + outpl(0xCF8, address); + + /* + * Read in word from CONFIG_DATA. + */ + tmp = (uchar) ((inpl(0xCFC) >> ((pciData->offset & 3) * 8)) & 0xFF); + + /* + * Restore registers. + */ + outpl(0xCF8, t1CF8); + outpl(0xCFC, t1CFC); + } + ASC_DBG1(4, "asc_get_cfg_byte: config data: %x\n", tmp); return tmp; } @@ -7725,6 +7850,8 @@ } ASC_DBG(4, "asc_put_cfg_byte: end\n"); } +#endif /* ASC_CONFIG_PCI */ +#endif /* version < v2.1.93 */ /* * Add a 'REQP' to the end of specified queue. Set 'tidmask' @@ -8134,9 +8261,9 @@ major, minor, letter >= 26 ? '?' : letter + 'A'); ASC_PRT_NEXT(); - /* Current available ROM BIOS release is 3.1E. */ + /* Current available ROM BIOS release is 3.1C. */ if (major < 3 || (major <= 3 && minor < 1) || - (major <= 3 && minor <= 1 && letter < ('E'- 'A'))) { + (major <= 3 && minor <= 1 && letter < ('C'- 'A'))) { upgrade = ASC_TRUE; } } @@ -8153,18 +8280,18 @@ * Add serial number to information bar if signature AAh * is found in at bit 15-9 (7 bits) of word 1. * - * Serial Number consists 12 alpha-numeric digits. + * Serial Number consists fo 12 alpha-numeric digits. * - * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits) - * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits) - * 3-4 - Product ID (0-99) Word0: 10-0 (11 bits) - * 5 - Product revision Word0: " " - * - * Signature Word1: 15-9 (7 bits) - * 6 - Year (4-9) Word1: 8-6 (3 bits) - * 7-8 - Week of the year Word1: 5-0 (6 bits) + * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits) + * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits) + * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits) + * 5 - Product revision (A-J) Word0: " " + * + * Signature Word1: 15-9 (7 bits) + * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit) + * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits) * - * 9-12 - Serial Number Word2: 15-0 (16 bits) + * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits) * * Note 1: Only production cards will have a serial number. * @@ -8186,7 +8313,11 @@ w = serialnum[0]; /* Product type - 1st digit. */ - *cp++ = 'A' + ((w & 0xE000) >> 13); + if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') { + /* Product type is P=Prototype */ + *cp += 0x8; + } + cp++; /* Manufacturing location - 2nd digit. */ *cp++ = 'A' + ((w & 0x1C00) >> 10); @@ -8205,8 +8336,17 @@ */ w = serialnum[1]; - /* Year - 6th digit. */ - *cp++ = '0' + ((w & 0x1C0) >> 6); + /* + * Year - 6th digit. + * + * If bit 15 of third word is set, then the + * last digit of the year is greater than 7. + */ + if (serialnum[2] & 0x8000) { + *cp++ = '8' + ((w & 0x1C0) >> 6); + } else { + *cp++ = '0' + ((w & 0x1C0) >> 6); + } /* Week of year - 7th, 8th digits. */ num = w & 0x003F; @@ -8217,7 +8357,7 @@ /* * Third word */ - w = serialnum[2]; + w = serialnum[2] & 0x7FFF; /* Serial number - 9th digit. */ *cp++ = 'A' + (w / 1000); @@ -9233,6 +9373,8 @@ ushort offset) ) { +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) +#ifdef ASC_CONFIG_PCI PCI_DATA pciData; pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info); @@ -9241,6 +9383,21 @@ pciData.offset = offset; pciData.type = pci_scan_method; return asc_get_cfg_byte(&pciData); +#else /* ASC_CONFIG_PCI */ + return 0; +#endif /* ASC_CONFIG_PCI */ +#else /* version >= v2.1.93 */ +#ifdef CONFIG_PCI + uchar byte_data; + pcibios_read_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info), + PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info), + ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)), + offset, &byte_data); + return byte_data; +#else /* CONFIG_PCI */ + return 0; +#endif /* CONFIG_PCI */ +#endif /* version >= v2.1.93 */ } /* @@ -9254,6 +9411,8 @@ uchar byte_data) ) { +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) +#ifdef ASC_CONFIG_PCI PCI_DATA pciData; pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info); @@ -9262,6 +9421,15 @@ pciData.offset = offset; pciData.type = pci_scan_method; asc_put_cfg_byte(&pciData, byte_data); +#endif /* ASC_CONFIG_PCI */ +#else /* version >= v2.1.93 */ +#ifdef CONFIG_PCI + pcibios_write_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info), + PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info), + ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)), + offset, byte_data); +#endif /* CONFIG_PCI */ +#endif /* version >= v2.1.93 */ } /* @@ -9358,6 +9526,8 @@ ushort offset) ) { +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) +#ifdef ASC_CONFIG_PCI PCI_DATA pciData; pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info); @@ -9366,6 +9536,21 @@ pciData.offset = offset; pciData.type = pci_scan_method; return asc_get_cfg_byte(&pciData); +#else /* ASC_CONFIG_PCI */ + return 0; +#endif /* ASC_CONFIG_PCI */ +#else /* version >= v2.1.93 */ +#ifdef CONFIG_PCI + uchar byte_data; + pcibios_read_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info), + PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info), + ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)), + offset, &byte_data); + return byte_data; +#else /* CONFIG_PCI */ + return 0; +#endif /* CONFIG_PCI */ +#endif /* version >= v2.1.93 */ } /* @@ -9379,6 +9564,8 @@ uchar byte_data) ) { +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) +#ifdef ASC_CONFIG_PCI PCI_DATA pciData; pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info); @@ -9387,6 +9574,15 @@ pciData.offset = offset; pciData.type = pci_scan_method; asc_put_cfg_byte(&pciData, byte_data); +#endif /* ASC_CONFIG_PCI */ +#else /* version >= v2.1.93 */ +#ifdef CONFIG_PCI + pcibios_write_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info), + PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info), + ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)), + offset, byte_data); +#endif /* CONFIG_PCI */ +#endif /* version >= v2.1.93 */ } /* @@ -9703,8 +9899,9 @@ printk("ASC_DVC_CFG at addr %x\n", (unsigned) h); printk( -" can_tagged_qng %x, cmd_qng_enabled %x, disc_enable %x, res %x,\n", - h->can_tagged_qng, h->cmd_qng_enabled, h->disc_enable, h->res); +" can_tagged_qng %x, cmd_qng_enabled %x, disc_enable %x, sdtr_enable %x,\n", + h->can_tagged_qng, h->cmd_qng_enabled, h->disc_enable, + h->sdtr_enable); printk( " chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n", @@ -10889,200 +11086,156 @@ return (int_pending); } -STATIC int -AscScsiSetupCmdQ( - REG ASC_DVC_VAR asc_ptr_type * asc_dvc, - REG ASC_SCSI_REQ_Q * scsiq, - uchar * buf_addr, - ulong buf_len -) -{ - ulong phy_addr; - - scsiq->r1.cntl = 0; - scsiq->r1.sg_queue_cnt = 0; - scsiq->r1.q_no = 0; - scsiq->r1.extra_bytes = 0; - scsiq->r3.scsi_stat = 0; - scsiq->r3.scsi_msg = 0; - scsiq->r3.host_stat = 0; - scsiq->r3.done_stat = 0; - scsiq->r2.vm_id = 0; - scsiq->r1.data_cnt = buf_len; - scsiq->cdbptr = (uchar *) scsiq->cdb; - scsiq->sense_ptr = (uchar *) scsiq->sense ; - scsiq->r1.sense_len = ASC_MIN_SENSE_LEN ; - scsiq->r2.tag_code = (uchar) M2_QTAG_MSG_SIMPLE; - scsiq->r2.flag = (uchar) ASC_FLAG_SCSIQ_REQ; - scsiq->r2.srb_ptr = (ulong) scsiq; - scsiq->r1.status = (uchar) QS_READY; - scsiq->r1.data_addr = 0L; - if (buf_len != 0L) { - if ((phy_addr = AscGetOnePhyAddr(asc_dvc, - (uchar *) buf_addr, scsiq->r1.data_cnt)) == 0L) { - return (ERR); - } - scsiq->r1.data_addr = phy_addr; - } - if ((phy_addr = AscGetOnePhyAddr(asc_dvc, - (uchar *) scsiq->sense_ptr, - (ulong) scsiq->r1.sense_len)) == 0L) { - return (ERR); - } - scsiq->r1.sense_addr = phy_addr ; - return (0); -} - STATIC uchar _asc_mcode_buf[] ASC_INITDATA = { 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xDB, 0x0C, 0x0A, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x91, 0x10, 0x0A, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x23, 0x00, 0x23, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x88, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x24, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x88, 0x00, 0x00, 0x00, 0x00, 0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40, 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2, 0xC2, 0x00, 0x92, 0x80, - 0x10, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x3A, 0x98, 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, - 0x4F, 0x00, 0xF5, 0x00, 0x3A, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62, + 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, + 0x4F, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62, 0x92, 0x80, 0x00, 0x46, 0x17, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8, 0xCD, 0x04, 0x4D, 0x00, - 0x00, 0xA3, 0xD6, 0x00, 0x98, 0x97, 0x7F, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE0, 0x84, 0xD2, 0xC1, - 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xE2, 0x01, 0x98, 0x97, 0xCE, 0x81, 0x00, 0x33, - 0x02, 0x00, 0xB2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0x02, 0x01, 0x4F, 0x00, - 0x76, 0x97, 0x07, 0xA6, 0x0C, 0x01, 0x00, 0x33, 0x03, 0x00, 0xB2, 0x88, 0x03, 0x03, 0x03, 0xDE, - 0x00, 0x33, 0x05, 0x00, 0xB2, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, + 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1, + 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xE2, 0x01, 0xA6, 0x97, 0xCE, 0x81, 0x00, 0x33, + 0x02, 0x00, 0xC0, 0x88, 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0x02, 0x01, 0x4F, 0x00, + 0x84, 0x97, 0x07, 0xA6, 0x0C, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC0, 0x88, 0x03, 0x03, 0x03, 0xDE, + 0x00, 0x33, 0x05, 0x00, 0xC0, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x80, 0x01, 0x80, 0x63, 0x07, 0xA6, 0x2C, 0x01, 0x80, 0x81, 0x03, 0x03, 0x80, 0x63, - 0xE2, 0x00, 0x07, 0xA6, 0x3C, 0x01, 0x00, 0x33, 0x04, 0x00, 0xB2, 0x88, 0x03, 0x07, 0x02, 0x01, - 0x04, 0xCA, 0x0D, 0x23, 0x5A, 0x98, 0x4D, 0x04, 0xFE, 0x84, 0x05, 0xD8, 0x0D, 0x23, 0x5A, 0x98, - 0xCD, 0x04, 0x15, 0x23, 0xE8, 0x88, 0xFB, 0x23, 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, - 0x06, 0xA3, 0x6A, 0x01, 0x00, 0x33, 0x0A, 0x00, 0xB2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x76, 0x01, - 0x00, 0x33, 0x0B, 0x00, 0xB2, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1A, 0x00, 0xB2, 0x88, + 0xE2, 0x00, 0x07, 0xA6, 0x3C, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC0, 0x88, 0x03, 0x07, 0x02, 0x01, + 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8, 0x0D, 0x23, 0x68, 0x98, + 0xCD, 0x04, 0x15, 0x23, 0xF6, 0x88, 0xFB, 0x23, 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, + 0x06, 0xA3, 0x6A, 0x01, 0x00, 0x33, 0x0A, 0x00, 0xC0, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x76, 0x01, + 0x00, 0x33, 0x0B, 0x00, 0xC0, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1A, 0x00, 0xC0, 0x88, 0x50, 0x04, 0x90, 0x81, 0x06, 0xAB, 0x8A, 0x01, 0x90, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x9A, 0x01, - 0x50, 0x00, 0x00, 0xA3, 0x44, 0x01, 0x00, 0x05, 0x84, 0x81, 0x38, 0x97, 0x02, 0x01, 0x05, 0xC6, + 0x50, 0x00, 0x00, 0xA3, 0x44, 0x01, 0x00, 0x05, 0x84, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6, 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xC6, 0x81, 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xBC, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, - 0x00, 0x33, 0x1B, 0x00, 0xB2, 0x88, 0x06, 0x23, 0x5A, 0x98, 0xCD, 0x04, 0xE0, 0x84, 0x06, 0x01, - 0x00, 0xA2, 0xDC, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xE2, 0x01, 0xE0, 0x84, 0x80, 0x23, 0xA0, 0x01, - 0xE0, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x08, 0x02, 0x04, 0x01, 0x0C, 0xDE, - 0x02, 0x01, 0x03, 0xCC, 0x4F, 0x00, 0x76, 0x97, 0x04, 0x82, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01, - 0x4F, 0x00, 0x54, 0x97, 0x48, 0x04, 0x84, 0x80, 0xE2, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, + 0x00, 0x33, 0x1B, 0x00, 0xC0, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01, + 0x00, 0xA2, 0xDC, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xE2, 0x01, 0xE6, 0x84, 0x80, 0x23, 0xA0, 0x01, + 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x08, 0x02, 0x04, 0x01, 0x0C, 0xDE, + 0x02, 0x01, 0x03, 0xCC, 0x4F, 0x00, 0x84, 0x97, 0x04, 0x82, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01, + 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29, 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x67, 0xEB, - 0x11, 0x23, 0xE8, 0x88, 0xF6, 0x97, 0xF4, 0x80, 0x80, 0x73, 0x80, 0x77, 0x06, 0xA6, 0x36, 0x02, - 0x00, 0x33, 0x31, 0x00, 0xB2, 0x88, 0x04, 0x01, 0x03, 0xD8, 0xA4, 0x98, 0x4C, 0x96, 0x48, 0x82, - 0xDC, 0x95, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x72, 0x02, 0x07, 0xA6, - 0x60, 0x02, 0x06, 0xA6, 0x64, 0x02, 0x03, 0xA6, 0x68, 0x02, 0x00, 0x33, 0x10, 0x00, 0xB2, 0x88, - 0x76, 0x95, 0x4A, 0x82, 0x42, 0x96, 0x4A, 0x82, 0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, - 0x36, 0x84, 0x04, 0x01, 0x0C, 0xDC, 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, - 0xA8, 0x01, 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, - 0x1C, 0x01, 0x02, 0xA6, 0xB0, 0x02, 0x07, 0xA6, 0x60, 0x02, 0x06, 0xA6, 0x64, 0x02, 0x03, 0xA6, - 0x1A, 0x04, 0x01, 0xA6, 0xBA, 0x02, 0x00, 0xA6, 0xBA, 0x02, 0x00, 0x33, 0x12, 0x00, 0xB2, 0x88, - 0x00, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x92, 0x02, 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, - 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35, 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, - 0x00, 0x3F, 0x00, 0x00, 0xF0, 0x82, 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE8, 0x02, 0x04, 0x01, - 0x9C, 0xC8, 0x00, 0x33, 0x1F, 0x00, 0xB2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, - 0x70, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x1A, 0x03, 0x00, 0xA6, 0x1A, 0x03, 0x07, 0xA6, 0x12, 0x03, - 0x06, 0xA6, 0x16, 0x03, 0x03, 0xA6, 0x1A, 0x04, 0x02, 0xA6, 0x72, 0x02, 0x00, 0x33, 0x33, 0x00, - 0xB2, 0x88, 0x76, 0x95, 0xF4, 0x82, 0x42, 0x96, 0xF4, 0x82, 0x74, 0x98, 0x80, 0x42, 0x70, 0x98, - 0x60, 0xE4, 0x04, 0x01, 0x29, 0xC8, 0x31, 0x05, 0x07, 0x01, 0x00, 0xA2, 0x5A, 0x03, 0x00, 0x43, - 0x87, 0x01, 0x05, 0x05, 0x78, 0x98, 0x70, 0x98, 0x00, 0xA6, 0x1C, 0x03, 0x07, 0xA6, 0x52, 0x03, - 0x03, 0xA6, 0x36, 0x04, 0x06, 0xA6, 0x56, 0x03, 0x01, 0xA6, 0x1C, 0x03, 0x00, 0x33, 0x25, 0x00, - 0xB2, 0x88, 0x76, 0x95, 0x38, 0x83, 0x42, 0x96, 0x38, 0x83, 0x04, 0x01, 0x0C, 0xCE, 0x03, 0xC8, - 0x00, 0x33, 0x42, 0x00, 0xB2, 0x88, 0x00, 0x01, 0x05, 0x05, 0xFF, 0xA2, 0x78, 0x03, 0xB1, 0x01, - 0x08, 0x23, 0xB2, 0x01, 0x34, 0x83, 0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x98, 0x03, 0xEC, 0x00, - 0x6E, 0x00, 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x94, 0x03, 0x00, 0xA6, - 0x94, 0x03, 0x0C, 0x84, 0x80, 0x42, 0x70, 0x98, 0x01, 0xA6, 0xA2, 0x03, 0x00, 0xA6, 0xBA, 0x03, - 0x0C, 0x84, 0x98, 0x98, 0x80, 0x42, 0x01, 0xA6, 0xA2, 0x03, 0x07, 0xA6, 0xB0, 0x03, 0xD2, 0x83, - 0x76, 0x95, 0xA6, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xB2, 0x88, 0x98, 0x98, 0x80, 0x42, 0x00, 0xA6, - 0xBA, 0x03, 0x07, 0xA6, 0xC8, 0x03, 0xD2, 0x83, 0x76, 0x95, 0xBE, 0x83, 0x00, 0x33, 0x26, 0x00, - 0xB2, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, - 0x0C, 0x84, 0x06, 0xF0, 0x06, 0xA4, 0xF0, 0x03, 0x80, 0x6B, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63, - 0x03, 0xA6, 0x0A, 0x04, 0x07, 0xA6, 0x02, 0x04, 0x06, 0xA6, 0x06, 0x04, 0x00, 0x33, 0x17, 0x00, - 0xB2, 0x88, 0x76, 0x95, 0xF0, 0x83, 0x42, 0x96, 0xF0, 0x83, 0x1A, 0x84, 0x06, 0xF0, 0x06, 0xA4, - 0x1A, 0x04, 0x80, 0x6B, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x03, 0xA6, 0x36, 0x04, - 0x07, 0xA6, 0x2E, 0x04, 0x06, 0xA6, 0x32, 0x04, 0x00, 0x33, 0x30, 0x00, 0xB2, 0x88, 0x76, 0x95, - 0x1A, 0x84, 0x42, 0x96, 0x1A, 0x84, 0x1D, 0x01, 0x06, 0xCC, 0x00, 0x33, 0x00, 0x84, 0xC0, 0x20, - 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63, 0x07, 0xA6, 0x54, 0x04, 0x00, 0x33, - 0x18, 0x00, 0xB2, 0x88, 0x03, 0x03, 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x5E, 0x04, 0x23, 0x01, - 0x00, 0xA2, 0x80, 0x04, 0x0A, 0xA0, 0x70, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00, 0xB2, 0x88, - 0x0B, 0xA0, 0x7C, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00, 0xB2, 0x88, 0x42, 0x23, 0xE8, 0x88, - 0x00, 0x23, 0x22, 0xA3, 0xE0, 0x04, 0x08, 0x23, 0x22, 0xA3, 0x9C, 0x04, 0x28, 0x23, 0x22, 0xA3, - 0xA8, 0x04, 0x02, 0x23, 0x22, 0xA3, 0xBE, 0x04, 0x42, 0x23, 0xE8, 0x88, 0x4A, 0x00, 0x06, 0x61, - 0x00, 0xA0, 0xA8, 0x04, 0x45, 0x23, 0xE8, 0x88, 0xF6, 0x97, 0x00, 0xA2, 0xBA, 0x04, 0xA4, 0x98, - 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, 0x81, 0x62, 0xF0, 0x81, 0x47, 0x23, 0xE8, 0x88, 0x04, 0x01, - 0x0B, 0xDE, 0xF6, 0x97, 0xA4, 0x98, 0x00, 0x33, 0x00, 0x81, 0xC0, 0x20, 0x81, 0x62, 0x14, 0x01, - 0x00, 0xA0, 0x08, 0x02, 0x43, 0x23, 0xE8, 0x88, 0x04, 0x23, 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, - 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, 0xEE, 0x04, 0x00, 0x33, 0x27, 0x00, 0xB2, 0x88, 0x04, 0x01, - 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xF6, 0x97, 0x20, 0x95, 0x4B, 0x00, - 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x1C, 0x05, 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, - 0x00, 0xA2, 0x16, 0x05, 0x04, 0x85, 0x38, 0x97, 0xCD, 0x04, 0x1E, 0x85, 0x48, 0x04, 0x84, 0x80, - 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x2E, 0x85, 0x02, 0x23, 0xA0, 0x01, 0x4A, 0x00, - 0x06, 0x61, 0x00, 0xA2, 0x3A, 0x05, 0x1D, 0x01, 0x04, 0xD6, 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, - 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x49, 0x00, 0x81, 0x01, 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, - 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00, 0x00, 0x05, 0x00, 0x01, - 0xFF, 0xA0, 0x5A, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00, 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, - 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, 0x07, 0xA4, 0xDA, 0x05, 0x03, 0x03, 0x02, 0xA0, 0x88, 0x05, - 0xD6, 0x85, 0x00, 0x33, 0x2D, 0x00, 0xB2, 0x88, 0x04, 0xA0, 0xAE, 0x05, 0x80, 0x63, 0x4A, 0x00, - 0x06, 0x61, 0x00, 0xA2, 0x9A, 0x05, 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, - 0x50, 0x00, 0x54, 0x97, 0xFE, 0x84, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0xFE, 0x84, 0x08, 0xA0, - 0xB4, 0x05, 0xD6, 0x85, 0x03, 0xA0, 0xBA, 0x05, 0xD6, 0x85, 0x01, 0xA0, 0xC4, 0x05, 0x88, 0x00, - 0x80, 0x63, 0xB2, 0x86, 0x07, 0xA0, 0xD0, 0x05, 0x06, 0x23, 0x5A, 0x98, 0x48, 0x23, 0xE8, 0x88, - 0x07, 0x23, 0x80, 0x00, 0xF8, 0x86, 0x80, 0x63, 0x76, 0x85, 0x00, 0x63, 0x4A, 0x00, 0x06, 0x61, - 0x00, 0xA2, 0x18, 0x06, 0x1D, 0x01, 0x18, 0xD4, 0xC0, 0x23, 0x07, 0x41, 0x83, 0x03, 0x80, 0x63, - 0x06, 0xA6, 0xFA, 0x05, 0x00, 0x33, 0x37, 0x00, 0xB2, 0x88, 0x1D, 0x01, 0x02, 0xD6, 0x46, 0x23, - 0xE8, 0x88, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x12, 0x06, 0x00, 0x33, 0x38, 0x00, - 0xB2, 0x88, 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00, 0x52, 0x00, - 0x06, 0x61, 0x00, 0xA2, 0x30, 0x06, 0x1D, 0x01, 0x03, 0xCA, 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, - 0x1D, 0x01, 0x04, 0xCC, 0x00, 0x33, 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, - 0x00, 0x63, 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x06, 0xA6, 0x5E, 0x06, - 0x07, 0xA6, 0x76, 0x05, 0x02, 0xA6, 0xEC, 0x06, 0x00, 0x33, 0x39, 0x00, 0xB2, 0x88, 0x00, 0x00, - 0x01, 0xA0, 0x06, 0x07, 0xDC, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x72, 0x06, 0x07, 0xA6, - 0x76, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x06, 0x07, 0x00, 0x2B, 0x40, 0x0E, 0x80, 0x63, 0x01, 0x00, - 0x06, 0xA6, 0x8E, 0x06, 0x07, 0xA6, 0x76, 0x05, 0x00, 0x33, 0x3A, 0x00, 0xB2, 0x88, 0x40, 0x0E, - 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x80, 0x06, 0x06, 0xA6, 0xA6, 0x06, 0x07, 0xA6, 0x76, 0x05, - 0x00, 0x33, 0x3B, 0x00, 0xB2, 0x88, 0x80, 0x67, 0x40, 0x0E, 0x80, 0x63, 0x07, 0xA6, 0x76, 0x05, - 0x00, 0x63, 0x07, 0xA6, 0xBC, 0x06, 0x00, 0x33, 0x2A, 0x00, 0xB2, 0x88, 0x03, 0x03, 0x80, 0x63, - 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0xCE, 0x06, 0x00, 0x33, 0x29, 0x00, 0xB2, 0x88, 0x00, 0x43, - 0x00, 0xA2, 0xDA, 0x06, 0xC0, 0x0E, 0x80, 0x63, 0xC4, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, - 0xC0, 0x20, 0x81, 0x62, 0x04, 0x01, 0x08, 0xDA, 0x80, 0x63, 0x76, 0x85, 0x80, 0x67, 0x00, 0x33, - 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x6A, 0x06, - 0x00, 0x33, 0x2C, 0x00, 0xB2, 0x88, 0x0C, 0xA2, 0x20, 0x07, 0xDC, 0x95, 0x83, 0x03, 0x80, 0x63, - 0x06, 0xA6, 0x1E, 0x07, 0x07, 0xA6, 0x76, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xB2, 0x88, 0x00, 0x00, - 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x36, 0x07, 0x07, 0xA6, 0x76, 0x05, 0xBF, 0x23, - 0x04, 0x61, 0x84, 0x01, 0xE0, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, - 0xF2, 0x00, 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04, 0x80, 0x05, - 0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, - 0x81, 0x01, 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, - 0x80, 0x01, 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, 0xF1, 0x00, - 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, - 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, - 0xA2, 0x01, 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, 0xB6, 0x07, - 0x00, 0x33, 0x07, 0x00, 0xB2, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, - 0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, - 0xD6, 0x07, 0x00, 0x05, 0xCC, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x05, 0x05, - 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, - 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, - 0x00, 0xA0, 0x06, 0x08, 0x08, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, - 0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, - 0x36, 0x08, 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x16, 0x08, - 0xF6, 0x97, 0x20, 0x95, 0x16, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, 0x4C, 0x88, - 0x02, 0x01, 0x04, 0xD8, 0x38, 0x97, 0xF6, 0x97, 0x20, 0x95, 0x3C, 0x88, 0x75, 0x00, 0x00, 0xA3, - 0x56, 0x08, 0x00, 0x05, 0x40, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, - 0x68, 0x08, 0x00, 0x33, 0x3E, 0x00, 0xB2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, - 0x38, 0x2B, 0x8E, 0x88, 0x38, 0x2B, 0x84, 0x88, 0x32, 0x09, 0x31, 0x05, 0x84, 0x98, 0x05, 0x05, - 0xB2, 0x09, 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, - 0x80, 0x36, 0x80, 0x3A, 0x80, 0x3E, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32, 0x40, 0x36, 0x40, 0x3A, - 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0xA4, 0x08, 0x5D, 0x00, 0xFE, 0xC3, - 0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73, - 0x13, 0x23, 0xE8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, 0xA1, 0x23, 0xA1, 0x01, - 0x81, 0x62, 0xD2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, - 0xF1, 0xC7, 0x41, 0x23, 0xE8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE0, 0x84, - + 0x11, 0x23, 0xF6, 0x88, 0x04, 0x98, 0xF4, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x32, 0x02, + 0x7C, 0x95, 0x06, 0xA6, 0x3C, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0xC0, 0x88, 0x04, 0x01, 0x03, 0xD8, + 0xB2, 0x98, 0x6A, 0x96, 0x4E, 0x82, 0xFE, 0x95, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, + 0x02, 0xA6, 0x78, 0x02, 0x07, 0xA6, 0x66, 0x02, 0x06, 0xA6, 0x6A, 0x02, 0x03, 0xA6, 0x6E, 0x02, + 0x00, 0x33, 0x10, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0x50, 0x82, 0x60, 0x96, 0x50, 0x82, 0x04, 0x23, + 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC, 0xE0, 0x23, 0x25, 0x61, + 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01, 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01, + 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xB6, 0x02, 0x07, 0xA6, 0x66, 0x02, + 0x06, 0xA6, 0x6A, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xC0, 0x02, 0x00, 0xA6, 0xC0, 0x02, + 0x00, 0x33, 0x12, 0x00, 0xC0, 0x88, 0x00, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x98, 0x02, + 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35, + 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xF6, 0x82, 0x18, 0x23, 0x04, 0x61, + 0x18, 0xA0, 0xEE, 0x02, 0x04, 0x01, 0x9C, 0xC8, 0x00, 0x33, 0x1F, 0x00, 0xC0, 0x88, 0x08, 0x31, + 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x20, 0x03, 0x00, 0xA6, + 0x20, 0x03, 0x07, 0xA6, 0x18, 0x03, 0x06, 0xA6, 0x1C, 0x03, 0x03, 0xA6, 0x20, 0x04, 0x02, 0xA6, + 0x78, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0xFA, 0x82, 0x60, 0x96, 0xFA, 0x82, + 0x82, 0x98, 0x80, 0x42, 0x7E, 0x98, 0x60, 0xE4, 0x04, 0x01, 0x29, 0xC8, 0x31, 0x05, 0x07, 0x01, + 0x00, 0xA2, 0x60, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98, 0x7E, 0x98, 0x00, 0xA6, + 0x22, 0x03, 0x07, 0xA6, 0x58, 0x03, 0x03, 0xA6, 0x3C, 0x04, 0x06, 0xA6, 0x5C, 0x03, 0x01, 0xA6, + 0x22, 0x03, 0x00, 0x33, 0x25, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0x3E, 0x83, 0x60, 0x96, 0x3E, 0x83, + 0x04, 0x01, 0x0C, 0xCE, 0x03, 0xC8, 0x00, 0x33, 0x42, 0x00, 0xC0, 0x88, 0x00, 0x01, 0x05, 0x05, + 0xFF, 0xA2, 0x7E, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x3A, 0x83, 0x05, 0x05, 0x15, 0x01, + 0x00, 0xA2, 0x9E, 0x03, 0xEC, 0x00, 0x6E, 0x00, 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, + 0x01, 0xA6, 0x9A, 0x03, 0x00, 0xA6, 0x9A, 0x03, 0x12, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6, + 0xA8, 0x03, 0x00, 0xA6, 0xC0, 0x03, 0x12, 0x84, 0xA6, 0x98, 0x80, 0x42, 0x01, 0xA6, 0xA8, 0x03, + 0x07, 0xA6, 0xB6, 0x03, 0xD8, 0x83, 0x7C, 0x95, 0xAC, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC0, 0x88, + 0xA6, 0x98, 0x80, 0x42, 0x00, 0xA6, 0xC0, 0x03, 0x07, 0xA6, 0xCE, 0x03, 0xD8, 0x83, 0x7C, 0x95, + 0xC4, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC0, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, 0x04, 0x23, + 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x12, 0x84, 0x06, 0xF0, 0x06, 0xA4, 0xF6, 0x03, 0x80, 0x6B, + 0x05, 0x23, 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x10, 0x04, 0x07, 0xA6, 0x08, 0x04, 0x06, 0xA6, + 0x0C, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0xF6, 0x83, 0x60, 0x96, 0xF6, 0x83, + 0x20, 0x84, 0x06, 0xF0, 0x06, 0xA4, 0x20, 0x04, 0x80, 0x6B, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63, + 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6, 0x38, 0x04, 0x00, 0x33, + 0x30, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0x20, 0x84, 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC, + 0x00, 0x33, 0x00, 0x84, 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63, + 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC0, 0x88, 0x03, 0x03, 0x80, 0x63, 0xA3, 0x01, + 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2, 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00, + 0x00, 0x33, 0x1D, 0x00, 0xC0, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00, + 0xC0, 0x88, 0x42, 0x23, 0xF6, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04, 0x08, 0x23, 0x22, 0xA3, + 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04, 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23, + 0xF6, 0x88, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF6, 0x88, 0x04, 0x98, + 0x00, 0xA2, 0xC0, 0x04, 0xB2, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, 0x81, 0x62, 0xF0, 0x81, + 0x47, 0x23, 0xF6, 0x88, 0x04, 0x01, 0x0B, 0xDE, 0x04, 0x98, 0xB2, 0x98, 0x00, 0x33, 0x00, 0x81, + 0xC0, 0x20, 0x81, 0x62, 0x14, 0x01, 0x00, 0xA0, 0x08, 0x02, 0x43, 0x23, 0xF6, 0x88, 0x04, 0x23, + 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, 0xF4, 0x04, 0x00, 0x33, + 0x27, 0x00, 0xC0, 0x88, 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, + 0x04, 0x98, 0x26, 0x95, 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05, + 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85, 0x46, 0x97, 0xCD, 0x04, + 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85, + 0x02, 0x23, 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6, + 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x49, 0x00, 0x81, 0x01, + 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, + 0xC9, 0x00, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00, + 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, 0x07, 0xA4, 0xF8, 0x05, + 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85, 0x00, 0x33, 0x2D, 0x00, 0xC0, 0x88, 0x04, 0xA0, + 0xB8, 0x05, 0x80, 0x63, 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05, + 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00, 0x62, 0x97, 0x04, 0x85, + 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85, 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0, + 0xC4, 0x05, 0xF4, 0x85, 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0, + 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05, 0x80, 0x67, 0x80, 0x63, + 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23, 0x68, 0x98, 0x48, 0x23, 0xF6, 0x88, 0x07, 0x23, + 0x80, 0x00, 0x06, 0x87, 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00, + 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23, 0x07, 0x41, 0x83, 0x03, + 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33, 0x37, 0x00, 0xC0, 0x88, 0x1D, 0x01, 0x01, 0xD6, + 0x20, 0x23, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05, + 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00, 0x52, 0x00, 0x06, 0x61, + 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA, 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, + 0x04, 0xCC, 0x00, 0x33, 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63, + 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23, 0xDF, 0x00, 0x06, 0xA6, + 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, + 0x81, 0x62, 0x00, 0x63, 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06, + 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B, 0x40, 0x0E, 0x80, 0x63, + 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, + 0x00, 0xA0, 0xA2, 0x06, 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E, + 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x07, 0xA6, 0xD6, 0x06, + 0x00, 0x33, 0x2A, 0x00, 0xC0, 0x88, 0x03, 0x03, 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, + 0xE8, 0x06, 0x00, 0x33, 0x29, 0x00, 0xC0, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E, + 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20, 0x81, 0x62, 0x04, 0x01, + 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33, + 0x2C, 0x00, 0xC0, 0x88, 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, + 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC0, 0x88, 0x00, 0x00, 0x80, 0x67, + 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61, + 0x84, 0x01, 0xE6, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00, + 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04, 0x80, 0x05, 0x81, 0x05, + 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01, + 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01, + 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, 0xF1, 0x00, 0x70, 0x00, + 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00, + 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01, + 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, 0xC4, 0x07, 0x00, 0x33, + 0x07, 0x00, 0xC0, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01, + 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07, + 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x05, 0x05, 0x00, 0x63, + 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02, + 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0, + 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, 0xF3, 0x04, + 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08, + 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98, + 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, 0x5A, 0x88, 0x02, 0x01, + 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95, 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08, + 0x00, 0x05, 0x4E, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08, + 0x00, 0x33, 0x3E, 0x00, 0xC0, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x38, 0x2B, + 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09, 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09, + 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36, + 0x80, 0x3A, 0x80, 0x3E, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32, 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E, + 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0xB2, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63, + 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73, 0x13, 0x23, + 0xF6, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62, + 0xE0, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7, + 0x41, 0x23, 0xF6, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84, }; STATIC ushort _asc_mcode_size ASC_INITDATA = sizeof(_asc_mcode_buf); -STATIC ulong _asc_mcode_chksum ASC_INITDATA = 0x012A727FUL ; +STATIC ulong _asc_mcode_chksum ASC_INITDATA = 0x012B5442UL; #define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16 STATIC uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = @@ -12190,7 +12343,7 @@ if ((cur_req = asc_dvc->cur_dvc_qng[tid_no]) == 0) { break; } - DvcSleepMilliSecond(100L); + DvcSleepMilliSecond(1000L); if (asc_dvc->cur_dvc_qng[tid_no] == cur_req) { break; } @@ -12808,11 +12961,12 @@ asc_dvc->cfg->can_tagged_qng = 0 ; asc_dvc->cfg->cmd_qng_enabled = 0; asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL; - asc_dvc->init_sdtr = ASC_SCSI_WIDTH_BIT_SET; + asc_dvc->init_sdtr = 0; asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG; asc_dvc->scsi_reset_wait = 3; asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET; asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type); + asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET; asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET; asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID; asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER; @@ -12967,7 +13121,7 @@ warn_code |= ASC_WARN_EEPROM_CHKSUM ; } } - asc_dvc->init_sdtr = eep_config->init_sdtr; + asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr ; asc_dvc->cfg->disc_enable = eep_config->disc_enable; asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng; asc_dvc->cfg->isa_dma_speed = eep_config->isa_dma_speed; @@ -13085,47 +13239,6 @@ return (warn_code); } -STATIC void -AscInitPollIsrCallBack( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_QDONE_INFO * scsi_done_q -) -{ - ASC_SCSI_REQ_Q *scsiq_req; - ASC_ISR_CALLBACK asc_isr_callback; - uchar cp_sen_len; - uchar i; - - ASC_DBG(1, "AscInitPollIsrCallBack: begin\n"); - if ((scsi_done_q->d2.flag & ASC_FLAG_SCSIQ_REQ) != 0) { - scsiq_req = (ASC_SCSI_REQ_Q *) scsi_done_q->d2.srb_ptr; - scsiq_req->r3.done_stat = scsi_done_q->d3.done_stat; - scsiq_req->r3.host_stat = scsi_done_q->d3.host_stat; - scsiq_req->r3.scsi_stat = scsi_done_q->d3.scsi_stat; - scsiq_req->r3.scsi_msg = scsi_done_q->d3.scsi_msg; - ASC_DBG4(1, "AscInitPollIsrCallBack: done_stat %x, host_stat %x, scsi_stat %x, scsi_msg %x\n", - scsi_done_q->d3.done_stat, scsi_done_q->d3.host_stat, - scsi_done_q->d3.scsi_stat, scsi_done_q->d3.scsi_msg); - if ((scsi_done_q->d3.scsi_stat == SS_CHK_CONDITION) && - (scsi_done_q->d3.host_stat == 0)) { - cp_sen_len = (uchar) ASC_MIN_SENSE_LEN; - if (scsiq_req->r1.sense_len < ASC_MIN_SENSE_LEN) { - cp_sen_len = (uchar) scsiq_req->r1.sense_len; - } - for (i = 0; i < cp_sen_len; i++) { - scsiq_req->sense[i] = scsiq_req->sense_ptr[i]; - } - } - } else { - if (asc_dvc->isr_callback != 0) { - asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback; - (*asc_isr_callback) (asc_dvc, scsi_done_q); - } - } - ASC_DBG(1, "AscInitPollIsrCallBack: end\n"); - return; -} - ASC_INITFUNC( STATIC int AscTestExternalLram( @@ -13395,413 +13508,124 @@ return (n_error); } -STATIC int -AscInitPollBegin( - REG ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - PortAddr iop_base; - - iop_base = asc_dvc->iop_base; - AscDisableInterrupt(iop_base); - asc_dvc->init_state |= ASC_INIT_STATE_BEG_INQUIRY; - AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, 0x00); - asc_dvc->use_tagged_qng = 0; - asc_dvc->cfg->can_tagged_qng = 0; - asc_dvc->saved_ptr2func = (ulong) asc_dvc->isr_callback; - asc_dvc->isr_callback = ASC_GET_PTR2FUNC(AscInitPollIsrCallBack); - return (0); -} - -STATIC int -AscInitPollEnd( - REG ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - PortAddr iop_base; - rint i; - - iop_base = asc_dvc->iop_base; - asc_dvc->isr_callback = (Ptr2Func) asc_dvc->saved_ptr2func; - AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, - asc_dvc->cfg->disc_enable); - AscWriteLramByte(iop_base, ASCV_USE_TAGGED_QNG_B, - asc_dvc->use_tagged_qng); - AscWriteLramByte(iop_base, ASCV_CAN_TAGGED_QNG_B, - asc_dvc->cfg->can_tagged_qng); - for (i = 0; i <= ASC_MAX_TID; i++) { - AscWriteLramByte(iop_base, - (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) i), - asc_dvc->max_dvc_qng[i]); - } - AscAckInterrupt(iop_base); - AscEnableInterrupt(iop_base); - asc_dvc->init_state |= ASC_INIT_STATE_END_INQUIRY; - return (0); -} - -STATIC int -AscInitPollTarget( - REG ASC_DVC_VAR asc_ptr_type * asc_dvc, - REG ASC_SCSI_REQ_Q * scsiq, - REG ASC_SCSI_INQUIRY * inq, - REG ASC_CAP_INFO * cap_info -) +STATIC void +AscAsyncFix( + ASC_DVC_VAR asc_ptr_type *asc_dvc, + uchar tid_no, + ASC_SCSI_INQUIRY *inq) { - uchar tid_no, lun; - uchar dvc_type; + uchar dvc_type; ASC_SCSI_BIT_ID_TYPE tid_bits; - int dvc_found; - int support_read_cap; - int tmp_disable_init_sdtr; - int sta; - dvc_found = 0; - tmp_disable_init_sdtr = FALSE; - tid_bits = scsiq->r1.target_id; - lun = scsiq->r1.target_lun; - tid_no = ASC_TIX_TO_TID(scsiq->r2.target_ix); - if (((asc_dvc->init_sdtr & tid_bits) != 0) && - ((asc_dvc->sdtr_done & tid_bits) == 0)) { - asc_dvc->init_sdtr &= ~tid_bits; - tmp_disable_init_sdtr = TRUE; - } - ASC_DBG(1, "AscInitPollTarget: before PollScsiInquiry\n"); - if (PollScsiInquiry(asc_dvc, scsiq, (uchar *) inq, - sizeof (ASC_SCSI_INQUIRY)) == 1) { - dvc_found = 1; - dvc_type = inq->byte0.peri_dvc_type; - if (dvc_type != SCSI_TYPE_UNKNOWN) { - support_read_cap = TRUE; - if ((dvc_type != SCSI_TYPE_DASD) - && (dvc_type != SCSI_TYPE_WORM) - && (dvc_type != SCSI_TYPE_CDROM) - && (dvc_type != SCSI_TYPE_OPTMEM)) { - asc_dvc->start_motor &= ~tid_bits; - support_read_cap = FALSE; - } - if (lun == 0) { - if ((inq->byte3.rsp_data_fmt >= 2) || - (inq->byte2.ansi_apr_ver >= 2)) { - if (inq->byte7.CmdQue) { - asc_dvc->cfg->can_tagged_qng |= tid_bits; - if (asc_dvc->cfg->cmd_qng_enabled & tid_bits) { - asc_dvc->use_tagged_qng |= tid_bits; - asc_dvc->max_dvc_qng[tid_no] = asc_dvc->cfg->max_tag_qng[tid_no]; - } - } - if (!inq->byte7.Sync) { - asc_dvc->init_sdtr &= ~tid_bits; - asc_dvc->sdtr_done &= ~tid_bits; - } else if (tmp_disable_init_sdtr) { - asc_dvc->init_sdtr |= tid_bits; - } - } else { - asc_dvc->init_sdtr &= ~tid_bits; - asc_dvc->sdtr_done &= ~tid_bits; - asc_dvc->use_tagged_qng &= ~tid_bits; - } - } - if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) { - if (!(asc_dvc->init_sdtr & tid_bits)) { - if ((dvc_type == SCSI_TYPE_CDROM) && - (AscCompareString((uchar *) inq->vendor_id, - (uchar *) "HP ", 3) == 0)) { - asc_dvc->pci_fix_asyn_xfer_always |= tid_bits; - } - asc_dvc->pci_fix_asyn_xfer |= tid_bits; - if ((dvc_type == SCSI_TYPE_PROC) || (dvc_type == SCSI_TYPE_SCANNER)) { - asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; - } - if ((dvc_type == SCSI_TYPE_SASD) && - (AscCompareString((uchar *) inq->vendor_id, - (uchar *) "TANDBERG", 8) == 0) && - (AscCompareString((uchar *) inq->product_id, - (uchar *) " TDC 36", 7) == 0)) { - asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; - } - if ((dvc_type == SCSI_TYPE_SASD) && - (AscCompareString((uchar *) inq->vendor_id, - (uchar *) "WANGTEK ", 8) == 0)) { - asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; - } + dvc_type = inq->byte0.peri_dvc_type; + tid_bits = ASC_TIX_TO_TARGET_ID(tid_no); - if ((dvc_type == SCSI_TYPE_CDROM) && - (AscCompareString((uchar *)inq->vendor_id, - (uchar *)"NEC ", 8) == 0) && - (AscCompareString((uchar *)inq->product_id, - (uchar *)"CD-ROM DRIVE ", 16) == 0)) { - asc_dvc->pci_fix_asyn_xfer &= ~tid_bits ; - } - if ((dvc_type == SCSI_TYPE_CDROM) && - (AscCompareString((uchar *) inq->vendor_id, - (uchar *) "YAMAHA", 6) == 0) && - (AscCompareString((uchar *) inq->product_id, - (uchar *) "CDR400", 6) == 0)) - { - asc_dvc->pci_fix_asyn_xfer &= ~tid_bits ; - } - - if (asc_dvc->pci_fix_asyn_xfer & tid_bits) { - AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no, - ASYN_SDTR_DATA_FIX_PCI_REV_AB); - } - } - } - sta = 1; - ASC_DBG(1, "AscInitPollTarget: before InitTestUnitReady\n"); - sta = InitTestUnitReady(asc_dvc, scsiq); - if (sta == 1) { - if ((cap_info != 0L) && support_read_cap) { - ASC_DBG(1, - "AscInitPollTarget: before PollScsiReadCapacity\n"); - if (PollScsiReadCapacity(asc_dvc, scsiq, - cap_info) != 1) { - cap_info->lba = 0L; - cap_info->blk_size = 0x0000; - } else { - } - } + if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) { + if (!(asc_dvc->init_sdtr & tid_bits)) { + if ((dvc_type == SCSI_TYPE_CDROM) && + (AscCompareString((uchar *) inq->vendor_id, + (uchar *) "HP ", 3) == 0)) { + asc_dvc->pci_fix_asyn_xfer_always |= tid_bits; + } + asc_dvc->pci_fix_asyn_xfer |= tid_bits; + if ((dvc_type == SCSI_TYPE_PROC) || + (dvc_type == SCSI_TYPE_SCANNER)) { + asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; + } + if ((dvc_type == SCSI_TYPE_SASD) && + (AscCompareString((uchar *) inq->vendor_id, + (uchar *) "TANDBERG", 8) == 0) && + (AscCompareString((uchar *) inq->product_id, + (uchar *) " TDC 36", 7) == 0)) { + asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; + } + if ((dvc_type == SCSI_TYPE_SASD) && + (AscCompareString((uchar *) inq->vendor_id, + (uchar *) "WANGTEK ", 8) == 0)) { + asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; + } + + if ((dvc_type == SCSI_TYPE_CDROM) && + (AscCompareString((uchar *) inq->vendor_id, + (uchar *) "NEC ", 8) == 0) && + (AscCompareString((uchar *) inq->product_id, + (uchar *) "CD-ROM DRIVE ", 16) == 0)) { + asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; + } + + if ((dvc_type == SCSI_TYPE_CDROM) && + (AscCompareString((uchar *) inq->vendor_id, + (uchar *) "YAMAHA", 6) == 0) && + (AscCompareString((uchar *) inq->product_id, + (uchar *) "CDR400", 6) == 0)) { + asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; + } + if (asc_dvc->pci_fix_asyn_xfer & tid_bits) { + AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no, + ASYN_SDTR_DATA_FIX_PCI_REV_AB); } - } else { - asc_dvc->start_motor &= ~tid_bits; } - } else if (tmp_disable_init_sdtr) { - asc_dvc->init_sdtr |= tid_bits; } - ASC_DBG1(1, "AscInitPollTarget: dvc_found %d\n", dvc_found); - return (dvc_found); -} - -STATIC int -PollQueueDone( - REG ASC_DVC_VAR asc_ptr_type * asc_dvc, - REG ASC_SCSI_REQ_Q * scsiq, - int timeout_sec -) -{ - int status; - int retry = 0; - - ASC_DBG1(1, "PollQueueDone: timeout_sec %d\n", timeout_sec); - do { - ASC_DBG(1, "PollQueueDone: before AscExeScsiQueue\n"); - if ((status = AscExeScsiQueue(asc_dvc, - (ASC_SCSI_Q *) scsiq)) == 1) { - ASC_DBG(1, "PollQueueDone: before AscPollQDone\n"); - if ((status = AscPollQDone(asc_dvc, scsiq, - timeout_sec)) != 1) { - ASC_DBG1(1, "PollQueueDone: status %x\n", status); - if (status == 0x80) { - if (retry++ > ASC_MAX_INIT_BUSY_RETRY) { - break; - } - scsiq->r3.done_stat = 0; - scsiq->r3.host_stat = 0; - scsiq->r3.scsi_stat = 0; - scsiq->r3.scsi_msg = 0; - DvcSleepMilliSecond(1000); - continue; - } - scsiq->r3.done_stat = 0; - scsiq->r3.host_stat = 0; - scsiq->r3.scsi_stat = 0; - scsiq->r3.scsi_msg = 0; - ASC_DBG(1, "PollQueueDone: before AscAbortSRB()\n"); - AscAbortSRB(asc_dvc, (ulong) scsiq); - } - ASC_DBG1(1, "PollQueueDone: status %x\n", status); - ASC_DBG1(1, "PollQueueDone: done_stat %x\n", scsiq->r3.done_stat); - return (scsiq->r3.done_stat); - } - ASC_DBG1(1, "PollQueueDone: status %x\n", status); - DvcSleepMilliSecond(5); - } while (((status == 0) || (status == 0x80)) && - retry++ < ASC_MAX_INIT_BUSY_RETRY); - ASC_DBG1(1, "PollQueueDone: status %x\n", status); - ASC_DBG(1, "PollQueueDone: done_stat QD_WITH_ERROR\n"); - return (scsiq->r3.done_stat = QD_WITH_ERROR); -} - -STATIC int -PollScsiInquiry( - REG ASC_DVC_VAR asc_ptr_type * asc_dvc, - REG ASC_SCSI_REQ_Q * scsiq, - uchar * buf, - int buf_len -) -{ - if (AscScsiInquiry(asc_dvc, scsiq, buf, buf_len) == ERR) { - return (scsiq->r3.done_stat = QD_WITH_ERROR); - } - return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q *) scsiq, 4)); -} - -STATIC int -PollScsiStartUnit( - REG ASC_DVC_VAR asc_ptr_type * asc_dvc, - REG ASC_SCSI_REQ_Q * scsiq -) -{ - if (AscScsiStartStopUnit(asc_dvc, scsiq, 1) == ERR) { - return (scsiq->r3.done_stat = QD_WITH_ERROR); - } - return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q *) scsiq, 40)); + return; } STATIC int -PollScsiReadCapacity( - REG ASC_DVC_VAR asc_ptr_type * asc_dvc, - REG ASC_SCSI_REQ_Q * scsiq, - REG ASC_CAP_INFO * cap_info -) +AscTagQueuingSafe(ASC_SCSI_INQUIRY *inq) { - ASC_CAP_INFO scsi_cap_info; - int status; - - if (AscScsiReadCapacity(asc_dvc, scsiq, - (uchar *) & scsi_cap_info) == ERR) { - return (scsiq->r3.done_stat = QD_WITH_ERROR); - } - status = PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q *) scsiq, 8); - if (status == 1) { - cap_info->lba = (ulong) * swapfarbuf4((uchar *) & scsi_cap_info.lba); - cap_info->blk_size = (ulong) * swapfarbuf4((uchar *) & scsi_cap_info.blk_size); - return (scsiq->r3.done_stat); + if ((inq->add_len >= 32) && + (AscCompareString((uchar *) inq->vendor_id, + (uchar *) "QUANTUM XP34301", 15) == 0) && + (AscCompareString((uchar *) inq->product_rev_level, + (uchar *) "1071", 4) == 0)) + { + return 0; } - return (scsiq->r3.done_stat = QD_WITH_ERROR); -} - -STATIC ulong * -swapfarbuf4( - uchar *buf -) -{ - uchar tmp; - - tmp = buf[3]; - buf[3] = buf[0]; - buf[0] = tmp; - - tmp = buf[1]; - buf[1] = buf[2]; - buf[2] = tmp; - - return ((ulong *) buf); + return 1; } -STATIC int -PollScsiTestUnitReady( - REG ASC_DVC_VAR asc_ptr_type * asc_dvc, - REG ASC_SCSI_REQ_Q * scsiq -) +STATIC void +AscInquiryHandling(ASC_DVC_VAR asc_ptr_type *asc_dvc, + uchar tid_no, ASC_SCSI_INQUIRY *inq) { - if (AscScsiTestUnitReady(asc_dvc, scsiq) == ERR) { - return (scsiq->r3.done_stat = QD_WITH_ERROR); - } - return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q *) scsiq, 12)); -} + ASC_SCSI_BIT_ID_TYPE tid_bit = ASC_TIX_TO_TARGET_ID(tid_no); + ASC_SCSI_BIT_ID_TYPE orig_init_sdtr, orig_use_tagged_qng; -STATIC int -InitTestUnitReady( - REG ASC_DVC_VAR asc_ptr_type * asc_dvc, - REG ASC_SCSI_REQ_Q * scsiq -) -{ - ASC_SCSI_BIT_ID_TYPE tid_bits; - int retry; - ASC_REQ_SENSE *sen; + orig_init_sdtr = asc_dvc->init_sdtr; + orig_use_tagged_qng = asc_dvc->use_tagged_qng; - retry = 0; - tid_bits = scsiq->r1.target_id; - while (retry++ < 4) { - PollScsiTestUnitReady(asc_dvc, scsiq); - if (scsiq->r3.done_stat == 0x01) { - return (1); - } else if (scsiq->r3.done_stat == QD_WITH_ERROR) { - sen = (ASC_REQ_SENSE *) scsiq->sense_ptr; - if ((scsiq->r3.scsi_stat == SS_CHK_CONDITION) && - ((sen->err_code & 0x70) != 0)) { - if (sen->sense_key == SCSI_SENKEY_NOT_READY) { - if (sen->asc == SCSI_ASC_NOMEDIA) - { - break; - } - if (asc_dvc->start_motor & tid_bits) { - if (PollScsiStartUnit(asc_dvc, scsiq) == 1) { - DvcSleepMilliSecond(250); - continue; - } else { - asc_dvc->start_motor &= ~tid_bits; - break; - } - } else { - DvcSleepMilliSecond(250); - } - } else if (sen->sense_key == SCSI_SENKEY_ATTENTION) { - DvcSleepMilliSecond(250); - } else { - break; - } - } else { - break; + asc_dvc->init_sdtr &= ~tid_bit; + asc_dvc->cfg->can_tagged_qng &= ~tid_bit; + asc_dvc->use_tagged_qng &= ~tid_bit; + + if (inq->byte3.rsp_data_fmt >= 2 || inq->byte2.ansi_apr_ver >= 2) { + if ((asc_dvc->cfg->sdtr_enable & tid_bit) && inq->byte7.Sync) { + asc_dvc->init_sdtr |= tid_bit; + } + if ((asc_dvc->cfg->cmd_qng_enabled & tid_bit) && inq->byte7.CmdQue) { + if (AscTagQueuingSafe(inq)) { + asc_dvc->use_tagged_qng |= tid_bit; + asc_dvc->cfg->can_tagged_qng |= tid_bit; } - } else if (scsiq->r3.done_stat == QD_ABORTED_BY_HOST) { - break; - } else { - break; } } - return (0); -} - -STATIC int -AscPollQDone( - REG ASC_DVC_VAR asc_ptr_type * asc_dvc, - REG ASC_SCSI_REQ_Q * scsiq, - int timeout_sec -) -{ - int loop, loop_end; - int sta; - PortAddr iop_base; - - iop_base = asc_dvc->iop_base; - loop = 0; - loop_end = timeout_sec * 100; - sta = 1; - while (TRUE) { - if (asc_dvc->err_code != 0) { - scsiq->r3.done_stat = QD_WITH_ERROR; - ASC_DBG1(1, "AscPollQDone: err_code %x\n", asc_dvc->err_code); - sta = ERR; - break; - } - if (scsiq->r3.done_stat != QD_IN_PROGRESS) { - if ((scsiq->r3.done_stat == QD_WITH_ERROR) && - (scsiq->r3.scsi_stat == SS_TARGET_BUSY)) { - sta = 0x80; - } - break; - } - DvcSleepMilliSecond(10); - if (loop++ > loop_end) { - ASC_DBG(1, "AscPollQDone: loop finished\n"); - sta = 0; - break; - } - if (AscIsChipHalted(iop_base)) { - ASC_DBG(1, "AscPollQDone: AscIsChipHalted()\n"); - AscISR(asc_dvc); - loop = 0; - } else { - if (AscIsIntPending(iop_base)) { - ASC_DBG(1, "AscPollQDone: AscIsIntPending()\n"); - AscISR(asc_dvc); - } - } + if (orig_use_tagged_qng != asc_dvc->use_tagged_qng) { + AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B, + asc_dvc->cfg->disc_enable); + AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B, + asc_dvc->use_tagged_qng); + AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B, + asc_dvc->cfg->can_tagged_qng); + + asc_dvc->max_dvc_qng[tid_no] = + asc_dvc->cfg->max_tag_qng[tid_no]; + AscWriteLramByte(asc_dvc->iop_base, + (ushort) (ASCV_MAX_DVC_QNG_BEG + tid_no), + asc_dvc->max_dvc_qng[tid_no]); } - return (sta); + if (orig_init_sdtr != asc_dvc->init_sdtr) { + AscAsyncFix(asc_dvc, tid_no, inq); + } + return; } STATIC int @@ -13998,105 +13822,16 @@ } -STATIC int -AscScsiInquiry( - REG ASC_DVC_VAR asc_ptr_type * asc_dvc, - REG ASC_SCSI_REQ_Q * scsiq, - uchar * buf, - int buf_len -) -{ - if (AscScsiSetupCmdQ(asc_dvc, scsiq, buf, - (ulong) buf_len) == ERR) { - return (scsiq->r3.done_stat = QD_WITH_ERROR); - } - scsiq->cdb[0] = (uchar) SCSICMD_Inquiry; - scsiq->cdb[1] = scsiq->r1.target_lun << 5; - scsiq->cdb[2] = 0; - scsiq->cdb[3] = 0; - scsiq->cdb[4] = buf_len; - scsiq->cdb[5] = 0; - scsiq->r2.cdb_len = 6; - return (0); -} - -STATIC int -AscScsiReadCapacity( - REG ASC_DVC_VAR asc_ptr_type * asc_dvc, - REG ASC_SCSI_REQ_Q * scsiq, - uchar * info -) -{ - if (AscScsiSetupCmdQ(asc_dvc, scsiq, info, 8L) == ERR) { - return (scsiq->r3.done_stat = QD_WITH_ERROR); - } - scsiq->cdb[0] = (uchar) SCSICMD_ReadCapacity; - scsiq->cdb[1] = scsiq->r1.target_lun << 5; - scsiq->cdb[2] = 0; - scsiq->cdb[3] = 0; - scsiq->cdb[4] = 0; - scsiq->cdb[5] = 0; - scsiq->cdb[6] = 0; - scsiq->cdb[7] = 0; - scsiq->cdb[8] = 0; - scsiq->cdb[9] = 0; - scsiq->r2.cdb_len = 10; - return (0); -} - -STATIC int -AscScsiTestUnitReady( - REG ASC_DVC_VAR asc_ptr_type * asc_dvc, - REG ASC_SCSI_REQ_Q * scsiq -) -{ - if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR, - (ulong) 0L) == ERR) { - return (scsiq->r3.done_stat = QD_WITH_ERROR); - } - scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA; - scsiq->cdb[0] = (uchar) SCSICMD_TestUnitReady; - scsiq->cdb[1] = scsiq->r1.target_lun << 5; - scsiq->cdb[2] = 0; - scsiq->cdb[3] = 0; - scsiq->cdb[4] = 0; - scsiq->cdb[5] = 0; - scsiq->r2.cdb_len = 6; - return (0); -} - -STATIC int -AscScsiStartStopUnit( - REG ASC_DVC_VAR asc_ptr_type * asc_dvc, - REG ASC_SCSI_REQ_Q * scsiq, - uchar op_mode -) -{ - if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR, (ulong) 0L) == ERR) { - return (scsiq->r3.done_stat = QD_WITH_ERROR); - } - scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA; - scsiq->cdb[0] = (uchar) SCSICMD_StartStopUnit; - scsiq->cdb[1] = scsiq->r1.target_lun << 5; - scsiq->cdb[2] = 0; - scsiq->cdb[3] = 0; - scsiq->cdb[4] = op_mode; - scsiq->cdb[5] = 0; - scsiq->r2.cdb_len = 6; - return (0); -} - - /* * --- Adv Library Functions */ /* a_qswap.h */ STATIC unsigned char _adv_mcode_buf[] ASC_INITDATA = { - 0x9C, 0xF0, 0x80, 0x01, 0x00, 0xF0, 0x40, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9C, 0xF0, 0x80, 0x01, 0x00, 0xF0, 0x44, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x01, 0xD2, 0x11, 0x00, 0x00, 0x70, 0x01, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x0F, 0x22, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x01, 0xD6, 0x11, 0x00, 0x00, 0x70, 0x01, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x10, 0x2D, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -14116,273 +13851,274 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x04, 0xF7, 0x70, 0x01, 0x0C, 0x1C, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF2, 0xD2, 0x0A, + 0x00, 0x00, 0x04, 0xF7, 0x70, 0x01, 0x0C, 0x1C, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF2, 0xD6, 0x0A, 0x04, 0xF7, 0x70, 0x01, 0x06, 0xF7, 0x02, 0x00, 0x3E, 0x57, 0x3C, 0x56, 0x0C, 0x1C, 0x00, 0xFC, - 0xA6, 0x00, 0x01, 0x58, 0xAA, 0x13, 0x20, 0xF0, 0x9A, 0x03, 0x06, 0xEC, 0xB9, 0x00, 0x0E, 0x47, + 0xA6, 0x00, 0x01, 0x58, 0xAA, 0x13, 0x20, 0xF0, 0xA6, 0x03, 0x06, 0xEC, 0xB9, 0x00, 0x0E, 0x47, 0x03, 0xE6, 0x10, 0x00, 0xCE, 0x45, 0x02, 0x13, 0x3E, 0x57, 0x06, 0xEA, 0xB9, 0x00, 0x47, 0x4B, - 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x64, 0x0A, 0x01, 0x48, 0x4E, 0x12, 0x03, 0xF6, 0xC0, 0x00, - 0x00, 0xF2, 0x64, 0x0A, 0x41, 0x58, 0x03, 0xF6, 0xD0, 0x00, 0x00, 0xF2, 0x64, 0x0A, 0x49, 0x44, - 0x59, 0xF0, 0x0A, 0x02, 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x64, 0x0A, 0x44, 0x58, 0x00, 0xF2, - 0xDE, 0x0D, 0x02, 0xCC, 0x4A, 0xE4, 0x01, 0x00, 0x55, 0xF0, 0x08, 0x03, 0x45, 0xF4, 0x02, 0x00, - 0x83, 0x5A, 0x04, 0xCC, 0x01, 0x4A, 0x12, 0x12, 0x00, 0xF2, 0xDE, 0x0D, 0x00, 0xCD, 0x48, 0xE4, - 0x01, 0x00, 0xE9, 0x13, 0x00, 0xF2, 0xC2, 0x0F, 0xFA, 0x10, 0x0E, 0x47, 0x03, 0xE6, 0x10, 0x00, + 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x01, 0x48, 0x4E, 0x12, 0x03, 0xF6, 0xC0, 0x00, + 0x00, 0xF2, 0x68, 0x0A, 0x41, 0x58, 0x03, 0xF6, 0xD0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x49, 0x44, + 0x59, 0xF0, 0x0A, 0x02, 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x44, 0x58, 0x00, 0xF2, + 0xE2, 0x0D, 0x02, 0xCC, 0x4A, 0xE4, 0x01, 0x00, 0x55, 0xF0, 0x08, 0x03, 0x45, 0xF4, 0x02, 0x00, + 0x83, 0x5A, 0x04, 0xCC, 0x01, 0x4A, 0x12, 0x12, 0x00, 0xF2, 0xE2, 0x0D, 0x00, 0xCD, 0x48, 0xE4, + 0x01, 0x00, 0xE9, 0x13, 0x00, 0xF2, 0xC6, 0x0F, 0xFA, 0x10, 0x0E, 0x47, 0x03, 0xE6, 0x10, 0x00, 0xCE, 0x45, 0x02, 0x13, 0x3E, 0x57, 0xCE, 0x47, 0x97, 0x13, 0x04, 0xEC, 0xB4, 0x00, 0x00, 0xF2, - 0xDE, 0x0D, 0x00, 0xCD, 0x48, 0xE4, 0x00, 0x00, 0x12, 0x12, 0x3E, 0x57, 0x06, 0xCC, 0x45, 0xF4, + 0xE2, 0x0D, 0x00, 0xCD, 0x48, 0xE4, 0x00, 0x00, 0x12, 0x12, 0x3E, 0x57, 0x06, 0xCC, 0x45, 0xF4, 0x02, 0x00, 0x83, 0x5A, 0x00, 0xCC, 0x00, 0xEA, 0xB4, 0x00, 0x92, 0x10, 0x00, 0xF0, 0x8C, 0x01, 0x43, 0xF0, 0x5C, 0x02, 0x44, 0xF0, 0x60, 0x02, 0x45, 0xF0, 0x64, 0x02, 0x46, 0xF0, 0x68, 0x02, 0x47, 0xF0, 0x6E, 0x02, 0x48, 0xF0, 0x9E, 0x02, 0xB9, 0x54, 0x62, 0x10, 0x00, 0x1C, 0x5A, 0x10, - 0x02, 0x1C, 0x56, 0x10, 0x1E, 0x1C, 0x52, 0x10, 0x00, 0xF2, 0x1A, 0x11, 0x50, 0x10, 0x06, 0xFC, - 0xA8, 0x00, 0x03, 0xF6, 0xBE, 0x00, 0x00, 0xF2, 0x4A, 0x0A, 0x8C, 0x10, 0x01, 0xF6, 0x01, 0x00, - 0x01, 0xFA, 0xA8, 0x00, 0x00, 0xF2, 0x28, 0x0B, 0x06, 0x10, 0xB9, 0x54, 0x01, 0xFA, 0xA8, 0x00, - 0x03, 0xF6, 0xBE, 0x00, 0x00, 0xF2, 0x54, 0x0A, 0x01, 0xFC, 0xA8, 0x00, 0x20, 0x10, 0x58, 0x1C, - 0x00, 0xF2, 0x18, 0x0B, 0x5A, 0x1C, 0x01, 0xF6, 0x01, 0x00, 0x38, 0x54, 0x00, 0xFA, 0xA6, 0x00, + 0x02, 0x1C, 0x56, 0x10, 0x1E, 0x1C, 0x52, 0x10, 0x00, 0xF2, 0x1E, 0x11, 0x50, 0x10, 0x06, 0xFC, + 0xA8, 0x00, 0x03, 0xF6, 0xBE, 0x00, 0x00, 0xF2, 0x4E, 0x0A, 0x8C, 0x10, 0x01, 0xF6, 0x01, 0x00, + 0x01, 0xFA, 0xA8, 0x00, 0x00, 0xF2, 0x2C, 0x0B, 0x06, 0x10, 0xB9, 0x54, 0x01, 0xFA, 0xA8, 0x00, + 0x03, 0xF6, 0xBE, 0x00, 0x00, 0xF2, 0x58, 0x0A, 0x01, 0xFC, 0xA8, 0x00, 0x20, 0x10, 0x58, 0x1C, + 0x00, 0xF2, 0x1C, 0x0B, 0x5A, 0x1C, 0x01, 0xF6, 0x01, 0x00, 0x38, 0x54, 0x00, 0xFA, 0xA6, 0x00, 0x01, 0xFA, 0xA8, 0x00, 0x20, 0x1C, 0x00, 0xF0, 0x72, 0x01, 0x01, 0xF6, 0x01, 0x00, 0x38, 0x54, 0x00, 0xFA, 0xA6, 0x00, 0x01, 0xFA, 0xA8, 0x00, 0x20, 0x1C, 0x00, 0xF0, 0x80, 0x01, 0x03, 0xF6, - 0xE0, 0x00, 0x00, 0xF2, 0x64, 0x0A, 0x01, 0x48, 0x0A, 0x13, 0x00, 0xF2, 0x34, 0x10, 0x00, 0xF2, - 0x50, 0x0F, 0x24, 0x10, 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x64, 0x0A, 0x02, 0xF6, 0xD0, 0x00, - 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x49, 0x44, 0x5B, 0xF0, 0x04, 0x03, 0x00, 0xF2, 0x98, 0x0F, - 0x00, 0xF0, 0x80, 0x01, 0x00, 0xF2, 0x10, 0x10, 0x0C, 0x1C, 0x02, 0x4B, 0xBF, 0x57, 0x9E, 0x43, - 0x77, 0x57, 0x07, 0x4B, 0x20, 0xF0, 0x9A, 0x03, 0x40, 0x1C, 0x1E, 0xF0, 0x30, 0x03, 0x26, 0xF0, - 0x2C, 0x03, 0xA0, 0xF0, 0x1A, 0x03, 0x11, 0xF0, 0x9A, 0x03, 0x12, 0x10, 0x9F, 0xF0, 0x3E, 0x03, - 0x46, 0x1C, 0x82, 0xE7, 0x05, 0x00, 0x9E, 0xE7, 0x11, 0x00, 0x00, 0xF0, 0x02, 0x0A, 0x0C, 0x1C, + 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x01, 0x48, 0x0A, 0x13, 0x00, 0xF2, 0x38, 0x10, 0x00, 0xF2, + 0x54, 0x0F, 0x24, 0x10, 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x02, 0xF6, 0xD0, 0x00, + 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x49, 0x44, 0x5B, 0xF0, 0x04, 0x03, 0x00, 0xF2, 0x9C, 0x0F, + 0x00, 0xF0, 0x80, 0x01, 0x00, 0xF2, 0x14, 0x10, 0x0C, 0x1C, 0x02, 0x4B, 0xBF, 0x57, 0x9E, 0x43, + 0x77, 0x57, 0x07, 0x4B, 0x20, 0xF0, 0xA6, 0x03, 0x40, 0x1C, 0x1E, 0xF0, 0x30, 0x03, 0x26, 0xF0, + 0x2C, 0x03, 0xA0, 0xF0, 0x1A, 0x03, 0x11, 0xF0, 0xA6, 0x03, 0x12, 0x10, 0x9F, 0xF0, 0x3E, 0x03, + 0x46, 0x1C, 0x82, 0xE7, 0x05, 0x00, 0x9E, 0xE7, 0x11, 0x00, 0x00, 0xF0, 0x06, 0x0A, 0x0C, 0x1C, 0x48, 0x1C, 0x46, 0x1C, 0x38, 0x54, 0x00, 0xEC, 0xBA, 0x00, 0x08, 0x44, 0x00, 0xEA, 0xBA, 0x00, - 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x64, 0x0A, 0x08, 0x44, 0x00, 0x4C, 0x82, 0xE7, 0x02, 0x00, - 0x00, 0xF2, 0x0E, 0x11, 0x00, 0xF2, 0x0E, 0x11, 0x06, 0xF0, 0x74, 0x03, 0x1E, 0xF0, 0xF8, 0x09, - 0x00, 0xF0, 0xFE, 0x09, 0x00, 0xFC, 0xBE, 0x00, 0x98, 0x57, 0x55, 0xF0, 0xA0, 0x04, 0x01, 0xE6, - 0x0C, 0x00, 0x00, 0xF2, 0x4A, 0x0D, 0x00, 0xF2, 0x0E, 0x11, 0x00, 0xF2, 0xB8, 0x11, 0x00, 0xF2, - 0xC4, 0x11, 0x01, 0xF0, 0x7C, 0x02, 0x00, 0xF0, 0x8A, 0x02, 0x46, 0x1C, 0x0C, 0x1C, 0x67, 0x1B, - 0xBF, 0x57, 0x77, 0x57, 0x02, 0x4B, 0x48, 0x1C, 0x32, 0x1C, 0x00, 0xF2, 0x8E, 0x0D, 0x30, 0x1C, - 0x96, 0xF0, 0xB0, 0x03, 0xB1, 0xF0, 0xB4, 0x03, 0x1E, 0xF0, 0xF8, 0x09, 0x85, 0xF0, 0xFE, 0x09, - 0x00, 0xFC, 0xBE, 0x00, 0x98, 0x57, 0x14, 0x12, 0x01, 0xE6, 0x0C, 0x00, 0x00, 0xF2, 0x4A, 0x0D, - 0x00, 0xF2, 0x0E, 0x11, 0x01, 0xF0, 0x7C, 0x02, 0x00, 0xF0, 0x8A, 0x02, 0x03, 0xF6, 0xE0, 0x00, - 0x00, 0xF2, 0x64, 0x0A, 0x01, 0x48, 0x55, 0xF0, 0x8C, 0x04, 0x03, 0x82, 0x03, 0xFC, 0xA0, 0x00, - 0x9B, 0x57, 0x40, 0x12, 0x69, 0x18, 0x00, 0xF2, 0x0E, 0x11, 0x85, 0xF0, 0x36, 0x04, 0x69, 0x08, - 0x00, 0xF2, 0x0E, 0x11, 0x85, 0xF0, 0xFE, 0x09, 0x68, 0x08, 0x4C, 0x44, 0x28, 0x12, 0x44, 0x48, - 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x64, 0x0A, 0x45, 0x58, 0x00, 0xF2, 0xF2, 0x0D, 0x00, 0xCC, - 0x01, 0x48, 0x55, 0xF0, 0x8C, 0x04, 0x4C, 0x44, 0xEF, 0x13, 0x00, 0xF2, 0xC2, 0x0F, 0x00, 0xF2, - 0x10, 0x10, 0x08, 0x10, 0x68, 0x18, 0x45, 0x5A, 0x00, 0xF2, 0xF2, 0x0D, 0x04, 0x80, 0x18, 0xE4, - 0x10, 0x00, 0x28, 0x12, 0x01, 0xE6, 0x06, 0x00, 0x04, 0x80, 0x18, 0xE4, 0x01, 0x00, 0x04, 0x12, - 0x01, 0xE6, 0x0D, 0x00, 0x00, 0xF2, 0x4A, 0x0D, 0x00, 0xF2, 0x0E, 0x11, 0x04, 0xE6, 0x02, 0x00, - 0x9E, 0xE7, 0x15, 0x00, 0x01, 0xF0, 0x18, 0x0A, 0x00, 0xF0, 0xFE, 0x09, 0x69, 0x08, 0x05, 0x80, - 0x48, 0xE4, 0x00, 0x00, 0x0C, 0x12, 0x00, 0xE6, 0x11, 0x00, 0x00, 0xEA, 0xB8, 0x00, 0x00, 0xF2, - 0xB2, 0x10, 0x82, 0xE7, 0x02, 0x00, 0x1C, 0x90, 0x40, 0x5C, 0x00, 0x16, 0x01, 0xE6, 0x06, 0x00, - 0x00, 0xF2, 0x4A, 0x0D, 0x01, 0xF0, 0x80, 0x01, 0x1E, 0xF0, 0x80, 0x01, 0x00, 0xF0, 0x94, 0x04, - 0x42, 0x5B, 0x06, 0xF7, 0x03, 0x00, 0x46, 0x59, 0xBF, 0x57, 0x77, 0x57, 0x01, 0xE6, 0x80, 0x00, - 0x07, 0x80, 0x31, 0x44, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x5E, 0x13, 0x20, 0x80, 0x48, 0xE4, - 0x03, 0x00, 0x56, 0x12, 0x04, 0x80, 0x18, 0xE4, 0x02, 0x00, 0x4C, 0x13, 0x00, 0xFC, 0xA2, 0x00, - 0x98, 0x57, 0x55, 0xF0, 0x18, 0x05, 0x31, 0xE4, 0x40, 0x00, 0x00, 0xFC, 0xA0, 0x00, 0x98, 0x57, - 0x36, 0x12, 0x4C, 0x1C, 0x00, 0xF2, 0x0E, 0x11, 0x89, 0x48, 0x00, 0xF2, 0x0E, 0x11, 0x86, 0xF0, - 0x2A, 0x05, 0x82, 0xE7, 0x06, 0x00, 0x1B, 0x80, 0x48, 0xE4, 0x22, 0x00, 0x5B, 0xF0, 0x08, 0x05, - 0x48, 0xE4, 0x20, 0x00, 0x59, 0xF0, 0x0C, 0x05, 0x00, 0xE6, 0x20, 0x00, 0x09, 0x48, 0x00, 0xF2, - 0x0E, 0x11, 0x86, 0xF0, 0x2A, 0x05, 0x83, 0x80, 0x04, 0x10, 0x00, 0xF2, 0x9E, 0x0D, 0x00, 0xE6, - 0x01, 0x00, 0x00, 0xEA, 0x26, 0x01, 0x01, 0xEA, 0x27, 0x01, 0x04, 0x80, 0x18, 0xE4, 0x10, 0x00, - 0x36, 0x12, 0xB9, 0x54, 0x00, 0xF2, 0xF2, 0x0E, 0x01, 0xE6, 0x06, 0x00, 0x04, 0x80, 0x18, 0xE4, - 0x01, 0x00, 0x04, 0x12, 0x01, 0xE6, 0x0D, 0x00, 0x00, 0xF2, 0x4A, 0x0D, 0x00, 0xF2, 0x0E, 0x11, - 0x00, 0xF2, 0xB8, 0x11, 0x00, 0xF2, 0xC4, 0x11, 0x04, 0xE6, 0x02, 0x00, 0x9E, 0xE7, 0x15, 0x00, - 0x01, 0xF0, 0x18, 0x0A, 0x00, 0xF0, 0xFE, 0x09, 0x00, 0xFC, 0x20, 0x01, 0x98, 0x57, 0x34, 0x12, - 0x00, 0xFC, 0x24, 0x01, 0x98, 0x57, 0x2C, 0x13, 0xB9, 0x54, 0x00, 0xF2, 0xF2, 0x0E, 0x86, 0xF0, - 0xA4, 0x05, 0x03, 0xF6, 0x01, 0x00, 0x00, 0xF2, 0x88, 0x0E, 0x85, 0xF0, 0x9A, 0x05, 0x82, 0xE7, - 0x03, 0x00, 0x00, 0xF2, 0x5C, 0x0B, 0x82, 0xE7, 0x02, 0x00, 0x00, 0xFC, 0x24, 0x01, 0xB0, 0x57, - 0x00, 0xFA, 0x24, 0x01, 0x00, 0xFC, 0x9E, 0x00, 0x98, 0x57, 0x5A, 0x12, 0x00, 0xFC, 0xB6, 0x00, - 0x98, 0x57, 0x52, 0x13, 0x03, 0xE6, 0x0C, 0x00, 0x00, 0xFC, 0x9C, 0x00, 0x98, 0x57, 0x04, 0x13, - 0x03, 0xE6, 0x19, 0x00, 0x05, 0xE6, 0x08, 0x00, 0x00, 0xF6, 0x00, 0x01, 0x00, 0x57, 0x00, 0x57, - 0x03, 0x58, 0x00, 0xDC, 0x18, 0xF4, 0x00, 0x80, 0x04, 0x13, 0x05, 0xE6, 0x0F, 0x00, 0xB9, 0x54, - 0x00, 0xF2, 0xF2, 0x0E, 0x86, 0xF0, 0x06, 0x06, 0x00, 0xF2, 0xB6, 0x0E, 0x85, 0xF0, 0xFC, 0x05, - 0x82, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x5C, 0x0B, 0x82, 0xE7, 0x02, 0x00, 0x00, 0xFC, 0xB6, 0x00, - 0xB0, 0x57, 0x00, 0xFA, 0xB6, 0x00, 0x01, 0xF6, 0x01, 0x00, 0x00, 0xF2, 0xF2, 0x0E, 0x9C, 0x32, - 0x4E, 0x1C, 0x32, 0x1C, 0x00, 0xF2, 0x8E, 0x0D, 0x30, 0x1C, 0x82, 0xE7, 0x04, 0x00, 0xB1, 0xF0, - 0x1E, 0x06, 0x0A, 0xF0, 0x3A, 0x06, 0x05, 0xF0, 0xD2, 0x06, 0x06, 0xF0, 0xD8, 0x06, 0x09, 0xF0, - 0x20, 0x09, 0x1E, 0xF0, 0xF8, 0x09, 0x00, 0xF0, 0xFE, 0x09, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, - 0x30, 0x12, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x0E, 0x11, 0x21, 0x80, 0x18, 0xE4, 0xE0, 0x00, - 0x09, 0x48, 0x00, 0xF2, 0x0E, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2, 0x0E, 0x11, 0x09, 0xE7, - 0x00, 0x00, 0x00, 0xF2, 0x0E, 0x11, 0x99, 0xA4, 0x00, 0xF2, 0x0E, 0x11, 0x09, 0xE7, 0x00, 0x00, - 0x9A, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x02, 0x00, 0x34, 0x12, 0x09, 0xE7, 0x1B, 0x00, 0x00, 0xF2, - 0x0E, 0x11, 0x21, 0x80, 0x18, 0xE4, 0xE0, 0x00, 0x09, 0x48, 0x00, 0xF2, 0x0E, 0x11, 0x09, 0xE7, - 0x00, 0x00, 0x00, 0xF2, 0x0E, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2, 0x0E, 0x11, 0x09, 0xE7, - 0x01, 0x00, 0x00, 0xF2, 0x0E, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF0, 0x08, 0x09, 0xBB, 0x55, - 0x9A, 0x81, 0x03, 0xF7, 0x20, 0x00, 0x09, 0x6F, 0x93, 0x45, 0x55, 0xF0, 0xDE, 0x06, 0xB1, 0xF0, - 0xBE, 0x06, 0x0A, 0xF0, 0xB6, 0x06, 0x09, 0xF0, 0x20, 0x09, 0x1E, 0xF0, 0xF8, 0x09, 0x00, 0xF0, - 0xFE, 0x09, 0x00, 0xF2, 0x5C, 0x0B, 0x47, 0x10, 0x09, 0xE7, 0x08, 0x00, 0x41, 0x10, 0x05, 0x80, - 0x48, 0xE4, 0x00, 0x00, 0x1E, 0x12, 0x00, 0xE6, 0x11, 0x00, 0x00, 0xEA, 0xB8, 0x00, 0x00, 0xF2, - 0xB2, 0x10, 0x2C, 0x90, 0xAE, 0x90, 0x08, 0x50, 0x8A, 0x50, 0x38, 0x54, 0x1F, 0x40, 0x00, 0xF2, - 0xB0, 0x0D, 0x08, 0x10, 0x08, 0x90, 0x8A, 0x90, 0x30, 0x50, 0xB2, 0x50, 0x9C, 0x32, 0x0C, 0x92, - 0x8E, 0x92, 0x38, 0x54, 0x04, 0x80, 0x30, 0xE4, 0x08, 0x00, 0x04, 0x40, 0x0C, 0x1C, 0x00, 0xF6, - 0x03, 0x00, 0xB1, 0xF0, 0x22, 0x07, 0x9E, 0xF0, 0x36, 0x07, 0x01, 0x48, 0x55, 0xF0, 0xF8, 0x09, - 0x0C, 0x1C, 0x10, 0x44, 0xED, 0x10, 0x0B, 0xF0, 0x5A, 0x07, 0x0C, 0xF0, 0x5E, 0x07, 0x05, 0xF0, - 0x4E, 0x07, 0x06, 0xF0, 0x54, 0x07, 0x09, 0xF0, 0x20, 0x09, 0x00, 0xF0, 0xFE, 0x09, 0x00, 0xF2, - 0x5C, 0x0B, 0xCF, 0x10, 0x09, 0xE7, 0x08, 0x00, 0xC9, 0x10, 0x2E, 0x1C, 0x02, 0x10, 0x2C, 0x1C, - 0xAA, 0xF0, 0x60, 0x07, 0xAC, 0xF0, 0x6E, 0x07, 0x40, 0x10, 0x34, 0x1C, 0xF3, 0x10, 0xAD, 0xF0, - 0x78, 0x07, 0xC8, 0x10, 0x36, 0x1C, 0xE9, 0x10, 0x2B, 0xF0, 0x7E, 0x08, 0x6B, 0x18, 0x18, 0xF4, - 0x00, 0xFE, 0x20, 0x12, 0x01, 0x58, 0xD2, 0xF0, 0x7E, 0x08, 0x76, 0x18, 0x18, 0xF4, 0x03, 0x00, - 0xEC, 0x12, 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0xE2, 0x12, 0x0B, 0xF0, 0x60, 0x07, - 0x0C, 0xF0, 0x60, 0x07, 0x36, 0x1C, 0x34, 0x1C, 0xB7, 0x10, 0x38, 0x54, 0xB9, 0x54, 0x84, 0x80, - 0x19, 0xE4, 0x20, 0x00, 0xB2, 0x13, 0x85, 0x80, 0x81, 0x48, 0x66, 0x12, 0x04, 0x80, 0x18, 0xE4, - 0x08, 0x00, 0x58, 0x13, 0x1F, 0x80, 0x08, 0x44, 0xC8, 0x44, 0x9F, 0x12, 0x1F, 0x40, 0x34, 0x91, - 0xB6, 0x91, 0x44, 0x55, 0xE5, 0x55, 0x02, 0xEC, 0xB8, 0x00, 0x02, 0x49, 0xBB, 0x55, 0x82, 0x81, - 0xC0, 0x55, 0x48, 0xF4, 0x0F, 0x00, 0x5A, 0xF0, 0x16, 0x08, 0x4A, 0xE4, 0x17, 0x00, 0xD5, 0xF0, - 0xF6, 0x07, 0x02, 0xF6, 0x0F, 0x00, 0x02, 0xF4, 0x02, 0x00, 0x02, 0xEA, 0xB8, 0x00, 0x04, 0x91, - 0x86, 0x91, 0x02, 0x4B, 0x2C, 0x90, 0x08, 0x50, 0x2E, 0x90, 0x0A, 0x50, 0x2C, 0x51, 0xAE, 0x51, - 0x00, 0xF2, 0xB2, 0x10, 0x38, 0x54, 0x00, 0xF2, 0xB0, 0x0D, 0x56, 0x10, 0x34, 0x91, 0xB6, 0x91, - 0x0C, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x08, 0x00, 0x41, 0x12, 0x0C, 0x91, 0x8E, 0x91, 0x04, 0x80, - 0x18, 0xE4, 0xF7, 0x00, 0x04, 0x40, 0x30, 0x90, 0xB2, 0x90, 0x36, 0x10, 0x02, 0x80, 0x48, 0xE4, - 0x10, 0x00, 0x31, 0x12, 0x82, 0xE7, 0x10, 0x00, 0x84, 0x80, 0x19, 0xE4, 0x20, 0x00, 0x10, 0x13, - 0x0C, 0x90, 0x8E, 0x90, 0x5D, 0xF0, 0x74, 0x07, 0x0C, 0x58, 0x8D, 0x58, 0x00, 0xF0, 0x60, 0x07, - 0x38, 0x54, 0xB9, 0x54, 0x19, 0x80, 0xF1, 0x10, 0x3A, 0x55, 0x19, 0x81, 0xBB, 0x55, 0x10, 0x90, - 0x92, 0x90, 0x10, 0x58, 0x91, 0x58, 0x14, 0x59, 0x95, 0x59, 0x00, 0xF0, 0x60, 0x07, 0x04, 0x80, - 0x18, 0xE4, 0x20, 0x00, 0x06, 0x12, 0x6C, 0x19, 0x19, 0x41, 0x7C, 0x10, 0x6C, 0x19, 0x0C, 0x51, - 0xED, 0x19, 0x8E, 0x51, 0x6B, 0x18, 0x18, 0xF4, 0x00, 0xFF, 0x02, 0x13, 0x6A, 0x10, 0x01, 0x58, - 0xD2, 0xF0, 0xBC, 0x08, 0x76, 0x18, 0x18, 0xF4, 0x03, 0x00, 0x0A, 0x12, 0x00, 0xFC, 0x22, 0x01, - 0x18, 0xF4, 0x01, 0x00, 0x06, 0x13, 0x9E, 0xE7, 0x16, 0x00, 0x4C, 0x10, 0xD1, 0xF0, 0xC6, 0x08, - 0x9E, 0xE7, 0x17, 0x00, 0x42, 0x10, 0xD0, 0xF0, 0xD0, 0x08, 0x9E, 0xE7, 0x19, 0x00, 0x38, 0x10, - 0xCF, 0xF0, 0xDA, 0x08, 0x9E, 0xE7, 0x20, 0x00, 0x2E, 0x10, 0xCE, 0xF0, 0xE4, 0x08, 0x9E, 0xE7, - 0x21, 0x00, 0x24, 0x10, 0xCD, 0xF0, 0xEE, 0x08, 0x9E, 0xE7, 0x22, 0x00, 0x1A, 0x10, 0xCC, 0xF0, - 0x00, 0x09, 0x84, 0x80, 0x19, 0xE4, 0x04, 0x00, 0x06, 0x12, 0x9E, 0xE7, 0x12, 0x00, 0x08, 0x10, - 0xCB, 0xF0, 0x08, 0x09, 0x9E, 0xE7, 0x24, 0x00, 0xB1, 0xF0, 0x08, 0x09, 0x05, 0xF0, 0x1A, 0x09, - 0x09, 0xF0, 0x20, 0x09, 0x1E, 0xF0, 0xF8, 0x09, 0xE4, 0x10, 0x00, 0xF2, 0x5C, 0x0B, 0xE9, 0x10, - 0x9C, 0x32, 0x82, 0xE7, 0x20, 0x00, 0x32, 0x1C, 0xE9, 0x09, 0x00, 0xF2, 0x0E, 0x11, 0x85, 0xF0, - 0xFE, 0x09, 0x69, 0x08, 0x01, 0xF0, 0x40, 0x09, 0x1E, 0xF0, 0xF8, 0x09, 0x00, 0xF0, 0x34, 0x09, - 0x30, 0x44, 0x06, 0x12, 0x9E, 0xE7, 0x42, 0x00, 0xB8, 0x10, 0x04, 0xF6, 0x01, 0x00, 0xB3, 0x45, - 0x74, 0x12, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x22, 0x13, 0x4B, 0xE4, 0x02, 0x00, 0x36, 0x12, - 0x4B, 0xE4, 0x28, 0x00, 0xAC, 0x13, 0x00, 0xF2, 0xB8, 0x11, 0x00, 0xF2, 0xC4, 0x11, 0x03, 0xF6, - 0xD0, 0x00, 0xFA, 0x14, 0x82, 0xE7, 0x01, 0x00, 0x00, 0xF0, 0x80, 0x01, 0x9E, 0xE7, 0x44, 0x00, - 0x4B, 0xE4, 0x02, 0x00, 0x06, 0x12, 0x03, 0xE6, 0x02, 0x00, 0x76, 0x10, 0x00, 0xF2, 0x9E, 0x0D, - 0x03, 0xE6, 0x02, 0x00, 0x6C, 0x10, 0x00, 0xF2, 0x9E, 0x0D, 0x19, 0x82, 0x34, 0x46, 0x0A, 0x13, - 0x03, 0xE6, 0x02, 0x00, 0x9E, 0xE7, 0x43, 0x00, 0x68, 0x10, 0x04, 0x80, 0x30, 0xE4, 0x20, 0x00, - 0x04, 0x40, 0x00, 0xF2, 0xB8, 0x11, 0x00, 0xF2, 0xC4, 0x11, 0x82, 0xE7, 0x01, 0x00, 0x06, 0xF7, - 0x02, 0x00, 0x00, 0xF0, 0x08, 0x03, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x06, 0x12, 0x03, 0xE6, - 0x02, 0x00, 0x3E, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x02, 0x00, 0x3A, 0x12, 0x04, 0x80, 0x18, 0xE4, - 0xFD, 0x00, 0x04, 0x40, 0x1C, 0x1C, 0x9D, 0xF0, 0xE6, 0x09, 0x1C, 0x1C, 0x9D, 0xF0, 0xEC, 0x09, - 0xC1, 0x10, 0x9E, 0xE7, 0x13, 0x00, 0x0A, 0x10, 0x9E, 0xE7, 0x41, 0x00, 0x04, 0x10, 0x9E, 0xE7, - 0x24, 0x00, 0x00, 0xFC, 0xBE, 0x00, 0x98, 0x57, 0xD5, 0xF0, 0x8A, 0x02, 0x04, 0xE6, 0x04, 0x00, - 0x06, 0x10, 0x04, 0xE6, 0x04, 0x00, 0x9D, 0x41, 0x1C, 0x42, 0x9F, 0xE7, 0x00, 0x00, 0x06, 0xF7, - 0x02, 0x00, 0x03, 0xF6, 0xE0, 0x00, 0x3C, 0x14, 0x44, 0x58, 0x45, 0x58, 0x00, 0xF2, 0xF2, 0x0D, - 0x00, 0xF2, 0x7A, 0x10, 0x00, 0xF2, 0xC2, 0x0F, 0x3C, 0x14, 0x1E, 0x1C, 0x00, 0xF0, 0x80, 0x01, - 0x12, 0x1C, 0x22, 0x1C, 0xD2, 0x14, 0x00, 0xF0, 0x72, 0x01, 0x83, 0x59, 0x03, 0xDC, 0x73, 0x57, - 0x80, 0x5D, 0x00, 0x16, 0x83, 0x59, 0x03, 0xDC, 0x38, 0x54, 0x70, 0x57, 0x33, 0x54, 0x3B, 0x54, - 0x80, 0x5D, 0x00, 0x16, 0x03, 0x57, 0x83, 0x59, 0x38, 0x54, 0x00, 0xCC, 0x00, 0x16, 0x03, 0x57, - 0x83, 0x59, 0x00, 0x4C, 0x00, 0x16, 0x02, 0x80, 0x48, 0xE4, 0x01, 0x00, 0x0E, 0x12, 0x48, 0xE4, - 0x05, 0x00, 0x08, 0x12, 0x00, 0xF2, 0xB8, 0x11, 0x00, 0xF2, 0xC4, 0x11, 0xC1, 0x5A, 0x3A, 0x55, - 0x02, 0xEC, 0xB5, 0x00, 0x45, 0x59, 0x00, 0xF2, 0xF2, 0x0D, 0x83, 0x58, 0x30, 0xE7, 0x00, 0x00, - 0x10, 0x4D, 0x30, 0xE7, 0x40, 0x00, 0x10, 0x4F, 0x38, 0x90, 0xBA, 0x90, 0x10, 0x5C, 0x80, 0x5C, - 0x83, 0x5A, 0x10, 0x4E, 0x04, 0xEA, 0xB5, 0x00, 0x43, 0x5B, 0x03, 0xF4, 0xE0, 0x00, 0x83, 0x59, - 0x04, 0xCC, 0x01, 0x4A, 0x0A, 0x12, 0x45, 0x5A, 0x00, 0xF2, 0xF2, 0x0D, 0x00, 0xF2, 0x34, 0x10, - 0x00, 0x16, 0x08, 0x1C, 0x00, 0xFC, 0xAC, 0x00, 0x06, 0x58, 0x67, 0x18, 0x18, 0xF4, 0x8F, 0xE1, - 0x01, 0xFC, 0xAE, 0x00, 0x19, 0xF4, 0x70, 0x1E, 0xB0, 0x54, 0x07, 0x58, 0x00, 0xFC, 0xB0, 0x00, - 0x08, 0x58, 0x00, 0xFC, 0xB2, 0x00, 0x09, 0x58, 0x0A, 0x1C, 0x00, 0xE6, 0x0F, 0x00, 0x00, 0xEA, - 0xB9, 0x00, 0x38, 0x54, 0x00, 0xFA, 0x24, 0x01, 0x00, 0xFA, 0xB6, 0x00, 0x18, 0x1C, 0x14, 0x1C, - 0x10, 0x1C, 0x32, 0x1C, 0x12, 0x1C, 0x00, 0x16, 0x3E, 0x57, 0x0C, 0x14, 0x0E, 0x47, 0x07, 0xE6, - 0x10, 0x00, 0xCE, 0x47, 0xF5, 0x13, 0x00, 0x16, 0x00, 0xF2, 0x9E, 0x0D, 0x02, 0x4B, 0x03, 0xF6, - 0xE0, 0x00, 0x00, 0xF2, 0x64, 0x0A, 0x01, 0x48, 0x20, 0x12, 0x44, 0x58, 0x45, 0x58, 0x9E, 0xE7, - 0x15, 0x00, 0x9C, 0xE7, 0x04, 0x00, 0x00, 0xF2, 0xF2, 0x0D, 0x00, 0xF2, 0x7A, 0x10, 0x00, 0xF2, - 0xC2, 0x0F, 0x00, 0xF2, 0x76, 0x0A, 0x1E, 0x1C, 0xD5, 0x10, 0x00, 0x16, 0x69, 0x08, 0x48, 0xE4, - 0x04, 0x00, 0x64, 0x12, 0x48, 0xE4, 0x02, 0x00, 0x20, 0x12, 0x48, 0xE4, 0x03, 0x00, 0x1A, 0x12, - 0x48, 0xE4, 0x08, 0x00, 0x14, 0x12, 0x48, 0xE4, 0x01, 0x00, 0xF0, 0x12, 0x48, 0xE4, 0x07, 0x00, - 0x12, 0x12, 0x01, 0xE6, 0x07, 0x00, 0x00, 0xF2, 0x4A, 0x0D, 0x00, 0xF2, 0x0E, 0x11, 0x05, 0xF0, - 0x5C, 0x0B, 0x00, 0x16, 0x00, 0xE6, 0x01, 0x00, 0x00, 0xEA, 0x99, 0x00, 0x02, 0x80, 0x48, 0xE4, - 0x03, 0x00, 0xB9, 0x12, 0x48, 0xE4, 0x06, 0x00, 0xB3, 0x12, 0x01, 0xE6, 0x06, 0x00, 0x00, 0xF2, - 0x4A, 0x0D, 0x00, 0xF2, 0x0E, 0x11, 0x04, 0xE6, 0x02, 0x00, 0x9E, 0xE7, 0x15, 0x00, 0x01, 0xF0, - 0x18, 0x0A, 0x00, 0xF0, 0xFE, 0x09, 0x00, 0x16, 0x02, 0x80, 0x48, 0xE4, 0x10, 0x00, 0x1C, 0x12, - 0x82, 0xE7, 0x08, 0x00, 0x3C, 0x56, 0x03, 0x82, 0x00, 0xF2, 0xDE, 0x0D, 0x30, 0xE7, 0x08, 0x00, - 0x04, 0xF7, 0x70, 0x01, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF0, 0x80, 0x01, 0x6C, 0x19, 0xED, 0x19, - 0x5D, 0xF0, 0xD0, 0x0B, 0x44, 0x55, 0xE5, 0x55, 0x59, 0xF0, 0x4E, 0x0C, 0x04, 0x55, 0xA5, 0x55, - 0x1F, 0x80, 0x01, 0xEC, 0xB8, 0x00, 0x82, 0x48, 0x82, 0x80, 0x49, 0x44, 0x2E, 0x13, 0x01, 0xEC, - 0xB8, 0x00, 0x41, 0xE4, 0x02, 0x00, 0x01, 0xEA, 0xB8, 0x00, 0x49, 0xE4, 0x11, 0x00, 0x59, 0xF0, - 0x2A, 0x0C, 0x01, 0xE6, 0x17, 0x00, 0x01, 0xEA, 0xB8, 0x00, 0x02, 0x4B, 0x88, 0x90, 0xAC, 0x50, - 0x8A, 0x90, 0xAE, 0x50, 0x01, 0xEC, 0xB8, 0x00, 0x82, 0x48, 0x82, 0x80, 0x10, 0x44, 0x02, 0x4B, - 0x1F, 0x40, 0xC0, 0x44, 0x00, 0xF2, 0xB0, 0x0D, 0x04, 0x55, 0xA5, 0x55, 0x9F, 0x10, 0x0C, 0x51, - 0x8E, 0x51, 0x30, 0x90, 0xB2, 0x90, 0x00, 0x56, 0xA1, 0x56, 0x30, 0x50, 0xB2, 0x50, 0x34, 0x90, - 0xB6, 0x90, 0x40, 0x56, 0xE1, 0x56, 0x34, 0x50, 0xB6, 0x50, 0x65, 0x10, 0xB1, 0xF0, 0x6C, 0x0C, - 0x85, 0xF0, 0xC6, 0x0B, 0xE9, 0x09, 0x4B, 0xE4, 0x03, 0x00, 0x78, 0x12, 0x4B, 0xE4, 0x02, 0x00, - 0x01, 0x13, 0xB1, 0xF0, 0x82, 0x0C, 0x85, 0xF0, 0xC6, 0x0B, 0x69, 0x08, 0x48, 0xE4, 0x03, 0x00, - 0xD5, 0xF0, 0x82, 0x0B, 0x00, 0xF2, 0x0E, 0x11, 0x85, 0xF0, 0xC6, 0x0B, 0xE8, 0x09, 0x3C, 0x56, - 0x00, 0xFC, 0x20, 0x01, 0x98, 0x57, 0x02, 0x13, 0xBB, 0x45, 0x4B, 0xE4, 0x00, 0x00, 0x08, 0x12, - 0x03, 0xE6, 0x01, 0x00, 0x04, 0xF6, 0x00, 0x80, 0xA8, 0x14, 0xD2, 0x14, 0x30, 0x1C, 0x02, 0x80, - 0x48, 0xE4, 0x03, 0x00, 0x10, 0x13, 0x00, 0xFC, 0xB6, 0x00, 0x98, 0x57, 0x02, 0x13, 0x4C, 0x1C, - 0x3E, 0x1C, 0x00, 0xF0, 0x8A, 0x0B, 0x00, 0xFC, 0x24, 0x01, 0xB0, 0x57, 0x00, 0xFA, 0x24, 0x01, - 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF2, 0x0E, 0x11, 0x86, 0xF0, 0x8A, 0x0B, 0x00, 0xF2, 0x88, 0x0E, - 0x00, 0xF0, 0x8A, 0x0B, 0xB1, 0xF0, 0xF4, 0x0C, 0x85, 0xF0, 0x82, 0x0B, 0x69, 0x08, 0x48, 0xE4, - 0x01, 0x00, 0xD5, 0xF0, 0x82, 0x0B, 0xFC, 0x14, 0x42, 0x58, 0x6C, 0x14, 0x80, 0x14, 0x30, 0x1C, - 0x4A, 0xF4, 0x02, 0x00, 0x55, 0xF0, 0x82, 0x0B, 0x4A, 0xF4, 0x01, 0x00, 0x0E, 0x12, 0x02, 0x80, - 0x48, 0xE4, 0x03, 0x00, 0x06, 0x13, 0x3E, 0x1C, 0x00, 0xF0, 0x8A, 0x0B, 0x00, 0xFC, 0xB6, 0x00, - 0xB0, 0x57, 0x00, 0xFA, 0xB6, 0x00, 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF2, 0x0E, 0x11, 0x86, 0xF0, - 0x8A, 0x0B, 0x00, 0xF2, 0xB6, 0x0E, 0x00, 0xF0, 0x8A, 0x0B, 0x4C, 0x1C, 0xB1, 0xF0, 0x4C, 0x0D, - 0x85, 0xF0, 0x58, 0x0D, 0x69, 0x08, 0xF3, 0x10, 0x86, 0xF0, 0x60, 0x0D, 0x4E, 0x1C, 0x89, 0x48, - 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01, 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x18, 0xF4, - 0xFF, 0x7F, 0x30, 0x56, 0x00, 0x5C, 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01, 0x00, 0x57, 0x00, 0x57, - 0x03, 0x58, 0x00, 0xDC, 0x18, 0xF4, 0x00, 0x80, 0x30, 0x56, 0x00, 0x5C, 0x00, 0x16, 0x00, 0xF6, - 0x00, 0x01, 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x0B, 0x58, 0x00, 0x16, 0x03, 0xF6, - 0x24, 0x01, 0x00, 0xF2, 0x54, 0x0A, 0x03, 0xF6, 0xB6, 0x00, 0x00, 0xF2, 0x54, 0x0A, 0x00, 0x16, - 0x02, 0xEC, 0xB8, 0x00, 0x02, 0x49, 0x18, 0xF4, 0xFF, 0x00, 0x00, 0x54, 0x00, 0x54, 0x00, 0x54, - 0x00, 0xF4, 0x08, 0x00, 0xE1, 0x18, 0x80, 0x54, 0x03, 0x58, 0x00, 0xDD, 0x01, 0xDD, 0x02, 0xDD, - 0x03, 0xDC, 0x02, 0x4B, 0x30, 0x50, 0xB2, 0x50, 0x34, 0x51, 0xB6, 0x51, 0x00, 0x16, 0x45, 0x5A, - 0x1D, 0xF4, 0xFF, 0x00, 0x85, 0x56, 0x85, 0x56, 0x85, 0x56, 0x05, 0xF4, 0x02, 0x12, 0x83, 0x5A, - 0x00, 0x16, 0x1D, 0xF4, 0xFF, 0x00, 0x85, 0x56, 0x85, 0x56, 0x85, 0x56, 0x05, 0xF4, 0x00, 0x12, - 0x83, 0x5A, 0x00, 0x16, 0x38, 0x54, 0xBB, 0x55, 0x3C, 0x56, 0xBD, 0x56, 0x00, 0xF2, 0x0E, 0x11, - 0x85, 0xF0, 0x7E, 0x0E, 0xE9, 0x09, 0xC1, 0x59, 0x00, 0xF2, 0x0E, 0x11, 0x85, 0xF0, 0x7E, 0x0E, - 0xE8, 0x0A, 0x83, 0x55, 0x83, 0x55, 0x4B, 0xF4, 0x90, 0x01, 0x5C, 0xF0, 0x32, 0x0E, 0xBD, 0x56, - 0x40, 0x10, 0x4B, 0xF4, 0x30, 0x00, 0x59, 0xF0, 0x44, 0x0E, 0x01, 0xF6, 0x0C, 0x00, 0x00, 0xF6, - 0x01, 0x00, 0x2E, 0x10, 0x02, 0xFC, 0x9C, 0x00, 0x9A, 0x57, 0x14, 0x13, 0x4B, 0xF4, 0x64, 0x00, - 0x59, 0xF0, 0x60, 0x0E, 0x03, 0xF6, 0x64, 0x00, 0x01, 0xF6, 0x19, 0x00, 0x00, 0xF6, 0x01, 0x00, - 0x43, 0xF4, 0x33, 0x00, 0x56, 0xF0, 0x72, 0x0E, 0x04, 0xF4, 0x00, 0x01, 0x43, 0xF4, 0x19, 0x00, - 0xF3, 0x10, 0xB4, 0x56, 0xC3, 0x58, 0x02, 0xFC, 0x9E, 0x00, 0x9A, 0x57, 0x08, 0x13, 0x3C, 0x56, - 0x00, 0xF6, 0x02, 0x00, 0x00, 0x16, 0x00, 0x16, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2, 0x0E, 0x11, - 0x86, 0xF0, 0xB4, 0x0E, 0x09, 0xE7, 0x02, 0x00, 0x00, 0xF2, 0x0E, 0x11, 0x86, 0xF0, 0xB4, 0x0E, - 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x0E, 0x11, 0x86, 0xF0, 0xB4, 0x0E, 0x4E, 0x1C, 0x89, 0x49, - 0x00, 0xF2, 0x0E, 0x11, 0x00, 0x16, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2, 0x0E, 0x11, 0x86, 0xF0, - 0xEE, 0x0E, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x0E, 0x11, 0x86, 0xF0, 0xEE, 0x0E, 0x09, 0xE7, - 0x01, 0x00, 0x00, 0xF2, 0x0E, 0x11, 0x86, 0xF0, 0xEE, 0x0E, 0x89, 0x49, 0x00, 0xF2, 0x0E, 0x11, - 0x86, 0xF0, 0xEE, 0x0E, 0x4E, 0x1C, 0x89, 0x4A, 0x00, 0xF2, 0x0E, 0x11, 0x00, 0x16, 0x3C, 0x56, - 0x00, 0x16, 0x00, 0xEC, 0x26, 0x01, 0x48, 0xE4, 0x01, 0x00, 0x1E, 0x13, 0x38, 0x44, 0x00, 0xEA, - 0x26, 0x01, 0x49, 0xF4, 0x00, 0x00, 0x04, 0x12, 0x4E, 0x1C, 0x02, 0x10, 0x4C, 0x1C, 0x01, 0xEC, - 0x27, 0x01, 0x89, 0x48, 0x00, 0xF2, 0x0E, 0x11, 0x02, 0x14, 0x00, 0x16, 0x85, 0xF0, 0x4E, 0x0F, - 0x38, 0x54, 0x00, 0xEA, 0x99, 0x00, 0x00, 0xF2, 0x5C, 0x0B, 0x02, 0x80, 0x48, 0xE4, 0x06, 0x00, - 0x1C, 0x13, 0x00, 0xEC, 0x99, 0x00, 0x48, 0xE4, 0x01, 0x00, 0x0A, 0x12, 0x04, 0x80, 0x30, 0xE4, - 0x01, 0x00, 0x04, 0x40, 0x08, 0x10, 0x04, 0x80, 0x18, 0xE4, 0xFE, 0x00, 0x04, 0x40, 0x00, 0x16, - 0x02, 0xF6, 0xE0, 0x00, 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x81, 0x48, 0x22, 0x12, 0x00, 0x4E, - 0x83, 0x5A, 0x90, 0x4C, 0x20, 0xE7, 0x00, 0x00, 0xC3, 0x58, 0x1B, 0xF4, 0xFF, 0x00, 0x83, 0x55, - 0x83, 0x55, 0x83, 0x55, 0x03, 0xF4, 0x00, 0x12, 0x8B, 0x55, 0x83, 0x59, 0x00, 0x4E, 0x00, 0x16, - 0x00, 0x4E, 0x02, 0xF6, 0xF0, 0x00, 0x02, 0x57, 0x03, 0x59, 0x00, 0x4E, 0x83, 0x5A, 0x30, 0xE7, - 0x00, 0x00, 0x20, 0xE7, 0x00, 0x00, 0x00, 0x16, 0x02, 0xF6, 0xF0, 0x00, 0x02, 0x57, 0x03, 0x59, - 0x01, 0xCC, 0x00, 0x4E, 0x83, 0x5A, 0x30, 0xE7, 0x00, 0x00, 0x80, 0x4C, 0xC3, 0x58, 0x1B, 0xF4, - 0xFF, 0x00, 0x83, 0x55, 0x83, 0x55, 0x83, 0x55, 0x03, 0xF4, 0x00, 0x12, 0x83, 0x59, 0x00, 0x4E, - 0x00, 0x16, 0x03, 0xF6, 0xE0, 0x00, 0x03, 0x57, 0x83, 0x59, 0x3A, 0x55, 0x02, 0xCC, 0x45, 0x5A, - 0x00, 0xF2, 0xF2, 0x0D, 0xC0, 0x5A, 0x40, 0x5C, 0x38, 0x54, 0x00, 0xCD, 0x01, 0xCC, 0x4A, 0x46, - 0x0A, 0x13, 0x83, 0x59, 0x00, 0x4C, 0x01, 0x48, 0x16, 0x13, 0x0C, 0x10, 0xC5, 0x58, 0x00, 0xF2, - 0xF2, 0x0D, 0x00, 0x4C, 0x01, 0x48, 0x08, 0x13, 0x05, 0xF6, 0xF0, 0x00, 0x05, 0x57, 0x08, 0x10, - 0x45, 0x58, 0x00, 0xF2, 0xF2, 0x0D, 0x8D, 0x56, 0x83, 0x5A, 0x80, 0x4C, 0x05, 0x17, 0x00, 0x16, - 0x02, 0x4B, 0x06, 0xF7, 0x04, 0x00, 0x62, 0x0B, 0x03, 0x82, 0x00, 0xF2, 0xDE, 0x0D, 0x02, 0x80, - 0x00, 0x4C, 0x45, 0xF4, 0x02, 0x00, 0x52, 0x14, 0x06, 0xF7, 0x02, 0x00, 0x06, 0x14, 0x00, 0xF2, - 0x50, 0x0F, 0x00, 0x16, 0x02, 0x4B, 0x01, 0xF6, 0xFF, 0x00, 0x38, 0x1C, 0x05, 0xF4, 0x04, 0x00, - 0x83, 0x5A, 0x18, 0xDF, 0x19, 0xDF, 0x1D, 0xF7, 0x3C, 0x00, 0xB8, 0xF0, 0x4A, 0x10, 0x9C, 0x14, - 0x01, 0x48, 0x1C, 0x13, 0x0E, 0xF7, 0x3C, 0x00, 0x03, 0xF7, 0x04, 0x00, 0xAF, 0x19, 0x03, 0x42, - 0x45, 0xF4, 0x02, 0x00, 0x83, 0x5A, 0x02, 0xCC, 0x02, 0x41, 0x45, 0xF4, 0x02, 0x00, 0x00, 0x16, - 0x91, 0x44, 0xD5, 0xF0, 0x3A, 0x10, 0x00, 0xF0, 0x9E, 0x02, 0x01, 0xF6, 0xFF, 0x00, 0x38, 0x1C, - 0x05, 0xF4, 0x04, 0x00, 0x83, 0x5A, 0x18, 0xDF, 0x19, 0xDF, 0x0E, 0xF7, 0x3C, 0x00, 0x03, 0xF7, - 0x04, 0x00, 0x0F, 0x79, 0x1C, 0xF7, 0x3C, 0x00, 0xB8, 0xF0, 0x98, 0x10, 0x4E, 0x14, 0x01, 0x48, - 0x06, 0x13, 0x45, 0xF4, 0x04, 0x00, 0x00, 0x16, 0x91, 0x44, 0xD5, 0xF0, 0x7E, 0x10, 0x00, 0xF0, - 0x9E, 0x02, 0x02, 0xF6, 0xFF, 0x00, 0x38, 0x1C, 0x2C, 0xBC, 0xAE, 0xBC, 0xE2, 0x08, 0x00, 0xEC, - 0xB8, 0x00, 0x02, 0x48, 0x1D, 0xF7, 0x80, 0x00, 0xB8, 0xF0, 0xC8, 0x10, 0x1E, 0x14, 0x01, 0x48, - 0x0E, 0x13, 0x0E, 0xF7, 0x80, 0x00, 0x38, 0x54, 0x03, 0x58, 0xAF, 0x19, 0x82, 0x48, 0x00, 0x16, - 0x82, 0x48, 0x12, 0x45, 0xD5, 0xF0, 0xB6, 0x10, 0x00, 0xF0, 0x9E, 0x02, 0x39, 0xF0, 0xF4, 0x10, - 0x38, 0x44, 0x00, 0x16, 0x7E, 0x18, 0x18, 0xF4, 0x03, 0x00, 0x04, 0x13, 0x61, 0x18, 0x00, 0x16, - 0x38, 0x1C, 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0xF1, 0x12, 0xE3, 0x10, 0x30, 0x44, - 0x30, 0x44, 0x30, 0x44, 0xB1, 0xF0, 0x14, 0x11, 0x00, 0x16, 0x3E, 0x57, 0x03, 0xF6, 0xE0, 0x00, - 0x03, 0x57, 0x83, 0x59, 0x04, 0xCC, 0x01, 0x4A, 0x6A, 0x12, 0x45, 0x5A, 0x00, 0xF2, 0xF2, 0x0D, - 0x02, 0x4B, 0x70, 0x14, 0x34, 0x13, 0x02, 0x80, 0x48, 0xE4, 0x08, 0x00, 0x18, 0x12, 0x9C, 0xE7, - 0x02, 0x00, 0x9E, 0xE7, 0x15, 0x00, 0x00, 0xF2, 0xC2, 0x0F, 0x00, 0xF2, 0x76, 0x0A, 0x1E, 0x1C, - 0x01, 0xF6, 0x01, 0x00, 0x00, 0x16, 0x30, 0xE4, 0x10, 0x00, 0x04, 0x40, 0x00, 0xF2, 0xDE, 0x0D, - 0x20, 0xE7, 0x01, 0x00, 0x01, 0xF6, 0x01, 0x00, 0x00, 0x16, 0x04, 0xDC, 0x01, 0x4A, 0x24, 0x12, - 0x45, 0x5A, 0x00, 0xF2, 0xF2, 0x0D, 0x43, 0x5B, 0x06, 0xEC, 0x98, 0x00, 0x00, 0xF2, 0x34, 0x10, - 0xC6, 0x59, 0x20, 0x14, 0x0A, 0x13, 0x00, 0xF2, 0xC2, 0x0F, 0x00, 0xF2, 0x10, 0x10, 0xA7, 0x10, - 0x83, 0x5A, 0xD7, 0x10, 0x0E, 0x47, 0x07, 0xE6, 0x10, 0x00, 0xCE, 0x47, 0x5A, 0xF0, 0x1C, 0x11, - 0xB9, 0x54, 0x00, 0x16, 0x14, 0x90, 0x96, 0x90, 0x02, 0xFC, 0xA8, 0x00, 0x03, 0xFC, 0xAA, 0x00, - 0x48, 0x55, 0x02, 0x13, 0xC9, 0x55, 0x00, 0x16, 0x00, 0xEC, 0xBA, 0x00, 0x10, 0x44, 0x00, 0xEA, - 0xBA, 0x00, 0x00, 0x16, 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x64, 0x0A, 0x10, 0x44, 0x00, 0x4C, - 0x00, 0x16 }; + 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x08, 0x44, 0x00, 0x4C, 0x82, 0xE7, 0x02, 0x00, + 0x00, 0xF2, 0x12, 0x11, 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0x70, 0x03, 0x00, 0xF2, 0x60, 0x0B, + 0x06, 0xF0, 0x80, 0x03, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, 0xFC, 0x09, 0x00, 0xF0, 0x02, 0x0A, + 0x00, 0xFC, 0xBE, 0x00, 0x98, 0x57, 0x55, 0xF0, 0xAC, 0x04, 0x01, 0xE6, 0x0C, 0x00, 0x00, 0xF2, + 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, 0x01, 0xF0, + 0x7C, 0x02, 0x00, 0xF0, 0x8A, 0x02, 0x46, 0x1C, 0x0C, 0x1C, 0x67, 0x1B, 0xBF, 0x57, 0x77, 0x57, + 0x02, 0x4B, 0x48, 0x1C, 0x32, 0x1C, 0x00, 0xF2, 0x92, 0x0D, 0x30, 0x1C, 0x96, 0xF0, 0xBC, 0x03, + 0xB1, 0xF0, 0xC0, 0x03, 0x1E, 0xF0, 0xFC, 0x09, 0x85, 0xF0, 0x02, 0x0A, 0x00, 0xFC, 0xBE, 0x00, + 0x98, 0x57, 0x14, 0x12, 0x01, 0xE6, 0x0C, 0x00, 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, + 0x01, 0xF0, 0x7C, 0x02, 0x00, 0xF0, 0x8A, 0x02, 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, + 0x01, 0x48, 0x55, 0xF0, 0x98, 0x04, 0x03, 0x82, 0x03, 0xFC, 0xA0, 0x00, 0x9B, 0x57, 0x40, 0x12, + 0x69, 0x18, 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0x42, 0x04, 0x69, 0x08, 0x00, 0xF2, 0x12, 0x11, + 0x85, 0xF0, 0x02, 0x0A, 0x68, 0x08, 0x4C, 0x44, 0x28, 0x12, 0x44, 0x48, 0x03, 0xF6, 0xE0, 0x00, + 0x00, 0xF2, 0x68, 0x0A, 0x45, 0x58, 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0xCC, 0x01, 0x48, 0x55, 0xF0, + 0x98, 0x04, 0x4C, 0x44, 0xEF, 0x13, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2, 0x14, 0x10, 0x08, 0x10, + 0x68, 0x18, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, 0x04, 0x80, 0x18, 0xE4, 0x10, 0x00, 0x28, 0x12, + 0x01, 0xE6, 0x06, 0x00, 0x04, 0x80, 0x18, 0xE4, 0x01, 0x00, 0x04, 0x12, 0x01, 0xE6, 0x0D, 0x00, + 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, 0x04, 0xE6, 0x02, 0x00, 0x9E, 0xE7, 0x15, 0x00, + 0x01, 0xF0, 0x1C, 0x0A, 0x00, 0xF0, 0x02, 0x0A, 0x69, 0x08, 0x05, 0x80, 0x48, 0xE4, 0x00, 0x00, + 0x0C, 0x12, 0x00, 0xE6, 0x11, 0x00, 0x00, 0xEA, 0xB8, 0x00, 0x00, 0xF2, 0xB6, 0x10, 0x82, 0xE7, + 0x02, 0x00, 0x1C, 0x90, 0x40, 0x5C, 0x00, 0x16, 0x01, 0xE6, 0x06, 0x00, 0x00, 0xF2, 0x4E, 0x0D, + 0x01, 0xF0, 0x80, 0x01, 0x1E, 0xF0, 0x80, 0x01, 0x00, 0xF0, 0xA0, 0x04, 0x42, 0x5B, 0x06, 0xF7, + 0x03, 0x00, 0x46, 0x59, 0xBF, 0x57, 0x77, 0x57, 0x01, 0xE6, 0x80, 0x00, 0x07, 0x80, 0x31, 0x44, + 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x56, 0x13, 0x20, 0x80, 0x48, 0xE4, 0x03, 0x00, 0x4E, 0x12, + 0x00, 0xFC, 0xA2, 0x00, 0x98, 0x57, 0x55, 0xF0, 0x1C, 0x05, 0x31, 0xE4, 0x40, 0x00, 0x00, 0xFC, + 0xA0, 0x00, 0x98, 0x57, 0x36, 0x12, 0x4C, 0x1C, 0x00, 0xF2, 0x12, 0x11, 0x89, 0x48, 0x00, 0xF2, + 0x12, 0x11, 0x86, 0xF0, 0x2E, 0x05, 0x82, 0xE7, 0x06, 0x00, 0x1B, 0x80, 0x48, 0xE4, 0x22, 0x00, + 0x5B, 0xF0, 0x0C, 0x05, 0x48, 0xE4, 0x20, 0x00, 0x59, 0xF0, 0x10, 0x05, 0x00, 0xE6, 0x20, 0x00, + 0x09, 0x48, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0x2E, 0x05, 0x83, 0x80, 0x04, 0x10, 0x00, 0xF2, + 0xA2, 0x0D, 0x00, 0xE6, 0x01, 0x00, 0x00, 0xEA, 0x26, 0x01, 0x01, 0xEA, 0x27, 0x01, 0x04, 0x80, + 0x18, 0xE4, 0x10, 0x00, 0x36, 0x12, 0xB9, 0x54, 0x00, 0xF2, 0xF6, 0x0E, 0x01, 0xE6, 0x06, 0x00, + 0x04, 0x80, 0x18, 0xE4, 0x01, 0x00, 0x04, 0x12, 0x01, 0xE6, 0x0D, 0x00, 0x00, 0xF2, 0x4E, 0x0D, + 0x00, 0xF2, 0x12, 0x11, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, 0x04, 0xE6, 0x02, 0x00, + 0x9E, 0xE7, 0x15, 0x00, 0x01, 0xF0, 0x1C, 0x0A, 0x00, 0xF0, 0x02, 0x0A, 0x00, 0xFC, 0x20, 0x01, + 0x98, 0x57, 0x34, 0x12, 0x00, 0xFC, 0x24, 0x01, 0x98, 0x57, 0x2C, 0x13, 0xB9, 0x54, 0x00, 0xF2, + 0xF6, 0x0E, 0x86, 0xF0, 0xA8, 0x05, 0x03, 0xF6, 0x01, 0x00, 0x00, 0xF2, 0x8C, 0x0E, 0x85, 0xF0, + 0x9E, 0x05, 0x82, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x60, 0x0B, 0x82, 0xE7, 0x02, 0x00, 0x00, 0xFC, + 0x24, 0x01, 0xB0, 0x57, 0x00, 0xFA, 0x24, 0x01, 0x00, 0xFC, 0x9E, 0x00, 0x98, 0x57, 0x5A, 0x12, + 0x00, 0xFC, 0xB6, 0x00, 0x98, 0x57, 0x52, 0x13, 0x03, 0xE6, 0x0C, 0x00, 0x00, 0xFC, 0x9C, 0x00, + 0x98, 0x57, 0x04, 0x13, 0x03, 0xE6, 0x19, 0x00, 0x05, 0xE6, 0x08, 0x00, 0x00, 0xF6, 0x00, 0x01, + 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x18, 0xF4, 0x00, 0x80, 0x04, 0x13, 0x05, 0xE6, + 0x0F, 0x00, 0xB9, 0x54, 0x00, 0xF2, 0xF6, 0x0E, 0x86, 0xF0, 0x0A, 0x06, 0x00, 0xF2, 0xBA, 0x0E, + 0x85, 0xF0, 0x00, 0x06, 0x82, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x60, 0x0B, 0x82, 0xE7, 0x02, 0x00, + 0x00, 0xFC, 0xB6, 0x00, 0xB0, 0x57, 0x00, 0xFA, 0xB6, 0x00, 0x01, 0xF6, 0x01, 0x00, 0x00, 0xF2, + 0xF6, 0x0E, 0x9C, 0x32, 0x4E, 0x1C, 0x32, 0x1C, 0x00, 0xF2, 0x92, 0x0D, 0x30, 0x1C, 0x82, 0xE7, + 0x04, 0x00, 0xB1, 0xF0, 0x22, 0x06, 0x0A, 0xF0, 0x3E, 0x06, 0x05, 0xF0, 0xD6, 0x06, 0x06, 0xF0, + 0xDC, 0x06, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, 0xFC, 0x09, 0x00, 0xF0, 0x02, 0x0A, 0x04, 0x80, + 0x18, 0xE4, 0x20, 0x00, 0x30, 0x12, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x21, 0x80, + 0x18, 0xE4, 0xE0, 0x00, 0x09, 0x48, 0x00, 0xF2, 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2, + 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x99, 0xA4, 0x00, 0xF2, 0x12, 0x11, + 0x09, 0xE7, 0x00, 0x00, 0x9A, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x02, 0x00, 0x34, 0x12, 0x09, 0xE7, + 0x1B, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x21, 0x80, 0x18, 0xE4, 0xE0, 0x00, 0x09, 0x48, 0x00, 0xF2, + 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2, + 0x12, 0x11, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF0, + 0x0C, 0x09, 0xBB, 0x55, 0x9A, 0x81, 0x03, 0xF7, 0x20, 0x00, 0x09, 0x6F, 0x93, 0x45, 0x55, 0xF0, + 0xE2, 0x06, 0xB1, 0xF0, 0xC2, 0x06, 0x0A, 0xF0, 0xBA, 0x06, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, + 0xFC, 0x09, 0x00, 0xF0, 0x02, 0x0A, 0x00, 0xF2, 0x60, 0x0B, 0x47, 0x10, 0x09, 0xE7, 0x08, 0x00, + 0x41, 0x10, 0x05, 0x80, 0x48, 0xE4, 0x00, 0x00, 0x1E, 0x12, 0x00, 0xE6, 0x11, 0x00, 0x00, 0xEA, + 0xB8, 0x00, 0x00, 0xF2, 0xB6, 0x10, 0x2C, 0x90, 0xAE, 0x90, 0x08, 0x50, 0x8A, 0x50, 0x38, 0x54, + 0x1F, 0x40, 0x00, 0xF2, 0xB4, 0x0D, 0x08, 0x10, 0x08, 0x90, 0x8A, 0x90, 0x30, 0x50, 0xB2, 0x50, + 0x9C, 0x32, 0x0C, 0x92, 0x8E, 0x92, 0x38, 0x54, 0x04, 0x80, 0x30, 0xE4, 0x08, 0x00, 0x04, 0x40, + 0x0C, 0x1C, 0x00, 0xF6, 0x03, 0x00, 0xB1, 0xF0, 0x26, 0x07, 0x9E, 0xF0, 0x3A, 0x07, 0x01, 0x48, + 0x55, 0xF0, 0xFC, 0x09, 0x0C, 0x1C, 0x10, 0x44, 0xED, 0x10, 0x0B, 0xF0, 0x5E, 0x07, 0x0C, 0xF0, + 0x62, 0x07, 0x05, 0xF0, 0x52, 0x07, 0x06, 0xF0, 0x58, 0x07, 0x09, 0xF0, 0x24, 0x09, 0x00, 0xF0, + 0x02, 0x0A, 0x00, 0xF2, 0x60, 0x0B, 0xCF, 0x10, 0x09, 0xE7, 0x08, 0x00, 0xC9, 0x10, 0x2E, 0x1C, + 0x02, 0x10, 0x2C, 0x1C, 0xAA, 0xF0, 0x64, 0x07, 0xAC, 0xF0, 0x72, 0x07, 0x40, 0x10, 0x34, 0x1C, + 0xF3, 0x10, 0xAD, 0xF0, 0x7C, 0x07, 0xC8, 0x10, 0x36, 0x1C, 0xE9, 0x10, 0x2B, 0xF0, 0x82, 0x08, + 0x6B, 0x18, 0x18, 0xF4, 0x00, 0xFE, 0x20, 0x12, 0x01, 0x58, 0xD2, 0xF0, 0x82, 0x08, 0x76, 0x18, + 0x18, 0xF4, 0x03, 0x00, 0xEC, 0x12, 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0xE2, 0x12, + 0x0B, 0xF0, 0x64, 0x07, 0x0C, 0xF0, 0x64, 0x07, 0x36, 0x1C, 0x34, 0x1C, 0xB7, 0x10, 0x38, 0x54, + 0xB9, 0x54, 0x84, 0x80, 0x19, 0xE4, 0x20, 0x00, 0xB2, 0x13, 0x85, 0x80, 0x81, 0x48, 0x66, 0x12, + 0x04, 0x80, 0x18, 0xE4, 0x08, 0x00, 0x58, 0x13, 0x1F, 0x80, 0x08, 0x44, 0xC8, 0x44, 0x9F, 0x12, + 0x1F, 0x40, 0x34, 0x91, 0xB6, 0x91, 0x44, 0x55, 0xE5, 0x55, 0x02, 0xEC, 0xB8, 0x00, 0x02, 0x49, + 0xBB, 0x55, 0x82, 0x81, 0xC0, 0x55, 0x48, 0xF4, 0x0F, 0x00, 0x5A, 0xF0, 0x1A, 0x08, 0x4A, 0xE4, + 0x17, 0x00, 0xD5, 0xF0, 0xFA, 0x07, 0x02, 0xF6, 0x0F, 0x00, 0x02, 0xF4, 0x02, 0x00, 0x02, 0xEA, + 0xB8, 0x00, 0x04, 0x91, 0x86, 0x91, 0x02, 0x4B, 0x2C, 0x90, 0x08, 0x50, 0x2E, 0x90, 0x0A, 0x50, + 0x2C, 0x51, 0xAE, 0x51, 0x00, 0xF2, 0xB6, 0x10, 0x38, 0x54, 0x00, 0xF2, 0xB4, 0x0D, 0x56, 0x10, + 0x34, 0x91, 0xB6, 0x91, 0x0C, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x08, 0x00, 0x41, 0x12, 0x0C, 0x91, + 0x8E, 0x91, 0x04, 0x80, 0x18, 0xE4, 0xF7, 0x00, 0x04, 0x40, 0x30, 0x90, 0xB2, 0x90, 0x36, 0x10, + 0x02, 0x80, 0x48, 0xE4, 0x10, 0x00, 0x31, 0x12, 0x82, 0xE7, 0x10, 0x00, 0x84, 0x80, 0x19, 0xE4, + 0x20, 0x00, 0x10, 0x13, 0x0C, 0x90, 0x8E, 0x90, 0x5D, 0xF0, 0x78, 0x07, 0x0C, 0x58, 0x8D, 0x58, + 0x00, 0xF0, 0x64, 0x07, 0x38, 0x54, 0xB9, 0x54, 0x19, 0x80, 0xF1, 0x10, 0x3A, 0x55, 0x19, 0x81, + 0xBB, 0x55, 0x10, 0x90, 0x92, 0x90, 0x10, 0x58, 0x91, 0x58, 0x14, 0x59, 0x95, 0x59, 0x00, 0xF0, + 0x64, 0x07, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x06, 0x12, 0x6C, 0x19, 0x19, 0x41, 0x7C, 0x10, + 0x6C, 0x19, 0x0C, 0x51, 0xED, 0x19, 0x8E, 0x51, 0x6B, 0x18, 0x18, 0xF4, 0x00, 0xFF, 0x02, 0x13, + 0x6A, 0x10, 0x01, 0x58, 0xD2, 0xF0, 0xC0, 0x08, 0x76, 0x18, 0x18, 0xF4, 0x03, 0x00, 0x0A, 0x12, + 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0x06, 0x13, 0x9E, 0xE7, 0x16, 0x00, 0x4C, 0x10, + 0xD1, 0xF0, 0xCA, 0x08, 0x9E, 0xE7, 0x17, 0x00, 0x42, 0x10, 0xD0, 0xF0, 0xD4, 0x08, 0x9E, 0xE7, + 0x19, 0x00, 0x38, 0x10, 0xCF, 0xF0, 0xDE, 0x08, 0x9E, 0xE7, 0x20, 0x00, 0x2E, 0x10, 0xCE, 0xF0, + 0xE8, 0x08, 0x9E, 0xE7, 0x21, 0x00, 0x24, 0x10, 0xCD, 0xF0, 0xF2, 0x08, 0x9E, 0xE7, 0x22, 0x00, + 0x1A, 0x10, 0xCC, 0xF0, 0x04, 0x09, 0x84, 0x80, 0x19, 0xE4, 0x04, 0x00, 0x06, 0x12, 0x9E, 0xE7, + 0x12, 0x00, 0x08, 0x10, 0xCB, 0xF0, 0x0C, 0x09, 0x9E, 0xE7, 0x24, 0x00, 0xB1, 0xF0, 0x0C, 0x09, + 0x05, 0xF0, 0x1E, 0x09, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, 0xFC, 0x09, 0xE4, 0x10, 0x00, 0xF2, + 0x60, 0x0B, 0xE9, 0x10, 0x9C, 0x32, 0x82, 0xE7, 0x20, 0x00, 0x32, 0x1C, 0xE9, 0x09, 0x00, 0xF2, + 0x12, 0x11, 0x85, 0xF0, 0x02, 0x0A, 0x69, 0x08, 0x01, 0xF0, 0x44, 0x09, 0x1E, 0xF0, 0xFC, 0x09, + 0x00, 0xF0, 0x38, 0x09, 0x30, 0x44, 0x06, 0x12, 0x9E, 0xE7, 0x42, 0x00, 0xB8, 0x10, 0x04, 0xF6, + 0x01, 0x00, 0xB3, 0x45, 0x74, 0x12, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x22, 0x13, 0x4B, 0xE4, + 0x02, 0x00, 0x36, 0x12, 0x4B, 0xE4, 0x28, 0x00, 0xAC, 0x13, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, + 0xC8, 0x11, 0x03, 0xF6, 0xD0, 0x00, 0xFA, 0x14, 0x82, 0xE7, 0x01, 0x00, 0x00, 0xF0, 0x80, 0x01, + 0x9E, 0xE7, 0x44, 0x00, 0x4B, 0xE4, 0x02, 0x00, 0x06, 0x12, 0x03, 0xE6, 0x02, 0x00, 0x76, 0x10, + 0x00, 0xF2, 0xA2, 0x0D, 0x03, 0xE6, 0x02, 0x00, 0x6C, 0x10, 0x00, 0xF2, 0xA2, 0x0D, 0x19, 0x82, + 0x34, 0x46, 0x0A, 0x13, 0x03, 0xE6, 0x02, 0x00, 0x9E, 0xE7, 0x43, 0x00, 0x68, 0x10, 0x04, 0x80, + 0x30, 0xE4, 0x20, 0x00, 0x04, 0x40, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, 0x82, 0xE7, + 0x01, 0x00, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF0, 0x08, 0x03, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, + 0x06, 0x12, 0x03, 0xE6, 0x02, 0x00, 0x3E, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x02, 0x00, 0x3A, 0x12, + 0x04, 0x80, 0x18, 0xE4, 0xFD, 0x00, 0x04, 0x40, 0x1C, 0x1C, 0x9D, 0xF0, 0xEA, 0x09, 0x1C, 0x1C, + 0x9D, 0xF0, 0xF0, 0x09, 0xC1, 0x10, 0x9E, 0xE7, 0x13, 0x00, 0x0A, 0x10, 0x9E, 0xE7, 0x41, 0x00, + 0x04, 0x10, 0x9E, 0xE7, 0x24, 0x00, 0x00, 0xFC, 0xBE, 0x00, 0x98, 0x57, 0xD5, 0xF0, 0x8A, 0x02, + 0x04, 0xE6, 0x04, 0x00, 0x06, 0x10, 0x04, 0xE6, 0x04, 0x00, 0x9D, 0x41, 0x1C, 0x42, 0x9F, 0xE7, + 0x00, 0x00, 0x06, 0xF7, 0x02, 0x00, 0x03, 0xF6, 0xE0, 0x00, 0x3C, 0x14, 0x44, 0x58, 0x45, 0x58, + 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0xF2, 0x7E, 0x10, 0x00, 0xF2, 0xC6, 0x0F, 0x3C, 0x14, 0x1E, 0x1C, + 0x00, 0xF0, 0x80, 0x01, 0x12, 0x1C, 0x22, 0x1C, 0xD2, 0x14, 0x00, 0xF0, 0x72, 0x01, 0x83, 0x59, + 0x03, 0xDC, 0x73, 0x57, 0x80, 0x5D, 0x00, 0x16, 0x83, 0x59, 0x03, 0xDC, 0x38, 0x54, 0x70, 0x57, + 0x33, 0x54, 0x3B, 0x54, 0x80, 0x5D, 0x00, 0x16, 0x03, 0x57, 0x83, 0x59, 0x38, 0x54, 0x00, 0xCC, + 0x00, 0x16, 0x03, 0x57, 0x83, 0x59, 0x00, 0x4C, 0x00, 0x16, 0x02, 0x80, 0x48, 0xE4, 0x01, 0x00, + 0x0E, 0x12, 0x48, 0xE4, 0x05, 0x00, 0x08, 0x12, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, + 0xC1, 0x5A, 0x3A, 0x55, 0x02, 0xEC, 0xB5, 0x00, 0x45, 0x59, 0x00, 0xF2, 0xF6, 0x0D, 0x83, 0x58, + 0x30, 0xE7, 0x00, 0x00, 0x10, 0x4D, 0x30, 0xE7, 0x40, 0x00, 0x10, 0x4F, 0x38, 0x90, 0xBA, 0x90, + 0x10, 0x5C, 0x80, 0x5C, 0x83, 0x5A, 0x10, 0x4E, 0x04, 0xEA, 0xB5, 0x00, 0x43, 0x5B, 0x03, 0xF4, + 0xE0, 0x00, 0x83, 0x59, 0x04, 0xCC, 0x01, 0x4A, 0x0A, 0x12, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, + 0x00, 0xF2, 0x38, 0x10, 0x00, 0x16, 0x08, 0x1C, 0x00, 0xFC, 0xAC, 0x00, 0x06, 0x58, 0x67, 0x18, + 0x18, 0xF4, 0x8F, 0xE1, 0x01, 0xFC, 0xAE, 0x00, 0x19, 0xF4, 0x70, 0x1E, 0xB0, 0x54, 0x07, 0x58, + 0x00, 0xFC, 0xB0, 0x00, 0x08, 0x58, 0x00, 0xFC, 0xB2, 0x00, 0x09, 0x58, 0x0A, 0x1C, 0x00, 0xE6, + 0x0F, 0x00, 0x00, 0xEA, 0xB9, 0x00, 0x38, 0x54, 0x00, 0xFA, 0x24, 0x01, 0x00, 0xFA, 0xB6, 0x00, + 0x18, 0x1C, 0x14, 0x1C, 0x10, 0x1C, 0x32, 0x1C, 0x12, 0x1C, 0x00, 0x16, 0x3E, 0x57, 0x0C, 0x14, + 0x0E, 0x47, 0x07, 0xE6, 0x10, 0x00, 0xCE, 0x47, 0xF5, 0x13, 0x00, 0x16, 0x00, 0xF2, 0xA2, 0x0D, + 0x02, 0x4B, 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x01, 0x48, 0x20, 0x12, 0x44, 0x58, + 0x45, 0x58, 0x9E, 0xE7, 0x15, 0x00, 0x9C, 0xE7, 0x04, 0x00, 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0xF2, + 0x7E, 0x10, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2, 0x7A, 0x0A, 0x1E, 0x1C, 0xD5, 0x10, 0x00, 0x16, + 0x69, 0x08, 0x48, 0xE4, 0x04, 0x00, 0x64, 0x12, 0x48, 0xE4, 0x02, 0x00, 0x20, 0x12, 0x48, 0xE4, + 0x03, 0x00, 0x1A, 0x12, 0x48, 0xE4, 0x08, 0x00, 0x14, 0x12, 0x48, 0xE4, 0x01, 0x00, 0xF0, 0x12, + 0x48, 0xE4, 0x07, 0x00, 0x12, 0x12, 0x01, 0xE6, 0x07, 0x00, 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, + 0x12, 0x11, 0x05, 0xF0, 0x60, 0x0B, 0x00, 0x16, 0x00, 0xE6, 0x01, 0x00, 0x00, 0xEA, 0x99, 0x00, + 0x02, 0x80, 0x48, 0xE4, 0x03, 0x00, 0xE7, 0x12, 0x48, 0xE4, 0x06, 0x00, 0xE1, 0x12, 0x01, 0xE6, + 0x06, 0x00, 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, 0x04, 0xE6, 0x02, 0x00, 0x9E, 0xE7, + 0x15, 0x00, 0x01, 0xF0, 0x1C, 0x0A, 0x00, 0xF0, 0x02, 0x0A, 0x00, 0x16, 0x02, 0x80, 0x48, 0xE4, + 0x10, 0x00, 0x1C, 0x12, 0x82, 0xE7, 0x08, 0x00, 0x3C, 0x56, 0x03, 0x82, 0x00, 0xF2, 0xE2, 0x0D, + 0x30, 0xE7, 0x08, 0x00, 0x04, 0xF7, 0x70, 0x01, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF0, 0x80, 0x01, + 0x6C, 0x19, 0xED, 0x19, 0x5D, 0xF0, 0xD4, 0x0B, 0x44, 0x55, 0xE5, 0x55, 0x59, 0xF0, 0x52, 0x0C, + 0x04, 0x55, 0xA5, 0x55, 0x1F, 0x80, 0x01, 0xEC, 0xB8, 0x00, 0x82, 0x48, 0x82, 0x80, 0x49, 0x44, + 0x2E, 0x13, 0x01, 0xEC, 0xB8, 0x00, 0x41, 0xE4, 0x02, 0x00, 0x01, 0xEA, 0xB8, 0x00, 0x49, 0xE4, + 0x11, 0x00, 0x59, 0xF0, 0x2E, 0x0C, 0x01, 0xE6, 0x17, 0x00, 0x01, 0xEA, 0xB8, 0x00, 0x02, 0x4B, + 0x88, 0x90, 0xAC, 0x50, 0x8A, 0x90, 0xAE, 0x50, 0x01, 0xEC, 0xB8, 0x00, 0x82, 0x48, 0x82, 0x80, + 0x10, 0x44, 0x02, 0x4B, 0x1F, 0x40, 0xC0, 0x44, 0x00, 0xF2, 0xB4, 0x0D, 0x04, 0x55, 0xA5, 0x55, + 0x9F, 0x10, 0x0C, 0x51, 0x8E, 0x51, 0x30, 0x90, 0xB2, 0x90, 0x00, 0x56, 0xA1, 0x56, 0x30, 0x50, + 0xB2, 0x50, 0x34, 0x90, 0xB6, 0x90, 0x40, 0x56, 0xE1, 0x56, 0x34, 0x50, 0xB6, 0x50, 0x65, 0x10, + 0xB1, 0xF0, 0x70, 0x0C, 0x85, 0xF0, 0xCA, 0x0B, 0xE9, 0x09, 0x4B, 0xE4, 0x03, 0x00, 0x78, 0x12, + 0x4B, 0xE4, 0x02, 0x00, 0x01, 0x13, 0xB1, 0xF0, 0x86, 0x0C, 0x85, 0xF0, 0xCA, 0x0B, 0x69, 0x08, + 0x48, 0xE4, 0x03, 0x00, 0xD5, 0xF0, 0x86, 0x0B, 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0xCA, 0x0B, + 0xE8, 0x09, 0x3C, 0x56, 0x00, 0xFC, 0x20, 0x01, 0x98, 0x57, 0x02, 0x13, 0xBB, 0x45, 0x4B, 0xE4, + 0x00, 0x00, 0x08, 0x12, 0x03, 0xE6, 0x01, 0x00, 0x04, 0xF6, 0x00, 0x80, 0xA8, 0x14, 0xD2, 0x14, + 0x30, 0x1C, 0x02, 0x80, 0x48, 0xE4, 0x03, 0x00, 0x10, 0x13, 0x00, 0xFC, 0xB6, 0x00, 0x98, 0x57, + 0x02, 0x13, 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF0, 0x8E, 0x0B, 0x00, 0xFC, 0x24, 0x01, 0xB0, 0x57, + 0x00, 0xFA, 0x24, 0x01, 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0x8E, 0x0B, + 0x00, 0xF2, 0x8C, 0x0E, 0x00, 0xF0, 0x8E, 0x0B, 0xB1, 0xF0, 0xF8, 0x0C, 0x85, 0xF0, 0x86, 0x0B, + 0x69, 0x08, 0x48, 0xE4, 0x01, 0x00, 0xD5, 0xF0, 0x86, 0x0B, 0xFC, 0x14, 0x42, 0x58, 0x6C, 0x14, + 0x80, 0x14, 0x30, 0x1C, 0x4A, 0xF4, 0x02, 0x00, 0x55, 0xF0, 0x86, 0x0B, 0x4A, 0xF4, 0x01, 0x00, + 0x0E, 0x12, 0x02, 0x80, 0x48, 0xE4, 0x03, 0x00, 0x06, 0x13, 0x3E, 0x1C, 0x00, 0xF0, 0x8E, 0x0B, + 0x00, 0xFC, 0xB6, 0x00, 0xB0, 0x57, 0x00, 0xFA, 0xB6, 0x00, 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF2, + 0x12, 0x11, 0x86, 0xF0, 0x8E, 0x0B, 0x00, 0xF2, 0xBA, 0x0E, 0x00, 0xF0, 0x8E, 0x0B, 0x4C, 0x1C, + 0xB1, 0xF0, 0x50, 0x0D, 0x85, 0xF0, 0x5C, 0x0D, 0x69, 0x08, 0xF3, 0x10, 0x86, 0xF0, 0x64, 0x0D, + 0x4E, 0x1C, 0x89, 0x48, 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01, 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, + 0x00, 0xDC, 0x18, 0xF4, 0xFF, 0x7F, 0x30, 0x56, 0x00, 0x5C, 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01, + 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x18, 0xF4, 0x00, 0x80, 0x30, 0x56, 0x00, 0x5C, + 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01, 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x0B, 0x58, + 0x00, 0x16, 0x03, 0xF6, 0x24, 0x01, 0x00, 0xF2, 0x58, 0x0A, 0x03, 0xF6, 0xB6, 0x00, 0x00, 0xF2, + 0x58, 0x0A, 0x00, 0x16, 0x02, 0xEC, 0xB8, 0x00, 0x02, 0x49, 0x18, 0xF4, 0xFF, 0x00, 0x00, 0x54, + 0x00, 0x54, 0x00, 0x54, 0x00, 0xF4, 0x08, 0x00, 0xE1, 0x18, 0x80, 0x54, 0x03, 0x58, 0x00, 0xDD, + 0x01, 0xDD, 0x02, 0xDD, 0x03, 0xDC, 0x02, 0x4B, 0x30, 0x50, 0xB2, 0x50, 0x34, 0x51, 0xB6, 0x51, + 0x00, 0x16, 0x45, 0x5A, 0x1D, 0xF4, 0xFF, 0x00, 0x85, 0x56, 0x85, 0x56, 0x85, 0x56, 0x05, 0xF4, + 0x02, 0x12, 0x83, 0x5A, 0x00, 0x16, 0x1D, 0xF4, 0xFF, 0x00, 0x85, 0x56, 0x85, 0x56, 0x85, 0x56, + 0x05, 0xF4, 0x00, 0x12, 0x83, 0x5A, 0x00, 0x16, 0x38, 0x54, 0xBB, 0x55, 0x3C, 0x56, 0xBD, 0x56, + 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0x82, 0x0E, 0xE9, 0x09, 0xC1, 0x59, 0x00, 0xF2, 0x12, 0x11, + 0x85, 0xF0, 0x82, 0x0E, 0xE8, 0x0A, 0x83, 0x55, 0x83, 0x55, 0x4B, 0xF4, 0x90, 0x01, 0x5C, 0xF0, + 0x36, 0x0E, 0xBD, 0x56, 0x40, 0x10, 0x4B, 0xF4, 0x30, 0x00, 0x59, 0xF0, 0x48, 0x0E, 0x01, 0xF6, + 0x0C, 0x00, 0x00, 0xF6, 0x01, 0x00, 0x2E, 0x10, 0x02, 0xFC, 0x9C, 0x00, 0x9A, 0x57, 0x14, 0x13, + 0x4B, 0xF4, 0x64, 0x00, 0x59, 0xF0, 0x64, 0x0E, 0x03, 0xF6, 0x64, 0x00, 0x01, 0xF6, 0x19, 0x00, + 0x00, 0xF6, 0x01, 0x00, 0x43, 0xF4, 0x33, 0x00, 0x56, 0xF0, 0x76, 0x0E, 0x04, 0xF4, 0x00, 0x01, + 0x43, 0xF4, 0x19, 0x00, 0xF3, 0x10, 0xB4, 0x56, 0xC3, 0x58, 0x02, 0xFC, 0x9E, 0x00, 0x9A, 0x57, + 0x08, 0x13, 0x3C, 0x56, 0x00, 0xF6, 0x02, 0x00, 0x00, 0x16, 0x00, 0x16, 0x09, 0xE7, 0x01, 0x00, + 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xB8, 0x0E, 0x09, 0xE7, 0x02, 0x00, 0x00, 0xF2, 0x12, 0x11, + 0x86, 0xF0, 0xB8, 0x0E, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xB8, 0x0E, + 0x4E, 0x1C, 0x89, 0x49, 0x00, 0xF2, 0x12, 0x11, 0x00, 0x16, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2, + 0x12, 0x11, 0x86, 0xF0, 0xF2, 0x0E, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, + 0xF2, 0x0E, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xF2, 0x0E, 0x89, 0x49, + 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xF2, 0x0E, 0x4E, 0x1C, 0x89, 0x4A, 0x00, 0xF2, 0x12, 0x11, + 0x00, 0x16, 0x3C, 0x56, 0x00, 0x16, 0x00, 0xEC, 0x26, 0x01, 0x48, 0xE4, 0x01, 0x00, 0x1E, 0x13, + 0x38, 0x44, 0x00, 0xEA, 0x26, 0x01, 0x49, 0xF4, 0x00, 0x00, 0x04, 0x12, 0x4E, 0x1C, 0x02, 0x10, + 0x4C, 0x1C, 0x01, 0xEC, 0x27, 0x01, 0x89, 0x48, 0x00, 0xF2, 0x12, 0x11, 0x02, 0x14, 0x00, 0x16, + 0x85, 0xF0, 0x52, 0x0F, 0x38, 0x54, 0x00, 0xEA, 0x99, 0x00, 0x00, 0xF2, 0x60, 0x0B, 0x02, 0x80, + 0x48, 0xE4, 0x06, 0x00, 0x1C, 0x13, 0x00, 0xEC, 0x99, 0x00, 0x48, 0xE4, 0x01, 0x00, 0x0A, 0x12, + 0x04, 0x80, 0x30, 0xE4, 0x01, 0x00, 0x04, 0x40, 0x08, 0x10, 0x04, 0x80, 0x18, 0xE4, 0xFE, 0x00, + 0x04, 0x40, 0x00, 0x16, 0x02, 0xF6, 0xE0, 0x00, 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x81, 0x48, + 0x22, 0x12, 0x00, 0x4E, 0x83, 0x5A, 0x90, 0x4C, 0x20, 0xE7, 0x00, 0x00, 0xC3, 0x58, 0x1B, 0xF4, + 0xFF, 0x00, 0x83, 0x55, 0x83, 0x55, 0x83, 0x55, 0x03, 0xF4, 0x00, 0x12, 0x8B, 0x55, 0x83, 0x59, + 0x00, 0x4E, 0x00, 0x16, 0x00, 0x4E, 0x02, 0xF6, 0xF0, 0x00, 0x02, 0x57, 0x03, 0x59, 0x00, 0x4E, + 0x83, 0x5A, 0x30, 0xE7, 0x00, 0x00, 0x20, 0xE7, 0x00, 0x00, 0x00, 0x16, 0x02, 0xF6, 0xF0, 0x00, + 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x00, 0x4E, 0x83, 0x5A, 0x30, 0xE7, 0x00, 0x00, 0x80, 0x4C, + 0xC3, 0x58, 0x1B, 0xF4, 0xFF, 0x00, 0x83, 0x55, 0x83, 0x55, 0x83, 0x55, 0x03, 0xF4, 0x00, 0x12, + 0x83, 0x59, 0x00, 0x4E, 0x00, 0x16, 0x03, 0xF6, 0xE0, 0x00, 0x03, 0x57, 0x83, 0x59, 0x3A, 0x55, + 0x02, 0xCC, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, 0xC0, 0x5A, 0x40, 0x5C, 0x38, 0x54, 0x00, 0xCD, + 0x01, 0xCC, 0x4A, 0x46, 0x0A, 0x13, 0x83, 0x59, 0x00, 0x4C, 0x01, 0x48, 0x16, 0x13, 0x0C, 0x10, + 0xC5, 0x58, 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0x4C, 0x01, 0x48, 0x08, 0x13, 0x05, 0xF6, 0xF0, 0x00, + 0x05, 0x57, 0x08, 0x10, 0x45, 0x58, 0x00, 0xF2, 0xF6, 0x0D, 0x8D, 0x56, 0x83, 0x5A, 0x80, 0x4C, + 0x05, 0x17, 0x00, 0x16, 0x02, 0x4B, 0x06, 0xF7, 0x04, 0x00, 0x62, 0x0B, 0x03, 0x82, 0x00, 0xF2, + 0xE2, 0x0D, 0x02, 0x80, 0x00, 0x4C, 0x45, 0xF4, 0x02, 0x00, 0x52, 0x14, 0x06, 0xF7, 0x02, 0x00, + 0x06, 0x14, 0x00, 0xF2, 0x54, 0x0F, 0x00, 0x16, 0x02, 0x4B, 0x01, 0xF6, 0xFF, 0x00, 0x38, 0x1C, + 0x05, 0xF4, 0x04, 0x00, 0x83, 0x5A, 0x18, 0xDF, 0x19, 0xDF, 0x1D, 0xF7, 0x3C, 0x00, 0xB8, 0xF0, + 0x4E, 0x10, 0x9C, 0x14, 0x01, 0x48, 0x1C, 0x13, 0x0E, 0xF7, 0x3C, 0x00, 0x03, 0xF7, 0x04, 0x00, + 0xAF, 0x19, 0x03, 0x42, 0x45, 0xF4, 0x02, 0x00, 0x83, 0x5A, 0x02, 0xCC, 0x02, 0x41, 0x45, 0xF4, + 0x02, 0x00, 0x00, 0x16, 0x91, 0x44, 0xD5, 0xF0, 0x3E, 0x10, 0x00, 0xF0, 0x9E, 0x02, 0x01, 0xF6, + 0xFF, 0x00, 0x38, 0x1C, 0x05, 0xF4, 0x04, 0x00, 0x83, 0x5A, 0x18, 0xDF, 0x19, 0xDF, 0x0E, 0xF7, + 0x3C, 0x00, 0x03, 0xF7, 0x04, 0x00, 0x0F, 0x79, 0x1C, 0xF7, 0x3C, 0x00, 0xB8, 0xF0, 0x9C, 0x10, + 0x4E, 0x14, 0x01, 0x48, 0x06, 0x13, 0x45, 0xF4, 0x04, 0x00, 0x00, 0x16, 0x91, 0x44, 0xD5, 0xF0, + 0x82, 0x10, 0x00, 0xF0, 0x9E, 0x02, 0x02, 0xF6, 0xFF, 0x00, 0x38, 0x1C, 0x2C, 0xBC, 0xAE, 0xBC, + 0xE2, 0x08, 0x00, 0xEC, 0xB8, 0x00, 0x02, 0x48, 0x1D, 0xF7, 0x80, 0x00, 0xB8, 0xF0, 0xCC, 0x10, + 0x1E, 0x14, 0x01, 0x48, 0x0E, 0x13, 0x0E, 0xF7, 0x80, 0x00, 0x38, 0x54, 0x03, 0x58, 0xAF, 0x19, + 0x82, 0x48, 0x00, 0x16, 0x82, 0x48, 0x12, 0x45, 0xD5, 0xF0, 0xBA, 0x10, 0x00, 0xF0, 0x9E, 0x02, + 0x39, 0xF0, 0xF8, 0x10, 0x38, 0x44, 0x00, 0x16, 0x7E, 0x18, 0x18, 0xF4, 0x03, 0x00, 0x04, 0x13, + 0x61, 0x18, 0x00, 0x16, 0x38, 0x1C, 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0xF1, 0x12, + 0xE3, 0x10, 0x30, 0x44, 0x30, 0x44, 0x30, 0x44, 0xB1, 0xF0, 0x18, 0x11, 0x00, 0x16, 0x3E, 0x57, + 0x03, 0xF6, 0xE0, 0x00, 0x03, 0x57, 0x83, 0x59, 0x04, 0xCC, 0x01, 0x4A, 0x6A, 0x12, 0x45, 0x5A, + 0x00, 0xF2, 0xF6, 0x0D, 0x02, 0x4B, 0x70, 0x14, 0x34, 0x13, 0x02, 0x80, 0x48, 0xE4, 0x08, 0x00, + 0x18, 0x12, 0x9C, 0xE7, 0x02, 0x00, 0x9E, 0xE7, 0x15, 0x00, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2, + 0x7A, 0x0A, 0x1E, 0x1C, 0x01, 0xF6, 0x01, 0x00, 0x00, 0x16, 0x30, 0xE4, 0x10, 0x00, 0x04, 0x40, + 0x00, 0xF2, 0xE2, 0x0D, 0x20, 0xE7, 0x01, 0x00, 0x01, 0xF6, 0x01, 0x00, 0x00, 0x16, 0x04, 0xDC, + 0x01, 0x4A, 0x24, 0x12, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, 0x43, 0x5B, 0x06, 0xEC, 0x98, 0x00, + 0x00, 0xF2, 0x38, 0x10, 0xC6, 0x59, 0x20, 0x14, 0x0A, 0x13, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2, + 0x14, 0x10, 0xA7, 0x10, 0x83, 0x5A, 0xD7, 0x10, 0x0E, 0x47, 0x07, 0xE6, 0x10, 0x00, 0xCE, 0x47, + 0x5A, 0xF0, 0x20, 0x11, 0xB9, 0x54, 0x00, 0x16, 0x14, 0x90, 0x96, 0x90, 0x02, 0xFC, 0xA8, 0x00, + 0x03, 0xFC, 0xAA, 0x00, 0x48, 0x55, 0x02, 0x13, 0xC9, 0x55, 0x00, 0x16, 0x00, 0xEC, 0xBA, 0x00, + 0x10, 0x44, 0x00, 0xEA, 0xBA, 0x00, 0x00, 0x16, 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x68, 0x0A, + 0x10, 0x44, 0x00, 0x4C, 0x00, 0x16 +}; unsigned short _adv_mcode_size ASC_INITDATA = - sizeof(_adv_mcode_buf); /* 0x11D2 */ -unsigned long _adv_mcode_chksum ASC_INITDATA = 0x0347D07AUL; + sizeof(_adv_mcode_buf); /* 0x11D6 */ +unsigned long _adv_mcode_chksum ASC_INITDATA = 0x03494981UL; /* a_init.c */ /* diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c --- v2.1.100/linux/drivers/scsi/aic7xxx.c Tue Apr 14 14:29:21 1998 +++ linux/drivers/scsi/aic7xxx.c Fri May 8 00:22:11 1998 @@ -242,7 +242,7 @@ # include #endif -#if !defined(__alpha__) +#if !defined(__alpha__) && !defined(__sparc__) # define MMAPIO #endif @@ -950,10 +950,10 @@ unsigned short needwdtr_copy; /* default config */ unsigned short ultraenb; /* Ultra mode target list */ unsigned short bios_control; /* bios control - SEEPROM */ + unsigned int irq; /* IRQ for this adapter */ unsigned short adapter_control; /* adapter control - SEEPROM */ unsigned char pci_bus; unsigned char pci_device_fn; - unsigned char irq; /* IRQ for this adapter */ #ifdef AIC7XXX_PROC_STATS /* @@ -5245,6 +5245,7 @@ } } +#if defined(__i386__) || defined(__alpha__) /*+F************************************************************************* * Function: * aic7xxx_probe @@ -5322,6 +5323,7 @@ return (AHC_NONE); } +#endif /* __i386__ || __alpha__ */ /*+F************************************************************************* * Function: @@ -7266,7 +7268,7 @@ unsigned short command; unsigned int devconfig, i; #ifdef MMAPIO - unsigned long page_offset; + unsigned long page_offset, base; #endif struct aic7xxx_host *first_7895 = NULL; #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/amiga7xx.c linux/drivers/scsi/amiga7xx.c --- v2.1.100/linux/drivers/scsi/amiga7xx.c Thu Mar 26 15:57:03 1998 +++ linux/drivers/scsi/amiga7xx.c Fri May 8 00:22:11 1998 @@ -33,17 +33,14 @@ S_IFDIR | S_IRUGO | S_IXUGO, 2 }; -extern ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip, - u32 base, int io_port, int irq, int dma, - long long options, int clock); - int amiga7xx_detect(Scsi_Host_Template *tpnt) { static unsigned char called = 0; unsigned int key; - int num = 0, clock; + int num = 0; + unsigned long address; long long options; - const struct ConfigDev *cd; + struct ConfigDev *cd; if (called || !MACH_IS_AMIGA) return 0; @@ -53,7 +50,6 @@ #ifdef CONFIG_WARPENGINE_SCSI if ((key = zorro_find(ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE_40xx, 0, 0))) { - unsigned long address; cd = zorro_get_board(key); address = (unsigned long)kernel_map((unsigned long)cd->cd_BoardAddr, cd->cd_BoardSize, KERNELMAP_NOCACHE_SER, NULL); @@ -87,9 +83,8 @@ #ifdef CONFIG_A4091_SCSI while ( (key = zorro_find(ZORRO_PROD_CBM_A4091_1, 0, 0)) || - (key = zorro_find(ZORRO_PROD_CBM_A4091_2, 0, 0)) ) + (key = zorro_find(ZORRO_PROD_CBM_A4091_2, 0, 0)) ) { - unsigned long address; cd = zorro_get_board(key); address = (unsigned long)kernel_map((unsigned long)cd->cd_BoardAddr, cd->cd_BoardSize, KERNELMAP_NOCACHE_SER, NULL); diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/blz1230.c linux/drivers/scsi/blz1230.c --- v2.1.100/linux/drivers/scsi/blz1230.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/blz1230.c Fri May 8 00:22:11 1998 @@ -0,0 +1,269 @@ +/* blz1230.c: Driver for Blizzard 1230 SCSI IV Controller. + * + * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk) + * + * This driver is based on the CyberStorm driver, hence the occasional + * reference to CyberStorm. + */ + +/* TODO: + * + * 1) Figure out how to make a cleaner merge with the sparc driver with regard + * to the caches and the Sparc MMU mapping. + * 2) Make as few routines required outside the generic driver. A lot of the + * routines in this file used to be inline! + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "NCR53C9x.h" +#include "blz1230.h" + +#include +#include +#include +#include + +#include + +#define MKIV 1 + +static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count); +static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp); +static void dma_dump_state(struct NCR_ESP *esp); +static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length); +static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length); +static void dma_ints_off(struct NCR_ESP *esp); +static void dma_ints_on(struct NCR_ESP *esp); +static int dma_irq_p(struct NCR_ESP *esp); +static int dma_ports_p(struct NCR_ESP *esp); +static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write); + +volatile unsigned char cmd_buffer[16]; + /* This is where all commands are put + * before they are trasfered to the ESP chip + * via PIO. + */ + +/***************************************************************** Detection */ +int blz1230_esp_detect(Scsi_Host_Template *tpnt) +{ + struct NCR_ESP *esp; + const struct ConfigDev *esp_dev; + unsigned int key; + unsigned long address; + struct ESP_regs *eregs; + +#if MKIV + if ((key = zorro_find(ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260, 0, 0))){ +#else + if ((key = zorro_find(ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060, 0, 0))){ +#endif + esp_dev = zorro_get_board(key); + + /* Do some magic to figure out if the blizzard is + * equipped with a SCSI controller + */ + address = (unsigned long)ZTWO_VADDR(esp_dev->cd_BoardAddr); +#if MKIV + eregs = (struct ESP_regs *)(address + BLZ1230_ESP_ADDR); +#else + eregs = (struct ESP_regs *)(address + BLZ1230II_ESP_ADDR); +#endif + + eregs->esp_cfg1 = (ESP_CONFIG1_PENABLE | 7); + udelay(5); + if(eregs->esp_cfg1 != (ESP_CONFIG1_PENABLE | 7)) + return 0; /* Bail out if address did not hold data */ + + esp = esp_allocate(tpnt, (void *) esp_dev); + + /* Do command transfer with programmed I/O */ + esp->do_pio_cmds = 1; + + /* Required functions */ + esp->dma_bytes_sent = &dma_bytes_sent; + esp->dma_can_transfer = &dma_can_transfer; + esp->dma_dump_state = &dma_dump_state; + esp->dma_init_read = &dma_init_read; + esp->dma_init_write = &dma_init_write; + esp->dma_ints_off = &dma_ints_off; + esp->dma_ints_on = &dma_ints_on; + esp->dma_irq_p = &dma_irq_p; + esp->dma_ports_p = &dma_ports_p; + esp->dma_setup = &dma_setup; + + /* Optional functions */ + esp->dma_barrier = 0; + esp->dma_drain = 0; + esp->dma_invalidate = 0; + esp->dma_irq_entry = 0; + esp->dma_irq_exit = 0; + esp->dma_led_on = 0; + esp->dma_led_off = 0; + esp->dma_poll = 0; + esp->dma_reset = 0; + + /* SCSI chip speed */ + esp->cfreq = 40000000; + + /* The DMA registers on the Blizzard are mapped + * relative to the device (i.e. in the same Zorro + * I/O block). + */ +#if MKIV + esp->dregs = (void *)(address + BLZ1230_DMA_ADDR); +#else + esp->dregs = (void *)(address + BLZ1230II_DMA_ADDR); +#endif + + /* ESP register base */ + esp->eregs = eregs; + + /* Set the command buffer */ + esp->esp_command_dvma = VTOP((unsigned long) cmd_buffer); + + esp->irq = IRQ_AMIGA_PORTS; + request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, + "Blizzard 1230 SCSI IV", esp_intr); + + /* Figure out our scsi ID on the bus */ + esp->scsi_id = 7; + + /* Check for differential SCSI-bus */ + /* What is this stuff? */ + esp->diff = 0; + + esp_initialize(esp); + + zorro_config_board(key, 0); + + printk("\nESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,esps_in_use); + esps_running = esps_in_use; + return esps_in_use; + } + return 0; +} + +/************************************************************* DMA Functions */ +static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count) +{ + /* Since the Blizzard DMA is fully dedicated to the ESP chip, + * the number of bytes sent (to the ESP chip) equals the number + * of bytes in the FIFO - there is no buffering in the DMA controller. + * XXXX Do I read this right? It is from host to ESP, right? + */ + return fifo_count; +} + +static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp) +{ + /* I don't think there's any limit on the Blizzard DMA. So we use what + * the ESP chip can handle (24 bit). + */ + unsigned long sz = sp->SCp.this_residual; + if(sz > 0x1000000) + sz = 0x1000000; + return sz; +} + +static void dma_dump_state(struct NCR_ESP *esp) +{ + ESPLOG(("intreq:<%04x>, intena:<%04x>\n", + custom.intreqr, custom.intenar)); +} + +void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) +{ +#if MKIV + struct blz1230_dma_registers *dregs = + (struct blz1230_dma_registers *) (esp->dregs); +#else + struct blz1230II_dma_registers *dregs = + (struct blz1230II_dma_registers *) (esp->dregs); +#endif + + cache_clear(addr, length); + + addr >>= 1; + addr &= ~(BLZ1230_DMA_WRITE); + + /* First set latch */ + dregs->dma_latch = (addr >> 24) & 0xff; + + /* Then pump the address to the DMA address register */ +#if MKIV + dregs->dma_addr = (addr >> 24) & 0xff; +#endif + dregs->dma_addr = (addr >> 16) & 0xff; + dregs->dma_addr = (addr >> 8) & 0xff; + dregs->dma_addr = (addr ) & 0xff; +} + +void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length) +{ +#if MKIV + struct blz1230_dma_registers *dregs = + (struct blz1230_dma_registers *) (esp->dregs); +#else + struct blz1230II_dma_registers *dregs = + (struct blz1230II_dma_registers *) (esp->dregs); +#endif + + cache_push(addr, length); + + addr >>= 1; + addr |= BLZ1230_DMA_WRITE; + + /* First set latch */ + dregs->dma_latch = (addr >> 24) & 0xff; + + /* Then pump the address to the DMA address register */ +#if MKIV + dregs->dma_addr = (addr >> 24) & 0xff; +#endif + dregs->dma_addr = (addr >> 16) & 0xff; + dregs->dma_addr = (addr >> 8) & 0xff; + dregs->dma_addr = (addr ) & 0xff; +} + +static void dma_ints_off(struct NCR_ESP *esp) +{ + disable_irq(esp->irq); +} + +static void dma_ints_on(struct NCR_ESP *esp) +{ + enable_irq(esp->irq); +} + +static int dma_irq_p(struct NCR_ESP *esp) +{ + return (esp->eregs->esp_status & ESP_STAT_INTR); +} + +static int dma_ports_p(struct NCR_ESP *esp) +{ + return ((custom.intenar) & IF_PORTS); +} + +static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) +{ + /* On the Sparc, DMA_ST_WRITE means "move data from device to memory" + * so when (write) is true, it actually means READ! + */ + if(write){ + dma_init_read(esp, addr, count); + } else { + dma_init_write(esp, addr, count); + } +} diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/blz1230.h linux/drivers/scsi/blz1230.h --- v2.1.100/linux/drivers/scsi/blz1230.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/blz1230.h Fri May 8 00:22:11 1998 @@ -0,0 +1,82 @@ +/* blz1230.h: Defines and structures for the Blizzard 1230 SCSI IV driver. + * + * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk) + * + * This file is based on cyber_esp.h (hence the occasional reference to + * CyberStorm). + */ + +#include "NCR53C9x.h" + +#ifndef BLZ1230_H +#define BLZ1230_H + +/* The controller registers can be found in the Z2 config area at these + * offsets: + */ +#define BLZ1230_ESP_ADDR 0x8000 +#define BLZ1230_DMA_ADDR 0x10000 +#define BLZ1230II_ESP_ADDR 0x10000 +#define BLZ1230II_DMA_ADDR 0x10021 + + +/* The Blizzard 1230 DMA interface + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Only two things can be programmed in the Blizzard DMA: + * 1) The data direction is controlled by the status of bit 31 (1 = write) + * 2) The source/dest address (word aligned, shifted one right) in bits 30-0 + * + * Program DMA by first latching the highest byte of the address/direction + * (i.e. bits 31-24 of the long word constructed as described in steps 1+2 + * above). Then write each byte of the address/direction (starting with the + * top byte, working down) to the DMA address register. + * + * Figure out interrupt status by reading the ESP status byte. + */ +struct blz1230_dma_registers { + volatile unsigned char dma_addr; /* DMA address [0x0000] */ + unsigned char dmapad2[0x7fff]; + volatile unsigned char dma_latch; /* DMA latch [0x8000] */ +}; + +struct blz1230II_dma_registers { + volatile unsigned char dma_addr; /* DMA address [0x0000] */ + unsigned char dmapad2[0xf]; + volatile unsigned char dma_latch; /* DMA latch [0x0010] */ +}; + +#define BLZ1230_DMA_WRITE 0x80000000 + +extern int blz1230_esp_detect(struct SHT *); +extern const char *esp_info(struct Scsi_Host *); +extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +extern int esp_command(Scsi_Cmnd *); +extern int esp_abort(Scsi_Cmnd *); +extern int esp_reset(Scsi_Cmnd *, unsigned int); +extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, + int hostno, int inout); + +#define SCSI_BLZ1230 { \ +/* struct SHT *next */ NULL, \ +/* long *usage_count */ NULL, \ +/* struct proc_dir_entry *proc_dir */ &proc_scsi_esp, \ +/* int (*proc_info)(char *, char **, off_t, int, int, int) */ &esp_proc_info, \ +/* const char *name */ "Blizzard1230 SCSI IV", \ +/* int detect(struct SHT *) */ blz1230_esp_detect, \ +/* int release(struct Scsi_Host *) */ NULL, \ +/* const char *info(struct Scsi_Host *) */ esp_info, \ +/* int command(Scsi_Cmnd *) */ esp_command, \ +/* int queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ esp_queue, \ +/* int abort(Scsi_Cmnd *) */ esp_abort, \ +/* int reset(Scsi_Cmnd *) */ esp_reset, \ +/* int slave_attach(int, int) */ NULL, \ +/* int bios_param(Disk *, kdev_t, int[]) */ NULL, \ +/* int can_queue */ 7, \ +/* int this_id */ 7, \ +/* short unsigned int sg_tablesize */ SG_ALL, \ +/* short cmd_per_lun */ 1, \ +/* unsigned char present */ 0, \ +/* unsigned unchecked_isa_dma:1 */ 0, \ +/* unsigned use_clustering:1 */ DISABLE_CLUSTERING, } + +#endif /* BLZ1230_H */ diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/blz2060.c linux/drivers/scsi/blz2060.c --- v2.1.100/linux/drivers/scsi/blz2060.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/blz2060.c Fri May 8 00:22:11 1998 @@ -0,0 +1,232 @@ +/* blz2060.c: Driver for Blizzard 2060 SCSI Controller. + * + * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk) + * + * This driver is based on the CyberStorm driver, hence the occasional + * reference to CyberStorm. + */ + +/* TODO: + * + * 1) Figure out how to make a cleaner merge with the sparc driver with regard + * to the caches and the Sparc MMU mapping. + * 2) Make as few routines required outside the generic driver. A lot of the + * routines in this file used to be inline! + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "NCR53C9x.h" +#include "blz2060.h" + +#include +#include +#include +#include + +#include + +static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count); +static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp); +static void dma_dump_state(struct NCR_ESP *esp); +static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length); +static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length); +static void dma_ints_off(struct NCR_ESP *esp); +static void dma_ints_on(struct NCR_ESP *esp); +static int dma_irq_p(struct NCR_ESP *esp); +static void dma_led_off(struct NCR_ESP *esp); +static void dma_led_on(struct NCR_ESP *esp); +static int dma_ports_p(struct NCR_ESP *esp); +static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write); + +volatile unsigned char cmd_buffer[16]; + /* This is where all commands are put + * before they are trasfered to the ESP chip + * via PIO. + */ + +/***************************************************************** Detection */ +int blz2060_esp_detect(Scsi_Host_Template *tpnt) +{ + struct NCR_ESP *esp; + const struct ConfigDev *esp_dev; + unsigned int key; + unsigned long address; + + if ((key = zorro_find(ZORRO_PROD_PHASE5_BLIZZARD_2060, 0, 0))){ + esp_dev = zorro_get_board(key); + esp = esp_allocate(tpnt, (void *) esp_dev); + + /* Do command transfer with programmed I/O */ + esp->do_pio_cmds = 1; + + /* Required functions */ + esp->dma_bytes_sent = &dma_bytes_sent; + esp->dma_can_transfer = &dma_can_transfer; + esp->dma_dump_state = &dma_dump_state; + esp->dma_init_read = &dma_init_read; + esp->dma_init_write = &dma_init_write; + esp->dma_ints_off = &dma_ints_off; + esp->dma_ints_on = &dma_ints_on; + esp->dma_irq_p = &dma_irq_p; + esp->dma_ports_p = &dma_ports_p; + esp->dma_setup = &dma_setup; + + /* Optional functions */ + esp->dma_barrier = 0; + esp->dma_drain = 0; + esp->dma_invalidate = 0; + esp->dma_irq_entry = 0; + esp->dma_irq_exit = 0; + esp->dma_led_on = &dma_led_on; + esp->dma_led_off = &dma_led_off; + esp->dma_poll = 0; + esp->dma_reset = 0; + + /* SCSI chip speed */ + esp->cfreq = 40000000; + + /* The DMA registers on the Blizzard are mapped + * relative to the device (i.e. in the same Zorro + * I/O block). + */ + address = (unsigned long)ZTWO_VADDR(esp_dev->cd_BoardAddr); + esp->dregs = (void *)(address + BLZ2060_DMA_ADDR); + + /* ESP register base */ + esp->eregs = (struct ESP_regs *)(address + BLZ2060_ESP_ADDR); + + /* Set the command buffer */ + esp->esp_command_dvma = VTOP((unsigned long) cmd_buffer); + + esp->irq = IRQ_AMIGA_PORTS; + request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, + "Blizzard 2060 SCSI", esp_intr); + + /* Figure out our scsi ID on the bus */ + esp->scsi_id = 7; + + /* Check for differential SCSI-bus */ + /* What is this stuff? */ + esp->diff = 0; + + esp_initialize(esp); + + zorro_config_board(key, 0); + + printk("\nESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,esps_in_use); + esps_running = esps_in_use; + return esps_in_use; + } + return 0; +} + +/************************************************************* DMA Functions */ +static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count) +{ + /* Since the Blizzard DMA is fully dedicated to the ESP chip, + * the number of bytes sent (to the ESP chip) equals the number + * of bytes in the FIFO - there is no buffering in the DMA controller. + * XXXX Do I read this right? It is from host to ESP, right? + */ + return fifo_count; +} + +static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp) +{ + /* I don't think there's any limit on the Blizzard DMA. So we use what + * the ESP chip can handle (24 bit). + */ + unsigned long sz = sp->SCp.this_residual; + if(sz > 0x1000000) + sz = 0x1000000; + return sz; +} + +static void dma_dump_state(struct NCR_ESP *esp) +{ + ESPLOG(("intreq:<%04x>, intena:<%04x>\n", + custom.intreqr, custom.intenar)); +} + +static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) +{ + struct blz2060_dma_registers *dregs = + (struct blz2060_dma_registers *) (esp->dregs); + + cache_clear(addr, length); + + addr >>= 1; + addr &= ~(BLZ2060_DMA_WRITE); + dregs->dma_addr3 = (addr ) & 0xff; + dregs->dma_addr2 = (addr >> 8) & 0xff; + dregs->dma_addr1 = (addr >> 16) & 0xff; + dregs->dma_addr0 = (addr >> 24) & 0xff; +} + +static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length) +{ + struct blz2060_dma_registers *dregs = + (struct blz2060_dma_registers *) (esp->dregs); + + cache_push(addr, length); + + addr >>= 1; + addr |= BLZ2060_DMA_WRITE; + dregs->dma_addr3 = (addr ) & 0xff; + dregs->dma_addr2 = (addr >> 8) & 0xff; + dregs->dma_addr1 = (addr >> 16) & 0xff; + dregs->dma_addr0 = (addr >> 24) & 0xff; +} + +static void dma_ints_off(struct NCR_ESP *esp) +{ + disable_irq(esp->irq); +} + +static void dma_ints_on(struct NCR_ESP *esp) +{ + enable_irq(esp->irq); +} + +static int dma_irq_p(struct NCR_ESP *esp) +{ + return (esp->eregs->esp_status & ESP_STAT_INTR); +} + +static void dma_led_off(struct NCR_ESP *esp) +{ + ((struct blz2060_dma_registers *) (esp->dregs))->dma_led_ctrl = + BLZ2060_DMA_LED; +} + +static void dma_led_on(struct NCR_ESP *esp) +{ + ((struct blz2060_dma_registers *) (esp->dregs))->dma_led_ctrl = 0; +} + +static int dma_ports_p(struct NCR_ESP *esp) +{ + return ((custom.intenar) & IF_PORTS); +} + +static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) +{ + /* On the Sparc, DMA_ST_WRITE means "move data from device to memory" + * so when (write) is true, it actually means READ! + */ + if(write){ + dma_init_read(esp, addr, count); + } else { + dma_init_write(esp, addr, count); + } +} diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/blz2060.h linux/drivers/scsi/blz2060.h --- v2.1.100/linux/drivers/scsi/blz2060.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/blz2060.h Fri May 8 00:22:11 1998 @@ -0,0 +1,78 @@ +/* blz2060.h: Defines and structures for the Blizzard 2060 SCSI driver. + * + * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk) + * + * This file is based on cyber_esp.h (hence the occasional reference to + * CyberStorm). + */ + +#include "NCR53C9x.h" + +#ifndef BLZ2060_H +#define BLZ2060_H + +/* The controller registers can be found in the Z2 config area at these + * offsets: + */ +#define BLZ2060_ESP_ADDR 0x1ff00 +#define BLZ2060_DMA_ADDR 0x1ffe0 + + +/* The Blizzard 2060 DMA interface + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Only two things can be programmed in the Blizzard DMA: + * 1) The data direction is controlled by the status of bit 31 (1 = write) + * 2) The source/dest address (word aligned, shifted one right) in bits 30-0 + * + * Figure out interrupt status by reading the ESP status byte. + */ +struct blz2060_dma_registers { + volatile unsigned char dma_led_ctrl; /* DMA led control [0x000] */ + unsigned char dmapad1[0x0f]; + volatile unsigned char dma_addr0; /* DMA address (MSB) [0x010] */ + unsigned char dmapad2[0x03]; + volatile unsigned char dma_addr1; /* DMA address [0x014] */ + unsigned char dmapad3[0x03]; + volatile unsigned char dma_addr2; /* DMA address [0x018] */ + unsigned char dmapad4[0x03]; + volatile unsigned char dma_addr3; /* DMA address (LSB) [0x01c] */ +}; + +#define BLZ2060_DMA_WRITE 0x80000000 + +/* DMA control bits */ +#define BLZ2060_DMA_LED 0x02 /* HD led control 1 = off */ + +extern int blz2060_esp_detect(struct SHT *); +extern const char *esp_info(struct Scsi_Host *); +extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +extern int esp_command(Scsi_Cmnd *); +extern int esp_abort(Scsi_Cmnd *); +extern int esp_reset(Scsi_Cmnd *, unsigned int); +extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, + int hostno, int inout); + +#define SCSI_BLZ2060 { \ +/* struct SHT *next */ NULL, \ +/* long *usage_count */ NULL, \ +/* struct proc_dir_entry *proc_dir */ &proc_scsi_esp, \ +/* int (*proc_info)(char *, char **, off_t, int, int, int) */ &esp_proc_info, \ +/* const char *name */ "Blizzard2060 SCSI", \ +/* int detect(struct SHT *) */ blz2060_esp_detect, \ +/* int release(struct Scsi_Host *) */ NULL, \ +/* const char *info(struct Scsi_Host *) */ esp_info, \ +/* int command(Scsi_Cmnd *) */ esp_command, \ +/* int queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ esp_queue, \ +/* int abort(Scsi_Cmnd *) */ esp_abort, \ +/* int reset(Scsi_Cmnd *) */ esp_reset, \ +/* int slave_attach(int, int) */ NULL, \ +/* int bios_param(Disk *, kdev_t, int[]) */ NULL, \ +/* int can_queue */ 7, \ +/* int this_id */ 7, \ +/* short unsigned int sg_tablesize */ SG_ALL, \ +/* short cmd_per_lun */ 1, \ +/* unsigned char present */ 0, \ +/* unsigned unchecked_isa_dma:1 */ 0, \ +/* unsigned use_clustering:1 */ DISABLE_CLUSTERING, } + +#endif /* BLZ2060_H */ diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/cyberstorm.c linux/drivers/scsi/cyberstorm.c --- v2.1.100/linux/drivers/scsi/cyberstorm.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/cyberstorm.c Fri May 8 00:22:12 1998 @@ -0,0 +1,297 @@ +/* cyberstorm.c: Driver for CyberStorm SCSI Controller. + * + * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk) + * + * The CyberStorm SCSI driver is based on David S. Miller's ESP driver + * for the Sparc computers. + * + * This work was made possible by Phase5 who willingly (and most generously) + * supported me with hardware and all the information I needed. + */ + +/* TODO: + * + * 1) Figure out how to make a cleaner merge with the sparc driver with regard + * to the caches and the Sparc MMU mapping. + * 2) Make as few routines required outside the generic driver. A lot of the + * routines in this file used to be inline! + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "NCR53C9x.h" +#include "cyberstorm.h" + +#include +#include +#include +#include + +#include + +static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count); +static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp); +static void dma_dump_state(struct NCR_ESP *esp); +static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length); +static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length); +static void dma_ints_off(struct NCR_ESP *esp); +static void dma_ints_on(struct NCR_ESP *esp); +static int dma_irq_p(struct NCR_ESP *esp); +static void dma_led_off(struct NCR_ESP *esp); +static void dma_led_on(struct NCR_ESP *esp); +static int dma_ports_p(struct NCR_ESP *esp); +static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write); + +static unsigned char ctrl_data = 0; /* Keep backup of the stuff written + * to ctrl_reg. Always write a copy + * to this register when writing to + * the hardware register! + */ + +volatile unsigned char cmd_buffer[16]; + /* This is where all commands are put + * before they are trasfered to the ESP chip + * via PIO. + */ + +/***************************************************************** Detection */ +int cyber_esp_detect(Scsi_Host_Template *tpnt) +{ + struct NCR_ESP *esp; + const struct ConfigDev *esp_dev; + unsigned int key; + unsigned long address; + + + if ((key = zorro_find(ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM, 0, 0)) || + (key = zorro_find(ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060, 0, 0))){ + esp_dev = zorro_get_board(key); + + /* Figure out if this is a CyberStorm or really a + * Fastlane/Blizzard Mk II by looking at the board size. + * CyberStorm maps 64kB + * (ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM does anyway) + */ + if((unsigned long)esp_dev->cd_BoardSize != 0x10000) + return 0; + + esp = esp_allocate(tpnt, (void *) esp_dev); + + /* Do command transfer with programmed I/O */ + esp->do_pio_cmds = 1; + + /* Required functions */ + esp->dma_bytes_sent = &dma_bytes_sent; + esp->dma_can_transfer = &dma_can_transfer; + esp->dma_dump_state = &dma_dump_state; + esp->dma_init_read = &dma_init_read; + esp->dma_init_write = &dma_init_write; + esp->dma_ints_off = &dma_ints_off; + esp->dma_ints_on = &dma_ints_on; + esp->dma_irq_p = &dma_irq_p; + esp->dma_ports_p = &dma_ports_p; + esp->dma_setup = &dma_setup; + + /* Optional functions */ + esp->dma_barrier = 0; + esp->dma_drain = 0; + esp->dma_invalidate = 0; + esp->dma_irq_entry = 0; + esp->dma_irq_exit = 0; + esp->dma_led_on = &dma_led_on; + esp->dma_led_off = &dma_led_off; + esp->dma_poll = 0; + esp->dma_reset = 0; + + /* SCSI chip speed */ + esp->cfreq = 40000000; + + /* The DMA registers on the CyberStorm are mapped + * relative to the device (i.e. in the same Zorro + * I/O block). + */ + address = (unsigned long)ZTWO_VADDR(esp_dev->cd_BoardAddr); + esp->dregs = (void *)(address + CYBER_DMA_ADDR); + + /* ESP register base */ + esp->eregs = (struct ESP_regs *)(address + CYBER_ESP_ADDR); + + /* Set the command buffer */ + esp->esp_command_dvma = VTOP((unsigned long) cmd_buffer); + + esp->irq = IRQ_AMIGA_PORTS; + request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, + "CyberStorm SCSI", esp_intr); + /* Figure out our scsi ID on the bus */ + /* The DMA cond flag contains a hardcoded jumper bit + * which can be used to select host number 6 or 7. + * However, even though it may change, we use a hardcoded + * value of 7. + */ + esp->scsi_id = 7; + + /* Check for differential SCSI-bus */ + /* What is this stuff? */ + esp->diff = 0; + + esp_initialize(esp); + + zorro_config_board(key, 0); + + printk("\nESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,esps_in_use); + esps_running = esps_in_use; + return esps_in_use; + } + return 0; +} + +/************************************************************* DMA Functions */ +static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count) +{ + /* Since the CyberStorm DMA is fully dedicated to the ESP chip, + * the number of bytes sent (to the ESP chip) equals the number + * of bytes in the FIFO - there is no buffering in the DMA controller. + * XXXX Do I read this right? It is from host to ESP, right? + */ + return fifo_count; +} + +static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp) +{ + /* I don't think there's any limit on the CyberDMA. So we use what + * the ESP chip can handle (24 bit). + */ + unsigned long sz = sp->SCp.this_residual; + if(sz > 0x1000000) + sz = 0x1000000; + return sz; +} + +static void dma_dump_state(struct NCR_ESP *esp) +{ + ESPLOG(("esp%d: dma -- cond_reg<%02x>\n", + esp->esp_id, ((struct cyber_dma_registers *) + (esp->dregs))->cond_reg)); + ESPLOG(("intreq:<%04x>, intena:<%04x>\n", + custom.intreqr, custom.intenar)); +} + +static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) +{ + struct cyber_dma_registers *dregs = + (struct cyber_dma_registers *) esp->dregs; + + cache_clear(addr, length); + + addr &= ~(1); + dregs->dma_addr0 = (addr >> 24) & 0xff; + dregs->dma_addr1 = (addr >> 16) & 0xff; + dregs->dma_addr2 = (addr >> 8) & 0xff; + dregs->dma_addr3 = (addr ) & 0xff; + ctrl_data &= ~(CYBER_DMA_WRITE); + + /* Check if physical address is outside Z2 space and of + * block length/block aligned in memory. If this is the + * case, enable 32 bit transfer. In all other cases, fall back + * to 16 bit transfer. + * Obviously 32 bit transfer should be enabled if the DMA address + * and length are 32 bit aligned. However, this leads to some + * strange behavior. Even 64 bit aligned addr/length fails. + * Until I've found a reason for this, 32 bit transfer is only + * used for full-block transfers (1kB). + * -jskov + */ +#if 0 + if((addr & 0x3fc) || length & 0x3ff || ((addr > 0x200000) && + (addr < 0xff0000))) + ctrl_data &= ~(CYBER_DMA_Z3); /* Z2, do 16 bit DMA */ + else + ctrl_data |= CYBER_DMA_Z3; /* CHIP/Z3, do 32 bit DMA */ +#else + ctrl_data &= ~(CYBER_DMA_Z3); /* Z2, do 16 bit DMA */ +#endif + dregs->ctrl_reg = ctrl_data; +} + +static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length) +{ + struct cyber_dma_registers *dregs = + (struct cyber_dma_registers *) esp->dregs; + + cache_push(addr, length); + + addr |= 1; + dregs->dma_addr0 = (addr >> 24) & 0xff; + dregs->dma_addr1 = (addr >> 16) & 0xff; + dregs->dma_addr2 = (addr >> 8) & 0xff; + dregs->dma_addr3 = (addr ) & 0xff; + ctrl_data |= CYBER_DMA_WRITE; + + /* See comment above */ +#if 0 + if((addr & 0x3fc) || length & 0x3ff || ((addr > 0x200000) && + (addr < 0xff0000))) + ctrl_data &= ~(CYBER_DMA_Z3); /* Z2, do 16 bit DMA */ + else + ctrl_data |= CYBER_DMA_Z3; /* CHIP/Z3, do 32 bit DMA */ +#else + ctrl_data &= ~(CYBER_DMA_Z3); /* Z2, do 16 bit DMA */ +#endif + dregs->ctrl_reg = ctrl_data; +} + +static void dma_ints_off(struct NCR_ESP *esp) +{ + disable_irq(esp->irq); +} + +static void dma_ints_on(struct NCR_ESP *esp) +{ + enable_irq(esp->irq); +} + +static int dma_irq_p(struct NCR_ESP *esp) +{ + /* It's important to check the DMA IRQ bit in the correct way! */ + return ((esp->eregs->esp_status & ESP_STAT_INTR) && + ((((struct cyber_dma_registers *)(esp->dregs))->cond_reg) & + CYBER_DMA_HNDL_INTR)); +} + +static void dma_led_off(struct NCR_ESP *esp) +{ + ctrl_data &= ~CYBER_DMA_LED; + ((struct cyber_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data; +} + +static void dma_led_on(struct NCR_ESP *esp) +{ + ctrl_data |= CYBER_DMA_LED; + ((struct cyber_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data; +} + +static int dma_ports_p(struct NCR_ESP *esp) +{ + return ((custom.intenar) & IF_PORTS); +} + +static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) +{ + /* On the Sparc, DMA_ST_WRITE means "move data from device to memory" + * so when (write) is true, it actually means READ! + */ + if(write){ + dma_init_read(esp, addr, count); + } else { + dma_init_write(esp, addr, count); + } +} diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/cyberstorm.h linux/drivers/scsi/cyberstorm.h --- v2.1.100/linux/drivers/scsi/cyberstorm.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/cyberstorm.h Fri May 8 00:22:12 1998 @@ -0,0 +1,82 @@ +/* cyberstorm.h: Defines and structures for the CyberStorm SCSI driver. + * + * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk) + */ + +#include "NCR53C9x.h" + +#ifndef CYBER_ESP_H +#define CYBER_ESP_H + +/* The controller registers can be found in the Z2 config area at these + * offsets: + */ +#define CYBER_ESP_ADDR 0xf400 +#define CYBER_DMA_ADDR 0xf800 + + +/* The CyberStorm DMA interface */ +struct cyber_dma_registers { + volatile unsigned char dma_addr0; /* DMA address (MSB) [0x000] */ + unsigned char dmapad1[1]; + volatile unsigned char dma_addr1; /* DMA address [0x002] */ + unsigned char dmapad2[1]; + volatile unsigned char dma_addr2; /* DMA address [0x004] */ + unsigned char dmapad3[1]; + volatile unsigned char dma_addr3; /* DMA address (LSB) [0x006] */ + unsigned char dmapad4[0x3fb]; + volatile unsigned char cond_reg; /* DMA cond (ro) [0x402] */ +#define ctrl_reg cond_reg /* DMA control (wo) [0x402] */ +}; + +/* DMA control bits */ +#define CYBER_DMA_LED 0x80 /* HD led control 1 = on */ +#define CYBER_DMA_WRITE 0x40 /* DMA direction. 1 = write */ +#define CYBER_DMA_Z3 0x20 /* 16 (Z2) or 32 (CHIP/Z3) bit DMA transfer */ + +/* DMA status bits */ +#define CYBER_DMA_HNDL_INTR 0x80 /* DMA IRQ pending? */ + +/* The bits below appears to be Phase5 Debug bits only; they were not + * described by Phase5 so using them may seem a bit stupid... + */ +#define CYBER_HOST_ID 0x02 /* If set, host ID should be 7, otherwise + * it should be 6. + */ +#define CYBER_SLOW_CABLE 0x08 /* If *not* set, assume SLOW_CABLE */ + +extern int cyber_esp_detect(struct SHT *); +extern const char *esp_info(struct Scsi_Host *); +extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +extern int esp_command(Scsi_Cmnd *); +extern int esp_abort(Scsi_Cmnd *); +extern int esp_reset(Scsi_Cmnd *, unsigned int); +extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, + int hostno, int inout); + + +#define SCSI_CYBERSTORM { \ +/* struct SHT *next */ NULL, \ +/* long *usage_count */ NULL, \ +/* struct proc_dir_entry *proc_dir */ &proc_scsi_esp, \ +/* int (*proc_info)(char *, char **, off_t, int, int, int) */ &esp_proc_info, \ +/* const char *name */ "CyberStorm SCSI", \ +/* int detect(struct SHT *) */ cyber_esp_detect, \ +/* int release(struct Scsi_Host *) */ NULL, \ +/* const char *info(struct Scsi_Host *) */ esp_info, \ +/* int command(Scsi_Cmnd *) */ esp_command, \ +/* int queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ esp_queue, \ +/* int abort(Scsi_Cmnd *) */ esp_abort, \ +/* int reset(Scsi_Cmnd *) */ esp_reset, \ +/* int slave_attach(int, int) */ NULL, \ +/* int bios_param(Disk *, kdev_t, int[]) */ NULL, \ +/* int can_queue */ 7, \ +/* int this_id */ 7, \ +/* short unsigned int sg_tablesize */ SG_ALL, \ +/* short cmd_per_lun */ 1, \ +/* unsigned char present */ 0, \ +/* unsigned unchecked_isa_dma:1 */ 0, \ +/* unsigned use_clustering:1 */ DISABLE_CLUSTERING, } + +#endif /* CYBER_ESP_H */ + diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/cyberstormII.c linux/drivers/scsi/cyberstormII.c --- v2.1.100/linux/drivers/scsi/cyberstormII.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/cyberstormII.c Fri May 8 00:22:12 1998 @@ -0,0 +1,244 @@ +/* cyberstormII.c: Driver for CyberStorm SCSI Mk II + * + * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk) + * + * This driver is based on cyberstorm.c + */ + +/* TODO: + * + * 1) Figure out how to make a cleaner merge with the sparc driver with regard + * to the caches and the Sparc MMU mapping. + * 2) Make as few routines required outside the generic driver. A lot of the + * routines in this file used to be inline! + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "NCR53C9x.h" +#include "cyberstormII.h" + +#include +#include +#include +#include + +#include + +static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count); +static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp); +static void dma_dump_state(struct NCR_ESP *esp); +static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length); +static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length); +static void dma_ints_off(struct NCR_ESP *esp); +static void dma_ints_on(struct NCR_ESP *esp); +static int dma_irq_p(struct NCR_ESP *esp); +static void dma_led_off(struct NCR_ESP *esp); +static void dma_led_on(struct NCR_ESP *esp); +static int dma_ports_p(struct NCR_ESP *esp); +static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write); + +volatile unsigned char cmd_buffer[16]; + /* This is where all commands are put + * before they are transfered to the ESP chip + * via PIO. + */ + +/***************************************************************** Detection */ +int cyberII_esp_detect(Scsi_Host_Template *tpnt) +{ + struct NCR_ESP *esp; + const struct ConfigDev *esp_dev; + unsigned int key; + unsigned long address; + struct ESP_regs *eregs; + + if((key = zorro_find(ZORRO_PROD_PHASE5_CYBERSTORM_MK_II, 0, 0))){ + esp_dev = zorro_get_board(key); + + /* Do some magic to figure out if the CyberStorm Mk II + * is equipped with a SCSI controller + */ + address = (unsigned long)ZTWO_VADDR(esp_dev->cd_BoardAddr); + eregs = (struct ESP_regs *)(address + CYBERII_ESP_ADDR); + + eregs->esp_cfg1 = (ESP_CONFIG1_PENABLE | 7); + udelay(5); + if(eregs->esp_cfg1 != (ESP_CONFIG1_PENABLE | 7)) + return 0; /* Bail out if address did not hold data */ + + esp = esp_allocate(tpnt, (void *) esp_dev); + + /* Do command transfer with programmed I/O */ + esp->do_pio_cmds = 1; + + /* Required functions */ + esp->dma_bytes_sent = &dma_bytes_sent; + esp->dma_can_transfer = &dma_can_transfer; + esp->dma_dump_state = &dma_dump_state; + esp->dma_init_read = &dma_init_read; + esp->dma_init_write = &dma_init_write; + esp->dma_ints_off = &dma_ints_off; + esp->dma_ints_on = &dma_ints_on; + esp->dma_irq_p = &dma_irq_p; + esp->dma_ports_p = &dma_ports_p; + esp->dma_setup = &dma_setup; + + /* Optional functions */ + esp->dma_barrier = 0; + esp->dma_drain = 0; + esp->dma_invalidate = 0; + esp->dma_irq_entry = 0; + esp->dma_irq_exit = 0; + esp->dma_led_on = &dma_led_on; + esp->dma_led_off = &dma_led_off; + esp->dma_poll = 0; + esp->dma_reset = 0; + + /* SCSI chip speed */ + esp->cfreq = 40000000; + + /* The DMA registers on the CyberStorm are mapped + * relative to the device (i.e. in the same Zorro + * I/O block). + */ + esp->dregs = (void *)(address + CYBERII_DMA_ADDR); + + /* ESP register base */ + esp->eregs = eregs; + + /* Set the command buffer */ + esp->esp_command_dvma = VTOP((unsigned long) cmd_buffer); + + esp->irq = IRQ_AMIGA_PORTS; + request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, + "CyberStorm SCSI Mk II", esp_intr); + + /* Figure out our scsi ID on the bus */ + esp->scsi_id = 7; + + /* Check for differential SCSI-bus */ + /* What is this stuff? */ + esp->diff = 0; + + esp_initialize(esp); + + zorro_config_board(key, 0); + + printk("\nESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,esps_in_use); + esps_running = esps_in_use; + return esps_in_use; + } + return 0; +} + +/************************************************************* DMA Functions */ +static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count) +{ + /* Since the CyberStorm DMA is fully dedicated to the ESP chip, + * the number of bytes sent (to the ESP chip) equals the number + * of bytes in the FIFO - there is no buffering in the DMA controller. + * XXXX Do I read this right? It is from host to ESP, right? + */ + return fifo_count; +} + +static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp) +{ + /* I don't think there's any limit on the CyberDMA. So we use what + * the ESP chip can handle (24 bit). + */ + unsigned long sz = sp->SCp.this_residual; + if(sz > 0x1000000) + sz = 0x1000000; + return sz; +} + +static void dma_dump_state(struct NCR_ESP *esp) +{ + ESPLOG(("esp%d: dma -- cond_reg<%02x>\n", + esp->esp_id, ((struct cyberII_dma_registers *) + (esp->dregs))->cond_reg)); + ESPLOG(("intreq:<%04x>, intena:<%04x>\n", + custom.intreqr, custom.intenar)); +} + +static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) +{ + struct cyberII_dma_registers *dregs = + (struct cyberII_dma_registers *) esp->dregs; + + cache_clear(addr, length); + + addr &= ~(1); + dregs->dma_addr0 = (addr >> 24) & 0xff; + dregs->dma_addr1 = (addr >> 16) & 0xff; + dregs->dma_addr2 = (addr >> 8) & 0xff; + dregs->dma_addr3 = (addr ) & 0xff; +} + +static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length) +{ + struct cyberII_dma_registers *dregs = + (struct cyberII_dma_registers *) esp->dregs; + + cache_push(addr, length); + + addr |= 1; + dregs->dma_addr0 = (addr >> 24) & 0xff; + dregs->dma_addr1 = (addr >> 16) & 0xff; + dregs->dma_addr2 = (addr >> 8) & 0xff; + dregs->dma_addr3 = (addr ) & 0xff; +} + +static void dma_ints_off(struct NCR_ESP *esp) +{ + disable_irq(esp->irq); +} + +static void dma_ints_on(struct NCR_ESP *esp) +{ + enable_irq(esp->irq); +} + +static int dma_irq_p(struct NCR_ESP *esp) +{ + /* It's important to check the DMA IRQ bit in the correct way! */ + return (esp->eregs->esp_status & ESP_STAT_INTR); +} + +static void dma_led_off(struct NCR_ESP *esp) +{ + ((struct cyberII_dma_registers *)(esp->dregs))->ctrl_reg &= ~CYBERII_DMA_LED; +} + +static void dma_led_on(struct NCR_ESP *esp) +{ + ((struct cyberII_dma_registers *)(esp->dregs))->ctrl_reg |= CYBERII_DMA_LED; +} + +static int dma_ports_p(struct NCR_ESP *esp) +{ + return ((custom.intenar) & IF_PORTS); +} + +static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) +{ + /* On the Sparc, DMA_ST_WRITE means "move data from device to memory" + * so when (write) is true, it actually means READ! + */ + if(write){ + dma_init_read(esp, addr, count); + } else { + dma_init_write(esp, addr, count); + } +} diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/cyberstormII.h linux/drivers/scsi/cyberstormII.h --- v2.1.100/linux/drivers/scsi/cyberstormII.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/cyberstormII.h Fri May 8 00:22:12 1998 @@ -0,0 +1,69 @@ +/* cyberstormII.h: Defines and structures for the CyberStorm SCSI Mk II driver. + * + * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk) + */ + +#include "NCR53C9x.h" + +#ifndef CYBERII_ESP_H +#define CYBERII_ESP_H + +/* The controller registers can be found in the Z2 config area at these + * offsets: + */ +#define CYBERII_ESP_ADDR 0x1ff03 +#define CYBERII_DMA_ADDR 0x1ff43 + + +/* The CyberStorm II DMA interface */ +struct cyberII_dma_registers { + volatile unsigned char cond_reg; /* DMA cond (ro) [0x000] */ +#define ctrl_reg cond_reg /* DMA control (wo) [0x000] */ + unsigned char dmapad4[0x3f]; + volatile unsigned char dma_addr0; /* DMA address (MSB) [0x040] */ + unsigned char dmapad1[3]; + volatile unsigned char dma_addr1; /* DMA address [0x044] */ + unsigned char dmapad2[3]; + volatile unsigned char dma_addr2; /* DMA address [0x048] */ + unsigned char dmapad3[3]; + volatile unsigned char dma_addr3; /* DMA address (LSB) [0x04c] */ +}; + +/* DMA control bits */ +#define CYBERII_DMA_LED 0x02 /* HD led control 1 = on */ + + +extern int cyberII_esp_detect(struct SHT *); +extern const char *esp_info(struct Scsi_Host *); +extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +extern int esp_command(Scsi_Cmnd *); +extern int esp_abort(Scsi_Cmnd *); +extern int esp_reset(Scsi_Cmnd *, unsigned int); +extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, + int hostno, int inout); + +#define SCSI_CYBERSTORMII { \ +/* struct SHT *next */ NULL, \ +/* long *usage_count */ NULL, \ +/* struct proc_dir_entry *proc_dir */ &proc_scsi_esp, \ +/* int (*proc_info)(char *, char **, off_t, int, int, int) */ &esp_proc_info, \ +/* const char *name */ "CyberStorm Mk II SCSI", \ +/* int detect(struct SHT *) */ cyberII_esp_detect, \ +/* int release(struct Scsi_Host *) */ NULL, \ +/* const char *info(struct Scsi_Host *) */ esp_info, \ +/* int command(Scsi_Cmnd *) */ esp_command, \ +/* int queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ esp_queue, \ +/* int abort(Scsi_Cmnd *) */ esp_abort, \ +/* int reset(Scsi_Cmnd *) */ esp_reset, \ +/* int slave_attach(int, int) */ NULL, \ +/* int bios_param(Disk *, kdev_t, int[]) */ NULL, \ +/* int can_queue */ 7, \ +/* int this_id */ 7, \ +/* short unsigned int sg_tablesize */ SG_ALL, \ +/* short cmd_per_lun */ 1, \ +/* unsigned char present */ 0, \ +/* unsigned unchecked_isa_dma:1 */ 0, \ +/* unsigned use_clustering:1 */ DISABLE_CLUSTERING, } + +#endif /* CYBERII_ESP_H */ + diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/esp.c linux/drivers/scsi/esp.c --- v2.1.100/linux/drivers/scsi/esp.c Tue Apr 14 14:29:22 1998 +++ linux/drivers/scsi/esp.c Fri May 8 00:22:12 1998 @@ -173,7 +173,9 @@ /* Forward declarations. */ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs); -static void do_esp_intr(int irq, void *dev_id, struct pt_regs *pregs); +#ifndef __sparc_v9__ +static void esp_intr_4d(int irq, void *dev_id, struct pt_regs *pregs); +#endif /* Debugging routines */ struct esp_cmdstrings { @@ -641,25 +643,385 @@ trash = eregs->esp_intrpt; } -/* Detecting ESP chips on the machine. This is the simple and easy - * version. - */ -__initfunc(int esp_detect(Scsi_Host_Template *tpnt)) +__initfunc(int detect_one_esp +(Scsi_Host_Template *tpnt, struct linux_sbus_device *esp_dev, struct linux_sbus_device *espdma, + struct linux_sbus *sbus, int id, int hme)) { -#ifdef __sparc_v9__ struct devid_cookie dcookie; -#endif struct Sparc_ESP *esp, *elink; struct Scsi_Host *esp_host; - struct linux_sbus *sbus; - struct linux_sbus_device *esp_dev, *sbdev_iter; struct Sparc_ESP_regs *eregs; struct sparc_dma_registers *dregs; struct Linux_SBus_DMA *dma, *dlink; unsigned int fmhz; unchar ccf, bsizes, bsizes_more; - int nesps = 0, esps_in_use = 0; int esp_node, i; + + esp_host = scsi_register(tpnt, sizeof(struct Sparc_ESP)); + if(!esp_host) + panic("Cannot register ESP SCSI host"); + if(hme) + esp_host->max_id = 16; + esp = (struct Sparc_ESP *) esp_host->hostdata; + if(!esp) + panic("No esp in hostdata"); + esp->ehost = esp_host; + esp->edev = esp_dev; + esp->esp_id = id; + + /* Put into the chain of esp chips detected */ + if(espchain) { + elink = espchain; + while(elink->next) elink = elink->next; + elink->next = esp; + } else { + espchain = esp; + } + esp->next = 0; + + /* Get misc. prom information */ +#define ESP_IS_MY_DVMA(esp, dma) \ + (!dma->SBus_dev || \ + ((esp->edev->my_bus == dma->SBus_dev->my_bus) && \ + (esp->edev->slot == dma->SBus_dev->slot) && \ + (!strcmp(dma->SBus_dev->prom_name, "dma") || \ + !strcmp(dma->SBus_dev->prom_name, "espdma")))) + + esp_node = esp_dev->prom_node; + prom_getstring(esp_node, "name", esp->prom_name, + sizeof(esp->prom_name)); + esp->prom_node = esp_node; + if(espdma) { + for_each_dvma(dlink) { + if(dlink->SBus_dev == espdma) + break; + } + } else { + for_each_dvma(dlink) { + if(ESP_IS_MY_DVMA(esp, dlink) && + !dlink->allocated) + break; + } + } +#undef ESP_IS_MY_DVMA + /* If we don't know how to handle the dvma, + * do not use this device. + */ + if(!dlink){ + printk ("Cannot find dvma for ESP%d's SCSI\n", + esp->esp_id); + scsi_unregister (esp_host); + return -1; + } + if (dlink->allocated){ + printk ("esp%d: can't use my espdma\n", + esp->esp_id); + scsi_unregister (esp_host); + return -1; + } + dlink->allocated = 1; + dma = dlink; + esp->dma = dma; + esp->dregs = dregs = dma->regs; + + /* Map in the ESP registers from I/O space */ + if(!hme) { + prom_apply_sbus_ranges(esp->edev->my_bus, + esp->edev->reg_addrs, + 1, esp->edev); + + esp->eregs = eregs = (struct Sparc_ESP_regs *) + sparc_alloc_io(esp->edev->reg_addrs[0].phys_addr, 0, + PAGE_SIZE, "ESP Registers", + esp->edev->reg_addrs[0].which_io, 0x0); + } else { + /* On HME, two reg sets exist, first is DVMA, + * second is ESP registers. + */ + esp->eregs = eregs = (struct Sparc_ESP_regs *) + sparc_alloc_io(esp->edev->reg_addrs[1].phys_addr, 0, + PAGE_SIZE, "ESP Registers", + esp->edev->reg_addrs[1].which_io, 0x0); + } + if(!eregs) + panic("ESP registers unmappable"); + esp->esp_command = + sparc_dvma_malloc(16, "ESP DVMA Cmd Block", + &esp->esp_command_dvma); + if(!esp->esp_command || !esp->esp_command_dvma) + panic("ESP DVMA transport area unmappable"); + + /* Set up the irq's etc. */ + esp->ehost->base = (unsigned char *) esp->eregs; + esp->ehost->io_port = + esp->edev->reg_addrs[0].phys_addr; + esp->ehost->n_io_port = (unsigned char) + esp->edev->reg_addrs[0].reg_size; + esp->ehost->irq = esp->irq = esp->edev->irqs[0].pri; + +#ifndef __sparc_v9__ + if (sparc_cpu_model != sun4d) { + /* Allocate the irq only if necessary */ + for_each_esp(elink) { + if((elink != esp) && (esp->irq == elink->irq)) { + goto esp_irq_acquired; /* BASIC rulez */ + } + } + if(request_irq(esp->ehost->irq, esp_intr, SA_SHIRQ, + "Sparc ESP SCSI", NULL)) + panic("Cannot acquire ESP irq line"); +esp_irq_acquired: + printk("esp%d: IRQ %d ", esp->esp_id, esp->ehost->irq); + } else { + dcookie.real_dev_id = esp; + dcookie.bus_cookie = esp_dev; + if (request_irq(esp->ehost->irq, esp_intr_4d, + (SA_SHIRQ | SA_DCOOKIE), + "Sparc ESP SCSI", &dcookie)) + panic("Cannot acquire ESP irq line"); + printk("esp%d: INO[%x] IRQ %d ", esp->esp_id, dcookie.ret_ino, esp->ehost->irq); + esp->ehost->irq = esp->irq = dcookie.ret_ino; + } +#else + /* On Ultra we must always call request_irq for each + * esp, so that imap registers get setup etc. + */ + dcookie.real_dev_id = esp; + dcookie.imap = dcookie.iclr = 0; + dcookie.pil = -1; + dcookie.bus_cookie = sbus; + if(request_irq(esp->ehost->irq, esp_intr, + (SA_SHIRQ | SA_SBUS | SA_DCOOKIE), + "Sparc ESP SCSI", &dcookie)) + panic("Cannot acquire ESP irq line"); + esp->ehost->irq = esp->irq = dcookie.ret_ino; + printk("esp%d: INO[%x] IRQ %d ", + esp->esp_id, esp->ehost->irq, dcookie.ret_pil); +#endif + + /* Figure out our scsi ID on the bus */ + esp->scsi_id = prom_getintdefault(esp->prom_node, + "initiator-id", + -1); + if(esp->scsi_id == -1) + esp->scsi_id = prom_getintdefault(esp->prom_node, + "scsi-initiator-id", + -1); + if(esp->scsi_id == -1) + esp->scsi_id = (!esp->edev->my_bus) ? 7 : + prom_getintdefault(esp->edev->my_bus->prom_node, + "scsi-initiator-id", + 7); + esp->ehost->this_id = esp->scsi_id; + esp->scsi_id_mask = (1 << esp->scsi_id); + + /* Check for differential SCSI-bus */ + esp->diff = prom_getbool(esp->prom_node, "differential"); + if(esp->diff) + printk("Differential "); + + /* Check out the clock properties of the chip. */ + + /* This is getting messy but it has to be done + * correctly or else you get weird behavior all + * over the place. We are trying to basically + * figure out three pieces of information. + * + * a) Clock Conversion Factor + * + * This is a representation of the input + * crystal clock frequency going into the + * ESP on this machine. Any operation whose + * timing is longer than 400ns depends on this + * value being correct. For example, you'll + * get blips for arbitration/selection during + * high load or with multiple targets if this + * is not set correctly. + * + * b) Selection Time-Out + * + * The ESP isn't very bright and will arbitrate + * for the bus and try to select a target + * forever if you let it. This value tells + * the ESP when it has taken too long to + * negotiate and that it should interrupt + * the CPU so we can see what happened. + * The value is computed as follows (from + * NCR/Symbios chip docs). + * + * (Time Out Period) * (Input Clock) + * STO = ---------------------------------- + * (8192) * (Clock Conversion Factor) + * + * You usually want the time out period to be + * around 250ms, I think we'll set it a little + * bit higher to account for fully loaded SCSI + * bus's and slow devices that don't respond so + * quickly to selection attempts. (yeah, I know + * this is out of spec. but there is a lot of + * buggy pieces of firmware out there so bite me) + * + * c) Imperical constants for synchronous offset + * and transfer period register values + * + * This entails the smallest and largest sync + * period we could ever handle on this ESP. + */ + + fmhz = prom_getintdefault(esp->prom_node, + "clock-frequency", + -1); + if(fmhz==-1) + fmhz = (!esp->edev->my_bus) ? 0 : + prom_getintdefault(esp->edev->my_bus->prom_node, + "clock-frequency", + -1); + if(fmhz <= (5000000)) + ccf = 0; + else + ccf = (((5000000 - 1) + (fmhz))/(5000000)); + if(!ccf || ccf > 8) { + /* If we can't find anything reasonable, + * just assume 20MHZ. This is the clock + * frequency of the older sun4c's where I've + * been unable to find the clock-frequency + * PROM property. All other machines provide + * useful values it seems. + */ + ccf = ESP_CCF_F4; + fmhz = (20000000); + } + if(ccf==(ESP_CCF_F7+1)) + esp->cfact = ESP_CCF_F0; + else if(ccf == ESP_CCF_NEVER) + esp->cfact = ESP_CCF_F2; + else + esp->cfact = ccf; + esp->cfreq = fmhz; + esp->ccycle = ESP_MHZ_TO_CYCLE(fmhz); + esp->ctick = ESP_TICK(ccf, esp->ccycle); + esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf); + esp->sync_defp = SYNC_DEFP_SLOW; + printk("SCSI ID %d Clock %d MHz CCF=%d Time-Out %d ", + esp->scsi_id, (fmhz / 1000000), + ccf, (int) esp->neg_defp); + + /* Find the burst sizes this dma/sbus/esp supports. */ + bsizes = prom_getintdefault(esp->prom_node, "burst-sizes", 0xff); + bsizes &= 0xff; + if(espdma) { + bsizes_more = prom_getintdefault( + espdma->prom_node, + "burst-sizes", 0xff); + if(bsizes_more != 0xff) + bsizes &= bsizes_more; + } + if (esp->edev->my_bus) { + bsizes_more = prom_getintdefault(esp->edev->my_bus->prom_node, + "burst-sizes", 0xff); + if(bsizes_more != 0xff) + bsizes &= bsizes_more; + } + + if(bsizes == 0xff || (bsizes & DMA_BURST16)==0 || + (bsizes & DMA_BURST32)==0) + bsizes = (DMA_BURST32 - 1); + + esp->bursts = bsizes; + + /* Probe the revision of this esp */ + esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7)); + esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY); + eregs->esp_cfg2 = esp->config2; + if((eregs->esp_cfg2 & ~(ESP_CONFIG2_MAGIC)) != + (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) { + printk("NCR53C90(esp100) detected\n"); + esp->erev = esp100; + } else { + eregs->esp_cfg2 = esp->config2 = 0; + eregs->esp_cfg3 = 0; + eregs->esp_cfg3 = esp->config3[0] = 5; + if(eregs->esp_cfg3 != 5) { + printk("NCR53C90A(esp100a) detected\n"); + esp->erev = esp100a; + } else { + int target; + + for(target=0; target<8; target++) + esp->config3[target] = 0; + eregs->esp_cfg3 = 0; + if(ccf > ESP_CCF_F5) { + printk("NCR53C9XF(espfast) detected\n"); + esp->erev = fast; + eregs->esp_cfg2 = esp->config2 = 0; + esp->sync_defp = SYNC_DEFP_FAST; + } else { + printk("NCR53C9x(esp236) detected\n"); + esp->erev = esp236; + eregs->esp_cfg2 = esp->config2 = 0; + } + } + } + + /* Initialize the command queues */ + esp->current_SC = 0; + esp->disconnected_SC = 0; + esp->issue_SC = 0; + + /* Clear the state machines. */ + esp->targets_present = 0; + esp->resetting_bus = 0; + esp->snip = 0; + esp->targets_present = 0; + for(i = 0; i < 32; i++) + esp->espcmdlog[i] = 0; + esp->espcmdent = 0; + for(i = 0; i < 16; i++) { + esp->cur_msgout[i] = 0; + esp->cur_msgin[i] = 0; + } + esp->prevmsgout = esp->prevmsgin = 0; + esp->msgout_len = esp->msgin_len = 0; + + /* Reset the thing before we try anything... */ + esp_bootup_reset(esp, eregs); + + return 0; +} + +/* Detecting ESP chips on the machine. This is the simple and easy + * version. + */ + +#ifdef CONFIG_SUN4 + +#include + +__initfunc(int esp_detect(Scsi_Host_Template *tpnt)) +{ + static struct linux_sbus_device esp_dev; + int esps_in_use = 0; + + espchain = 0; + + memset (&esp_dev, 0, sizeof(esp_dev)); + esp_dev.reg_addrs[0].phys_addr = SUN4_300_ESP_PHYSADDR; + esp_dev.irqs[0].pri = 4; + + if (!detect_one_esp(tpnt, &esp_dev, NULL, NULL, 0, 0)) + esps_in_use++; + printk("ESP: Total of 1 ESP hosts found, %d actually in use.\n", esps_in_use); + esps_running = esps_in_use; + return esps_in_use; +} + +#else /* !CONFIG_SUN4 */ + +__initfunc(int esp_detect(Scsi_Host_Template *tpnt)) +{ + struct linux_sbus *sbus; + struct linux_sbus_device *esp_dev, *sbdev_iter; + int nesps = 0, esps_in_use = 0; espchain = 0; if(!SBus_chain) { @@ -693,320 +1055,10 @@ continue; /* how can this happen? */ } } - esp_host = scsi_register(tpnt, sizeof(struct Sparc_ESP)); - if(!esp_host) - panic("Cannot register ESP SCSI host"); - if(hme) - esp_host->max_id = 16; - esp = (struct Sparc_ESP *) esp_host->hostdata; - if(!esp) - panic("No esp in hostdata"); - esp->ehost = esp_host; - esp->edev = esp_dev; - esp->esp_id = nesps++; - - /* Put into the chain of esp chips detected */ - if(espchain) { - elink = espchain; - while(elink->next) elink = elink->next; - elink->next = esp; - } else { - espchain = esp; - } - esp->next = 0; - - /* Get misc. prom information */ -#define ESP_IS_MY_DVMA(esp, dma) \ - ((esp->edev->my_bus == dma->SBus_dev->my_bus) && \ - (esp->edev->slot == dma->SBus_dev->slot) && \ - (!strcmp(dma->SBus_dev->prom_name, "dma") || \ - !strcmp(dma->SBus_dev->prom_name, "espdma"))) - - esp_node = esp_dev->prom_node; - prom_getstring(esp_node, "name", esp->prom_name, - sizeof(esp->prom_name)); - esp->prom_node = esp_node; - if(espdma) { - for_each_dvma(dlink) { - if(dlink->SBus_dev == espdma) - break; - } - } else { - for_each_dvma(dlink) { - if(ESP_IS_MY_DVMA(esp, dlink) && - !dlink->allocated) - break; - } - } -#undef ESP_IS_MY_DVMA - /* If we don't know how to handle the dvma, - * do not use this device. - */ - if(!dlink){ - printk ("Cannot find dvma for ESP%d's SCSI\n", - esp->esp_id); - scsi_unregister (esp_host); + + if (detect_one_esp(tpnt, esp_dev, espdma, sbus, nesps++, hme) < 0) continue; - } - if (dlink->allocated){ - printk ("esp%d: can't use my espdma\n", - esp->esp_id); - scsi_unregister (esp_host); - continue; - } - dlink->allocated = 1; - dma = dlink; - esp->dma = dma; - esp->dregs = dregs = dma->regs; - - /* Map in the ESP registers from I/O space */ - if(!hme) { - prom_apply_sbus_ranges(esp->edev->my_bus, - esp->edev->reg_addrs, - 1, esp->edev); - - esp->eregs = eregs = (struct Sparc_ESP_regs *) - sparc_alloc_io(esp->edev->reg_addrs[0].phys_addr, 0, - PAGE_SIZE, "ESP Registers", - esp->edev->reg_addrs[0].which_io, 0x0); - } else { - /* On HME, two reg sets exist, first is DVMA, - * second is ESP registers. - */ - esp->eregs = eregs = (struct Sparc_ESP_regs *) - sparc_alloc_io(esp->edev->reg_addrs[1].phys_addr, 0, - PAGE_SIZE, "ESP Registers", - esp->edev->reg_addrs[1].which_io, 0x0); - } - if(!eregs) - panic("ESP registers unmappable"); - esp->esp_command = - sparc_dvma_malloc(16, "ESP DVMA Cmd Block", - &esp->esp_command_dvma); - if(!esp->esp_command || !esp->esp_command_dvma) - panic("ESP DVMA transport area unmappable"); - - /* Set up the irq's etc. */ - esp->ehost->base = (unsigned char *) esp->eregs; - esp->ehost->io_port = - esp->edev->reg_addrs[0].phys_addr; - esp->ehost->n_io_port = (unsigned char) - esp->edev->reg_addrs[0].reg_size; - esp->ehost->irq = esp->irq = esp->edev->irqs[0].pri; - -#ifndef __sparc_v9__ - /* Allocate the irq only if necessary */ - for_each_esp(elink) { - if((elink != esp) && (esp->irq == elink->irq)) { - goto esp_irq_acquired; /* BASIC rulez */ - } - } - if(request_irq(esp->ehost->irq, do_esp_intr, SA_SHIRQ, - "Sparc ESP SCSI", NULL)) - panic("Cannot acquire ESP irq line"); -esp_irq_acquired: - printk("esp%d: IRQ %d ", esp->esp_id, esp->ehost->irq); -#else - /* On Ultra we must always call request_irq for each - * esp, so that imap registers get setup etc. - */ - dcookie.real_dev_id = esp; - dcookie.imap = dcookie.iclr = 0; - dcookie.pil = -1; - dcookie.bus_cookie = sbus; - if(request_irq(esp->ehost->irq, do_esp_intr, - (SA_SHIRQ | SA_SBUS | SA_DCOOKIE), - "Sparc ESP SCSI", &dcookie)) - panic("Cannot acquire ESP irq line"); - esp->ehost->irq = esp->irq = dcookie.ret_ino; - printk("esp%d: INO[%x] IRQ %d ", - esp->esp_id, esp->ehost->irq, dcookie.ret_pil); -#endif - - /* Figure out our scsi ID on the bus */ - esp->scsi_id = prom_getintdefault(esp->prom_node, - "initiator-id", - -1); - if(esp->scsi_id == -1) - esp->scsi_id = prom_getintdefault(esp->prom_node, - "scsi-initiator-id", - -1); - if(esp->scsi_id == -1) - esp->scsi_id = - prom_getintdefault(esp->edev->my_bus->prom_node, - "scsi-initiator-id", - 7); - esp->ehost->this_id = esp->scsi_id; - esp->scsi_id_mask = (1 << esp->scsi_id); - - /* Check for differential SCSI-bus */ - esp->diff = prom_getbool(esp->prom_node, "differential"); - if(esp->diff) - printk("Differential "); - - /* Check out the clock properties of the chip. */ - - /* This is getting messy but it has to be done - * correctly or else you get weird behavior all - * over the place. We are trying to basically - * figure out three pieces of information. - * - * a) Clock Conversion Factor - * - * This is a representation of the input - * crystal clock frequency going into the - * ESP on this machine. Any operation whose - * timing is longer than 400ns depends on this - * value being correct. For example, you'll - * get blips for arbitration/selection during - * high load or with multiple targets if this - * is not set correctly. - * - * b) Selection Time-Out - * - * The ESP isn't very bright and will arbitrate - * for the bus and try to select a target - * forever if you let it. This value tells - * the ESP when it has taken too long to - * negotiate and that it should interrupt - * the CPU so we can see what happened. - * The value is computed as follows (from - * NCR/Symbios chip docs). - * - * (Time Out Period) * (Input Clock) - * STO = ---------------------------------- - * (8192) * (Clock Conversion Factor) - * - * You usually want the time out period to be - * around 250ms, I think we'll set it a little - * bit higher to account for fully loaded SCSI - * bus's and slow devices that don't respond so - * quickly to selection attempts. (yeah, I know - * this is out of spec. but there is a lot of - * buggy pieces of firmware out there so bite me) - * - * c) Imperical constants for synchronous offset - * and transfer period register values - * - * This entails the smallest and largest sync - * period we could ever handle on this ESP. - */ - - fmhz = prom_getintdefault(esp->prom_node, - "clock-frequency", - -1); - if(fmhz==-1) - fmhz = prom_getintdefault(esp->edev->my_bus->prom_node, - "clock-frequency", - -1); - if(fmhz <= (5000000)) - ccf = 0; - else - ccf = (((5000000 - 1) + (fmhz))/(5000000)); - if(!ccf || ccf > 8) { - /* If we can't find anything reasonable, - * just assume 20MHZ. This is the clock - * frequency of the older sun4c's where I've - * been unable to find the clock-frequency - * PROM property. All other machines provide - * useful values it seems. - */ - ccf = ESP_CCF_F4; - fmhz = (20000000); - } - if(ccf==(ESP_CCF_F7+1)) - esp->cfact = ESP_CCF_F0; - else if(ccf == ESP_CCF_NEVER) - esp->cfact = ESP_CCF_F2; - else - esp->cfact = ccf; - esp->cfreq = fmhz; - esp->ccycle = ESP_MHZ_TO_CYCLE(fmhz); - esp->ctick = ESP_TICK(ccf, esp->ccycle); - esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf); - esp->sync_defp = SYNC_DEFP_SLOW; - printk("SCSI ID %d Clock %d MHz CCF=%d Time-Out %d ", - esp->scsi_id, (fmhz / 1000000), - ccf, (int) esp->neg_defp); - - /* Find the burst sizes this dma/sbus/esp supports. */ - bsizes = prom_getintdefault(esp->prom_node, "burst-sizes", 0xff); - bsizes &= 0xff; - if(espdma) { - bsizes_more = prom_getintdefault( - espdma->prom_node, - "burst-sizes", 0xff); - if(bsizes_more != 0xff) - bsizes &= bsizes_more; - } - bsizes_more = prom_getintdefault(esp->edev->my_bus->prom_node, - "burst-sizes", 0xff); - if(bsizes_more != 0xff) - bsizes &= bsizes_more; - - if(bsizes == 0xff || (bsizes & DMA_BURST16)==0 || - (bsizes & DMA_BURST32)==0) - bsizes = (DMA_BURST32 - 1); - - esp->bursts = bsizes; - - /* Probe the revision of this esp */ - esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7)); - esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY); - eregs->esp_cfg2 = esp->config2; - if((eregs->esp_cfg2 & ~(ESP_CONFIG2_MAGIC)) != - (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) { - printk("NCR53C90(esp100) detected\n"); - esp->erev = esp100; - } else { - eregs->esp_cfg2 = esp->config2 = 0; - eregs->esp_cfg3 = 0; - eregs->esp_cfg3 = esp->config3[0] = 5; - if(eregs->esp_cfg3 != 5) { - printk("NCR53C90A(esp100a) detected\n"); - esp->erev = esp100a; - } else { - int target; - - for(target=0; target<8; target++) - esp->config3[target] = 0; - eregs->esp_cfg3 = 0; - if(ccf > ESP_CCF_F5) { - printk("NCR53C9XF(espfast) detected\n"); - esp->erev = fast; - eregs->esp_cfg2 = esp->config2 = 0; - esp->sync_defp = SYNC_DEFP_FAST; - } else { - printk("NCR53C9x(esp236) detected\n"); - esp->erev = esp236; - eregs->esp_cfg2 = esp->config2 = 0; - } - } - } - - /* Initialize the command queues */ - esp->current_SC = 0; - esp->disconnected_SC = 0; - esp->issue_SC = 0; - - /* Clear the state machines. */ - esp->targets_present = 0; - esp->resetting_bus = 0; - esp->snip = 0; - esp->targets_present = 0; - for(i = 0; i < 32; i++) - esp->espcmdlog[i] = 0; - esp->espcmdent = 0; - for(i = 0; i < 16; i++) { - esp->cur_msgout[i] = 0; - esp->cur_msgin[i] = 0; - } - esp->prevmsgout = esp->prevmsgin = 0; - esp->msgout_len = esp->msgin_len = 0; - - /* Reset the thing before we try anything... */ - esp_bootup_reset(esp, eregs); - + esps_in_use++; } /* for each sbusdev */ } /* for each sbus */ @@ -1016,6 +1068,8 @@ return esps_in_use; } +#endif /* !CONFIG_SUN4 */ + /* The info function will return whatever useful * information the developer sees fit. If not provided, then * the name field will be used instead. @@ -4040,24 +4094,17 @@ return; } -static void do_esp_intr(int irq, void *dev_id, struct pt_regs *pregs) -{ - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - esp_intr(irq, dev_id, pregs); - spin_unlock_irqrestore(&io_request_lock, flags); -} - #ifndef __sparc_v9__ #ifndef __SMP__ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs) { struct Sparc_ESP *esp; + unsigned long flags; int again; /* Handle all ESP interrupts showing at this IRQ level. */ + spin_lock_irqsave(&io_request_lock, flags); repeat: again = 0; for_each_esp(esp) { @@ -4077,14 +4124,17 @@ } if(again) goto repeat; + spin_unlock_irqrestore(&io_request_lock, flags); } #else /* For SMP we only service one ESP on the list list at our IRQ level! */ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs) { struct Sparc_ESP *esp; + unsigned long flags; /* Handle all ESP interrupts showing at this IRQ level. */ + spin_lock_irqsave(&io_request_lock, flags); for_each_esp(esp) { if(((esp)->irq & 0xf) == irq) { if(DMA_IRQ_P(esp->dregs)) { @@ -4096,19 +4146,41 @@ ESPIRQ((")")); DMA_INTSON(esp->dregs); - return; + goto out; } } } +out: + spin_unlock_irqrestore(&io_request_lock, flags); } #endif +static void esp_intr_4d(int irq, void *dev_id, struct pt_regs *pregs) +{ + struct Sparc_ESP *esp = dev_id; + unsigned long flags; + + spin_lock_irqsave(&io_request_lock, flags); + if(DMA_IRQ_P(esp->dregs)) { + DMA_INTSOFF(esp->dregs); + + ESPIRQ(("I[%d:%d](", smp_processor_id(), esp->esp_id)); + esp_handle(esp); + ESPIRQ((")")); + + DMA_INTSON(esp->dregs); + } + spin_unlock_irqrestore(&io_request_lock, flags); +} + #else /* __sparc_v9__ */ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs) { struct Sparc_ESP *esp = dev_id; + unsigned long flags; + spin_lock_irqsave(&io_request_lock, flags); if(DMA_IRQ_P(esp->dregs)) { DMA_INTSOFF(esp->dregs); @@ -4118,6 +4190,6 @@ DMA_INTSON(esp->dregs); } + spin_unlock_irqrestore(&io_request_lock, flags); } - #endif diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/fastlane.c linux/drivers/scsi/fastlane.c --- v2.1.100/linux/drivers/scsi/fastlane.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/fastlane.c Fri May 8 00:22:12 1998 @@ -0,0 +1,343 @@ +/* fastlane.c: Driver for Phase5's Fastlane SCSI Controller. + * + * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk) + * + * This driver is based on the CyberStorm driver, hence the occasional + * reference to CyberStorm. + * + * Betatesting & crucial adjustments by Patrik Rak + * (prak3264@ss1000.ms.mff.cuni.cz) + * + */ + +/* TODO: + * + * o According to the doc from laire, it is required to reset the DMA when + * the transfer is done. ATM we reset DMA just before every new + * dma_init_(read|write). + * + * 1) Figure out how to make a cleaner merge with the sparc driver with regard + * to the caches and the Sparc MMU mapping. + * 2) Make as few routines required outside the generic driver. A lot of the + * routines in this file used to be inline! + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "NCR53C9x.h" +#include "fastlane.h" + +#include +#include +#include +#include + +#include + +/* Let this defined unless you really need to enable DMA IRQ one day */ +#define NODMAIRQ + +static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count); +static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp); +static inline void dma_clear(struct NCR_ESP *esp); +static void dma_dump_state(struct NCR_ESP *esp); +static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length); +static void dma_init_write(struct NCR_ESP *esp, __u32 vaddr, int length); +static void dma_ints_off(struct NCR_ESP *esp); +static void dma_ints_on(struct NCR_ESP *esp); +static int dma_irq_p(struct NCR_ESP *esp); +static void dma_led_off(struct NCR_ESP *esp); +static void dma_led_on(struct NCR_ESP *esp); +static int dma_ports_p(struct NCR_ESP *esp); +static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write); + +static unsigned char ctrl_data = 0; /* Keep backup of the stuff written + * to ctrl_reg. Always write a copy + * to this register when writing to + * the hardware register! + */ + +volatile unsigned char cmd_buffer[16]; + /* This is where all commands are put + * before they are trasfered to the ESP chip + * via PIO. + */ + +/***************************************************************** Detection */ +int fastlane_esp_detect(Scsi_Host_Template *tpnt) +{ + struct NCR_ESP *esp; + const struct ConfigDev *esp_dev; + unsigned int key; + unsigned long address; + + if ((key = zorro_find(ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060, 0, 0))){ + + esp_dev = zorro_get_board(key); + + /* Check if this is really a fastlane controller. The problem + * is that also the cyberstorm and blizzard controllers use + * this ID value. Fortunately only Fastlane maps in Z3 space + */ + if((unsigned long)esp_dev->cd_BoardAddr < 0x1000000) + return 0; + + esp = esp_allocate(tpnt, (void *) esp_dev); + + /* Do command transfer with programmed I/O */ + esp->do_pio_cmds = 1; + + /* Required functions */ + esp->dma_bytes_sent = &dma_bytes_sent; + esp->dma_can_transfer = &dma_can_transfer; + esp->dma_dump_state = &dma_dump_state; + esp->dma_init_read = &dma_init_read; + esp->dma_init_write = &dma_init_write; + esp->dma_ints_off = &dma_ints_off; + esp->dma_ints_on = &dma_ints_on; + esp->dma_irq_p = &dma_irq_p; + esp->dma_ports_p = &dma_ports_p; + esp->dma_setup = &dma_setup; + + /* Optional functions */ + esp->dma_barrier = 0; + esp->dma_drain = 0; + esp->dma_invalidate = 0; + esp->dma_irq_entry = 0; + esp->dma_irq_exit = 0; + esp->dma_led_on = &dma_led_on; + esp->dma_led_off = &dma_led_off; + esp->dma_poll = 0; + esp->dma_reset = 0; + + /* Initialize the portBits (enable IRQs) */ + ctrl_data = (FASTLANE_DMA_FCODE | +#ifndef NODMAIRQ + FASTLANE_DMA_EDI | +#endif + FASTLANE_DMA_ESI); + + + /* SCSI chip clock */ + esp->cfreq = 40000000; + + + /* Map the physical address space into virtual kernel space */ + address = (unsigned long) + kernel_map((unsigned long)esp_dev->cd_BoardAddr, + esp_dev->cd_BoardSize, + KERNELMAP_NOCACHE_SER, + NULL); + + if(!address){ + printk("Could not remap Fastlane controller memory!"); + scsi_unregister (esp->ehost); + return 0; + } + + + /* The DMA registers on the Fastlane are mapped + * relative to the device (i.e. in the same Zorro + * I/O block). + */ + esp->dregs = (void *)(address + FASTLANE_DMA_ADDR); + + /* ESP register base */ + esp->eregs = (struct ESP_regs *)(address + FASTLANE_ESP_ADDR); + + /* Board base */ + esp->edev = (void *) address; + + /* Set the command buffer */ + esp->esp_command_dvma = VTOP((unsigned long) cmd_buffer); + + esp->irq = IRQ_AMIGA_PORTS; + request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, + "Fastlane SCSI", esp_intr); + + /* Controller ID */ + esp->scsi_id = 7; + + /* Check for differential SCSI-bus */ + /* What is this stuff? */ + esp->diff = 0; + + dma_clear(esp); + esp_initialize(esp); + + zorro_config_board(key, 0); + + printk("\nESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,esps_in_use); + esps_running = esps_in_use; + return esps_in_use; + } + return 0; +} + + +/************************************************************* DMA Functions */ +static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count) +{ + /* Since the Fastlane DMA is fully dedicated to the ESP chip, + * the number of bytes sent (to the ESP chip) equals the number + * of bytes in the FIFO - there is no buffering in the DMA controller. + * XXXX Do I read this right? It is from host to ESP, right? + */ + return fifo_count; +} + +static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp) +{ + unsigned long sz = sp->SCp.this_residual; + if(sz > 0xfffc) + sz = 0xfffc; + return sz; +} + +static void dma_dump_state(struct NCR_ESP *esp) +{ + ESPLOG(("esp%d: dma -- cond_reg<%02x>\n", + esp->esp_id, ((struct fastlane_dma_registers *) + (esp->dregs))->cond_reg)); + ESPLOG(("intreq:<%04x>, intena:<%04x>\n", + custom.intreqr, custom.intenar)); +} + +static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) +{ + struct fastlane_dma_registers *dregs = + (struct fastlane_dma_registers *) (esp->dregs); + unsigned long *t; + + cache_clear(addr, length); + + dma_clear(esp); + + t = (unsigned long *)((addr & 0x00ffffff) + esp->edev); + + dregs->clear_strobe = 0; + *t = addr; + + ctrl_data = (ctrl_data & FASTLANE_DMA_MASK) | FASTLANE_DMA_ENABLE; + dregs->ctrl_reg = ctrl_data; +} + +static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length) +{ + struct fastlane_dma_registers *dregs = + (struct fastlane_dma_registers *) (esp->dregs); + unsigned long *t; + + cache_push(addr, length); + + dma_clear(esp); + + t = (unsigned long *)((addr & 0x00ffffff) + (esp->edev)); + + dregs->clear_strobe = 0; + *t = addr; + + ctrl_data = ((ctrl_data & FASTLANE_DMA_MASK) | + FASTLANE_DMA_ENABLE | + FASTLANE_DMA_WRITE); + dregs->ctrl_reg = ctrl_data; +} + +static inline void dma_clear(struct NCR_ESP *esp) +{ + struct fastlane_dma_registers *dregs = + (struct fastlane_dma_registers *) (esp->dregs); + unsigned long *t; + + ctrl_data = (ctrl_data & FASTLANE_DMA_MASK); + dregs->ctrl_reg = ctrl_data; + + t = (unsigned long *)(esp->edev); + + dregs->clear_strobe = 0; + *t = 0 ; +} + + +static void dma_ints_off(struct NCR_ESP *esp) +{ + disable_irq(esp->irq); +} + +static void dma_ints_on(struct NCR_ESP *esp) +{ + enable_irq(esp->irq); +} + +static int dma_irq_p(struct NCR_ESP *esp) +{ + struct fastlane_dma_registers *dregs = + (struct fastlane_dma_registers *) (esp->dregs); +#if 0 + unsigned char dma_status; + int r = 0; + + dma_status = dregs->cond_reg; + + if(dma_status & FASTLANE_DMA_IACT) + return 0; /* not our IRQ */ + + /* Return 1 if ESP requested IRQ */ + if( +#ifndef NODMAIRQ + (dma_status & FASTLANE_DMA_CREQ) && +#endif + (!(dma_status & FASTLANE_DMA_MINT)) && + ((((struct ESP_regs *) (esp->eregs))->esp_status) & ESP_STAT_INTR)) + r = 1; + + dregs->ctrl_reg = (ctrl_data & ~(FASTLANE_DMA_EDI|FASTLANE_DMA_ESI) ); + dregs->ctrl_reg = ctrl_data; + + return r; +#else + int r; + r = (((struct ESP_regs *) (esp->eregs))->esp_status) & ESP_STAT_INTR; + dregs->ctrl_reg = ctrl_data & ~(FASTLANE_DMA_EDI|FASTLANE_DMA_ESI); + dregs->ctrl_reg = ctrl_data; + return r; +#endif +} + +static void dma_led_off(struct NCR_ESP *esp) +{ + ctrl_data &= ~FASTLANE_DMA_LED; + ((struct fastlane_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data; +} + +static void dma_led_on(struct NCR_ESP *esp) +{ + ctrl_data |= FASTLANE_DMA_LED; + ((struct fastlane_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data; +} + +static int dma_ports_p(struct NCR_ESP *esp) +{ + return ((custom.intenar) & IF_PORTS); +} + +static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) +{ + /* On the Sparc, DMA_ST_WRITE means "move data from device to memory" + * so when (write) is true, it actually means READ! + */ + if(write){ + dma_init_read(esp, addr, count); + } else { + dma_init_write(esp, addr, count); + } +} diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/fastlane.h linux/drivers/scsi/fastlane.h --- v2.1.100/linux/drivers/scsi/fastlane.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/fastlane.h Fri May 8 00:22:12 1998 @@ -0,0 +1,73 @@ +/* fastlane.h: Defines and structures for the Fastlane SCSI driver. + * + * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk) + */ + +#include "NCR53C9x.h" + +#ifndef FASTLANE_H +#define FASTLANE_H + +/* The controller registers can be found in the Z2 config area at these + * offsets: + */ +#define FASTLANE_ESP_ADDR 0x1000001 +#define FASTLANE_DMA_ADDR 0x1000041 + + +/* The Fastlane DMA interface */ +struct fastlane_dma_registers { + volatile unsigned char cond_reg; /* DMA status (ro) [0x0000] */ +#define ctrl_reg cond_reg /* DMA control (wo) [0x0000] */ + unsigned char dmapad1[0x3f]; + volatile unsigned char clear_strobe; /* DMA clear (wo) [0x0040] */ +}; + + +/* DMA status bits */ +#define FASTLANE_DMA_MINT 0x80 +#define FASTLANE_DMA_IACT 0x40 +#define FASTLANE_DMA_CREQ 0x20 + +/* DMA control bits */ +#define FASTLANE_DMA_FCODE 0xa0 +#define FASTLANE_DMA_MASK 0xf3 +#define FASTLANE_DMA_LED 0x10 /* HD led control 1 = on */ +#define FASTLANE_DMA_WRITE 0x08 /* 1 = write */ +#define FASTLANE_DMA_ENABLE 0x04 /* Enable DMA */ +#define FASTLANE_DMA_EDI 0x02 /* Enable DMA IRQ ? */ +#define FASTLANE_DMA_ESI 0x01 /* Enable SCSI IRQ */ + +extern int fastlane_esp_detect(struct SHT *); +extern const char *esp_info(struct Scsi_Host *); +extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +extern int esp_command(Scsi_Cmnd *); +extern int esp_abort(Scsi_Cmnd *); +extern int esp_reset(Scsi_Cmnd *, unsigned int); +extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, + int hostno, int inout); + +#define SCSI_FASTLANE { \ +/* struct SHT *next */ NULL, \ +/* long *usage_count */ NULL, \ +/* struct proc_dir_entry *proc_dir */ &proc_scsi_esp, \ +/* int (*proc_info)(char *, char **, off_t, int, int, int) */ &esp_proc_info, \ +/* const char *name */ "Fastlane SCSI", \ +/* int detect(struct SHT *) */ fastlane_esp_detect, \ +/* int release(struct Scsi_Host *) */ NULL, \ +/* const char *info(struct Scsi_Host *) */ esp_info, \ +/* int command(Scsi_Cmnd *) */ esp_command, \ +/* int queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ esp_queue, \ +/* int abort(Scsi_Cmnd *) */ esp_abort, \ +/* int reset(Scsi_Cmnd *) */ esp_reset, \ +/* int slave_attach(int, int) */ NULL, \ +/* int bios_param(Disk *, kdev_t, int[]) */ NULL, \ +/* int can_queue */ 7, \ +/* int this_id */ 7, \ +/* short unsigned int sg_tablesize */ SG_ALL, \ +/* short cmd_per_lun */ 1, \ +/* unsigned char present */ 0, \ +/* unsigned unchecked_isa_dma:1 */ 0, \ +/* unsigned use_clustering:1 */ DISABLE_CLUSTERING, } + +#endif /* FASTLANE_H */ diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c --- v2.1.100/linux/drivers/scsi/hosts.c Thu Apr 23 20:21:35 1998 +++ linux/drivers/scsi/hosts.c Fri May 8 00:22:12 1998 @@ -57,6 +57,26 @@ #include "gvp11.h" #endif +#ifdef CONFIG_CYBERSTORM_SCSI +#include "cyberstorm.h" +#endif + +#ifdef CONFIG_CYBERSTORMII_SCSI +#include "cyberstormII.h" +#endif + +#ifdef CONFIG_BLZ2060_SCSI +#include "blz2060.h" +#endif + +#ifdef CONFIG_BLZ1230_SCSI +#include "blz1230.h" +#endif + +#ifdef CONFIG_FASTLANE_SCSI +#include "fastlane.h" +#endif + #ifdef CONFIG_ATARI_SCSI #include "atari_scsi.h" #endif @@ -263,6 +283,21 @@ #endif #ifdef CONFIG_GVP11_SCSI GVP11_SCSI, +#endif +#ifdef CONFIG_CYBERSTORM_SCSI + SCSI_CYBERSTORM, +#endif +#ifdef CONFIG_CYBERSTORMII_SCSI + SCSI_CYBERSTORMII, +#endif +#ifdef CONFIG_BLZ2060_SCSI + SCSI_BLZ2060, +#endif +#ifdef CONFIG_BLZ1230_SCSI + SCSI_BLZ1230, +#endif +#ifdef CONFIG_FASTLANE_SCSI + SCSI_FASTLANE, #endif #endif diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h --- v2.1.100/linux/drivers/scsi/hosts.h Sat Apr 25 18:13:11 1998 +++ linux/drivers/scsi/hosts.h Fri May 8 18:22:24 1998 @@ -345,8 +345,8 @@ unsigned char *base; unsigned long io_port; unsigned char n_io_port; - unsigned char irq; unsigned char dma_channel; + unsigned int irq; /* * This is a unique identifier that must be assigned so that we diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/mac53c94.c linux/drivers/scsi/mac53c94.c --- v2.1.100/linux/drivers/scsi/mac53c94.c Tue Apr 14 14:29:22 1998 +++ linux/drivers/scsi/mac53c94.c Fri May 8 00:22:12 1998 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -91,11 +92,11 @@ panic("no 53c94 state"); state->host = host; state->regs = (volatile struct mac53c94_regs *) - node->addrs[0].address; - state->intr = node->intrs[0]; + ioremap(node->addrs[0].address, 0x1000); + state->intr = node->intrs[0].line; state->dma = (volatile struct dbdma_regs *) - node->addrs[1].address; - state->dmaintr = node->intrs[1]; + ioremap(node->addrs[1].address, 0x1000); + state->dmaintr = node->intrs[1].line; clkprop = get_property(node, "clock-frequency", &proplen); if (clkprop == NULL || proplen != sizeof(int)) { @@ -504,9 +505,36 @@ data_goes_out(Scsi_Cmnd *cmd) { switch (cmd->cmnd[0]) { - case WRITE_6: - case WRITE_10: - case WRITE_12: /* any others? */ + case CHANGE_DEFINITION: + case COMPARE: + case COPY: + case COPY_VERIFY: + case FORMAT_UNIT: + case LOG_SELECT: + case MEDIUM_SCAN: + case MODE_SELECT: + case MODE_SELECT_10: + case REASSIGN_BLOCKS: + case RESERVE: + case SEARCH_EQUAL: + case SEARCH_EQUAL_12: + case SEARCH_HIGH: + case SEARCH_HIGH_12: + case SEARCH_LOW: + case SEARCH_LOW_12: + case SEND_DIAGNOSTIC: + case SEND_VOLUME_TAG: + case SET_WINDOW: + case UPDATE_BLOCK: + case WRITE_BUFFER: + case WRITE_6: + case WRITE_10: + case WRITE_12: + case WRITE_LONG: + case WRITE_LONG_2: /* alternate code for WRITE_LONG */ + case WRITE_SAME: + case WRITE_VERIFY: + case WRITE_VERIFY_12: return 1; default: return 0; diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/mesh.c linux/drivers/scsi/mesh.c --- v2.1.100/linux/drivers/scsi/mesh.c Tue Apr 14 14:29:22 1998 +++ linux/drivers/scsi/mesh.c Fri May 8 00:22:12 1998 @@ -21,15 +21,25 @@ #include #include #include +#include #include #include +#include +#include +#include #include #include "scsi.h" #include "hosts.h" #include "mesh.h" -#if 0 +/* + * To do: + * - handle aborts correctly + * - retry arbitration if lost (unless higher levels do this for us) + */ + +#if 1 #undef KERN_DEBUG #define KERN_DEBUG KERN_WARNING #endif @@ -56,6 +66,22 @@ S_IFDIR | S_IRUGO | S_IXUGO, 2 }; +#define MESH_DBG +#define N_DBG_LOG 50 +#define N_DBG_SLOG 20 +#define NUM_DBG_EVENTS 13 +#undef DBG_USE_TB /* bombs on 601 */ + +struct dbglog { + char *fmt; + u32 tb; + u8 phase; + u8 bs0; + u8 bs1; + u8 tgt; + int d; +}; + enum mesh_phase { idle, arbitrating, @@ -74,6 +100,7 @@ msg_out_xxx, msg_out_last, msg_in, + msg_in_bad, }; enum sdtr_phase { @@ -84,11 +111,16 @@ struct mesh_target { enum sdtr_phase sdtr_state; - enum mesh_phase phase; int sync_params; - int data_goes_out; + int data_goes_out; /* guess as to data direction */ Scsi_Cmnd *current_req; u32 saved_ptr; + int want_abort; +#ifdef MESH_DBG + int log_ix; + int n_log; + struct dbglog log[N_DBG_LOG]; +#endif }; struct mesh_state { @@ -105,9 +137,10 @@ int conn_tgt; /* target we're connected to */ Scsi_Cmnd *current_req; /* req we're currently working on */ int data_ptr; - int data_goes_out; /* guess as to data direction */ int dma_started; int dma_count; + int stat; + int aborting; int expect_reply; int n_msgin; u8 msgin[16]; @@ -116,18 +149,41 @@ u8 msgout[16]; struct dbdma_cmd *dma_cmds; /* space for dbdma commands, aligned */ int clk_freq; - struct mesh_target tgts[8]; - struct tq_struct tqueue; Scsi_Cmnd *completed_q; Scsi_Cmnd *completed_qtail; + struct mesh_target tgts[8]; + struct tq_struct tqueue; +#ifdef MESH_DBG + int log_ix; + int n_log; + struct dbglog log[N_DBG_SLOG]; +#endif }; +#ifdef MESH_DBG + +static void dlog(struct mesh_state *ms, char *fmt, int a); +static void dumplog(struct mesh_state *ms, int tgt); +static void dumpslog(struct mesh_state *ms); +#define MKWORD(a, b, c, d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) + +#else +static inline void dlog(struct mesh_state *ms, char *fmt, int a) +{} +static inline void dumplog(struct mesh_state *ms, int tgt) +{} +static inline void dumpslog(struct mesh_state *ms) +{} + +#endif /* MESH_DBG */ + static struct mesh_state *all_meshes; static void mesh_init(struct mesh_state *); static int mesh_notify_reboot(struct notifier_block *, unsigned long, void *); static void mesh_dump_regs(struct mesh_state *); static void mesh_start(struct mesh_state *); +static void mesh_start_cmd(struct mesh_state *, Scsi_Cmnd *); static void finish_cmds(void *); static void add_sdtr_msg(struct mesh_state *); static void set_sdtr(struct mesh_state *, int, int); @@ -138,14 +194,17 @@ static void phase_mismatch(struct mesh_state *); static void reselected(struct mesh_state *); static void handle_reset(struct mesh_state *); +static void handle_error(struct mesh_state *); +static void handle_exception(struct mesh_state *); static void mesh_interrupt(int, void *, struct pt_regs *); static void do_mesh_interrupt(int, void *, struct pt_regs *); static void handle_msgin(struct mesh_state *); -static void mesh_done(struct mesh_state *); +static void mesh_done(struct mesh_state *, int); static void mesh_completed(struct mesh_state *, Scsi_Cmnd *); static void set_dma_cmds(struct mesh_state *, Scsi_Cmnd *); static void halt_dma(struct mesh_state *); static int data_goes_out(Scsi_Cmnd *); +static void do_abort(struct mesh_state *ms); static struct notifier_block mesh_notifier = { mesh_notify_reboot, @@ -164,13 +223,25 @@ nmeshes = 0; prev_statep = &all_meshes; - for (mesh = find_devices("mesh"); mesh != 0; mesh = mesh->next) { - if (mesh->n_addrs != 2 || mesh->n_intrs != 2) - panic("mesh: expected 2 addrs and intrs (got %d/%d)", - mesh->n_addrs, mesh->n_intrs); + /* + * On powermacs, the MESH node has device_type "mesh". + * On chrp machines, its device_type is "scsi" with + * "chrp,mesh0" as its `compatible' property. + */ + mesh = find_devices("mesh"); + if (mesh == 0) + mesh = find_compatible_devices("scsi", "chrp,mesh0"); + for (; mesh != 0; mesh = mesh->next) { + if (mesh->n_addrs != 2 || mesh->n_intrs != 2) { + printk(KERN_ERR "mesh: expected 2 addrs and 2 intrs" + " (got %d,%d)", mesh->n_addrs, mesh->n_intrs); + continue; + } mesh_host = scsi_register(tp, sizeof(struct mesh_state)); - if (mesh_host == 0) - panic("couldn't register mesh host"); + if (mesh_host == 0) { + printk(KERN_ERR "mesh: couldn't register host"); + continue; + } mesh_host->unique_id = nmeshes; note_scsi_host(mesh, mesh_host); @@ -180,11 +251,11 @@ memset(ms, 0, sizeof(*ms)); ms->host = mesh_host; ms->mesh = (volatile struct mesh_regs *) - mesh->addrs[0].address; - ms->meshintr = mesh->intrs[0]; + ioremap(mesh->addrs[0].address, 0x1000); ms->dma = (volatile struct dbdma_regs *) - mesh->addrs[1].address; - ms->dmaintr = mesh->intrs[1]; + ioremap(mesh->addrs[1].address, 0x1000); + ms->meshintr = mesh->intrs[0].line; + ms->dmaintr = mesh->intrs[1].line; /* Space for dma command list: +1 for stop command, +1 to allow for aligning. */ @@ -213,8 +284,8 @@ printk(KERN_ERR "MESH: can't get irq %d\n", ms->meshintr); } - cfp = (int *) get_property(mesh, "clock-frequency", NULL); - if (cfp) { + if ((cfp = (int *) get_property(mesh, "clock-frequency", + NULL))) { ms->clk_freq = *cfp; } else { printk(KERN_INFO "mesh: assuming 50MHz clock frequency\n"); @@ -230,7 +301,7 @@ ++nmeshes; } - if (nmeshes > 0) + if (_machine == _MACH_Pmac && nmeshes > 0) register_reboot_notifier(&mesh_notifier); return nmeshes; @@ -242,16 +313,6 @@ unsigned long flags; struct mesh_state *ms; -#if 0 - if (data_goes_out(cmd)) { - printk(KERN_DEBUG "mesh_queue %p: command is", cmd); - for (i = 0; i < cmd->cmd_len; ++i) - printk(" %.2x", cmd->cmnd[i]); - printk("\n" KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n", - cmd->use_sg, cmd->request_bufflen, cmd->request_buffer); - } -#endif - cmd->scsi_done = done; cmd->host_scribble = NULL; @@ -275,8 +336,12 @@ int mesh_abort(Scsi_Cmnd *cmd) { + struct mesh_state *ms = (struct mesh_state *) cmd->host->hostdata; + printk(KERN_DEBUG "mesh_abort(%p)\n", cmd); - mesh_dump_regs((struct mesh_state *)(cmd->host->hostdata)); + mesh_dump_regs(ms); + dumplog(ms, cmd->target); + dumpslog(ms); return SCSI_ABORT_SNOOZE; } @@ -290,22 +355,24 @@ printk(KERN_DEBUG "mesh: state at %p, regs at %p, dma at %p\n", ms, mr, md); - printk(KERN_DEBUG " ct=%4x seq=%2x bs=%4x fc=%2x exc=%2x err=%2x sp=%2x\n", + printk(KERN_DEBUG " ct=%4x seq=%2x bs=%4x fc=%2x " + "exc=%2x err=%2x im=%2x int=%2x sp=%2x\n", (mr->count_hi << 8) + mr->count_lo, mr->sequence, (mr->bus_status1 << 8) + mr->bus_status0, mr->fifo_count, - mr->exception, mr->error, mr->sync_params); + mr->exception, mr->error, mr->intr_mask, mr->interrupt, + mr->sync_params); printk(KERN_DEBUG " dma stat=%x cmdptr=%x\n", in_le32(&md->status), in_le32(&md->cmdptr)); printk(KERN_DEBUG " phase=%d msgphase=%d conn_tgt=%d data_ptr=%d\n", ms->phase, ms->msgphase, ms->conn_tgt, ms->data_ptr); - printk(KERN_DEBUG " goes_out=%d dma_st=%d dma_ct=%d n_msgout=%d\n", - ms->data_goes_out, ms->dma_started, ms->dma_count, ms->n_msgout); + printk(KERN_DEBUG " dma_st=%d dma_ct=%d n_msgout=%d\n", + ms->dma_started, ms->dma_count, ms->n_msgout); for (t = 0; t < 8; ++t) { tp = &ms->tgts[t]; if (tp->current_req == NULL) continue; - printk(KERN_DEBUG " target %d: req=%p phase=%d saved_ptr=%d\n", - t, tp->current_req, tp->phase, tp->saved_ptr); + printk(KERN_DEBUG " target %d: req=%p goes_out=%d saved_ptr=%d\n", + t, tp->current_req, tp->data_goes_out, tp->saved_ptr); } } @@ -322,14 +389,17 @@ ret = SCSI_RESET_BUS_RESET; save_flags(flags); cli(); + out_le32(&md->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* stop dma */ out_8(&mr->exception, 0xff); /* clear all exception bits */ out_8(&mr->error, 0xff); /* clear all error bits */ - out_le32(&md->control, (RUN|PAUSE|FLUSH|WAKE) << 16); if (how & SCSI_RESET_SUGGEST_HOST_RESET) { out_8(&mr->sequence, SEQ_RESETMESH); ret |= SCSI_RESET_HOST_RESET; udelay(1); out_8(&mr->intr_mask, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + out_8(&mr->source_id, ms->host->this_id); + out_8(&mr->sel_timeout, 25); /* 250ms */ + out_8(&mr->sync_params, ASYNC_PARAMS); } out_8(&mr->bus_status1, BS1_RST); /* assert RST */ udelay(30); /* leave it on for >= 25us */ @@ -341,7 +411,6 @@ } else #endif { - out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); handle_reset(ms); restore_flags(flags); finish_cmds(ms); @@ -361,7 +430,7 @@ struct mesh_state *ms; volatile struct mesh_regs *mr; - if (code == SYS_DOWN || code == SYS_HALT) { + if (code == SYS_DOWN) { printk(KERN_INFO "resetting MESH scsi bus(es)\n"); for (ms = all_meshes; ms != 0; ms = ms->next) { mr = ms->mesh; @@ -405,29 +474,42 @@ mesh_start(struct mesh_state *ms) { Scsi_Cmnd *cmd, *prev, *next; - volatile struct mesh_regs *mr = ms->mesh; - if (ms->phase != idle || ms->current_req != NULL) - panic("inappropriate mesh_start (ms=%p)", ms); + if (ms->phase != idle || ms->current_req != NULL) { + printk(KERN_ERR "inappropriate mesh_start (phase=%d, ms=%p)", + ms->phase, ms); + return; + } - prev = NULL; - for (cmd = ms->request_q; ; cmd = (Scsi_Cmnd *) cmd->host_scribble) { - if (cmd == NULL) - return; - if (ms->tgts[cmd->target].current_req == NULL) - break; - prev = cmd; + while (ms->phase == idle) { + prev = NULL; + for (cmd = ms->request_q; ; cmd = (Scsi_Cmnd *) cmd->host_scribble) { + if (cmd == NULL) + return; + if (ms->tgts[cmd->target].current_req == NULL) + break; + prev = cmd; + } + next = (Scsi_Cmnd *) cmd->host_scribble; + if (prev == NULL) + ms->request_q = next; + else + prev->host_scribble = (void *) next; + if (next == NULL) + ms->request_qtail = prev; + + mesh_start_cmd(ms, cmd); } - next = (Scsi_Cmnd *) cmd->host_scribble; - if (prev == NULL) - ms->request_q = next; - else - prev->host_scribble = (void *) next; - if (next == NULL) - ms->request_qtail = prev; +} + +static void +mesh_start_cmd(struct mesh_state *ms, Scsi_Cmnd *cmd) +{ + volatile struct mesh_regs *mr = ms->mesh; + int t; ms->current_req = cmd; - ms->data_goes_out = data_goes_out(cmd); + ms->tgts[cmd->target].data_goes_out = data_goes_out(cmd); ms->tgts[cmd->target].current_req = cmd; #if 1 @@ -442,9 +524,6 @@ } #endif - /* Off we go */ - out_8(&mr->sequence, SEQ_ARBITRATE); - ms->phase = arbitrating; ms->msgphase = msg_none; ms->data_ptr = 0; @@ -454,6 +533,118 @@ ms->expect_reply = 0; ms->conn_tgt = cmd->target; ms->tgts[cmd->target].saved_ptr = 0; + ms->stat = DID_OK; + ms->aborting = 0; +#ifdef MESH_DBG + ms->tgts[cmd->target].n_log = 0; + dlog(ms, "start cmd=%x", (int) cmd); +#endif + + /* Off we go */ + dlog(ms, "about to arb, intr/exc/err/fc=%.8x", + MKWORD(mr->interrupt, mr->exception, mr->error, mr->fifo_count)); + out_8(&mr->interrupt, INT_CMDDONE); + out_8(&mr->sequence, SEQ_ENBRESEL); + udelay(1); + + if (mr->bus_status1 & (BS1_BSY | BS1_SEL)) { + /* + * Some other device has the bus or is arbitrating for it - + * probably a target which is about to reselect us. + */ + dlog(ms, "busy b4 arb, intr/exc/err/fc=%.8x", + MKWORD(mr->interrupt, mr->exception, + mr->error, mr->fifo_count)); + for (t = 100; t > 0; --t) { + if ((mr->bus_status1 & (BS1_BSY | BS1_SEL)) == 0) + break; + if (in_8(&mr->interrupt) != 0) { + dlog(ms, "intr b4 arb, intr/exc/err/fc=%.8x", + MKWORD(mr->interrupt, mr->exception, + mr->error, mr->fifo_count)); + mesh_interrupt(0, (void *)ms, 0); + if (ms->phase != arbitrating) + return; + } + udelay(1); + } + if (mr->bus_status1 & (BS1_BSY | BS1_SEL)) { + /* XXX should try again in a little while */ + ms->stat = DID_BUS_BUSY; + ms->phase = idle; + mesh_done(ms, 0); + return; + } + } + + /* + * Apparently the mesh has a bug where it will assert both its + * own bit and the target's bit on the bus during arbitration. + */ + out_8(&mr->dest_id, mr->source_id); + + /* + * There appears to be a race with reselection sometimes, + * where a target reselects us just as we issue the + * arbitrate command. It seems that then the arbitrate + * command just hangs waiting for the bus to be free + * without giving us a reselection exception. + * The only way I have found to get it to respond correctly + * is this: disable reselection before issuing the arbitrate + * command, then after issuing it, if it looks like a target + * is trying to reselect us, reset the mesh and then enable + * reselection. + */ + out_8(&mr->sequence, SEQ_DISRESEL); + if (in_8(&mr->interrupt) != 0) { + dlog(ms, "intr after disresel, intr/exc/err/fc=%.8x", + MKWORD(mr->interrupt, mr->exception, + mr->error, mr->fifo_count)); + mesh_interrupt(0, (void *)ms, 0); + if (ms->phase != arbitrating) + return; + dlog(ms, "after intr after disresel, intr/exc/err/fc=%.8x", + MKWORD(mr->interrupt, mr->exception, + mr->error, mr->fifo_count)); + } + + out_8(&mr->sequence, SEQ_ARBITRATE); + + for (t = 30; t > 0; --t) { + if (in_8(&mr->interrupt) != 0) + break; + udelay(1); + } + dlog(ms, "after arb, intr/exc/err/fc=%.8x", + MKWORD(mr->interrupt, mr->exception, mr->error, mr->fifo_count)); + if (mr->interrupt == 0 && (mr->bus_status1 & BS1_SEL) + && (mr->bus_status0 & BS0_IO)) { + /* looks like a reselection - try resetting the mesh */ + dlog(ms, "resel? after arb, intr/exc/err/fc=%.8x", + MKWORD(mr->interrupt, mr->exception, mr->error, mr->fifo_count)); + out_8(&mr->sequence, SEQ_RESETMESH); + udelay(10); + out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + out_8(&mr->intr_mask, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + out_8(&mr->sequence, SEQ_ENBRESEL); + for (t = 10; t > 0 && mr->interrupt == 0; --t) + udelay(1); + dlog(ms, "tried reset after arb, intr/exc/err/fc=%.8x", + MKWORD(mr->interrupt, mr->exception, mr->error, mr->fifo_count)); +#ifndef MESH_MULTIPLE_HOSTS + if (mr->interrupt == 0 && (mr->bus_status1 & BS1_SEL) + && (mr->bus_status0 & BS0_IO)) { + printk(KERN_ERR "mesh: controller not responding" + " to reselection!\n"); + /* + * If this is a target reselecting us, and the + * mesh isn't responding, the higher levels of + * the scsi code will eventually time out and + * reset the bus. + */ + } +#endif + } } static void @@ -541,10 +732,9 @@ Scsi_Cmnd *cmd = ms->current_req; struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; - if (cmd == 0) { - printk(KERN_ERR "mesh: start_phase but no cmd?\n"); - return; - } + dlog(ms, "start_phase err/exc/fc/seq = %.8x", + MKWORD(mr->error, mr->exception, mr->fifo_count, mr->sequence)); + out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); seq = SEQ_ACTIVE_NEG + (ms->n_msgout? SEQ_ATN: 0); switch (ms->msgphase) { case msg_none: @@ -563,20 +753,44 @@ * the last byte of the message, we have to do the * last byte specially. */ - if (DEBUG_TARGET(cmd)) { + if (ms->n_msgout <= 0) { + printk(KERN_ERR "mesh: msg_out but n_msgout=%d\n", + ms->n_msgout); + mesh_dump_regs(ms); + ms->msgphase = msg_none; + break; + } + if (ALLOW_DEBUG(ms->conn_tgt)) { printk(KERN_DEBUG "mesh: sending %d msg bytes:", ms->n_msgout); for (i = 0; i < ms->n_msgout; ++i) printk(" %x", ms->msgout[i]); printk("\n"); } + dlog(ms, "msgout msg=%.8x", MKWORD(ms->n_msgout, ms->msgout[0], + ms->msgout[1], ms->msgout[2])); out_8(&mr->count_hi, 0); - if (ms->n_msgout == 1) { - out_8(&mr->count_lo, 1); - out_8(&mr->sequence, SEQ_MSGOUT + SEQ_ACTIVE_NEG); + out_8(&mr->sequence, SEQ_FLUSHFIFO); + udelay(1); + /* + * If ATN is not already asserted, we assert it, then + * issue a SEQ_MSGOUT to get the mesh to drop ACK. + */ + if ((mr->bus_status0 & BS0_ATN) == 0) { + out_8(&mr->bus_status0, BS0_ATN); /* explicit ATN */ udelay(1); - out_8(&mr->fifo, ms->msgout[0]); - ms->msgphase = msg_out_last; + out_8(&mr->count_lo, 1); + out_8(&mr->sequence, SEQ_MSGOUT + seq); + out_8(&mr->bus_status0, 0); /* release explicit ATN */ + } + if (ms->n_msgout == 1) { + /* + * We can't issue the SEQ_MSGOUT without ATN + * until the target has asserted REQ. The logic + * in cmd_complete handles both situations: + * REQ already asserted or not. + */ + cmd_complete(ms); } else { out_8(&mr->count_lo, ms->n_msgout - 1); out_8(&mr->sequence, SEQ_MSGOUT + seq); @@ -592,16 +806,23 @@ switch (ms->phase) { case selecting: - out_8(&mr->dest_id, cmd->target); + out_8(&mr->dest_id, ms->conn_tgt); out_8(&mr->sequence, SEQ_SELECT + SEQ_ATN); break; case commanding: out_8(&mr->sync_params, tp->sync_params); out_8(&mr->count_hi, 0); - out_8(&mr->count_lo, cmd->cmd_len); - out_8(&mr->sequence, SEQ_COMMAND + seq); - for (i = 0; i < cmd->cmd_len; ++i) - out_8(&mr->fifo, cmd->cmnd[i]); + if (cmd) { + out_8(&mr->count_lo, cmd->cmd_len); + out_8(&mr->sequence, SEQ_COMMAND + seq); + for (i = 0; i < cmd->cmd_len; ++i) + out_8(&mr->fifo, cmd->cmnd[i]); + } else { + out_8(&mr->count_lo, 6); + out_8(&mr->sequence, SEQ_COMMAND + seq); + for (i = 0; i < 6; ++i) + out_8(&mr->fifo, 0); + } break; case dataing: /* transfer data, if any */ @@ -618,7 +839,7 @@ ms->data_ptr += nb; out_8(&mr->count_lo, nb); out_8(&mr->count_hi, nb >> 8); - out_8(&mr->sequence, (ms->data_goes_out? + out_8(&mr->sequence, (tp->data_goes_out? SEQ_DATAOUT: SEQ_DATAIN) + SEQ_DMA_MODE + seq); break; case statusing: @@ -630,11 +851,15 @@ case disconnecting: out_8(&mr->sequence, SEQ_ENBRESEL); udelay(1); + dlog(ms, "enbresel intr/exc/err/fc=%.8x", + MKWORD(mr->interrupt, mr->exception, mr->error, + mr->fifo_count)); out_8(&mr->sequence, SEQ_BUSFREE); break; default: printk(KERN_ERR "mesh: start_phase called with phase=%d\n", ms->phase); + dumpslog(ms); } } @@ -681,6 +906,7 @@ struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; int seq, n, t; + dlog(ms, "cmd_complete fc=%x", mr->fifo_count); seq = SEQ_ACTIVE_NEG + (ms->n_msgout? SEQ_ATN: 0); switch (ms->msgphase) { case msg_out_xxx: @@ -703,6 +929,13 @@ } break; + case msg_in_bad: + out_8(&mr->sequence, SEQ_FLUSHFIFO); + udelay(1); + out_8(&mr->count_lo, 1); + out_8(&mr->sequence, SEQ_MSGIN + SEQ_ATN + SEQ_ACTIVE_NEG); + break; + case msg_out: /* * To get the right timing on ATN wrt ACK, we have @@ -720,6 +953,28 @@ t = 30; /* wait up to 30us */ while ((mr->bus_status0 & BS0_REQ) == 0 && --t >= 0) udelay(1); + dlog(ms, "last_mbyte err/exc/fc/cl=%.8x", + MKWORD(mr->error, mr->exception, + mr->fifo_count, mr->count_lo)); + if (in_8(&mr->interrupt) & (INT_ERROR | INT_EXCEPTION)) { + /* whoops, target didn't do what we expected */ + ms->last_n_msgout = ms->n_msgout; + ms->n_msgout = 0; + if (in_8(&mr->interrupt) & INT_ERROR) { + printk(KERN_ERR "mesh: error %x in msg_out\n", + in_8(&mr->error)); + handle_error(ms); + return; + } + if (in_8(&mr->exception) != EXC_PHASEMM) + printk(KERN_ERR "mesh: exc %x in msg_out\n", + in_8(&mr->exception)); + else + printk(KERN_DEBUG "mesh: bs0=%x in msg_out\n", + in_8(&mr->bus_status0)); + handle_exception(ms); + return; + } if (mr->bus_status0 & BS0_REQ) { out_8(&mr->sequence, SEQ_MSGOUT + SEQ_ACTIVE_NEG); udelay(1); @@ -740,11 +995,19 @@ case msg_none: switch (ms->phase) { + case idle: + printk(KERN_ERR "mesh: interrupt in idle phase?\n"); + dumpslog(ms); + return; case selecting: - ms->msgout[0] = IDENTIFY(ALLOW_RESEL(cmd->target), cmd->lun); + ms->msgout[0] = IDENTIFY(ALLOW_RESEL(ms->conn_tgt), + (cmd? cmd->lun: 0)); ms->n_msgout = 1; ms->expect_reply = 0; - if (tp->sdtr_state == do_sdtr) { + if (ms->aborting) { + ms->msgout[0] = ABORT; + ms->n_msgout++; + } else if (tp->sdtr_state == do_sdtr) { /* add SDTR message */ add_sdtr_msg(ms); ms->expect_reply = 1; @@ -772,18 +1035,32 @@ start_phase(ms); return; } + /* + * We can get a phase mismatch here if the target + * changes to the status phase, even though we have + * had a command complete interrupt. Then, if we + * issue the SEQ_STATUS command, we'll get a sequence + * error interrupt. Which isn't so bad except that + * occasionally the mesh actually executes the + * SEQ_STATUS *as well as* giving us the sequence + * error and phase mismatch exception. + */ + out_8(&mr->sequence, 0); + out_8(&mr->interrupt, + INT_ERROR | INT_EXCEPTION | INT_CMDDONE); halt_dma(ms); break; case statusing: - cmd->SCp.Status = mr->fifo; - cmd->result = (DID_OK << 16) + cmd->SCp.Status; + if (cmd) { + cmd->SCp.Status = mr->fifo; + if (DEBUG_TARGET(cmd)) + printk(KERN_DEBUG "mesh: status is %x\n", + cmd->SCp.Status); + } ms->msgphase = msg_in; - if (DEBUG_TARGET(cmd)) - printk(KERN_DEBUG "mesh: status is %x\n", - cmd->SCp.Status); break; case busfreeing: - mesh_done(ms); + mesh_done(ms, 1); return; case disconnecting: ms->current_req = 0; @@ -804,6 +1081,8 @@ volatile struct mesh_regs *mr = ms->mesh; int phase; + dlog(ms, "phasemm ch/cl/seq/fc=%.8x", + MKWORD(mr->count_hi, mr->count_lo, mr->sequence, mr->fifo_count)); phase = mr->bus_status0 & BS0_PHASE; if (ms->msgphase == msg_out_xxx && phase == BP_MSGOUT) { /* output the last byte of the message, without ATN */ @@ -831,11 +1110,11 @@ ms->msgphase = msg_none; switch (phase) { case BP_DATAIN: - ms->data_goes_out = 0; + ms->tgts[ms->conn_tgt].data_goes_out = 0; ms->phase = dataing; break; case BP_DATAOUT: - ms->data_goes_out = 1; + ms->tgts[ms->conn_tgt].data_goes_out = 1; ms->phase = dataing; break; case BP_COMMAND: @@ -851,18 +1130,23 @@ case BP_MSGOUT: ms->msgphase = msg_out; if (ms->n_msgout == 0) { - if (ms->last_n_msgout == 0) { - printk(KERN_DEBUG "mesh: no msg to repeat\n"); - ms->msgout[0] = NOP; - ms->last_n_msgout = 1; + if (ms->aborting) { + do_abort(ms); + } else { + if (ms->last_n_msgout == 0) { + printk(KERN_DEBUG + "mesh: no msg to repeat\n"); + ms->msgout[0] = NOP; + ms->last_n_msgout = 1; + } + ms->n_msgout = ms->last_n_msgout; } - ms->n_msgout = ms->last_n_msgout; } break; default: printk(KERN_DEBUG "mesh: unknown scsi phase %x\n", phase); - ms->current_req->result = DID_ERROR << 16; - mesh_done(ms); + ms->stat = DID_ERROR; + mesh_done(ms, 1); return; } @@ -873,82 +1157,126 @@ reselected(struct mesh_state *ms) { volatile struct mesh_regs *mr = ms->mesh; - Scsi_Cmnd *cmd = ms->current_req; + Scsi_Cmnd *cmd; struct mesh_target *tp; - int b, t; + int b, t, prev; switch (ms->phase) { case idle: + break; case arbitrating: + if ((cmd = ms->current_req) != NULL) { + /* put the command back on the queue */ + cmd->host_scribble = (void *) ms->request_q; + if (ms->request_q == NULL) + ms->request_qtail = cmd; + ms->request_q = cmd; + tp = &ms->tgts[cmd->target]; + tp->current_req = NULL; + } break; case busfreeing: ms->phase = reselecting; - mesh_done(ms); - cmd = NULL; + mesh_done(ms, 0); break; case disconnecting: - cmd = NULL; break; default: - printk(KERN_ERR "mesh: reselected in phase %d/%d\n", - ms->msgphase, ms->phase); - } - if (cmd) { - /* put the command back on the queue */ - cmd->host_scribble = (void *) ms->request_q; - if (ms->request_q == NULL) - ms->request_qtail = cmd; - ms->request_q = cmd; - tp = &ms->tgts[cmd->target]; - tp->current_req = NULL; - ms->current_req = NULL; + printk(KERN_ERR "mesh: reselected in phase %d/%d tgt %d\n", + ms->msgphase, ms->phase, ms->conn_tgt); + dumplog(ms, ms->conn_tgt); + dumpslog(ms); } + ms->current_req = NULL; + ms->phase = dataing; + ms->msgphase = msg_in; + ms->dma_started = 0; + ms->n_msgout = 0; + ms->last_n_msgout = 0; + prev = ms->conn_tgt; + + /* + * We seem to get abortive reselections sometimes. + */ + while ((mr->bus_status1 & BS1_BSY) == 0) { + static int mesh_aborted_resels; + mesh_aborted_resels++; + out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + udelay(1); + out_8(&mr->sequence, SEQ_ENBRESEL); + udelay(5); + dlog(ms, "extra resel err/exc/fc = %.6x", + MKWORD(0, mr->error, mr->exception, mr->fifo_count)); + } + out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + udelay(1); + out_8(&mr->sequence, SEQ_ENBRESEL); + udelay(1); + out_8(&mr->sync_params, ASYNC_PARAMS); + /* * Find out who reselected us. */ if (mr->fifo_count == 0) { printk(KERN_ERR "mesh: reselection but nothing in fifo?\n"); - return; + ms->conn_tgt = ms->host->this_id; + goto bogus; } /* get the last byte in the fifo */ do { b = in_8(&mr->fifo); + dlog(ms, "reseldata %x", b); } while (in_8(&mr->fifo_count)); for (t = 0; t < 8; ++t) if ((b & (1 << t)) != 0 && t != ms->host->this_id) break; if (b != (1 << t) + (1 << ms->host->this_id)) { printk(KERN_ERR "mesh: bad reselection data %x\n", b); - return; + ms->conn_tgt = ms->host->this_id; + goto bogus; } + /* * Set up to continue with that target's transfer. */ + ms->conn_tgt = t; tp = &ms->tgts[t]; + out_8(&mr->sync_params, tp->sync_params); if (ALLOW_DEBUG(t)) { printk(KERN_DEBUG "mesh: reselected by target %d\n", t); - printk(KERN_DEBUG "mesh: saved_ptr=%x phase=%d cmd=%p\n", - tp->saved_ptr, tp->phase, tp->current_req); + printk(KERN_DEBUG "mesh: saved_ptr=%x goes_out=%d cmd=%p\n", + tp->saved_ptr, tp->data_goes_out, tp->current_req); } + ms->current_req = tp->current_req; if (tp->current_req == NULL) { printk(KERN_ERR "mesh: reselected by tgt %d but no cmd!\n", t); - return; + goto bogus; } - ms->current_req = tp->current_req; - ms->phase = tp->phase; - ms->msgphase = msg_in; - ms->data_goes_out = tp->data_goes_out; ms->data_ptr = tp->saved_ptr; - ms->conn_tgt = t; - ms->dma_started = 0; - ms->n_msgout = 0; - ms->last_n_msgout = 0; - out_8(&mr->sync_params, tp->sync_params); + dlog(ms, "resel prev tgt=%d", prev); + dlog(ms, "resel err/exc=%.4x", MKWORD(0, 0, mr->error, mr->exception)); + start_phase(ms); + return; + +bogus: + dumplog(ms, ms->conn_tgt); + dumpslog(ms); + ms->data_ptr = 0; + ms->aborting = 1; start_phase(ms); } +static void do_abort(struct mesh_state *ms) +{ + ms->msgout[0] = ABORT; + ms->n_msgout = 1; + ms->aborting = 1; + ms->stat = DID_ABORT; + dlog(ms, "abort", 0); +} + static void handle_reset(struct mesh_state *ms) { @@ -974,7 +1302,12 @@ mesh_completed(ms, cmd); } ms->phase = idle; + ms->msgphase = msg_none; + out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + out_8(&mr->sequence, SEQ_FLUSHFIFO); + udelay(1); out_8(&mr->sync_params, ASYNC_PARAMS); + out_8(&mr->sequence, SEQ_ENBRESEL); } static void @@ -987,90 +1320,153 @@ spin_unlock_irqrestore(&io_request_lock, flags); } +static void handle_error(struct mesh_state *ms) +{ + int err, exc, count; + volatile struct mesh_regs *mr = ms->mesh; + + err = in_8(&mr->error); + exc = in_8(&mr->exception); + out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + dlog(ms, "error err/exc/fc/cl=%.8x", + MKWORD(err, exc, mr->fifo_count, mr->count_lo)); + if (err & ERR_SCSIRESET) { + /* SCSI bus was reset */ + printk(KERN_INFO "mesh: SCSI bus reset detected: " + "waiting for end..."); + while ((mr->bus_status1 & BS1_RST) != 0) + udelay(1); + printk("done\n"); + handle_reset(ms); + /* request_q is empty, no point in mesh_start() */ + return; + } + if (err & ERR_UNEXPDISC) { + /* Unexpected disconnect */ + if (exc & EXC_RESELECTED) { + reselected(ms); + return; + } + if (!ms->aborting) { + printk(KERN_WARNING "mesh: target %d aborted\n", + ms->conn_tgt); + dumplog(ms, ms->conn_tgt); + dumpslog(ms); + } + out_8(&mr->interrupt, INT_CMDDONE); + ms->stat = DID_ABORT; + mesh_done(ms, 1); + return; + } + if (err & ERR_PARITY) { + if (ms->msgphase == msg_in) { + printk(KERN_ERR "mesh: msg parity error, target %d\n", + ms->conn_tgt); + ms->msgout[0] = MSG_PARITY_ERROR; + ms->n_msgout = 1; + ms->msgphase = msg_in_bad; + cmd_complete(ms); + return; + } + if (ms->stat == DID_OK) { + printk(KERN_ERR "mesh: parity error, target %d\n", + ms->conn_tgt); + ms->stat = DID_PARITY; + } + count = (mr->count_hi << 8) + mr->count_lo; + if (count == 0) { + cmd_complete(ms); + } else { + /* reissue the data transfer command */ + out_8(&mr->sequence, mr->sequence); + } + return; + } + if (err & ERR_SEQERR) { + if (exc & EXC_RESELECTED) { + /* This can happen if we issue a command to + get the bus just after the target reselects us. */ + static int mesh_resel_seqerr; + mesh_resel_seqerr++; + reselected(ms); + return; + } + if (exc == EXC_PHASEMM) { + static int mesh_phasemm_seqerr; + mesh_phasemm_seqerr++; + phase_mismatch(ms); + return; + } + printk(KERN_ERR "mesh: sequence error (err=%x exc=%x)\n", + err, exc); + } else { + printk(KERN_ERR "mesh: unknown error %x (exc=%x)\n", err, exc); + } + mesh_dump_regs(ms); + dumplog(ms, ms->conn_tgt); + if (ms->phase > selecting && (mr->bus_status1 & BS1_BSY)) { + /* try to do what the target wants */ + do_abort(ms); + phase_mismatch(ms); + return; + } + ms->stat = DID_ERROR; + mesh_done(ms, 1); +} + +static void handle_exception(struct mesh_state *ms) +{ + int exc; + volatile struct mesh_regs *mr = ms->mesh; + + exc = in_8(&mr->exception); + out_8(&mr->interrupt, INT_EXCEPTION | INT_CMDDONE); + if (exc & EXC_RESELECTED) { + static int mesh_resel_exc; + mesh_resel_exc++; + reselected(ms); + } else if (exc == EXC_ARBLOST) { + printk(KERN_DEBUG "mesh: lost arbitration\n"); + ms->stat = DID_BUS_BUSY; + mesh_done(ms, 1); + } else if (exc == EXC_SELTO) { + /* selection timed out */ + ms->stat = DID_BAD_TARGET; + mesh_done(ms, 1); + } else if (exc == EXC_PHASEMM) { + /* target wants to do something different: + find out what it wants and do it. */ + phase_mismatch(ms); + } else { + printk(KERN_ERR "mesh: can't cope with exception %x\n", exc); + mesh_dump_regs(ms); + dumplog(ms, ms->conn_tgt); + do_abort(ms); + phase_mismatch(ms); + } +} + static void mesh_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) { struct mesh_state *ms = (struct mesh_state *) dev_id; volatile struct mesh_regs *mr = ms->mesh; - Scsi_Cmnd *cmd = ms->current_req; - int stat, exc, err, intr; + int intr; #if 0 - if (DEBUG_TARGET(cmd)) - printk(KERN_DEBUG "mesh_intr, bs0=%x int=%x exc=%x err=%x phase=%d msgphase=%d\n", - mr->bus_status0, mr->interrupt, mr->exception, mr->error, ms->phase, ms->msgphase); + if (ALLOW_DEBUG(ms->conn_tgt)) + printk(KERN_DEBUG "mesh_intr, bs0=%x int=%x exc=%x err=%x " + "phase=%d msgphase=%d\n", mr->bus_status0, + mr->interrupt, mr->exception, mr->error, + ms->phase, ms->msgphase); #endif while ((intr = in_8(&mr->interrupt)) != 0) { + dlog(ms, "interrupt intr/err/exc/seq=%.8x", + MKWORD(intr, mr->error, mr->exception, mr->sequence)); if (intr & INT_ERROR) { - stat = DID_BAD_INTR << 16; - err = in_8(&mr->error); - exc = in_8(&mr->exception); - out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); - if (err & ERR_SCSIRESET) { - /* SCSI bus was reset */ - printk(KERN_INFO "mesh: SCSI bus reset detected: " - "waiting for end..."); - while ((mr->bus_status1 & BS1_RST) != 0) - udelay(1); - printk("done\n"); - handle_reset(ms); - /* request_q is empty, no point in mesh_start() */ - continue; - } else if (err & ERR_UNEXPDISC) { - /* Unexpected disconnect */ - printk(KERN_WARNING "mesh: target %d aborted\n", - ms->conn_tgt); - stat = DID_ABORT << 16; - } else if (err & ERR_PARITY) { - printk(KERN_ERR "mesh: parity error\n"); - stat = DID_PARITY << 16; - } else if ((err & ERR_SEQERR) && (exc & EXC_RESELECTED) - && ms->phase == arbitrating) { - /* This can happen if we issue a command to - get the bus just after the target - reselects us. */ - static int mesh_resel_seqerr; - mesh_resel_seqerr++; - reselected(ms); - continue; - } else { - printk(KERN_ERR "mesh: error %x (exc = %x)\n", - err, exc); - mesh_dump_regs(ms); - } - if (cmd != 0) { - cmd->result = stat; - mesh_done(ms); - } - + handle_error(ms); } else if (intr & INT_EXCEPTION) { - exc = in_8(&mr->exception); - out_8(&mr->interrupt, INT_EXCEPTION | INT_CMDDONE); - if (exc & EXC_RESELECTED) { - static int mesh_resel_exc; - mesh_resel_exc++; - reselected(ms); - } else if (cmd && exc == EXC_ARBLOST - && ms->phase == arbitrating) { - printk(KERN_DEBUG "mesh: lost arbitration\n"); - cmd->result = DID_BUS_BUSY << 16; - mesh_done(ms); - } else if (cmd && exc == EXC_SELTO && ms->phase == selecting) { - /* selection timed out */ - cmd->result = DID_BAD_TARGET << 16; - mesh_done(ms); - } else if (cmd && exc == EXC_PHASEMM - && (mr->bus_status0 & BS0_REQ) != 0) { - /* target wants to do something different: - find out what it wants and do it. */ - phase_mismatch(ms); - } else { - printk(KERN_ERR "mesh: can't cope with exception %x\n", - exc); - cmd->result = DID_ERROR << 16; - mesh_done(ms); - } - + handle_exception(ms); } else if (intr & INT_CMDDONE) { out_8(&mr->interrupt, INT_CMDDONE); cmd_complete(ms); @@ -1081,26 +1477,29 @@ static void handle_msgin(struct mesh_state *ms) { - int i; + int i, code; Scsi_Cmnd *cmd = ms->current_req; struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; if (ms->n_msgin == 0) return; - if (DEBUG_TARGET(cmd)) { + code = ms->msgin[0]; + if (ALLOW_DEBUG(ms->conn_tgt)) { printk(KERN_DEBUG "got %d message bytes:", ms->n_msgin); for (i = 0; i < ms->n_msgin; ++i) printk(" %x", ms->msgin[i]); printk("\n"); } + dlog(ms, "msgin msg=%.8x", + MKWORD(ms->n_msgin, code, ms->msgin[1], ms->msgin[2])); ms->expect_reply = 0; ms->n_msgout = 0; if (ms->n_msgin < msgin_length(ms)) goto reject; if (cmd) - cmd->SCp.Message = ms->msgin[0]; - switch (ms->msgin[0]) { + cmd->SCp.Message = code; + switch (code) { case COMMAND_COMPLETE: break; case EXTENDED_MESSAGE: @@ -1136,8 +1535,6 @@ ms->data_ptr = tp->saved_ptr; break; case DISCONNECT: - tp->phase = ms->phase; - tp->data_goes_out = ms->data_goes_out; ms->phase = disconnecting; break; case ABORT: @@ -1149,14 +1546,16 @@ case NOP: break; default: - if (cmd && IDENTIFY_BASE <= ms->msgin[0] - && ms->msgin[0] <= IDENTIFY_BASE + 7) { - i = ms->msgin[0] - IDENTIFY_BASE; - if (i != cmd->lun) + if (IDENTIFY_BASE <= code && code <= IDENTIFY_BASE + 7) { + if (cmd == NULL) { + do_abort(ms); + ms->msgphase = msg_out; + } else if (code != cmd->lun + IDENTIFY_BASE) { printk(KERN_WARNING "mesh: lun mismatch " "(%d != %d) on reselection from " "target %d\n", i, cmd->lun, ms->conn_tgt); + } break; } goto reject; @@ -1164,35 +1563,45 @@ return; reject: - printk(KERN_WARNING "mesh: rejecting message %x from target %d\n", - ms->msgin[0], ms->conn_tgt); + printk(KERN_WARNING "mesh: rejecting message from target %d:", + ms->conn_tgt); + for (i = 0; i < ms->n_msgin; ++i) + printk(" %x", ms->msgin[i]); + printk("\n"); ms->msgout[0] = MESSAGE_REJECT; ms->n_msgout = 1; ms->msgphase = msg_out; } static void -mesh_done(struct mesh_state *ms) +mesh_done(struct mesh_state *ms, int start_next) { Scsi_Cmnd *cmd; struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; cmd = ms->current_req; - if (DEBUG_TARGET(cmd)) { - printk(KERN_DEBUG "mesh_done: result = %x, data_ptr=%d, buflen=%d\n", - cmd->result, ms->data_ptr, cmd->request_bufflen); - if ((cmd->cmnd[0] == 0 || cmd->cmnd[0] == 0x12 || cmd->cmnd[0] == 3) - && cmd->request_buffer != 0) { - unsigned char *b = cmd->request_buffer; - printk(KERN_DEBUG "buffer = %x %x %x %x %x %x %x %x\n", - b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + ms->current_req = 0; + tp->current_req = 0; + if (cmd) { + cmd->result = (ms->stat << 16) + cmd->SCp.Status; + if (ms->stat == DID_OK) + cmd->result += (cmd->SCp.Message << 8); + if (DEBUG_TARGET(cmd)) { + printk(KERN_DEBUG "mesh_done: result = %x, data_ptr=%d, buflen=%d\n", + cmd->result, ms->data_ptr, cmd->request_bufflen); + if ((cmd->cmnd[0] == 0 || cmd->cmnd[0] == 0x12 || cmd->cmnd[0] == 3) + && cmd->request_buffer != 0) { + unsigned char *b = cmd->request_buffer; + printk(KERN_DEBUG "buffer = %x %x %x %x %x %x %x %x\n", + b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + } } + cmd->SCp.this_residual -= ms->data_ptr; + mesh_completed(ms, cmd); } - tp->current_req = 0; - cmd->SCp.this_residual -= ms->data_ptr; - ms->current_req = NULL; - mesh_completed(ms, cmd); - if (ms->phase != reselecting) { + if (start_next) { + out_8(&ms->mesh->sequence, SEQ_ENBRESEL); + udelay(1); ms->phase = idle; mesh_start(ms); } @@ -1221,51 +1630,49 @@ struct scatterlist *scl; struct dbdma_cmd *dcmds; - dma_cmd = ms->data_goes_out? OUTPUT_MORE: INPUT_MORE; + dma_cmd = ms->tgts[ms->conn_tgt].data_goes_out? + OUTPUT_MORE: INPUT_MORE; dcmds = ms->dma_cmds; dtot = 0; - cmd->SCp.this_residual = cmd->request_bufflen; - if (cmd->use_sg > 0) { - total = 0; - scl = (struct scatterlist *) cmd->buffer; - off = ms->data_ptr; - for (i = 0; i < cmd->use_sg; ++i, ++scl) { - total += scl->length; - if (off >= scl->length) { - off -= scl->length; - continue; + if (cmd) { + cmd->SCp.this_residual = cmd->request_bufflen; + if (cmd->use_sg > 0) { + total = 0; + scl = (struct scatterlist *) cmd->buffer; + off = ms->data_ptr; + for (i = 0; i < cmd->use_sg; ++i, ++scl) { + total += scl->length; + if (off >= scl->length) { + off -= scl->length; + continue; + } + if (scl->length > 0xffff) + panic("mesh: scatterlist element >= 64k"); + st_le16(&dcmds->req_count, scl->length - off); + st_le16(&dcmds->command, dma_cmd); + st_le32(&dcmds->phy_addr, + virt_to_phys(scl->address) + off); + dcmds->xfer_status = 0; + ++dcmds; + dtot += scl->length - off; + off = 0; } - if (scl->length > 0xffff) - panic("mesh: scatterlist element >= 64k"); - st_le16(&dcmds->req_count, scl->length - off); - st_le16(&dcmds->command, dma_cmd); + } else if (ms->data_ptr < cmd->request_bufflen) { + dtot = cmd->request_bufflen - ms->data_ptr; + if (dtot > 0xffff) + panic("mesh: transfer size >= 64k"); + st_le16(&dcmds->req_count, dtot); st_le32(&dcmds->phy_addr, - virt_to_phys(scl->address) + off); + virt_to_phys(cmd->request_buffer) + ms->data_ptr); dcmds->xfer_status = 0; ++dcmds; - dtot += scl->length - off; - off = 0; } - } else if (ms->data_ptr < cmd->request_bufflen) { - dtot = cmd->request_bufflen - ms->data_ptr; - if (dtot > 0xffff) - panic("mesh: transfer size >= 64k"); - st_le16(&dcmds->req_count, dtot); - st_le32(&dcmds->phy_addr, - virt_to_phys(cmd->request_buffer) + ms->data_ptr); - dcmds->xfer_status = 0; - ++dcmds; } if (dtot == 0) { /* Either the target has overrun our buffer, or the caller didn't provide a buffer. */ static char mesh_extra_buf[64]; - if (cmd->request_bufflen != 0) - printk(KERN_DEBUG "mesh: target %d overrun, " - "data_ptr=%x total=%x goes_out=%d\n", - ms->conn_tgt, ms->data_ptr, - cmd->request_bufflen, ms->data_goes_out); dtot = sizeof(mesh_extra_buf); st_le16(&dcmds->req_count, dtot); st_le32(&dcmds->phy_addr, virt_to_phys(mesh_extra_buf)); @@ -1284,9 +1691,10 @@ { volatile struct dbdma_regs *md = ms->dma; volatile struct mesh_regs *mr = ms->mesh; + Scsi_Cmnd *cmd = ms->current_req; int t, nb; - if (!ms->data_goes_out) { + if (!ms->tgts[ms->conn_tgt].data_goes_out) { /* wait a little while until the fifo drains */ t = 50; while (t > 0 && mr->fifo_count != 0 @@ -1297,15 +1705,28 @@ } out_le32(&md->control, RUN << 16); /* turn off RUN bit */ nb = (mr->count_hi << 8) + mr->count_lo; - if (ms->data_goes_out) + dlog(ms, "halt_dma fc/count=%.6x", + MKWORD(0, mr->fifo_count, 0, nb)); + if (ms->tgts[ms->conn_tgt].data_goes_out) nb += mr->fifo_count; /* nb is the number of bytes not yet transferred to/from the target. */ ms->data_ptr -= nb; + dlog(ms, "data_ptr %x", ms->data_ptr); if (ms->data_ptr < 0) { printk(KERN_ERR "mesh: halt_dma: data_ptr=%d (nb=%d, ms=%p)\n", ms->data_ptr, nb, ms); ms->data_ptr = 0; +#ifdef MESH_DBG + dumplog(ms, ms->conn_tgt); + dumpslog(ms); +#endif /* MESH_DBG */ + } else if (cmd && cmd->request_bufflen != 0 && + ms->data_ptr > cmd->request_bufflen) { + printk(KERN_DEBUG "mesh: target %d overrun, " + "data_ptr=%x total=%x goes_out=%d\n", + ms->conn_tgt, ms->data_ptr, cmd->request_bufflen, + ms->tgts[ms->conn_tgt].data_goes_out); } ms->dma_started = 0; } @@ -1319,13 +1740,129 @@ data_goes_out(Scsi_Cmnd *cmd) { switch (cmd->cmnd[0]) { + case CHANGE_DEFINITION: + case COMPARE: + case COPY: + case COPY_VERIFY: + case FORMAT_UNIT: + case LOG_SELECT: + case MEDIUM_SCAN: case MODE_SELECT: case MODE_SELECT_10: - case WRITE_6: - case WRITE_10: - case WRITE_12: /* any others? */ + case REASSIGN_BLOCKS: + case RESERVE: + case SEARCH_EQUAL: + case SEARCH_EQUAL_12: + case SEARCH_HIGH: + case SEARCH_HIGH_12: + case SEARCH_LOW: + case SEARCH_LOW_12: + case SEND_DIAGNOSTIC: + case SEND_VOLUME_TAG: + case SET_WINDOW: + case UPDATE_BLOCK: + case WRITE_BUFFER: + case WRITE_6: + case WRITE_10: + case WRITE_12: + case WRITE_LONG: + case WRITE_LONG_2: /* alternate code for WRITE_LONG */ + case WRITE_SAME: + case WRITE_VERIFY: + case WRITE_VERIFY_12: return 1; default: return 0; } } + +#ifdef MESH_DBG +static inline u32 readtb(void) +{ + u32 tb; + +#ifdef DBG_USE_TB + /* Beware: if you enable this, it will crash on 601s. */ + asm ("mftb %0" : "=r" (tb) : ); +#else + tb = 0; +#endif + return tb; +} + +static void dlog(struct mesh_state *ms, char *fmt, int a) +{ + struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; + struct dbglog *tlp, *slp; + + tlp = &tp->log[tp->log_ix]; + slp = &ms->log[ms->log_ix]; + tlp->fmt = fmt; + tlp->tb = readtb(); + tlp->phase = (ms->msgphase << 4) + ms->phase; + tlp->bs0 = ms->mesh->bus_status0; + tlp->bs1 = ms->mesh->bus_status1; + tlp->tgt = ms->conn_tgt; + tlp->d = a; + *slp = *tlp; + if (++tp->log_ix >= N_DBG_LOG) + tp->log_ix = 0; + if (tp->n_log < N_DBG_LOG) + ++tp->n_log; + if (++ms->log_ix >= N_DBG_SLOG) + ms->log_ix = 0; + if (ms->n_log < N_DBG_SLOG) + ++ms->n_log; +} + +static void dumplog(struct mesh_state *ms, int t) +{ + struct mesh_target *tp = &ms->tgts[t]; + struct dbglog *lp; + int i; + + if (tp->n_log == 0) + return; + i = tp->log_ix - tp->n_log; + if (i < 0) + i += N_DBG_LOG; + tp->n_log = 0; + do { + lp = &tp->log[i]; + printk(KERN_DEBUG "mesh log %d: bs=%.2x%.2x ph=%.2x ", + t, lp->bs1, lp->bs0, lp->phase); +#ifdef DBG_USE_TB + printk("tb=%10u ", lp->tb); +#endif + printk(lp->fmt, lp->d); + printk("\n"); + if (++i >= N_DBG_LOG) + i = 0; + } while (i != tp->log_ix); +} + +static void dumpslog(struct mesh_state *ms) +{ + struct dbglog *lp; + int i; + + if (ms->n_log == 0) + return; + i = ms->log_ix - ms->n_log; + if (i < 0) + i += N_DBG_SLOG; + ms->n_log = 0; + do { + lp = &ms->log[i]; + printk(KERN_DEBUG "mesh log: bs=%.2x%.2x ph=%.2x t%d ", + lp->bs1, lp->bs0, lp->phase, lp->tgt); +#ifdef DBG_USE_TB + printk("tb=%10u ", lp->tb); +#endif + printk(lp->fmt, lp->d); + printk("\n"); + if (++i >= N_DBG_SLOG) + i = 0; + } while (i != ms->log_ix); +} +#endif /* MESH_DBG */ diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c --- v2.1.100/linux/drivers/scsi/ncr53c8xx.c Tue Apr 14 14:29:22 1998 +++ linux/drivers/scsi/ncr53c8xx.c Fri May 8 00:22:12 1998 @@ -4638,12 +4638,27 @@ ** Then enable disconnects. */ save_flags(flags); cli(); - if (ncr_reset_scsi_bus(np, 1, driver_setup.settle_delay) != 0) { - printf("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, TERMINATION, DEVICE POWER etc.!\n", ncr_name(np)); - restore_flags(flags); - goto attach_error; - } - ncr_exception (np); + do { + if (ncr_reset_scsi_bus(np, 1, driver_setup.settle_delay) != 0) { + printf("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, " + "TERMINATION, DEVICE POWER etc.!\n", + ncr_name(np)); + restore_flags(flags); + goto attach_error; + } + + /* + ** On Ultra/AXi, the NCR53C876 sometimes does not get the + ** RST bit set in SIST the first time, so retry resetting + ** the SCSI bus until the chip is properly initialized. + */ + np->disc = 1; + ncr_exception (np); + if (np->disc) { + printk("%s: Chip not responding to CRST, retrying\n", + ncr_name(np)); + } + } while (np->disc); restore_flags(flags); np->disc = 1; diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/qlogicisp.c linux/drivers/scsi/qlogicisp.c --- v2.1.100/linux/drivers/scsi/qlogicisp.c Tue Apr 14 14:29:23 1998 +++ linux/drivers/scsi/qlogicisp.c Fri May 8 00:22:12 1998 @@ -55,6 +55,8 @@ #define DEFAULT_LOOP_COUNT 1000000 +#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) + /* End Configuration section *************************************************/ #include @@ -1160,7 +1162,7 @@ static int isp1020_init(struct Scsi_Host *sh) { - u_int io_base; + u_long io_base; struct isp1020_hostdata *hostdata; u_char revision; u_int irq; diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/qlogicpti.c linux/drivers/scsi/qlogicpti.c --- v2.1.100/linux/drivers/scsi/qlogicpti.c Thu Apr 23 20:21:35 1998 +++ linux/drivers/scsi/qlogicpti.c Fri May 8 00:22:12 1998 @@ -563,7 +563,6 @@ } } -static void qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs); static void do_qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs); /* Detect all PTI Qlogic ISP's in the machine. */ @@ -1051,18 +1050,10 @@ return (sts->scsi_status & STATUS_MASK) | (host_status << 16); } -static void do_qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - qlogicpti_intr_handler(irq, dev_id, regs); - spin_unlock_irqrestore(&io_request_lock, flags); -} - #ifndef __sparc_v9__ -static void qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs) +static __inline__ void qlogicpti_intr_handler(int irq, void *dev_id, + struct pt_regs *regs) { static int running = 0; Scsi_Cmnd *Cmnd; @@ -1150,7 +1141,8 @@ #else /* __sparc_v9__ */ -static void qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs) +static __inline__ void qlogicpti_intr_handler(int irq, void *dev_id, + struct pt_regs *regs) { struct qlogicpti *qpti = dev_id; Scsi_Cmnd *Cmnd; @@ -1217,6 +1209,15 @@ } #endif + +static void do_qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + + spin_lock_irqsave(&io_request_lock, flags); + qlogicpti_intr_handler(irq, dev_id, regs); + spin_unlock_irqrestore(&io_request_lock, flags); +} int qlogicpti_abort(Scsi_Cmnd *Cmnd) { diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/sgiwd93.c linux/drivers/scsi/sgiwd93.c --- v2.1.100/linux/drivers/scsi/sgiwd93.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/sgiwd93.c Fri May 8 00:22:12 1998 @@ -0,0 +1,273 @@ +/* + * sgiwd93.c: SGI WD93 scsi driver. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * (In all truth, Jed Schimmel wrote all this code.) + * + * $Id: sgiwd93.c,v 1.1 1998/05/01 01:35:42 ralf Exp $ + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "wd33c93.h" +#include "sgiwd93.h" + +#include + +struct hpc_chunk { + struct hpc_dma_desc desc; + unsigned long padding; +}; + +struct proc_dir_entry proc_scsi_sgiwd93 = { + PROC_SCSI_SGIWD93, 5, "SGIWD93", + S_IFDIR | S_IRUGO | S_IXUGO, 2 +}; + +struct Scsi_Host *sgiwd93_host = NULL; + +/* Wuff wuff, wuff, wd33c93.c, wuff wuff, object oriented, bow wow. */ +static inline void write_wd33c93_count(wd33c93_regs *regp, unsigned long value) +{ + regp->SASR = WD_TRANSFER_COUNT_MSB; + regp->SCMD = ((value >> 16) & 0xff); + regp->SCMD = ((value >> 8) & 0xff); + regp->SCMD = ((value >> 0) & 0xff); +} + +static inline unsigned long read_wd33c93_count(wd33c93_regs *regp) +{ + unsigned long value; + + regp->SASR = WD_TRANSFER_COUNT_MSB; + value = ((regp->SCMD & 0xff) << 16); + value |= ((regp->SCMD & 0xff) << 8); + value |= ((regp->SCMD & 0xff) << 0); + return value; +} + +/* XXX woof! */ +static void sgiwd93_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + wd33c93_intr(sgiwd93_host); +} + +#undef DEBUG_DMA + +static int dma_setup(Scsi_Cmnd *cmd, int datainp) +{ + struct WD33C93_hostdata *hdata = CMDHOSTDATA(cmd); + wd33c93_regs *regp = hdata->regp; + struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) cmd->host->base; + struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->dma_bounce_buffer; + +#ifdef DEBUG_DMA + printk("dma_setup: datainp<%d> hcp<%p> ", + datainp, hcp); +#endif + + hdata->dma_dir = datainp; + + if(cmd->use_sg) { + struct scatterlist *slp = cmd->SCp.buffer; + int i, totlen = 0; + +#ifdef DEBUG_DMA + printk("SCLIST<"); +#endif + for(i = 0; i <= (cmd->use_sg - 1); i++, hcp++) { +#ifdef DEBUG_DMA + printk("[%p,%d]", slp[i].address, slp[i].length); +#endif + dma_cache_wback_inv((unsigned long)slp[i].address, + PAGE_SIZE); + hcp->desc.pbuf = PHYSADDR(slp[i].address); + hcp->desc.cntinfo = (slp[i].length & HPCDMA_BCNT); + totlen += slp[i].length; + } +#ifdef DEBUG_DMA + printk(">tlen<%d>", totlen); +#endif + hdata->dma_bounce_len = totlen; /* a trick... */ + write_wd33c93_count(regp, totlen); + } else { + /* Non-scattered dma. */ +#ifdef DEBUG_DMA + printk("ONEBUF<%p,%d>", cmd->SCp.ptr, cmd->SCp.this_residual); +#endif + dma_cache_wback_inv((unsigned long)cmd->SCp.ptr, PAGE_SIZE); + hcp->desc.pbuf = PHYSADDR(cmd->SCp.ptr); + hcp->desc.cntinfo = (cmd->SCp.this_residual & HPCDMA_BCNT); + hcp++; + write_wd33c93_count(regp, cmd->SCp.this_residual); + } + + /* To make sure, if we trip an HPC bug, that we transfer + * every single byte, we tag on an extra zero length dma + * descriptor at the end of the chain. + */ + hcp->desc.pbuf = 0; + hcp->desc.cntinfo = (HPCDMA_EOX); + +#ifdef DEBUG_DMA + printk(" HPCGO\n"); +#endif + + /* Start up the HPC. */ + hregs->ndptr = PHYSADDR(hdata->dma_bounce_buffer); + if(datainp) + hregs->ctrl = (HPC3_SCTRL_ACTIVE); + else + hregs->ctrl = (HPC3_SCTRL_ACTIVE | HPC3_SCTRL_DIR); + return 0; +} + +static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *SCpnt, + int status) +{ + struct WD33C93_hostdata *hdata = INSTHOSTDATA(instance); + wd33c93_regs *regp = hdata->regp; + struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) SCpnt->host->base; + +#ifdef DEBUG_DMA + printk("dma_stop: status<%d> ", status); +#endif + + /* First stop the HPC and flush it's FIFO. */ + if(hdata->dma_dir) { + hregs->ctrl |= HPC3_SCTRL_FLUSH; + while(hregs->ctrl & HPC3_SCTRL_ACTIVE) + barrier(); + } + hregs->ctrl = 0; + + /* See how far we got and update scatterlist state if necessary. */ + if(SCpnt->use_sg) { + struct scatterlist *slp = SCpnt->SCp.buffer; + int totlen, wd93_residual, transferred, i; + + /* Yep, we were doing the scatterlist thang. */ + totlen = hdata->dma_bounce_len; + wd93_residual = read_wd33c93_count(regp); + transferred = totlen - wd93_residual; + +#ifdef DEBUG_DMA + printk("tlen<%d>resid<%d>transf<%d> ", + totlen, wd93_residual, transferred); +#endif + + /* Avoid long winded partial-transfer search for common case. */ + if(transferred != totlen) { + /* This is the nut case. */ +#ifdef DEBUG_DMA + printk("Jed was here..."); +#endif + for(i = 0; i <= (SCpnt->use_sg - 1); i++) { + if(slp[i].length >= transferred) + break; + transferred -= slp[i].length; + } + } else { + /* This is the common case. */ +#ifdef DEBUG_DMA + printk("did it all..."); +#endif + i = (SCpnt->use_sg - 1); + } + SCpnt->SCp.buffer = &slp[i]; + SCpnt->SCp.buffers_residual = (SCpnt->use_sg - 1 - i); + SCpnt->SCp.ptr = (char *) slp[i].address; + SCpnt->SCp.this_residual = slp[i].length; + } +#ifdef DEBUG_DMA + printk("\n"); +#endif +} + +static inline void init_hpc_chain(uchar *buf) +{ + struct hpc_chunk *hcp = (struct hpc_chunk *) buf; + unsigned long start, end; + + start = (unsigned long) buf; + end = start + PAGE_SIZE; + while(start < end) { + hcp->desc.pnext = PHYSADDR((hcp + 1)); + hcp->desc.cntinfo = HPCDMA_EOX; + hcp++; + start += sizeof(struct hpc_chunk); + }; + hcp--; + hcp->desc.pnext = PHYSADDR(buf); +} + +__initfunc(int sgiwd93_detect(Scsi_Host_Template *HPsUX)) +{ + static unsigned char called = 0; + struct hpc3_scsiregs *hregs = &hpc3c0->scsi_chan0; + struct WD33C93_hostdata *hdata; + uchar *buf; + + if(called) + return 0; /* Should bitch on the console about this... */ + + HPsUX->proc_dir = &proc_scsi_sgiwd93; + + sgiwd93_host = scsi_register(HPsUX, sizeof(struct WD33C93_hostdata)); + sgiwd93_host->base = (unsigned char *) hregs; + + buf = (uchar *) get_free_page(GFP_KERNEL); + init_hpc_chain(buf); + dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE); + + wd33c93_init(sgiwd93_host, (wd33c93_regs *) 0xbfbc0003, + dma_setup, dma_stop, WD33C93_FS_16_20); + + hdata = INSTHOSTDATA(sgiwd93_host); + hdata->no_sync = 0; + hdata->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf)); + dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE); + + request_irq(1, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host); + called = 1; + + return 1; /* Found one. */ +} + +#ifdef MODULE + +#define HOSTS_C + +#include "sgiwd93.h" + +Scsi_Host_Template driver_template = SGIWD93_SCSI; + +#include "scsi_module.c" + +#endif + +int sgiwd93_release(struct Scsi_Host *instance) +{ +#ifdef MODULE + free_irq(1, sgiwd93_intr); + free_page(KSEG0ADDR(hdata->dma_bounce_buffer)); + wd33c93_release(); +#endif + return 1; +} diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/sgiwd93.h linux/drivers/scsi/sgiwd93.h --- v2.1.100/linux/drivers/scsi/sgiwd93.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/sgiwd93.h Fri May 8 00:22:12 1998 @@ -0,0 +1,43 @@ +/* $Id: sgiwd93.h,v 1.2 1998/05/04 09:18:49 ralf Exp $ + * sgiwd93.h: SGI WD93 scsi definitions. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#ifndef _SGIWD93_H +#define _SGIWD93_H + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef CMD_PER_LUN +#define CMD_PER_LUN 8 +#endif + +#ifndef CAN_QUEUE +#define CAN_QUEUE 16 +#endif + +int sgiwd93_detect(Scsi_Host_Template *); +int sgiwd93_release(struct Scsi_Host *instance); +const char *wd33c93_info(void); +int wd33c93_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +int wd33c93_abort(Scsi_Cmnd *); +int wd33c93_reset(Scsi_Cmnd *, unsigned int); + +extern struct proc_dir_entry proc_scsi_sgiwd93; + +#define SGIWD93_SCSI {proc_dir: &proc_scsi_sgiwd93, \ + name: "SGI WD93", \ + detect: sgiwd93_detect, \ + release: sgiwd93_release, \ + queuecommand: wd33c93_queuecommand, \ + abort: wd33c93_abort, \ + reset: wd33c93_reset, \ + can_queue: CAN_QUEUE, \ + this_id: 7, \ + sg_tablesize: SG_ALL, \ + cmd_per_lun: CMD_PER_LUN, \ + use_clustering: DISABLE_CLUSTERING } + +#endif /* !(_SGIWD93_H) */ diff -u --recursive --new-file v2.1.100/linux/drivers/sgi/char/cons_newport.c linux/drivers/sgi/char/cons_newport.c --- v2.1.100/linux/drivers/sgi/char/cons_newport.c Wed Dec 10 10:31:11 1997 +++ linux/drivers/sgi/char/cons_newport.c Fri May 8 00:23:41 1998 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: cons_newport.c,v 1.1 1997/12/02 02:28:23 ralf Exp $ + * $Id: cons_newport.c,v 1.1 1998/01/10 19:05:47 ecd Exp $ */ #include diff -u --recursive --new-file v2.1.100/linux/drivers/sgi/char/newport.h linux/drivers/sgi/char/newport.h --- v2.1.100/linux/drivers/sgi/char/newport.h Wed Dec 10 10:31:11 1997 +++ linux/drivers/sgi/char/newport.h Fri May 8 00:23:41 1998 @@ -1,4 +1,4 @@ -/* $Id: newport.h,v 1.2 1996/06/10 16:38:34 dm Exp $ +/* $Id: newport.h,v 1.1 1998/01/10 19:05:58 ecd Exp $ * newport.h: Defines and register layout for NEWPORT graphics * hardware. * diff -u --recursive --new-file v2.1.100/linux/drivers/sgi/char/sgiserial.c linux/drivers/sgi/char/sgiserial.c --- v2.1.100/linux/drivers/sgi/char/sgiserial.c Thu May 7 22:51:51 1998 +++ linux/drivers/sgi/char/sgiserial.c Fri May 8 00:23:41 1998 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -52,6 +53,19 @@ static int zs_cons_chanin = 0; struct sgi_serial *zs_consinfo = 0; +static struct console sgi_console_driver = { + "debug", + NULL, /* write */ + NULL, /* read */ + NULL, /* device */ + NULL, /* wait_key */ + NULL, /* unblank */ + NULL, /* setup */ + CON_PRINTBUFFER, + -1, + 0, + NULL +}; static unsigned char kgdb_regs[16] = { 0, 0, 0, /* write 0, 1, 2 */ (Rx8 | RxENABLE), /* write 3 */ @@ -960,14 +974,14 @@ /* * zs_console_print is registered for printk. */ -static void zs_console_print(const char *p) + +static void zs_console_print(struct console *co, const char *str, unsigned int count) { - char c; - while((c=*(p++)) != 0) { - if(c == '\n') + while(count--) { + if(*str == '\n') rs_put_char('\r'); - rs_put_char(c); + rs_put_char(*str++); } /* Comment this if you want to have a strict interrupt-driven output */ @@ -1712,7 +1726,7 @@ } -extern void register_console(void (*proc)(const char *)); + static inline void rs_cons_check(struct sgi_serial *ss, int channel) @@ -1723,6 +1737,7 @@ i = o = io = 0; + /* Is this one of the serial console lines? */ if((zs_cons_chanout != channel) && (zs_cons_chanin != channel)) @@ -1730,16 +1745,20 @@ zs_conschan = ss->zs_channel; zs_consinfo = ss; + /* Register the console output putchar, if necessary */ if((zs_cons_chanout == channel)) { o = 1; /* double whee.. */ + if(!consout_registered) { - register_console(zs_console_print); + sgi_console_driver.write = zs_console_print; + register_console(&sgi_console_driver); consout_registered = 1; } } + /* If this is console input, we handle the break received * status interrupt on this line to mean prom_halt(). */ @@ -1756,6 +1775,7 @@ panic("Console baud rate weirdness"); } + /* Set flag variable for this port so that it cannot be * opened for other uses by accident. */ @@ -1766,9 +1786,11 @@ printk("zs%d: console I/O\n", ((channel>>1)&1)); msg_printed = 1; } + } else { printk("zs%d: console %s\n", ((channel>>1)&1), (i==1 ? "input" : (o==1 ? "output" : "WEIRD"))); + } } @@ -1780,6 +1802,7 @@ int chip, channel, i, flags; struct sgi_serial *info; + /* Setup base handler, and timer table. */ init_bh(SERIAL_BH, do_serial_bh); timer_table[RS_TIMER].fn = rs_timer; @@ -1966,6 +1989,7 @@ { int channel; + if(chip) panic("rs_cons_hook called with chip not zero"); if(line != 1 && line != 2) @@ -1981,10 +2005,11 @@ zs_soft[channel].change_needed = 0; zs_soft[channel].clk_divisor = 16; zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); - if(out) + if(out) zs_cons_chanout = ((chip * 2) + channel); - else + else zs_cons_chanin = ((chip * 2) + channel); + rs_cons_check(&zs_soft[channel], channel); } diff -u --recursive --new-file v2.1.100/linux/fs/Makefile linux/fs/Makefile --- v2.1.100/linux/fs/Makefile Mon Apr 6 17:41:00 1998 +++ linux/fs/Makefile Fri May 8 17:54:39 1998 @@ -13,21 +13,17 @@ O_OBJS = open.o read_write.o devices.o file_table.o buffer.o \ super.o block_dev.o stat.o exec.o pipe.o namei.o fcntl.o \ ioctl.o readdir.o select.o fifo.o locks.o filesystems.o \ - inode.o dcache.o attr.o bad_inode.o $(BINFMTS) + dcache.o inode.o attr.o bad_inode.o $(BINFMTS) MOD_LIST_NAME := FS_MODULES ALL_SUB_DIRS = coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \ hpfs sysv smbfs ncpfs ufs affs romfs autofs hfs lockd nfsd \ - nls devpts + nls devpts adfs ifeq ($(CONFIG_QUOTA),y) O_OBJS += dquot.o else O_OBJS += noquot.o -endif - -ifeq ($(CONFIG_TRANS_NAMES),y) -O_OBJS += nametrans.o endif ifeq ($(CONFIG_CODA_FS),y) diff -u --recursive --new-file v2.1.100/linux/fs/affs/Changes linux/fs/affs/Changes --- v2.1.100/linux/fs/affs/Changes Tue Mar 10 10:03:33 1998 +++ linux/fs/affs/Changes Thu May 7 22:58:04 1998 @@ -28,6 +28,26 @@ Please direct bug reports to: hjw@zvw.de +Version 3.9 +----------- + +- Moved cleanup from release_file() to put_inode(). + This makes the the first one obsolete. + +- truncate() zeroes the unused remainder of a + partially used last block when a file is truncated. + It also marks the inode dirty now (which is not + really neccessary as notify_change() will do + it anyway). + +- Added a few comments, fixed some typos (and + introduced some new ones), made the debug messages + more consistent. Changed a bad example in the + doc file (affs.txt). + +- Sets the NOEXEC flag in read_super() for old file + systems, since you can't run programs on them. + Version 3.8 ----------- Bill Hawes kindly reviewed the affs and sent me the diff -u --recursive --new-file v2.1.100/linux/fs/affs/amigaffs.c linux/fs/affs/amigaffs.c --- v2.1.100/linux/fs/affs/amigaffs.c Tue Dec 2 22:25:07 1997 +++ linux/fs/affs/amigaffs.c Thu May 7 22:58:04 1998 @@ -24,7 +24,6 @@ /* * Functions for accessing Amiga-FFS structures. - * */ /* Set *NAME to point to the file name in a file header block in memory @@ -85,7 +84,7 @@ return 0; } -/* Remove a header block from it's hash table (directory). +/* Remove a header block from its hash table (directory). * 'inode' may be any inode on the partition, it's only * used for calculating the block size and superblock * reference. @@ -226,7 +225,7 @@ orig_ino = be32_to_cpu(FILE_END(bh->b_data,inode)->original); if (orig_ino) { /* This is just a link. Nothing much to do. */ - pr_debug(" Removing link.\n"); + pr_debug("AFFS: Removing link.\n"); if ((error = affs_remove_link(bh,inode))) return error; if ((error = affs_remove_hash(bh,inode))) @@ -237,7 +236,7 @@ link_ino = be32_to_cpu(FILE_END(bh->b_data,inode)->link_chain); if (link_ino) { /* This is the complicated case. Yuck. */ - pr_debug(" Removing original with links to it.\n"); + pr_debug("AFFS: Removing original with links to it.\n"); /* Unlink the object and its first link from their directories. */ if ((error = affs_remove_hash(bh,inode))) return error; @@ -275,7 +274,7 @@ return 1; } /* Plain file/dir. This is the simplest case. */ - pr_debug(" Removing plain file/dir.\n"); + pr_debug("AFFS: Removing plain file/dir.\n"); if ((error = affs_remove_hash(bh,inode))) return error; return 0; @@ -307,6 +306,11 @@ sum += be32_to_cpu(*p++); return sum; } + +/* + * Calculate the checksum of a disk block and store it + * at the indicated position. + */ void affs_fix_checksum(int bsize, void *data, int cspos) diff -u --recursive --new-file v2.1.100/linux/fs/affs/bitmap.c linux/fs/affs/bitmap.c --- v2.1.100/linux/fs/affs/bitmap.c Tue Mar 10 10:03:33 1998 +++ linux/fs/affs/bitmap.c Thu May 7 22:58:04 1998 @@ -103,6 +103,15 @@ unlock_super(sb); } +/* + * Allocate a block in the given allocation zone. + * Since we have to byte-swap the bitmap on little-endian + * machines, this is rather expensive. Therefor we will + * preallocate up to 16 blocks from the same word, if + * possible. We are not doing preallocations in the + * header zone, though. + */ + static s32 affs_balloc(struct inode *inode, int zone_no) { @@ -174,6 +183,8 @@ return block; } +/* Find a new allocation zone, starting at zone_no. */ + static int affs_find_new_zone(struct super_block *sb, int zone_no) { @@ -257,12 +268,14 @@ zone->z_end = zone->z_start + az->az_size; zone->z_az_no = i; zone->z_lru_time = jiffies; - pr_debug(" ++ found zone (%d) in bm %d at lw offset %d with %d free blocks\n", + pr_debug("AFFS: found zone (%d) in bm %d at lw offset %d with %d free blocks\n", i,(i >> (sb->s_blocksize_bits - 7)),zone->z_start,az->az_free); unlock_super(sb); return az->az_free; } +/* Allocate a new header block. */ + s32 affs_new_header(struct inode *inode) { @@ -292,6 +305,8 @@ return block; } +/* Allocate a new data block. */ + s32 affs_new_data(struct inode *inode) { @@ -378,9 +393,7 @@ pr_debug("AFFS: make_zones(): num_zones=%d\n",sb->u.affs_sb.s_num_az); mid = (sb->u.affs_sb.s_num_az + 1) / 2; - sb->u.affs_sb.s_zones[0].z_az_no = mid; - affs_find_new_zone(sb,0); - for (i = 1; i < MAX_ZONES; i++) { + for (i = 0; i < MAX_ZONES; i++) { sb->u.affs_sb.s_zones[i].z_az_no = mid; affs_find_new_zone(sb,i); } diff -u --recursive --new-file v2.1.100/linux/fs/affs/file.c linux/fs/affs/file.c --- v2.1.100/linux/fs/affs/file.c Tue Mar 10 10:03:33 1998 +++ linux/fs/affs/file.c Thu May 7 22:58:04 1998 @@ -41,7 +41,6 @@ static ssize_t affs_file_read_ofs(struct file *filp, char *buf, size_t count, loff_t *ppos); static ssize_t affs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos); static ssize_t affs_file_write_ofs(struct file *filp, const char *buf, size_t cnt, loff_t *ppos); -static int affs_release_file(struct inode *inode, struct file *filp); static int alloc_ext_cache(struct inode *inode); static struct file_operations affs_file_operations = { @@ -53,7 +52,7 @@ NULL, /* ioctl - default */ generic_file_mmap, /* mmap */ NULL, /* no special open */ - affs_release_file, /* release */ + NULL, /* release */ file_fsync, /* brute force, but works */ NULL, /* fasync */ NULL, /* check_media_change */ @@ -93,7 +92,7 @@ NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open */ - affs_release_file, /* release */ + NULL, /* release */ file_fsync, /* brute force, but works */ NULL, /* fasync */ NULL, /* check_media_change */ @@ -184,7 +183,7 @@ } /* Now the other way round: Calculate the sequence - * number of a extension block of a key at the + * number of an extension block of a key at the * given index in the cache. */ @@ -545,7 +544,7 @@ } blocksize = AFFS_I2BSIZE(inode) - 24; if (!(S_ISREG(inode->i_mode))) { - pr_debug("affs_file_read: mode = %07o",inode->i_mode); + pr_debug("AFFS: file_read: mode = %07o",inode->i_mode); return -EINVAL; } if (*ppos >= inode->i_size || count <= 0) @@ -680,11 +679,8 @@ inode->i_mode); return -EINVAL; } - if (!inode->u.affs_i.i_ec) { - if (alloc_ext_cache(inode)) { - return -ENOMEM; - } - } + if (!inode->u.affs_i.i_ec && alloc_ext_cache(inode)) + return -ENOMEM; if (filp->f_flags & O_APPEND) pos = inode->i_size; else @@ -740,11 +736,13 @@ return written; } -/* Free any preallocated blocks */ +/* Free any preallocated blocks. */ + void affs_free_prealloc(struct inode *inode) { - struct super_block *sb = inode->i_sb; + struct super_block *sb = inode->i_sb; + struct affs_zone *zone; int block; pr_debug("AFFS: free_prealloc(ino=%lu)\n", inode->i_ino); @@ -755,123 +753,141 @@ inode->u.affs_i.i_pa_cnt--; affs_free_block(sb, block); } + if (inode->u.affs_i.i_zone) { + zone = &sb->u.affs_sb.s_zones[inode->u.affs_i.i_zone]; + if (zone->z_ino == inode->i_ino) + zone->z_ino = 0; + } } +/* Truncate (or enlarge) a file to the requested size. */ + void affs_truncate(struct inode *inode) { - struct buffer_head *bh; - struct buffer_head *ebh; - struct affs_zone *zone; - int first; + struct buffer_head *bh = NULL; + int first; /* First block to be thrown away */ int block; s32 key; s32 *keyp; s32 ekey; s32 ptype, stype; int freethis; - int blocksize; + int net_blocksize; + int blocksize = AFFS_I2BSIZE(inode); int rem; int ext; pr_debug("AFFS: truncate(inode=%ld,size=%lu)\n",inode->i_ino,inode->i_size); - blocksize = AFFS_I2BSIZE(inode) - ((inode->i_sb->u.affs_sb.s_flags & SF_OFS) ? 24 : 0); - first = (inode->i_size + blocksize - 1) / blocksize; + net_blocksize = blocksize - ((inode->i_sb->u.affs_sb.s_flags & SF_OFS) ? 24 : 0); + first = (inode->i_size + net_blocksize - 1) / net_blocksize; if (inode->u.affs_i.i_lastblock < first - 1) { - if (!inode->u.affs_i.i_ec) { - if (alloc_ext_cache(inode)) { - /* Fine! No way to indicate an error. What can we do? */ - return; - } + /* There has to be at least one new block to be allocated */ + if (!inode->u.affs_i.i_ec && alloc_ext_cache(inode)) { + /* XXX Fine! No way to indicate an error. */ + return /* -ENOSPC */; } bh = affs_getblock(inode,first - 1); - - affs_free_prealloc(inode); - if (inode->u.affs_i.i_zone) { - lock_super(inode->i_sb); - zone = &inode->i_sb->u.affs_sb.s_zones[inode->u.affs_i.i_zone]; - if (zone->z_ino == inode->i_ino) - zone->z_ino = 0; - unlock_super(inode->i_sb); - } if (!bh) { affs_warning(inode->i_sb,"truncate","Cannot extend file"); - inode->i_size = blocksize * (inode->u.affs_i.i_lastblock + 1); + inode->i_size = net_blocksize * (inode->u.affs_i.i_lastblock + 1); } else if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) { - rem = inode->i_size % blocksize; - DATA_FRONT(bh)->data_size = cpu_to_be32(rem ? rem : blocksize); - affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5); + rem = inode->i_size % net_blocksize; + DATA_FRONT(bh)->data_size = cpu_to_be32(rem ? rem : net_blocksize); + affs_fix_checksum(blocksize,bh->b_data,5); mark_buffer_dirty(bh,0); } - affs_brelse(bh); - return; + goto out_truncate; } - ekey = inode->i_ino; - ext = 0; + ekey = inode->i_ino; + ext = 0; + /* Free all blocks starting at 'first' and all then-empty + * extension blocks. Do not free the header block, though. + */ while (ekey) { - if (!(bh = affs_bread(inode->i_dev,ekey,AFFS_I2BSIZE(inode)))) { + if (!(bh = affs_bread(inode->i_dev,ekey,blocksize))) { affs_error(inode->i_sb,"truncate","Cannot read block %d",ekey); - break; + goto out_truncate; } - ptype = be32_to_cpu(((struct file_front *)bh->b_data)->primary_type); - stype = be32_to_cpu(FILE_END(bh->b_data,inode)->secondary_type); - if (stype != ST_FILE || (ptype != T_SHORT && ptype != T_LIST)) { - affs_error(inode->i_sb,"truncate","Bad block (ptype=%d, stype=%d)", - ptype,stype); - affs_brelse(bh); - break; + if (affs_checksum_block(blocksize,bh->b_data,&ptype,&stype)) { + affs_error(inode->i_sb,"truncate","Checksum error in header/ext block %d", + ekey); + goto out_truncate; } - /* Do not throw away file header */ + if (stype != ST_FILE || (ptype != T_SHORT && ptype != T_LIST)) { + affs_error(inode->i_sb,"truncate", + "Bad block (key=%d, ptype=%d, stype=%d)",ekey,ptype,stype); + goto out_truncate; + } + /* Do we have to free this extension block after + * freeing the data blocks pointed to? + */ freethis = first == 0 && ekey != inode->i_ino; + + /* Free the data blocks. 'first' is relative to this + * extension block and may well lie behind this block. + */ for (block = first; block < AFFS_I2HSIZE(inode); block++) { keyp = &AFFS_BLOCK(bh->b_data,inode,block); key = be32_to_cpu(*keyp); if (key) { *keyp = 0; affs_free_block(inode->i_sb,key); - } else { - block = AFFS_I2HSIZE(inode); + } else break; - } } - keyp = &GET_END_PTR(struct file_end,bh->b_data,AFFS_I2BSIZE(inode))->extension; + keyp = &GET_END_PTR(struct file_end,bh->b_data,blocksize)->extension; key = be32_to_cpu(*keyp); + + /* If 'first' is in this block or is the first + * in the next one, this will be the last in + * the list, thus we have to adjust the count + * and zero the pointer to the next ext block. + */ if (first <= AFFS_I2HSIZE(inode)) { - ((struct file_front *)bh->b_data)->block_count = be32_to_cpu(first); + ((struct file_front *)bh->b_data)->block_count = cpu_to_be32(first); first = 0; *keyp = 0; - if ((inode->i_sb->u.affs_sb.s_flags & SF_OFS) && first > 0) { - block = be32_to_cpu(AFFS_BLOCK(bh->b_data,inode,first - 1)); - if ((ebh = affs_bread(inode->i_dev,block,AFFS_I2BSIZE(inode)))) { - if(!(affs_checksum_block(AFFS_I2BSIZE(inode),ebh->b_data, - &ptype,NULL))) { - rem = inode->i_size % blocksize; - rem = cpu_to_be32(rem ? blocksize : rem); - ((struct data_front *)ebh->b_data)->data_size = rem; - ((struct data_front *)ebh->b_data)->next_data = 0; - affs_fix_checksum(AFFS_I2BSIZE(inode),ebh->b_data,5); - mark_buffer_dirty(ebh,1); - } - affs_brelse(ebh); - } - } - } else { + affs_fix_checksum(blocksize,bh->b_data,5); + mark_buffer_dirty(bh,1); + } else first -= AFFS_I2HSIZE(inode); - } - if (freethis) { /* Don't bother fixing checksum */ - affs_brelse(bh); + affs_brelse(bh); + bh = NULL; + if (freethis) /* Don't bother fixing checksum */ affs_free_block(inode->i_sb,ekey); - } else { - affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5); - mark_buffer_dirty(bh,1); - affs_brelse(bh); - } ekey = key; } - inode->u.affs_i.i_lastblock = ((inode->i_size + blocksize - 1) / blocksize) - 1; + block = ((inode->i_size + net_blocksize - 1) / net_blocksize) - 1; + inode->u.affs_i.i_lastblock = block; + + /* If the file is not truncated to a block boundary, + * the partial block after the EOF must be zeroed + * so it cannot become accessible again. + */ + + rem = inode->i_size % net_blocksize; + if (rem) { + if ((inode->i_sb->u.affs_sb.s_flags & SF_OFS)) + rem += 24; + pr_debug("AFFS: Zeroing from offset %d in block %d\n",rem,block); + bh = affs_getblock(inode,block); + if (bh) { + memset(bh->b_data + rem,0,blocksize - rem); + if ((inode->i_sb->u.affs_sb.s_flags & SF_OFS)) { + ((struct data_front *)bh->b_data)->data_size = cpu_to_be32(rem); + ((struct data_front *)bh->b_data)->next_data = 0; + affs_fix_checksum(blocksize,bh->b_data,5); + } + mark_buffer_dirty(bh,1); + } else + affs_error(inode->i_sb,"truncate","Cannot read block %d",block); + } +out_truncate: + affs_brelse(bh); /* Invalidate cache */ if (inode->u.affs_i.i_ec) { inode->u.affs_i.i_ec->max_ext = 0; @@ -880,31 +896,13 @@ inode->u.affs_i.i_ec->kc[key].kc_last = -1; } } - -} - -static int -affs_release_file(struct inode *inode, struct file *filp) -{ - struct super_block *sb = inode->i_sb; - struct affs_zone *zone; - - pr_debug("AFFS: release_file(ino=%lu)\n",inode->i_ino); - - if (filp->f_mode & 2) { /* Free preallocated blocks */ - affs_free_prealloc(inode); - if (inode->u.affs_i.i_zone) { - zone = &sb->u.affs_sb.s_zones[inode->u.affs_i.i_zone]; - if (zone->z_ino == inode->i_ino) - zone->z_ino = 0; - } - } - return 0; + mark_inode_dirty(inode); } /* * Called only when we need to allocate the extension cache. */ + static int alloc_ext_cache(struct inode *inode) { @@ -928,9 +926,7 @@ /* We only have to initialize non-zero values. * get_free_page() zeroed the page already. */ - key = inode->u.affs_i.i_original; - if (!inode->u.affs_i.i_original) - key = inode->i_ino; + key = inode->i_ino; inode->u.affs_i.i_ec->ec[0] = key; for (i = 0; i < 4; i++) { inode->u.affs_i.i_ec->kc[i].kc_this_key = key; diff -u --recursive --new-file v2.1.100/linux/fs/affs/inode.c linux/fs/affs/inode.c --- v2.1.100/linux/fs/affs/inode.c Tue Mar 10 10:03:33 1998 +++ linux/fs/affs/inode.c Thu May 7 22:58:04 1998 @@ -255,6 +255,8 @@ { pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n", inode->i_ino,inode->i_nlink); + + affs_free_prealloc(inode); if (inode->i_count == 1) { unsigned long cache_page = (unsigned long) inode->u.affs_i.i_ec; if (cache_page) { @@ -323,6 +325,11 @@ return inode; } + +/* + * Add an entry to a directory. Create the header block + * and insert it into the hash table. + */ int affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode, diff -u --recursive --new-file v2.1.100/linux/fs/affs/namei.c linux/fs/affs/namei.c --- v2.1.100/linux/fs/affs/namei.c Thu May 7 22:51:51 1998 +++ linux/fs/affs/namei.c Thu May 7 22:58:04 1998 @@ -253,6 +253,7 @@ inode->i_nlink = retval; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; + dir->i_version = ++event; mark_inode_dirty(inode); d_delete(dentry); mark_inode_dirty(dir); @@ -277,7 +278,7 @@ if (!inode) goto out; - pr_debug(" -- ino=%lu\n",inode->i_ino); + pr_debug("AFFS: ino=%lu\n",inode->i_ino); if (dir->i_sb->u.affs_sb.s_flags & SF_OFS) inode->i_op = &affs_file_inode_operations_ofs; else @@ -390,6 +391,7 @@ inode->i_nlink = retval; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; retval = 0; + dir->i_version = ++event; mark_inode_dirty(dir); mark_inode_dirty(inode); d_delete(dentry); @@ -546,7 +548,7 @@ unsigned long new_ino; int retval; - pr_debug("AFFS: rename(old=%lu,\"%*s\" (inode=%p) to new=%lu,\"%*s\" (inode=%p) )\n", + pr_debug("AFFS: rename(old=%lu,\"%*s\" (inode=%p) to new=%lu,\"%*s\" (inode=%p))\n", old_dir->i_ino,old_dentry->d_name.len,old_dentry->d_name.name,old_inode, new_dir->i_ino,new_dentry->d_name.len,new_dentry->d_name.name,new_inode); diff -u --recursive --new-file v2.1.100/linux/fs/affs/super.c linux/fs/affs/super.c --- v2.1.100/linux/fs/affs/super.c Mon Apr 6 17:41:00 1998 +++ linux/fs/affs/super.c Thu May 7 22:58:04 1998 @@ -44,7 +44,7 @@ { int i; - pr_debug("affs_put_super()\n"); + pr_debug("AFFS: put_super()\n"); for (i = 0; i < sb->u.affs_sb.s_bm_count; i++) affs_brelse(sb->u.affs_sb.s_bitmap[i].bm_bh); @@ -262,7 +262,7 @@ unsigned long mount_flags; unsigned long offset; - pr_debug("affs_read_super(%s)\n",data ? (const char *)data : "no options"); + pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options"); MOD_INC_USE_COUNT; lock_super(s); @@ -396,6 +396,7 @@ /* fall thru */ case FS_OFS: s->u.affs_sb.s_flags |= SF_OFS; + s->s_flags |= MS_NOEXEC; break; case MUFS_DCOFS: case MUFS_INTLOFS: @@ -403,6 +404,7 @@ case FS_DCOFS: case FS_INTLOFS: s->u.affs_sb.s_flags |= SF_INTL | SF_OFS; + s->s_flags |= MS_NOEXEC; break; default: goto out_unknown_fs; @@ -433,7 +435,7 @@ ptype = num_bm * sizeof(struct affs_bm_info) + az_no * sizeof(struct affs_alloc_zone) + MAX_ZONES * sizeof(struct affs_zone); - pr_debug("num_bm=%d, az_no=%d, sum=%d\n",num_bm,az_no,ptype); + pr_debug("AFFS: num_bm=%d, az_no=%d, sum=%d\n",num_bm,az_no,ptype); if (!(s->u.affs_sb.s_bitmap = kmalloc(ptype, GFP_KERNEL))) goto out_no_bitmap; memset(s->u.affs_sb.s_bitmap,0,ptype); @@ -597,7 +599,7 @@ mapidx, num_bm); goto out_free_bitmap; out_no_root: - printk(KERN_ERR "AFFS: get root inode failed\n"); + printk(KERN_ERR "AFFS: Get root inode failed\n"); /* * Begin the cascaded cleanup ... diff -u --recursive --new-file v2.1.100/linux/fs/buffer.c linux/fs/buffer.c --- v2.1.100/linux/fs/buffer.c Thu May 7 22:51:52 1998 +++ linux/fs/buffer.c Fri May 8 17:54:39 1998 @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -266,9 +267,9 @@ sync_supers(dev); sync_inodes(dev); sync_buffers(dev, 0); - sync_dquots(dev, -1); - /* - * FIXME(eric) we need to sync the physical devices here. + DQUOT_SYNC(dev); + /* + * FIXME(eric) we need to sync the physical devices here. * This is because some (scsi) controllers have huge amounts of * cache onboard (hundreds of Mb), and we need to instruct * them to commit all of the dirty memory to disk, and we should @@ -285,7 +286,7 @@ sync_buffers(dev, 0); sync_supers(dev); sync_inodes(dev); - sync_dquots(dev, -1); + DQUOT_SYNC(dev); return sync_buffers(dev, 1); } diff -u --recursive --new-file v2.1.100/linux/fs/dquot.c linux/fs/dquot.c --- v2.1.100/linux/fs/dquot.c Thu May 7 22:51:53 1998 +++ linux/fs/dquot.c Fri May 8 17:54:39 1998 @@ -9,33 +9,22 @@ * have a consistent diskquota tracking system. The ideas of both * user and group quotas are based on the Melbourne quota system as * used on BSD derived systems. The internal implementation is - * based on the LINUX inode-subsystem with added complexity of the - * diskquota system. This implementation is not based on any BSD - * kernel sourcecode. + * based on one of the several variants of the LINUX inode-subsystem + * with added complexity of the diskquota system. * - * Version: $Id: dquot.c,v 1.11 1997/01/06 06:53:02 davem Exp $ + * Version: $Id: dquot.c,v 6.3 1996/11/17 18:35:34 mvw Exp mvw $ * - * Author: Marco van Wieringen - * - * Fixes: Dmitry Gorodchanin , 11 Feb 96 - * removed race conditions in dqput(), dqget() and iput(). - * Andi Kleen removed all verify_area() calls, 31 Dec 96 - * Nick Kralevich , 21 Jul 97 - * Fixed a condition where user and group quotas could get mixed up. + * Author: Marco van Wieringen * - * Chris Rankin , 31 Dec 97, 2-4 Jan 98 - * Fixed kernel API so that the user can get the quota for any - * group s/he belongs to. Also return useful error codes when - * turning quotas off, and fixed sync_dquot() so that all devices - * are synced when dev==NODEV. - * - * (C) Copyright 1994, 1995 Marco van Wieringen + * Fixes: Dmitry Gorodchanin , 11 Feb 96 * + * (C) Copyright 1994 - 1997 Marco van Wieringen */ #include #include #include + #include #include #include @@ -46,129 +35,153 @@ #include #include #include +#include +#include #include -#define __DQUOT_VERSION__ "dquot_5.6.0" +#define __DQUOT_VERSION__ "dquot_6.4.0" + +int nr_dquots = 0, nr_free_dquots = 0; +int max_dquots = NR_DQUOTS; static char quotamessage[MAX_QUOTA_MESSAGE]; static char *quotatypes[] = INITQFNAMES; -static int nr_dquots = 0, nr_free_dquots = 0; -static struct dquot *hash_table[NR_DQHASH]; -static struct dquot *first_dquot; +static kmem_cache_t *dquot_cachep; + +static struct dquot *dquot_hash[NR_DQHASH]; +static struct free_dquot_queue { + struct dquot *head; + struct dquot **last; +} free_dquots = { NULL, &free_dquots.head }; +static struct dquot *inuse_list = NULL; +static int dquot_updating[NR_DQHASH]; + static struct dqstats dqstats; +static struct wait_queue *dquot_wait = (struct wait_queue *)NULL, + *update_wait = (struct wait_queue *)NULL; -static struct wait_queue *dquot_wait = (struct wait_queue *)NULL; +static inline char is_enabled(struct vfsmount *vfsmnt, short type) +{ + switch (type) { + case USRQUOTA: + return((vfsmnt->mnt_dquot.flags & DQUOT_USR_ENABLED) != 0); + case GRPQUOTA: + return((vfsmnt->mnt_dquot.flags & DQUOT_GRP_ENABLED) != 0); + } + return(0); +} -extern void add_dquot_ref(kdev_t dev, short type); -extern void reset_dquot_ptrs(kdev_t dev, short type); +static inline char sb_has_quota_enabled(struct super_block *sb, short type) +{ + struct vfsmount *vfsmnt; -#ifndef min -#define min(a,b) ((a) < (b)) ? (a) : (b) -#endif + return((vfsmnt = lookup_vfsmnt(sb->s_dev)) != (struct vfsmount *)NULL && is_enabled(vfsmnt, type)); +} -/* - * Functions for management of the hashlist. - */ -static inline int const hashfn(kdev_t dev, unsigned int id, short type) +static inline char dev_has_quota_enabled(kdev_t dev, short type) { - return((HASHDEV(dev) ^ id) * (MAXQUOTAS - type)) % NR_DQHASH; + struct vfsmount *vfsmnt; + + return((vfsmnt = lookup_vfsmnt(dev)) != (struct vfsmount *)NULL && is_enabled(vfsmnt, type)); } -static inline struct dquot **const hash(kdev_t dev, unsigned int id, short type) +static inline int const hashfn(kdev_t dev, unsigned int id, short type) { - return(hash_table + hashfn(dev, id, type)); + return((HASHDEV(dev) ^ id) * (MAXQUOTAS - type)) % NR_DQHASH; } -static inline int has_quota_enabled(kdev_t dev, short type) +static inline void insert_dquot_hash(struct dquot *dquot) { - struct vfsmount *vfsmnt; + struct dquot **htable; - return((vfsmnt = lookup_vfsmnt(dev)) != (struct vfsmount *)NULL && - (vfsmnt->mnt_quotas[type] != (struct file *)NULL)); + htable = &dquot_hash[hashfn(dquot->dq_dev, dquot->dq_id, dquot->dq_type)]; + if ((dquot->dq_hash_next = *htable) != NULL) + (*htable)->dq_hash_pprev = &dquot->dq_hash_next; + *htable = dquot; + dquot->dq_hash_pprev = htable; } -static void insert_dquot_free(struct dquot *dquot) +static inline void hash_dquot(struct dquot *dquot) { - dquot->dq_next = first_dquot; - dquot->dq_prev = first_dquot->dq_prev; - dquot->dq_next->dq_prev = dquot; - dquot->dq_prev->dq_next = dquot; - first_dquot = dquot; + insert_dquot_hash(dquot); } -static void remove_dquot_free(struct dquot *dquot) +static inline void unhash_dquot(struct dquot *dquot) { - if (first_dquot == dquot) - first_dquot = first_dquot->dq_next; - if (dquot->dq_next) - dquot->dq_next->dq_prev = dquot->dq_prev; - if (dquot->dq_prev) - dquot->dq_prev->dq_next = dquot->dq_next; - dquot->dq_next = dquot->dq_prev = NODQUOT; + if (dquot->dq_hash_pprev) { + if (dquot->dq_hash_next) + dquot->dq_hash_next->dq_hash_pprev = dquot->dq_hash_pprev; + *(dquot->dq_hash_pprev) = dquot->dq_hash_next; + dquot->dq_hash_pprev = NULL; + } } -static void insert_dquot_hash(struct dquot *dquot) +static inline struct dquot *find_dquot(unsigned int hashent, kdev_t dev, unsigned int id, short type) { - struct dquot **hash_ent; + struct dquot *dquot; - hash_ent = hash(dquot->dq_dev, dquot->dq_id, dquot->dq_type); - dquot->dq_hash_next = *hash_ent; - dquot->dq_hash_prev = NODQUOT; - if (dquot->dq_hash_next) - dquot->dq_hash_next->dq_hash_prev = dquot; - *hash_ent = dquot; + for (dquot = dquot_hash[hashent]; dquot; dquot = dquot->dq_hash_next) + if (dquot->dq_dev == dev && dquot->dq_id == id && dquot->dq_type == type) + break; + return dquot; } -static void remove_dquot_hash(struct dquot *dquot) +static inline void put_dquot_head(struct dquot *dquot) { - struct dquot **hash_ent; + if ((dquot->dq_next = free_dquots.head) != NULL) + free_dquots.head->dq_pprev = &dquot->dq_next; + else + free_dquots.last = &dquot->dq_next; + free_dquots.head = dquot; + dquot->dq_pprev = &free_dquots.head; + nr_free_dquots++; +} - hash_ent = hash(dquot->dq_dev, dquot->dq_id, dquot->dq_type); - if (*hash_ent == dquot) - *hash_ent = dquot->dq_hash_next; - if (dquot->dq_hash_next) - dquot->dq_hash_next->dq_hash_prev = dquot->dq_hash_prev; - if (dquot->dq_hash_prev) - dquot->dq_hash_prev->dq_hash_next = dquot->dq_hash_next; - dquot->dq_hash_prev = dquot->dq_hash_next = NODQUOT; +static inline void put_dquot_last(struct dquot *dquot) +{ + dquot->dq_next = NULL; + dquot->dq_pprev = free_dquots.last; + *free_dquots.last = dquot; + free_dquots.last = &dquot->dq_next; + nr_free_dquots++; } -static void put_last_free(struct dquot *dquot) +static inline void remove_free_dquot(struct dquot *dquot) { - remove_dquot_free(dquot); - dquot->dq_prev = first_dquot->dq_prev; - dquot->dq_prev->dq_next = dquot; - dquot->dq_next = first_dquot; - dquot->dq_next->dq_prev = dquot; + if (dquot->dq_pprev) { + if (dquot->dq_next) + dquot->dq_next->dq_pprev = dquot->dq_pprev; + else + free_dquots.last = dquot->dq_pprev; + *dquot->dq_pprev = dquot->dq_next; + dquot->dq_pprev = NULL; + nr_free_dquots--; + } } -static void grow_dquots(void) +static inline void put_inuse(struct dquot *dquot) { - struct dquot *dquot; - int cnt; + if ((dquot->dq_next = inuse_list) != NULL) + inuse_list->dq_pprev = &dquot->dq_next; + inuse_list = dquot; + dquot->dq_pprev = &inuse_list; +} - if (!(dquot = (struct dquot*) get_free_page(GFP_KERNEL))) - return; - dqstats.pages_allocated++; - cnt = PAGE_SIZE / sizeof(struct dquot); - nr_dquots += cnt; - nr_free_dquots += cnt; - if (!first_dquot) { - dquot->dq_next = dquot->dq_prev = first_dquot = dquot++; - cnt--; +static inline void remove_inuse(struct dquot *dquot) +{ + if (dquot->dq_pprev) { + if (dquot->dq_next) + dquot->dq_next->dq_pprev = dquot->dq_pprev; + *dquot->dq_pprev = dquot->dq_next; + dquot->dq_pprev = NULL; } - for (; cnt; cnt--) - insert_dquot_free(dquot++); } -/* - * Functions for locking and waiting on dquots. - */ static void __wait_on_dquot(struct dquot *dquot) { - struct wait_queue wait = {current, NULL}; + struct wait_queue wait = { current, NULL }; add_wait_queue(&dquot->dq_wait, &wait); repeat: @@ -202,39 +215,22 @@ wake_up(&dquot->dq_wait); } } -/* - * Note that we don't want to disturb any wait-queues when we discard - * an dquot. - * - * FIXME: As soon as we have a nice solution for the inode problem we - * can also fix this one. I.e. the volatile part. - */ -static void clear_dquot(struct dquot * dquot) -{ - struct wait_queue *wait; - - wait_on_dquot(dquot); - remove_dquot_hash(dquot); - remove_dquot_free(dquot); - wait = ((volatile struct dquot *) dquot)->dq_wait; - if (dquot->dq_count) - nr_free_dquots++; - memset(dquot, 0, sizeof(*dquot)); - ((volatile struct dquot *) dquot)->dq_wait = wait; - insert_dquot_free(dquot); -} static void write_dquot(struct dquot *dquot) { - short type = dquot->dq_type; - struct file *filp = dquot->dq_mnt->mnt_quotas[type]; + short type; + struct file *filp; mm_segment_t fs; loff_t offset; + type = dquot->dq_type; + filp = dquot->dq_mnt->mnt_dquot.files[type]; + if (!(dquot->dq_flags & DQ_MOD) || (filp == (struct file *)NULL)) return; + lock_dquot(dquot); - down(&dquot->dq_mnt->mnt_sem); + down(&dquot->dq_mnt->mnt_dquot.semaphore); offset = dqoff(dquot->dq_id); fs = get_fs(); set_fs(KERNEL_DS); @@ -242,29 +238,35 @@ if (filp->f_op->write(filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk), &offset) == sizeof(struct dqblk)) dquot->dq_flags &= ~DQ_MOD; - up(&dquot->dq_mnt->mnt_sem); + up(&dquot->dq_mnt->mnt_dquot.semaphore); set_fs(fs); + unlock_dquot(dquot); dqstats.writes++; } static void read_dquot(struct dquot *dquot) { - short type = dquot->dq_type; - struct file *filp = dquot->dq_mnt->mnt_quotas[type]; + short type; + struct file *filp; mm_segment_t fs; loff_t offset; + type = dquot->dq_type; + filp = dquot->dq_mnt->mnt_dquot.files[type]; + if (filp == (struct file *)NULL) return; + lock_dquot(dquot); - down(&dquot->dq_mnt->mnt_sem); + down(&dquot->dq_mnt->mnt_dquot.semaphore); offset = dqoff(dquot->dq_id); fs = get_fs(); set_fs(KERNEL_DS); filp->f_op->read(filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk), &offset); - up(&dquot->dq_mnt->mnt_sem); + up(&dquot->dq_mnt->mnt_dquot.semaphore); set_fs(fs); + if (dquot->dq_bhardlimit == 0 && dquot->dq_bsoftlimit == 0 && dquot->dq_ihardlimit == 0 && dquot->dq_isoftlimit == 0) dquot->dq_flags |= DQ_FAKE; @@ -272,46 +274,292 @@ dqstats.reads++; } +void clear_dquot(struct dquot *dquot) +{ + struct wait_queue *wait; + + /* So we don't disappear. */ + dquot->dq_count++; + + wait_on_dquot(dquot); + + if (--dquot->dq_count > 0) + remove_inuse(dquot); + else + remove_free_dquot(dquot); + unhash_dquot(dquot); + wait = dquot->dq_wait; + memset(dquot, 0, sizeof(*dquot)); barrier(); + dquot->dq_wait = wait; + put_dquot_head(dquot); +} + +void invalidate_dquots(kdev_t dev, short type) +{ + struct dquot *dquot, *next = NULL; + int pass = 0; + + dquot = free_dquots.head; +repeat: + while (dquot) { + next = dquot->dq_next; + if (dquot->dq_dev != dev || dquot->dq_type != type) + goto next; + clear_dquot(dquot); + next: + dquot = next; + } + + if (pass == 0) { + dquot = inuse_list; + pass = 1; + goto repeat; + } +} + int sync_dquots(kdev_t dev, short type) { - struct dquot *dquot = first_dquot; - int i; + struct dquot *dquot, *next; + int pass = 0; - dqstats.syncs++; - for (i = 0; i < nr_dquots * 2; i++, dquot = dquot->dq_next) { - if ((dev != NODEV && dquot->dq_dev != dev) || dquot->dq_count == 0 ) - continue; - if (type != -1 && dquot->dq_type != type) - continue; + dquot = free_dquots.head; +repeat: + while (dquot) { + next = dquot->dq_next; + if ((dev && dquot->dq_dev != dev) || + (type != -1 && dquot->dq_type != type)) + goto next; wait_on_dquot(dquot); if (dquot->dq_flags & DQ_MOD) write_dquot(dquot); + next: + dquot = next; + } + + if (pass == 0) { + dquot = inuse_list; + pass = 1; + goto repeat; } + dqstats.syncs++; return(0); } -/* - * Trash the cache for a certain type on a device. - */ -void invalidate_dquots(kdev_t dev, short type) +void dqput(struct dquot *dquot) { - struct dquot *dquot, *next; - int cnt; + if (!dquot) + return; - next = first_dquot; - for (cnt = nr_dquots ; cnt > 0 ; cnt--) { - dquot = next; - next = dquot->dq_next; - if (dquot->dq_dev != dev || dquot->dq_type != type) + /* + * If the dq_mnt pointer isn't initialized this entry needs no + * checking and doesn't need to be written. It just an empty + * dquot that is put back on to the freelist. + */ + if (dquot->dq_mnt != (struct vfsmount *)NULL) { + dqstats.drops++; + wait_on_dquot(dquot); + + if (!dquot->dq_count) { + printk("VFS: dqput: trying to free free dquot\n"); + printk("VFS: device %s, dquot of %s %d\n", kdevname(dquot->dq_dev), + quotatypes[dquot->dq_type], dquot->dq_id); + return; + } +we_slept: + if (dquot->dq_count > 1) { + dquot->dq_count--; + return; + } else { + wake_up(&dquot_wait); + + if (dquot->dq_flags & DQ_MOD) { + write_dquot(dquot); + wait_on_dquot(dquot); + goto we_slept; + } + } + } + + if (--dquot->dq_count == 0) { + remove_inuse(dquot); + put_dquot_last(dquot); /* Place at end of LRU free queue */ + } + + return; +} + +static void grow_dquots(void) +{ + struct dquot *dquot; + int cnt = 32; + + while (cnt > 0) { + dquot = kmem_cache_alloc(dquot_cachep, SLAB_KERNEL); + if(!dquot) + return; + + nr_dquots++; + memset((caddr_t)dquot, 0, sizeof(struct dquot)); + put_dquot_head(dquot); + cnt--; + } +} + +static struct dquot *find_best_candidate_weighted(struct dquot *dquot) +{ + int limit, myscore; + unsigned long bestscore; + struct dquot *best = NULL; + + if (dquot) { + bestscore = 2147483647; + limit = nr_free_dquots >> 2; + do { + if (!((dquot->dq_flags & DQ_LOCKED) || (dquot->dq_flags & DQ_MOD))) { + myscore = dquot->dq_referenced; + if (myscore < bestscore) { + bestscore = myscore; + best = dquot; + } + } + dquot = dquot->dq_next; + } while (dquot && --limit); + } + return best; +} + +static inline struct dquot *find_best_free(struct dquot *dquot) +{ + int limit; + + if (dquot) { + limit = nr_free_dquots >> 5; + do { + if (dquot->dq_referenced == 0) + return dquot; + dquot = dquot->dq_next; + } while (dquot && --limit); + } + return NULL; +} + +struct dquot *get_empty_dquot(void) +{ + struct dquot *dquot; + +repeat: + dquot = find_best_free(free_dquots.head); + if (!dquot) + goto pressure; +got_it: + dquot->dq_count++; + wait_on_dquot(dquot); + unhash_dquot(dquot); + remove_free_dquot(dquot); + + memset(dquot, 0, sizeof(*dquot)); + dquot->dq_count = 1; + + put_inuse(dquot); + return dquot; +pressure: + if (nr_dquots < max_dquots) { + grow_dquots(); + goto repeat; + } + + dquot = find_best_candidate_weighted(free_dquots.head); + if (!dquot) { + printk("VFS: No free dquots, contact mvw@planets.elm.net\n"); + sleep_on(&dquot_wait); + goto repeat; + } + if (dquot->dq_flags & DQ_LOCKED) { + wait_on_dquot(dquot); + goto repeat; + } else if (dquot->dq_flags & DQ_MOD) { + write_dquot(dquot); + goto repeat; + } + goto got_it; +} + +struct dquot *dqget(kdev_t dev, unsigned int id, short type) +{ + unsigned int hashent = hashfn(dev, id, type); + struct dquot *dquot, *empty = NULL; + struct vfsmount *vfsmnt; + + if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL || is_enabled(vfsmnt, type) == 0) + return(NODQUOT); + +we_slept: + if ((dquot = find_dquot(hashent, dev, id, type)) == NULL) { + if (empty == NULL) { + dquot_updating[hashent]++; + empty = get_empty_dquot(); + if (!--dquot_updating[hashent]) + wake_up(&update_wait); + goto we_slept; + } + dquot = empty; + dquot->dq_id = id; + dquot->dq_type = type; + dquot->dq_dev = dev; + dquot->dq_mnt = vfsmnt; + read_dquot(dquot); + hash_dquot(dquot); + } else { + if (!dquot->dq_count++) { + remove_free_dquot(dquot); + put_inuse(dquot); + } else + dqstats.cache_hits++; + wait_on_dquot(dquot); + if (empty) + dqput(empty); + } + + while (dquot_updating[hashent]) + sleep_on(&update_wait); + + dquot->dq_referenced++; + dqstats.lookups++; + + return dquot; +} + +static void add_dquot_ref(kdev_t dev, short type) +{ + struct file *filp; + struct inode *inode; + + for (filp = inuse_filps; filp; filp = filp->f_next) { + inode = filp->f_dentry->d_inode; + if (!inode || inode->i_dev != dev) continue; - if (dquot->dq_flags & DQ_LOCKED) { - printk("VFS: dquot busy on removed device %s\n", kdevname(dev)); + if (filp->f_mode & FMODE_WRITE && inode->i_sb && inode->i_sb->dq_op) { + inode->i_sb->dq_op->initialize(inode, type); + inode->i_flags |= S_QUOTA; + } + } +} + +static void reset_dquot_ptrs(kdev_t dev, short type) +{ + struct file *filp; + struct inode *inode; + + for (filp = inuse_filps; filp; filp = filp->f_next) { + inode = filp->f_dentry->d_inode; + if (!inode || inode->i_dev != dev) continue; + if (IS_QUOTAINIT(inode)) { + if (inode->i_sb && inode->i_sb->dq_op) + inode->i_sb->dq_op->drop(inode); + inode->i_dquot[type] = NODQUOT; + inode->i_flags &= ~S_QUOTA; } - if (dquot->dq_flags & DQ_MOD) - write_dquot(dquot); - dqstats.drops++; - clear_dquot(dquot); } } @@ -359,229 +607,108 @@ unlock_dquot(dquot); } -static inline int need_print_warning(short type, struct dquot *dquot) +static inline char need_print_warning(short type, uid_t initiator, struct dquot *dquot) { switch (type) { case USRQUOTA: - return(current->fsuid == dquot->dq_id); + return(initiator == dquot->dq_id); case GRPQUOTA: - return(current->fsgid == dquot->dq_id); + return(initiator == dquot->dq_id); } return(0); } -static int check_idq(struct dquot *dquot, short type, u_long short inodes) +static inline char ignore_hardlimit(struct dquot *dquot, uid_t initiator) +{ + return(initiator == 0 && dquot->dq_mnt->mnt_dquot.rsquash[dquot->dq_type] == 0); +} + +static int check_idq(struct dquot *dquot, short type, u_long short inodes, uid_t initiator, struct tty_struct *tty) { if (inodes <= 0 || dquot->dq_flags & DQ_FAKE) return(QUOTA_OK); + if (dquot->dq_ihardlimit && - (dquot->dq_curinodes + inodes) > dquot->dq_ihardlimit && - !capable(CAP_SYS_RESOURCE)) { + (dquot->dq_curinodes + inodes) > dquot->dq_ihardlimit && + !ignore_hardlimit(dquot, initiator)) { if ((dquot->dq_flags & DQ_INODES) == 0 && - need_print_warning(type, dquot)) { - sprintf(quotamessage, "%s: write failed, %s file limit reached\r\n", + need_print_warning(type, initiator, dquot)) { + sprintf(quotamessage, "%s: write failed, %s file limit reached\n", dquot->dq_mnt->mnt_dirname, quotatypes[type]); - tty_write_message(current->tty, quotamessage); + tty_write_message(tty, quotamessage); dquot->dq_flags |= DQ_INODES; } return(NO_QUOTA); } + if (dquot->dq_isoftlimit && (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit && - dquot->dq_itime && CURRENT_TIME >= dquot->dq_itime && - !capable(CAP_SYS_RESOURCE)) { - if (need_print_warning(type, dquot)) { - sprintf(quotamessage, "%s: warning, %s file quota exceeded too long.\r\n", + dquot->dq_itime && CURRENT_TIME >= dquot->dq_itime && + !ignore_hardlimit(dquot, initiator)) { + if (need_print_warning(type, initiator, dquot)) { + sprintf(quotamessage, "%s: warning, %s file quota exceeded too long.\n", dquot->dq_mnt->mnt_dirname, quotatypes[type]); - tty_write_message(current->tty, quotamessage); + tty_write_message(tty, quotamessage); } return(NO_QUOTA); } + if (dquot->dq_isoftlimit && (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit && - dquot->dq_itime == 0 && - !capable(CAP_SYS_RESOURCE)) { - if (need_print_warning(type, dquot)) { - sprintf(quotamessage, "%s: warning, %s file quota exceeded\r\n", + dquot->dq_itime == 0) { + if (need_print_warning(type, initiator, dquot)) { + sprintf(quotamessage, "%s: warning, %s file quota exceeded\n", dquot->dq_mnt->mnt_dirname, quotatypes[type]); - tty_write_message(current->tty, quotamessage); + tty_write_message(tty, quotamessage); } - dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_iexp[type]; + dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.inode_expire[type]; } + return(QUOTA_OK); } -static int check_bdq(struct dquot *dquot, short type, u_long blocks) +static int check_bdq(struct dquot *dquot, short type, u_long blocks, uid_t initiator, struct tty_struct *tty, char warn) { if (blocks <= 0 || dquot->dq_flags & DQ_FAKE) return(QUOTA_OK); + if (dquot->dq_bhardlimit && - (dquot->dq_curblocks + blocks) > dquot->dq_bhardlimit && - !capable(CAP_SYS_RESOURCE)) { - if ((dquot->dq_flags & DQ_BLKS) == 0 && - need_print_warning(type, dquot)) { - sprintf(quotamessage, "%s: write failed, %s disk limit reached.\r\n", + (dquot->dq_curblocks + blocks) > dquot->dq_bhardlimit && + !ignore_hardlimit(dquot, initiator)) { + if (warn && (dquot->dq_flags & DQ_BLKS) == 0 && + need_print_warning(type, initiator, dquot)) { + sprintf(quotamessage, "%s: write failed, %s disk limit reached.\n", dquot->dq_mnt->mnt_dirname, quotatypes[type]); - tty_write_message(current->tty, quotamessage); + tty_write_message(tty, quotamessage); dquot->dq_flags |= DQ_BLKS; } return(NO_QUOTA); } + if (dquot->dq_bsoftlimit && (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit && - dquot->dq_btime && CURRENT_TIME >= dquot->dq_btime && - !capable(CAP_SYS_RESOURCE)) { - if (need_print_warning(type, dquot)) { - sprintf(quotamessage, "%s: write failed, %s disk quota exceeded too long.\r\n", + dquot->dq_btime && CURRENT_TIME >= dquot->dq_btime && + !ignore_hardlimit(dquot, initiator)) { + if (warn && need_print_warning(type, initiator, dquot)) { + sprintf(quotamessage, "%s: write failed, %s disk quota exceeded too long.\n", dquot->dq_mnt->mnt_dirname, quotatypes[type]); - tty_write_message(current->tty, quotamessage); + tty_write_message(tty, quotamessage); } return(NO_QUOTA); } + if (dquot->dq_bsoftlimit && (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit && - dquot->dq_btime == 0 && - !capable(CAP_SYS_RESOURCE)) { - if (need_print_warning(type, dquot)) { - sprintf(quotamessage, "%s: warning, %s disk quota exceeded\r\n", + dquot->dq_btime == 0) { + if (warn && need_print_warning(type, initiator, dquot)) { + sprintf(quotamessage, "%s: warning, %s disk quota exceeded\n", dquot->dq_mnt->mnt_dirname, quotatypes[type]); - tty_write_message(current->tty, quotamessage); - } - dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_bexp[type]; - } - return(QUOTA_OK); -} - -static void dqput(struct dquot *dquot) -{ - if (!dquot) - return; - /* - * If the dq_mnt pointer isn't initialized this entry needs no - * checking and doesn't need to be written. It just an empty - * dquot that is put back into the freelist. - */ - if (dquot->dq_mnt != (struct vfsmount *)NULL) { - dqstats.drops++; - wait_on_dquot(dquot); - if (!dquot->dq_count) { - printk("VFS: dqput: trying to free free dquot\n"); - printk("VFS: device %s, dquot of %s %d\n", kdevname(dquot->dq_dev), - quotatypes[dquot->dq_type], dquot->dq_id); - return; + tty_write_message(tty, quotamessage); } -repeat: - if (dquot->dq_count > 1) { - dquot->dq_count--; - return; - } - wake_up(&dquot_wait); - if (dquot->dq_flags & DQ_MOD) { - write_dquot(dquot); /* we can sleep - so do again */ - wait_on_dquot(dquot); - goto repeat; - } - } - if (dquot->dq_count) { - dquot->dq_count--; - nr_free_dquots++; + dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.block_expire[type]; } - return; -} - -static struct dquot *get_empty_dquot(void) -{ - struct dquot *dquot, *best; - int cnt; - - if (nr_dquots < NR_DQUOTS && nr_free_dquots < (nr_dquots >> 2)) - grow_dquots(); -repeat: - dquot = first_dquot; - best = NODQUOT; - for (cnt = 0; cnt < nr_dquots; dquot = dquot->dq_next, cnt++) { - if (!dquot->dq_count) { - if (!best) - best = dquot; - if (!(dquot->dq_flags & DQ_MOD) && !(dquot->dq_flags & DQ_LOCKED)) { - best = dquot; - break; - } - } - } - if (!best || best->dq_flags & DQ_MOD || best->dq_flags & DQ_LOCKED) - if (nr_dquots < NR_DQUOTS) { - grow_dquots(); - goto repeat; - } - dquot = best; - if (!dquot) { - printk("VFS: No free dquots - contact mvw@mcs.ow.org\n"); - sleep_on(&dquot_wait); - goto repeat; - } - if (dquot->dq_flags & DQ_LOCKED) { - wait_on_dquot(dquot); - goto repeat; - } - if (dquot->dq_flags & DQ_MOD) { - write_dquot(dquot); - goto repeat; - } - if (dquot->dq_count) - goto repeat; - clear_dquot(dquot); - dquot->dq_count = 1; - nr_free_dquots--; - if (nr_free_dquots < 0) { - printk ("VFS: get_empty_dquot: bad free dquot count.\n"); - nr_free_dquots = 0; - } - return(dquot); -} - -static struct dquot *dqget(kdev_t dev, unsigned int id, short type) -{ - struct dquot *dquot, *empty; - struct vfsmount *vfsmnt; - - if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL || - (vfsmnt->mnt_quotas[type] == (struct file *)0)) - return(NODQUOT); - dqstats.lookups++; - empty = get_empty_dquot(); -repeat: - dquot = *(hash(dev, id, type)); - while (dquot) { - if (dquot->dq_dev != dev || dquot->dq_id != id || - dquot->dq_type != type) { - dquot = dquot->dq_hash_next; - continue; - } - wait_on_dquot(dquot); - if (dquot->dq_dev != dev || dquot->dq_id != id || - dquot->dq_type != type) - goto repeat; - if (!dquot->dq_count) - nr_free_dquots--; - dquot->dq_count++; - if (empty) - dqput(empty); - dqstats.cache_hits++; - return(dquot); - } - if (!empty) - return(NODQUOT); - dquot = empty; - dquot->dq_id = id; - dquot->dq_type = type; - dquot->dq_dev = dev; - dquot->dq_mnt = vfsmnt; - put_last_free(dquot); - insert_dquot_hash(dquot); - read_dquot(dquot); - return(dquot); + return(QUOTA_OK); } /* @@ -590,54 +717,57 @@ */ static int set_dqblk(kdev_t dev, int id, short type, int flags, struct dqblk *dqblk) { + int error; struct dquot *dquot; struct dqblk dq_dqblk; if (dqblk == (struct dqblk *)NULL) return(-EFAULT); - if (flags & QUOTA_SYSCALL) { - if (copy_from_user(&dq_dqblk, dqblk, sizeof(struct dqblk))) - return -EFAULT; - } else { - memcpy(&dq_dqblk, dqblk, sizeof(struct dqblk)); - } + if (flags & QUOTA_SYSCALL) + if ((error = copy_from_user((caddr_t)&dq_dqblk, (caddr_t)dqblk, sizeof(struct dqblk))) != 0) + return(error); + else + memcpy((caddr_t)&dq_dqblk, (caddr_t)dqblk, sizeof(struct dqblk)); + if ((dquot = dqget(dev, id, type)) != NODQUOT) { lock_dquot(dquot); - if (id > 0 && (flags & (SET_QUOTA|SET_QLIMIT))) { + + if (id > 0 && ((flags & SET_QUOTA) || (flags & SET_QLIMIT))) { dquot->dq_bhardlimit = dq_dqblk.dqb_bhardlimit; dquot->dq_bsoftlimit = dq_dqblk.dqb_bsoftlimit; dquot->dq_ihardlimit = dq_dqblk.dqb_ihardlimit; dquot->dq_isoftlimit = dq_dqblk.dqb_isoftlimit; } - if (flags & (SET_QUOTA|SET_USE)) { + + if ((flags & SET_QUOTA) || (flags & SET_USE)) { if (dquot->dq_isoftlimit && dquot->dq_curinodes < dquot->dq_isoftlimit && dq_dqblk.dqb_curinodes >= dquot->dq_isoftlimit) - dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_iexp[type]; + dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.inode_expire[type]; dquot->dq_curinodes = dq_dqblk.dqb_curinodes; if (dquot->dq_curinodes < dquot->dq_isoftlimit) dquot->dq_flags &= ~DQ_INODES; if (dquot->dq_bsoftlimit && dquot->dq_curblocks < dquot->dq_bsoftlimit && dq_dqblk.dqb_curblocks >= dquot->dq_bsoftlimit) - dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_bexp[type]; + dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.block_expire[type]; dquot->dq_curblocks = dq_dqblk.dqb_curblocks; if (dquot->dq_curblocks < dquot->dq_bsoftlimit) dquot->dq_flags &= ~DQ_BLKS; } + if (id == 0) { - /* - * Change in expiretimes, change them in dq_mnt. - */ - dquot->dq_mnt->mnt_bexp[type] = dquot->dq_btime = dq_dqblk.dqb_btime; - dquot->dq_mnt->mnt_iexp[type] = dquot->dq_itime = dq_dqblk.dqb_itime; + dquot->dq_mnt->mnt_dquot.block_expire[type] = dquot->dq_btime = dq_dqblk.dqb_btime; + dquot->dq_mnt->mnt_dquot.inode_expire[type] = dquot->dq_itime = dq_dqblk.dqb_itime; } + if (dq_dqblk.dqb_bhardlimit == 0 && dq_dqblk.dqb_bsoftlimit == 0 && dq_dqblk.dqb_ihardlimit == 0 && dq_dqblk.dqb_isoftlimit == 0) dquot->dq_flags |= DQ_FAKE; else dquot->dq_flags &= ~DQ_FAKE; + dquot->dq_flags |= DQ_MOD; unlock_dquot(dquot); dqput(dquot); @@ -650,14 +780,14 @@ struct dquot *dquot; int error; - if (has_quota_enabled(dev, type)) { + if (dev_has_quota_enabled(dev, type)) { if (dqblk == (struct dqblk *)NULL) return(-EFAULT); if ((dquot = dqget(dev, id, type)) != NODQUOT) { - error = copy_to_user(dqblk, (char *)&dquot->dq_dqb, sizeof(struct dqblk)); + error = copy_to_user((caddr_t)dqblk, (caddr_t)&dquot->dq_dqb, sizeof(struct dqblk)); dqput(dquot); - return error ? -EFAULT : 0; + return(error); } } return(-ESRCH); @@ -667,25 +797,67 @@ { dqstats.allocated_dquots = nr_dquots; dqstats.free_dquots = nr_free_dquots; - return copy_to_user(addr, (caddr_t)&dqstats, sizeof(struct dqstats)) - ? -EFAULT : 0; + return(copy_to_user(addr, (caddr_t)&dqstats, sizeof(struct dqstats))); +} + +static int quota_root_squash(kdev_t dev, short type, int *addr) +{ + struct vfsmount *vfsmnt; + int new_value, error; + + if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL) + return(-ENODEV); + + if ((error = copy_from_user((caddr_t)&new_value, (caddr_t)addr, sizeof(int))) != 0) + return(error); + + vfsmnt->mnt_dquot.rsquash[type] = new_value; + return(0); } /* - * Initialize pointer in an inode to the right dquots. + * This is a simple algorithm that calculates the size of a file in blocks. + * This is only used on filesystems that do not have an i_blocks count. + */ +static u_long isize_to_blocks(size_t isize, size_t blksize) +{ + u_long blocks; + u_long indirect; + + if (!blksize) + blksize = BLOCK_SIZE; + blocks = (isize / blksize) + ((isize % blksize) ? 1 : 0); + if (blocks > 10) { + indirect = ((blocks - 11) >> 8) + 1; /* single indirect blocks */ + if (blocks > (10 + 256)) { + indirect += ((blocks - 267) >> 16) + 1; /* double indirect blocks */ + if (blocks > (10 + 256 + (256 << 8))) + indirect++; /* triple indirect blocks */ + } + blocks += indirect; + } + return(blocks); +} + +/* + * Externally referenced functions through dquot_operations in inode. */ void dquot_initialize(struct inode *inode, short type) { + struct dquot *dquot; unsigned int id = 0; short cnt; - struct dquot *tmp; - if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) { + if (S_ISREG(inode->i_mode) || + S_ISDIR(inode->i_mode) || + S_ISLNK(inode->i_mode)) { for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (type != -1 && cnt != type) continue; - if (!has_quota_enabled(inode->i_dev, cnt)) + + if (!sb_has_quota_enabled(inode->i_sb, cnt)) continue; + if (inode->i_dquot[cnt] == NODQUOT) { switch (cnt) { case USRQUOTA: @@ -695,17 +867,13 @@ id = inode->i_gid; break; } - - tmp = dqget(inode->i_dev, id, cnt); - /* We may sleep in dqget(), so check it again. - * Dmitry Gorodchanin 02/11/96 - */ + dquot = dqget(inode->i_dev, id, cnt); if (inode->i_dquot[cnt] != NODQUOT) { - dqput(tmp); + dqput(dquot); continue; } - inode->i_dquot[cnt] = tmp; - inode->i_flags |= S_WRITE; + inode->i_dquot[cnt] = dquot; + inode->i_flags |= S_QUOTA; } } } @@ -713,82 +881,58 @@ void dquot_drop(struct inode *inode) { + struct dquot *dquot; short cnt; - struct dquot * tmp; + inode->i_flags &= ~S_QUOTA; for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (inode->i_dquot[cnt] == NODQUOT) continue; - /* We can sleep at dqput(). So we must do it this way. - * Dmitry Gorodchanin 02/11/96 - */ - tmp = inode->i_dquot[cnt]; + dquot = inode->i_dquot[cnt]; inode->i_dquot[cnt] = NODQUOT; - dqput(tmp); - } - inode->i_flags &= ~S_WRITE; -} - -/* - * This is a simple algorithm that calculates the size of a file in blocks. - * This is only used on filesystems that do not have an i_blocks count. - */ -static u_long isize_to_blocks(size_t isize, size_t blksize) -{ - u_long blocks; - u_long indirect; - - if (!blksize) - blksize = BLOCK_SIZE; - blocks = (isize / blksize) + ((isize % blksize) ? 1 : 0); - if (blocks > 10) { - indirect = ((blocks - 11) >> 8) + 1; /* single indirect blocks */ - if (blocks > (10 + 256)) { - indirect += ((blocks - 267) >> 16) + 1; /* double indirect blocks */ - if (blocks > (10 + 256 + (256 << 8))) - indirect++; /* triple indirect blocks */ - } - blocks += indirect; + dqput(dquot); } - return(blocks); } -/* - * Externally referenced functions through dquot_operations. - */ -int dquot_alloc_block(const struct inode *inode, unsigned long number) +int dquot_alloc_block(const struct inode *inode, unsigned long number, uid_t initiator, char warn) { unsigned short cnt; + struct tty_struct *tty = current->tty; for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (inode->i_dquot[cnt] == NODQUOT) continue; - if (check_bdq(inode->i_dquot[cnt], cnt, number)) + if (check_bdq(inode->i_dquot[cnt], cnt, number, initiator, tty, warn)) return(NO_QUOTA); } + for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (inode->i_dquot[cnt] == NODQUOT) continue; dquot_incr_blocks(inode->i_dquot[cnt], number); } + return(QUOTA_OK); } -int dquot_alloc_inode(const struct inode *inode, unsigned long number) +int dquot_alloc_inode(const struct inode *inode, unsigned long number, uid_t initiator) { unsigned short cnt; + struct tty_struct *tty = current->tty; for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (inode->i_dquot[cnt] == NODQUOT) continue; - if (check_idq(inode->i_dquot[cnt], cnt, number)) + if (check_idq(inode->i_dquot[cnt], cnt, number, initiator, tty)) return(NO_QUOTA); } + for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (inode->i_dquot[cnt] == NODQUOT) continue; dquot_incr_inodes(inode->i_dquot[cnt], number); } + return(QUOTA_OK); } @@ -817,11 +961,12 @@ /* * Transfer the number of inode and blocks from one diskquota to an other. */ -int dquot_transfer(struct inode *inode, struct iattr *iattr, char direction) +int dquot_transfer(struct inode *inode, struct iattr *iattr, char direction, uid_t initiator) { unsigned long blocks; struct dquot *transfer_from[MAXQUOTAS]; struct dquot *transfer_to[MAXQUOTAS]; + struct tty_struct *tty = current->tty; short cnt, disc; /* @@ -840,7 +985,7 @@ transfer_from[cnt] = NODQUOT; transfer_to[cnt] = NODQUOT; - if (!has_quota_enabled(inode->i_dev, cnt)) + if (!sb_has_quota_enabled(inode->i_sb, cnt)) continue; switch (cnt) { @@ -858,8 +1003,8 @@ break; } - if (check_idq(transfer_to[cnt], cnt, 1) == NO_QUOTA || - check_bdq(transfer_to[cnt], cnt, blocks) == NO_QUOTA) { + if (check_idq(transfer_to[cnt], cnt, 1, initiator, tty) == NO_QUOTA || + check_bdq(transfer_to[cnt], cnt, blocks, initiator, tty, 0) == NO_QUOTA) { for (disc = 0; disc <= cnt; disc++) { dqput(transfer_from[disc]); dqput(transfer_to[disc]); @@ -883,10 +1028,12 @@ dquot_decr_inodes(transfer_from[cnt], 1); dquot_decr_blocks(transfer_from[cnt], blocks); } + if (transfer_to[cnt] != NODQUOT) { dquot_incr_inodes(transfer_to[cnt], 1); dquot_incr_blocks(transfer_to[cnt], blocks); } + if (inode->i_dquot[cnt] != NODQUOT) { dqput(transfer_from[cnt]); dqput(inode->i_dquot[cnt]); @@ -896,16 +1043,24 @@ dqput(transfer_to[cnt]); } } + return(QUOTA_OK); } -void dquot_init(void) + +__initfunc(void dquot_init_hash(void)) { - printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\r\n", - __DQUOT_VERSION__); - memset(hash_table, 0, sizeof(hash_table)); + printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\n", __DQUOT_VERSION__); + + dquot_cachep = kmem_cache_create("dquot", sizeof(struct dquot), + sizeof(unsigned long) * 4, + SLAB_HWCACHE_ALIGN, NULL, NULL); + + if (!dquot_cachep) + panic("Cannot create dquot SLAB cache\n"); + + memset(dquot_hash, 0, sizeof(dquot_hash)); memset((caddr_t)&dqstats, 0, sizeof(dqstats)); - first_dquot = NODQUOT; } /* @@ -921,6 +1076,30 @@ dquot_transfer }; +static inline void set_enable_flags(struct vfsmount *vfsmnt, short type) +{ + switch (type) { + case USRQUOTA: + vfsmnt->mnt_dquot.flags |= DQUOT_USR_ENABLED; + break; + case GRPQUOTA: + vfsmnt->mnt_dquot.flags |= DQUOT_GRP_ENABLED; + break; + } +} + +static inline void reset_enable_flags(struct vfsmount *vfsmnt, short type) +{ + switch (type) { + case USRQUOTA: + vfsmnt->mnt_dquot.flags &= ~DQUOT_USR_ENABLED; + break; + case GRPQUOTA: + vfsmnt->mnt_dquot.flags &= ~DQUOT_GRP_ENABLED; + break; + } +} + /* * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount) */ @@ -929,25 +1108,28 @@ struct vfsmount *vfsmnt; short cnt; - if ( !(vfsmnt = lookup_vfsmnt(dev)) ) - return -ENODEV; - for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (type != -1 && cnt != type) continue; - if (vfsmnt->mnt_quotas[cnt] == (struct file *)NULL) - { - if(type == -1) - continue; - return -ESRCH; - } + + if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL || + is_enabled(vfsmnt, cnt) == 0 || + vfsmnt->mnt_sb == (struct super_block *)NULL) + continue; + vfsmnt->mnt_sb->dq_op = (struct dquot_operations *)NULL; + reset_dquot_ptrs(dev, cnt); invalidate_dquots(dev, cnt); - fput(vfsmnt->mnt_quotas[cnt]); - vfsmnt->mnt_quotas[cnt] = (struct file *)NULL; - vfsmnt->mnt_iexp[cnt] = vfsmnt->mnt_bexp[cnt] = (time_t)NULL; + + fput(vfsmnt->mnt_dquot.files[cnt]); + + reset_enable_flags(vfsmnt, cnt); + vfsmnt->mnt_dquot.files[cnt] = (struct file *)NULL; + vfsmnt->mnt_dquot.inode_expire[cnt] = 0; + vfsmnt->mnt_dquot.block_expire[cnt] = 0; } + return(0); } @@ -962,11 +1144,11 @@ int error; vfsmnt = lookup_vfsmnt(dev); - if (vfsmnt == NULL) + if (vfsmnt == (struct vfsmount *)NULL) return -ENODEV; - if (vfsmnt->mnt_quotas[type] != NULL) - return -EBUSY; + if (is_enabled(vfsmnt, type)) + return(-EBUSY); tmp = getname(path); error = PTR_ERR(tmp); @@ -986,8 +1168,13 @@ return -EACCES; } + if (inode->i_size == 0 || (inode->i_size % sizeof(struct dqblk)) != 0) { + iput(inode); + return(-EINVAL); + } + filp = get_empty_filp(); - if (filp != NULL) { + if (filp != (struct file *)NULL) { filp->f_mode = (O_RDWR + 1) & O_ACCMODE; filp->f_flags = O_RDWR; filp->f_dentry = dentry; @@ -1000,14 +1187,18 @@ if (filp->f_op && filp->f_op->open) error = filp->f_op->open(inode, filp); if (!error) { - vfsmnt->mnt_quotas[type] = filp; + set_enable_flags(vfsmnt, type); + vfsmnt->mnt_dquot.files[type] = filp; + dquot = dqget(dev, 0, type); - vfsmnt->mnt_iexp[type] = (dquot) ? dquot->dq_itime : MAX_IQ_TIME; - vfsmnt->mnt_bexp[type] = (dquot) ? dquot->dq_btime : MAX_DQ_TIME; + vfsmnt->mnt_dquot.inode_expire[type] = (dquot) ? dquot->dq_itime : MAX_IQ_TIME; + vfsmnt->mnt_dquot.block_expire[type] = (dquot) ? dquot->dq_btime : MAX_DQ_TIME; dqput(dquot); + vfsmnt->mnt_sb->dq_op = &dquot_operations; add_dquot_ref(dev, type); - return 0; + + return(0); } put_write_access(inode); } @@ -1016,8 +1207,10 @@ put_filp(filp); } else error = -EMFILE; + dput(dentry); - return error; + + return(error); } /* @@ -1045,17 +1238,17 @@ break; case Q_GETQUOTA: if (((type == USRQUOTA && current->uid != id) || - (type == GRPQUOTA && in_group_p(id))) && - !capable(CAP_SYS_ADMIN)) + (type == GRPQUOTA && current->gid != id)) && + !capable(CAP_SYS_RESOURCE)) goto out; break; default: - if (!capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_RESOURCE)) goto out; } ret = -EINVAL; - dev = NODEV; + dev = 0; if (special != NULL || (cmds != Q_SYNC && cmds != Q_GETSTATS)) { mode_t mode; struct dentry * dentry; @@ -1098,12 +1291,17 @@ goto out; case Q_GETSTATS: ret = get_stats(addr); + goto out; + case Q_RSQUASH: + ret = quota_root_squash(dev, type, (int *) addr); + goto out; default: goto out; } flags |= QUOTA_SYSCALL; - if (has_quota_enabled(dev, type)) + + if (dev_has_quota_enabled(dev, type)) ret = set_dqblk(dev, id, type, flags, (struct dqblk *) addr); else ret = -ESRCH; diff -u --recursive --new-file v2.1.100/linux/fs/ext2/balloc.c linux/fs/ext2/balloc.c --- v2.1.100/linux/fs/ext2/balloc.c Thu May 7 22:51:53 1998 +++ linux/fs/ext2/balloc.c Fri May 8 17:54:39 1998 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -321,8 +322,7 @@ "bit already cleared for block %lu", block); else { - if (sb->dq_op) - sb->dq_op->free_block(inode, fs_to_dq_blocks(1, sb->s_blocksize)); + DQUOT_FREE_BLOCK(sb, inode, 1); gdp->bg_free_blocks_count = cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)+1); es->s_free_blocks_count = @@ -524,12 +524,7 @@ /* * Check quota for allocation of this block. */ - if (sb->dq_op) - if (sb->dq_op->alloc_block (inode, fs_to_dq_blocks(1, sb->s_blocksize))) { - unlock_super (sb); - *err = -EDQUOT; - return 0; - } + DQUOT_ALLOC_BLOCK(sb, inode, 1); tmp = j + i * EXT2_BLOCKS_PER_GROUP(sb) + le32_to_cpu(es->s_first_data_block); @@ -544,8 +539,7 @@ if (ext2_set_bit (j, bh->b_data)) { ext2_warning (sb, "ext2_new_block", "bit already set for block %d", j); - if (sb->dq_op) - sb->dq_op->free_block(inode, fs_to_dq_blocks(1, sb->s_blocksize)); + DQUOT_FREE_BLOCK(sb, inode, 1); goto repeat; } @@ -566,12 +560,9 @@ for (k = 1; k < prealloc_goal && (j + k) < EXT2_BLOCKS_PER_GROUP(sb); k++) { - if (sb->dq_op) - if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(1, sb->s_blocksize))) - break; + DQUOT_PREALLOC_BLOCK(sb, inode, 1); if (ext2_set_bit (j + k, bh->b_data)) { - if (sb->dq_op) - sb->dq_op->free_block(inode, fs_to_dq_blocks(1, sb->s_blocksize)); + DQUOT_FREE_BLOCK(sb, inode, 1); break; } (*prealloc_count)++; diff -u --recursive --new-file v2.1.100/linux/fs/ext2/ialloc.c linux/fs/ext2/ialloc.c --- v2.1.100/linux/fs/ext2/ialloc.c Mon Apr 6 17:41:00 1998 +++ linux/fs/ext2/ialloc.c Fri May 8 17:54:39 1998 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -231,8 +232,7 @@ is_directory = S_ISDIR(inode->i_mode); /* Do this BEFORE marking the inode not in use */ - if (sb->dq_op) - sb->dq_op->free_inode (inode, 1); + DQUOT_FREE_INODE(sb, inode); clear_inode (inode); /* Ok, now we can actually update the inode bitmaps.. */ @@ -493,17 +493,7 @@ inc_inode_version (inode, gdp, mode); unlock_super (sb); - if (sb->dq_op) { - sb->dq_op->initialize (inode, -1); - if (sb->dq_op->alloc_inode (inode, 1)) { - sb->dq_op->drop (inode); - inode->i_nlink = 0; - iput (inode); - *err = -EDQUOT; - return NULL; - } - inode->i_flags |= S_WRITE; - } + DQUOT_ALLOC_INODE(sb, inode); ext2_debug ("allocating inode %lu\n", inode->i_ino); *err = 0; diff -u --recursive --new-file v2.1.100/linux/fs/ext2/namei.c linux/fs/ext2/namei.c --- v2.1.100/linux/fs/ext2/namei.c Thu May 7 22:51:53 1998 +++ linux/fs/ext2/namei.c Fri May 8 17:54:39 1998 @@ -28,6 +28,7 @@ #include #include #include +#include /* @@ -625,8 +626,7 @@ goto end_rmdir; inode = dentry->d_inode; - if (inode->i_sb->dq_op) - inode->i_sb->dq_op->initialize (inode, -1); + DQUOT_INIT(inode); retval = -EPERM; if ((dir->i_mode & S_ISVTX) && @@ -715,8 +715,7 @@ goto end_unlink; inode = dentry->d_inode; - if (inode->i_sb->dq_op) - inode->i_sb->dq_op->initialize (inode, -1); + DQUOT_INIT(inode); retval = -EPERM; if (S_ISDIR(inode->i_mode)) @@ -936,8 +935,7 @@ brelse (new_bh); new_bh = NULL; } else { - if (new_inode->i_sb->dq_op) - new_inode->i_sb->dq_op->initialize (new_inode, -1); + DQUOT_INIT(new_inode); } } retval = 0; diff -u --recursive --new-file v2.1.100/linux/fs/file_table.c linux/fs/file_table.c --- v2.1.100/linux/fs/file_table.c Sun Oct 12 10:10:40 1997 +++ linux/fs/file_table.c Fri May 8 17:54:39 1998 @@ -5,7 +5,6 @@ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) */ -#include #include #include #include @@ -122,43 +121,3 @@ else return 0; } - -#ifdef CONFIG_QUOTA - -void add_dquot_ref(kdev_t dev, short type) -{ - struct file *filp; - - for (filp = inuse_filps; filp; filp = filp->f_next) { - struct inode * inode; - if (!filp->f_dentry) - continue; - inode = filp->f_dentry->d_inode; - if (!inode || inode->i_dev != dev) - continue; - if (filp->f_mode & FMODE_WRITE && inode->i_sb->dq_op) { - inode->i_sb->dq_op->initialize(inode, type); - inode->i_flags |= S_WRITE; - } - } -} - -void reset_dquot_ptrs(kdev_t dev, short type) -{ - struct file *filp; - - for (filp = inuse_filps; filp; filp = filp->f_next) { - struct inode * inode; - if (!filp->f_dentry) - continue; - inode = filp->f_dentry->d_inode; - if (!inode || inode->i_dev != dev) - continue; - if (IS_WRITABLE(inode)) { - inode->i_dquot[type] = NODQUOT; - inode->i_flags &= ~S_WRITE; - } - } -} - -#endif diff -u --recursive --new-file v2.1.100/linux/fs/inode.c linux/fs/inode.c --- v2.1.100/linux/fs/inode.c Tue Mar 10 10:03:34 1998 +++ linux/fs/inode.c Fri May 8 17:54:39 1998 @@ -8,6 +8,7 @@ #include #include #include +#include /* * New inode.c implementation. @@ -190,6 +191,7 @@ continue; sync_list(&sb->s_dirty); + if (dev) break; } @@ -223,8 +225,8 @@ if (inode->i_nrpages) truncate_inode_pages(inode, 0); wait_on_inode(inode); - if (IS_WRITABLE(inode) && inode->i_sb && inode->i_sb->dq_op) - inode->i_sb->dq_op->drop(inode); + if (IS_QUOTAINIT(inode)) + DQUOT_DROP(inode); if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->clear_inode) inode->i_sb->s_op->clear_inode(inode); diff -u --recursive --new-file v2.1.100/linux/fs/namei.c linux/fs/namei.c --- v2.1.100/linux/fs/namei.c Thu May 7 22:51:53 1998 +++ linux/fs/namei.c Fri May 8 17:54:39 1998 @@ -22,10 +22,12 @@ #include #include #include +#include #include #include #include +#include #include /* This can be removed after the beta phase. */ @@ -84,48 +86,48 @@ * semantics. See the comments in "open_namei" and "do_link" below. */ -static char * quicklist = NULL; -static int quickcount = 0; -struct semaphore quicklock = MUTEX; +char * getname_quicklist = NULL; +int getname_quickcount = 0; +spinlock_t getname_quicklock = SPIN_LOCK_UNLOCKED; /* Tuning: increase locality by reusing same pages again... - * if quicklist becomes too long on low memory machines, either a limit + * if getname_quicklist becomes too long on low memory machines, either a limit * should be added or after a number of cycles some pages should * be released again ... */ static inline char * get_page(void) { char * res; - down(&quicklock); - res = quicklist; + spin_lock(&getname_quicklock); + res = getname_quicklist; if (res) { #ifdef DEBUG char * tmp = res; int i; - for(i=0; id_inode->i_op || !dir->d_inode->i_op->create) error = -EACCES; else if ((error = permission(dir->d_inode,MAY_WRITE | MAY_EXEC)) == 0) { - if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op) - dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1); + DQUOT_INIT(dir->d_inode); error = dir->d_inode->i_op->create(dir->d_inode, dentry, mode); /* Don't check for write permission, don't truncate */ acc_mode = 0; @@ -637,8 +638,7 @@ */ error = locks_verify_locked(inode); if (!error) { - if (inode->i_sb && inode->i_sb->dq_op) - inode->i_sb->dq_op->initialize(inode, -1); + DQUOT_INIT(inode); error = do_truncate(dentry, 0); } @@ -647,8 +647,7 @@ goto exit; } else if (flag & FMODE_WRITE) - if (inode->i_sb && inode->i_sb->dq_op) - inode->i_sb->dq_op->initialize(inode, -1); + DQUOT_INIT(inode); return dentry; @@ -690,8 +689,7 @@ if (!dir->d_inode->i_op || !dir->d_inode->i_op->mknod) goto exit_lock; - if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op) - dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1); + DQUOT_INIT(dir->d_inode); error = dir->d_inode->i_op->mknod(dir->d_inode, dentry, mode, dev); retval = ERR_PTR(error); if (!error) @@ -775,8 +773,7 @@ if (!dir->d_inode->i_op || !dir->d_inode->i_op->mkdir) goto exit_lock; - if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op) - dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1); + DQUOT_INIT(dir->d_inode); mode &= 0777 & ~current->fs->umask; error = dir->d_inode->i_op->mkdir(dir->d_inode, dentry, mode); @@ -848,8 +845,7 @@ if (!dir->d_inode->i_op || !dir->d_inode->i_op->rmdir) goto exit_lock; - if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op) - dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1); + DQUOT_INIT(dir->d_inode); if (dentry->d_count > 1) shrink_dcache_parent(dentry); @@ -924,8 +920,7 @@ if (!dir->d_inode->i_op || !dir->d_inode->i_op->unlink) goto exit_lock; - if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op) - dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1); + DQUOT_INIT(dir->d_inode); error = dir->d_inode->i_op->unlink(dir->d_inode, dentry); @@ -986,8 +981,7 @@ if (!dir->d_inode->i_op || !dir->d_inode->i_op->symlink) goto exit_lock; - if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op) - dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1); + DQUOT_INIT(dir->d_inode); error = dir->d_inode->i_op->symlink(dir->d_inode, dentry, oldname); exit_lock: @@ -1082,8 +1076,7 @@ if (!dir->d_inode->i_op || !dir->d_inode->i_op->link) goto exit_lock; - if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op) - dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1); + DQUOT_INIT(dir->d_inode); error = dir->d_inode->i_op->link(old_dentry, dir->d_inode, new_dentry); exit_lock: @@ -1207,8 +1200,8 @@ if (!old_dir->d_inode->i_op || !old_dir->d_inode->i_op->rename) goto exit_lock; - if (new_dir->d_inode->i_sb && new_dir->d_inode->i_sb->dq_op) - new_dir->d_inode->i_sb->dq_op->initialize(new_dir->d_inode, -1); + DQUOT_INIT(old_dir->d_inode); + DQUOT_INIT(new_dir->d_inode); error = old_dir->d_inode->i_op->rename(old_dir->d_inode, old_dentry, new_dir->d_inode, new_dentry); diff -u --recursive --new-file v2.1.100/linux/fs/nametrans.c linux/fs/nametrans.c --- v2.1.100/linux/fs/nametrans.c Mon Dec 1 10:34:11 1997 +++ linux/fs/nametrans.c Wed Dec 31 16:00:00 1969 @@ -1,310 +0,0 @@ -/* - * $Id: nametrans.c,v 1.2 1997/06/04 23:45:44 davem Exp $ - * - * linux/fs/nametrans.c - context-dependend filename suffixes. - * Copyright (C) 1997, Thomas Schoebel-Theuer, - * . - * - * translates names of the form "filename#host=myhost#" to "filename" - * as if both names were hardlinked to the same file. - * benefit: diskless clients can mount the / filesystem of the - * server if /etc/fstab (and other config files) are organized using - * context suffixes. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -char nametrans_txt[MAX_DEFAULT_TRANSLEN] = ""; -static struct translations * global_trans = NULL; -static int default_trans = 1; -static const char version[] = "revision: 2.3 "; -int translations_dirty = 1; -static char * transl_names[] = { -#ifdef CONFIG_TR_NODENAME - "host=", system_utsname.nodename, -#endif -#ifdef CONFIG_TR_KERNNAME - "kname=", CONFIG_KERNNAME, -#endif -#ifdef CONFIG_TR_KERNTYPE - "ktype=", CONFIG_KERNTYPE, -#endif -#ifdef CONFIG_TR_MACHINE - "machine=", system_utsname.machine, -#endif -#ifdef CONFIG_TR_SYSNAME - "system=", system_utsname.sysname, -#endif - 0, 0 -}; - -/* Convert and do syntax checking. */ -static void convert(char * txt, struct translations * res) -{ - char * tmp = txt; - char * space = (char*)res + sizeof(struct translations); - - res->count = 0; - while(*tmp) { - struct qstr * name = &res->name[res->count]; - struct qstr * c_name = &res->c_name[res->count]; - int len; - char * p = tmp; - - if(*p++ != '#') - goto next; - while(*p && *p != '=' && *p != ':') - p++; - if(*p != '=') - goto next; - p++; - len = (unsigned long)p - (unsigned long)tmp; - c_name->name = space; - memcpy(space, tmp, len); - memcpy(space + len, "CREATE#", 8); - c_name->len = len + 7; - if(c_name->len >= MAX_TRANS_SUFFIX) - goto next; - while(*p && *p != '#' && *p != ':') - p++; - if(*p != '#') - goto next; - p++; - if(*p != ':' && *p) - goto next; - space += len + 8; - name->len = len = (unsigned long)p - (unsigned long)tmp; - if(len >= MAX_TRANS_SUFFIX) - goto next; - name->name = space; - memcpy(space, tmp, len); - space[len] = '\0'; - space += len + 1; - res->count++; - if(res->count >= MAX_TRANSLATIONS || - (unsigned long)space - (unsigned long)res >= PAGE_SIZE-2*MAX_TRANS_SUFFIX) - return; - next: - while(*p && *p++ != ':') ; - tmp = p; - } -} - -static inline void trans_to_string(struct translations * trans, char * buf, int maxlen) -{ - int i; - - for(i = 0; i < trans->count; i++) { - int len = trans->name[i].len; - if(len < maxlen) { - memcpy(buf, trans->name[i].name, len); - buf += len; - maxlen -= len; - *buf++ = ':'; - maxlen--; - } - } - buf--; - *buf = '\0'; -} - -static inline void default_nametrans(char * buf) -{ - char * res = buf; - char ** entry; - char * ptr; - - for (entry = transl_names; *entry; entry++) { - *res++ = '#'; - for(ptr = *entry; *ptr; ptr++) - *res++ = *ptr; - entry++; - for(ptr = *entry; *ptr; ptr++) - *res++ = *ptr; - *res++ = '#'; - *res++ = ':'; - } - res--; - *res = '\0'; -} - -void nametrans_setup(char * line) -{ - if(line) { - default_trans = (!line[0]); - if(!global_trans) { - /* This can happen at boot time, and there is no chance - * to allocate memory at this early stage. - */ - strncpy(nametrans_txt, line, MAX_DEFAULT_TRANSLEN); - } else { - if(default_trans) { - default_nametrans(nametrans_txt); - line = nametrans_txt; - } - convert(line, global_trans); - - /* Show what really was recognized after parsing... */ - trans_to_string(global_trans, nametrans_txt, MAX_DEFAULT_TRANSLEN); - } - } -} - -/* If the _first_ environment variable is "NAMETRANS", return - * a pointer to the list of appendices. - * You can set the first environment variable using - * 'env - NAMETRANS=... "`env`" command ...' - */ -char* env_transl(void) -{ - char* env; - int i; - - if(current && current->mm && (env = (char*)current->mm->env_start) - && !segment_eq(get_ds(), get_fs()) - && current->mm->env_end>=current->mm->env_start+10 - && !verify_area(VERIFY_READ,env,10)) { - for(i=0; i<10; i++) { - char c; - - get_user(c, env++); - if(c != "NAMETRANS="[i]) - return 0; - } - return env; - } - return 0; -} - -/* If name has the correct suffix "#keyword=correct_context#", - * return position of the suffix, else 0. - */ -char *testname(int restricted, char* name) -{ - char * ptr = name; - char * cut; - char * env; - struct translations * trans; - int i, len; - char c, tmp; - - env = env_transl(); -#ifdef CONFIG_TRANS_RESTRICT - if(!env && restricted) - goto done; -#else - (void)restricted; /* inhibit parameter usage warning */ -#endif - if(get_user(c, ptr)) - goto done; - while(c && c != '#') { - ptr++; - __get_user(c, ptr); - } - if(!c) - goto done; - cut = ptr++; - if(get_user(c, ptr)) - goto done; - while (c && c != '#') { - ptr++; - get_user(c, ptr); - } - if(!c) - goto done; - get_user(tmp, ptr); - if(tmp) - goto done; - trans = get_translations(env); - len = (unsigned long)ptr - (unsigned long)cut; - for(i = 0; i < trans->count; i++) - if(trans->name[i].len == len) { - const char * p1 = cut; - const char * p2 = trans->name[i].name; - get_user(c, p1); - while(c && c == *p2++) { - p1++; - get_user(c, p1); - } - if(!c) - return cut; - } -done: - return NULL; -} - -static inline void check_dirty(void) -{ - if(translations_dirty && default_trans) { - nametrans_setup(""); - translations_dirty = 0; - } -} - -struct translations * get_translations(char * env) -{ - struct translations * res; - - if(env) { - char * env_txt = (char*)__get_free_page(GFP_KERNEL); - - strncpy_from_user(env_txt, env, PAGE_SIZE); - res = (struct translations *)__get_free_page(GFP_KERNEL); - convert(env_txt, res); - free_page((unsigned long)env_txt); - } else { - check_dirty(); - res = global_trans; - } - return res; -} - -int nametrans_dostring(ctl_table * table, int write, struct file * filp, - void * buffer, size_t * lenp) -{ - int res; - check_dirty(); - res = proc_dostring(table, write, filp, buffer, lenp); - if(!res && write) - nametrans_setup(nametrans_txt); - - return res; -} - -int nametrans_string(ctl_table * table, int * name, int nlen, - void * oldval, size_t * oldlenp, - void * newval, size_t newlen, void ** context) -{ - int res; - check_dirty(); - res = sysctl_string(table, name, nlen, oldval, oldlenp, newval, newlen, context); - if(!res && newval && newlen) - nametrans_setup(nametrans_txt); - - return res; -} - -void init_nametrans(void) -{ - if(!global_trans) - global_trans = (struct translations*)__get_free_page(GFP_KERNEL); - if(!global_trans) { - printk("NAMETRANS: No free memory\n"); - return; - } - nametrans_setup(nametrans_txt); - - /* Notify user for the default/supplied translations. - * Extremely useful for finding translation problems. - */ - printk("Nametrans %s\nNametrans %s: %s\n", version, - default_trans ? "default translations" : "external parameter", - nametrans_txt); -} diff -u --recursive --new-file v2.1.100/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c --- v2.1.100/linux/fs/nfsd/vfs.c Fri Jan 30 11:28:08 1998 +++ linux/fs/nfsd/vfs.c Fri May 8 17:54:39 1998 @@ -31,6 +31,7 @@ #include #include +#include #if LINUX_VERSION_CODE >= 0x020100 #include @@ -289,6 +290,9 @@ filp->f_mode = wflag? FMODE_WRITE : FMODE_READ; filp->f_dentry = dentry; + if (wflag) + DQUOT_INIT(inode); + err = 0; if (filp->f_op && filp->f_op->open) { err = filp->f_op->open(inode, filp); @@ -325,8 +329,10 @@ dentry->d_parent->d_name.name, dentry->d_name.name); if (filp->f_op && filp->f_op->release) filp->f_op->release(inode, filp); - if (filp->f_mode & FMODE_WRITE) + if (filp->f_mode & FMODE_WRITE) { put_write_access(inode); + DQUOT_DROP(inode); + } } /* @@ -604,6 +610,7 @@ /* Looks good, lock the directory. */ fh_lock(fhp); + DQUOT_INIT(dirp); switch (type) { case S_IFREG: err = dirp->i_op->create(dirp, dchild, iap->ia_mode); @@ -617,6 +624,7 @@ err = dirp->i_op->mknod(dirp, dchild, iap->ia_mode, rdev); break; } + DQUOT_DROP(dirp); fh_unlock(fhp); if (err < 0) @@ -674,6 +682,7 @@ /* Things look sane, lock and do it. */ fh_lock(fhp); + DQUOT_INIT(inode); newattrs.ia_size = size; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; err = notify_change(dentry, &newattrs); @@ -683,6 +692,7 @@ inode->i_op->truncate(inode); } put_write_access(inode); + DQUOT_DROP(inode); fh_unlock(fhp); out_nfserr: if (err) @@ -771,7 +781,9 @@ err = -EEXIST; if (!dnew->d_inode) { fh_lock(fhp); + DQUOT_INIT(dirp); err = dirp->i_op->symlink(dirp, dnew, path); + DQUOT_DROP(dirp); fh_unlock(fhp); if (!err) { if (EX_ISSYNC(fhp->fh_export)) @@ -840,7 +852,9 @@ goto dput_and_out; fh_lock(ffhp); + DQUOT_INIT(dirp); err = dirp->i_op->link(dold, dirp, dnew); + DQUOT_DROP(dirp); fh_unlock(ffhp); if (!err && EX_ISSYNC(ffhp->fh_export)) { @@ -938,11 +952,16 @@ nfsd_double_down(&tdir->i_sem, &fdir->i_sem); /* N.B. check for parent changes after locking?? */ + DQUOT_INIT(fdir); + DQUOT_INIT(tdir); err = fdir->i_op->rename(fdir, odentry, tdir, ndentry); if (!err && EX_ISSYNC(tfhp->fh_export)) { write_inode_now(fdir); write_inode_now(tdir); } + DQUOT_DROP(fdir); + DQUOT_DROP(tdir); + nfsd_double_up(&tdir->i_sem, &fdir->i_sem); dput(ndentry); @@ -987,6 +1006,7 @@ goto out_nfserr; fh_lock(fhp); + DQUOT_INIT(dirp); if (type == S_IFDIR) { err = -ENOTDIR; if (dirp->i_op && dirp->i_op->rmdir) @@ -996,6 +1016,7 @@ if (dirp->i_op && dirp->i_op->unlink) err = dirp->i_op->unlink(dirp, rdentry); } + DQUOT_DROP(dirp); fh_unlock(fhp); dput(rdentry); diff -u --recursive --new-file v2.1.100/linux/fs/noquot.c linux/fs/noquot.c --- v2.1.100/linux/fs/noquot.c Mon Oct 28 04:21:41 1996 +++ linux/fs/noquot.c Fri May 8 17:54:39 1998 @@ -1,79 +1,15 @@ -/* - * A Non implementation of disk quotas. Chainsawed from dquot.c by - * Alan Cox . This saves us memory without - * having zillions of #ifdefs (Or if it had been done right one - * - * QUOTA_OP(inode,func) - * - * macro.) +/* noquot.c: Quota stubs necessary for when quotas are not + * compiled into the kernel. */ -#include #include -#include #include -#include -#include -#include -#include -#include -#include - -#include - -#ifndef min -#define min(a,b) ((a) < (b)) ? (a) : (b) -#endif - -int sync_dquots(kdev_t dev, short type) -{ - return(0); -} - -/* - * Trash the cache for a certain type on a device. - */ - -void invalidate_dquots(kdev_t dev, short type) -{ -} - -/* - * Initialize pointer in an inode to the right dquots. - */ -void dquot_initialize(struct inode *inode, short type) -{ -} - -void dquot_drop(struct inode *inode) -{ -} - -void dquot_init(void) -{ -} - -/* - * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount) - */ +#include -int quota_off(kdev_t dev, short type) -{ - return(0); -} +int nr_dquots = 0, nr_free_dquots = 0; +int max_dquots = 0; -int quota_on(kdev_t dev, short type, char *path) -{ - return(-ENOPKG); -} - -/* - * Ok this is the systemcall interface, this communicates with - * the userlevel programs. Currently this only supports diskquota - * calls. Maybe we need to add the process quotas etc in the future. - * But we probably better use rlimits for that. - */ asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr) { - return(-ENOPKG); + return(-ENOSYS); } diff -u --recursive --new-file v2.1.100/linux/fs/open.c linux/fs/open.c --- v2.1.100/linux/fs/open.c Thu May 7 22:51:53 1998 +++ linux/fs/open.c Fri May 8 17:54:39 1998 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -134,8 +135,7 @@ length < inode->i_size ? length : inode->i_size, abs(inode->i_size - length)); if (!error) { - if (inode->i_sb && inode->i_sb->dq_op) - inode->i_sb->dq_op->initialize(inode, -1); + DQUOT_INIT(inode); error = do_truncate(dentry, length); } put_write_access(inode); @@ -552,16 +552,7 @@ newattrs.ia_mode &= ~S_ISGID; newattrs.ia_valid |= ATTR_MODE; } - if (inode->i_sb && inode->i_sb->dq_op) { - inode->i_sb->dq_op->initialize(inode, -1); - error = -EDQUOT; - if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0)) - goto out; - error = notify_change(dentry, &newattrs); - if (error) - inode->i_sb->dq_op->transfer(inode, &newattrs, 1); - } else - error = notify_change(dentry, &newattrs); + DQUOT_TRANSFER(dentry, newattrs); out: return error; } @@ -599,6 +590,7 @@ unlock_kernel(); return error; } + asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group) { diff -u --recursive --new-file v2.1.100/linux/fs/proc/fd.c linux/fs/proc/fd.c --- v2.1.100/linux/fs/proc/fd.c Wed Apr 1 20:11:53 1998 +++ linux/fs/proc/fd.c Fri May 8 18:10:30 1998 @@ -4,6 +4,10 @@ * Copyright (C) 1991, 1992 Linus Torvalds * * proc fd directory handling functions + * + * 01-May-98 Edgar Toernig + * Added support for more than 256 fds. + * Limit raised to 32768. */ #include @@ -91,7 +95,7 @@ goto out; fd *= 10; fd += c; - if (fd & 0xffff0000) + if (fd & 0xffff8000) goto out; } @@ -111,8 +115,7 @@ if (!file || !file->f_dentry) goto out; - /* N.B. What happens if fd > 255?? */ - ino = (pid << 16) + (PROC_PID_FD_DIR << 8) + fd; + ino = (pid << 16) + PROC_PID_FD_DIR + fd; inode = proc_get_inode(dir->i_sb, ino, NULL); if (inode) { d_add(dentry, inode); @@ -144,7 +147,7 @@ goto out; for (fd = filp->f_pos; fd < 2; fd++, filp->f_pos++) { - unsigned long ino = inode->i_ino; + ino = inode->i_ino; if (fd) ino = (ino & 0xffff0000) | PROC_PID_INO; if (filldir(dirent, "..", fd+1, fd, ino) < 0) @@ -176,7 +179,7 @@ /* Drop the task lock, as the filldir function may block */ read_unlock(&tasklist_lock); - ino = (pid << 16) + (PROC_PID_FD_DIR << 8) + fd; + ino = (pid << 16) + PROC_PID_FD_DIR + fd; if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino) < 0) goto out; diff -u --recursive --new-file v2.1.100/linux/fs/proc/inode-alloc.txt linux/fs/proc/inode-alloc.txt --- v2.1.100/linux/fs/proc/inode-alloc.txt Wed Dec 31 16:00:00 1969 +++ linux/fs/proc/inode-alloc.txt Fri May 8 18:10:30 1998 @@ -0,0 +1,50 @@ +Inode allocations in the proc-fs (hex-numbers): + + 00000000 reserved + 00000001-00000fff static entries + 001 root-ino + 002 load-avg + 003 uptime + ... + 080 net/* + ... + 100 scsi/* + ... + xxx mca/* + ... + yyy bus/* + ... + fff end + + 00001000-00001fff dynamic entries + + 00002000-00002fff openprom entries + + 0001xxxx-7fffxxxx pid-dir entries for pid 1-7fff + 0000 unused + 0001 unused + 0002 pid + 0003 pid/status + ... + 0008 pid/fd + ... + 00xx-00ff unused + 01xx pid/fd/* for fd 0-ff + ... + 01ff end + 0200-ffff unused + + 80000000-ffffffff unused + + + +New allocation: + + 00000000-0000ffff unchanged + + 0001xxxx-7fffxxxx pid-dir entries for pid 1-7fff + 0000-00ff unchanged + 0100-7fff unused + 8000-ffff pid/fd/* for fd 0-7fff + + 80000000-ffffffff unchanged diff -u --recursive --new-file v2.1.100/linux/fs/proc/inode.c linux/fs/proc/inode.c --- v2.1.100/linux/fs/proc/inode.c Thu May 7 22:51:54 1998 +++ linux/fs/proc/inode.c Fri May 8 18:10:30 1998 @@ -382,10 +382,9 @@ inode->i_uid = p->euid; inode->i_gid = p->egid; } - switch (ino >> 8) { + if (ino & PROC_PID_FD_DIR) { struct file * file; - case PROC_PID_FD_DIR: - ino &= 0xff; + ino &= 0x7fff; file = fcheck_task(p, ino); if (!file) goto out_unlock; diff -u --recursive --new-file v2.1.100/linux/fs/proc/link.c linux/fs/proc/link.c --- v2.1.100/linux/fs/proc/link.c Mon Apr 6 17:41:01 1998 +++ linux/fs/proc/link.c Fri May 8 18:10:30 1998 @@ -111,10 +111,9 @@ goto out_unlock; } default: - switch (ino >> 8) { + if (ino & PROC_PID_FD_DIR) { struct file * file; - case PROC_PID_FD_DIR: - ino &= 0xff; + ino &= 0x7fff; file = fcheck_task(p, ino); if (!file || !file->f_dentry) goto out_unlock; diff -u --recursive --new-file v2.1.100/linux/fs/read_write.c linux/fs/read_write.c --- v2.1.100/linux/fs/read_write.c Tue Mar 10 10:03:34 1998 +++ linux/fs/read_write.c Fri May 8 00:28:49 1998 @@ -79,7 +79,7 @@ return retval; } -#if !defined(__alpha__) && !defined(__sparc_v9__) +#if !defined(__alpha__) asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t * result, unsigned int origin) @@ -132,7 +132,6 @@ file = fget(fd); if (!file) goto bad_file; - ret = -EBADF; if (!(file->f_mode & FMODE_READ)) goto out; ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode, diff -u --recursive --new-file v2.1.100/linux/fs/super.c linux/fs/super.c --- v2.1.100/linux/fs/super.c Thu May 7 22:51:54 1998 +++ linux/fs/super.c Fri May 8 17:54:39 1998 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -109,7 +110,9 @@ lptr->mnt_sb = sb; lptr->mnt_dev = sb->s_dev; lptr->mnt_flags = sb->s_flags; - sema_init(&lptr->mnt_sem, 1); + + sema_init(&lptr->mnt_dquot.semaphore, 1); + lptr->mnt_dquot.flags = 0; /* N.B. Is it really OK to have a vfsmount without names? */ if (dev_name && !IS_ERR(tmp = getname(dev_name))) { @@ -642,7 +645,11 @@ * on the device. If the umount fails, too bad -- there * are no quotas running anymore. Just turn them on again. */ - quota_off(dev, -1); + DQUOT_OFF(dev); + +#ifdef CONFIG_BSD_PROCESS_ACCT + (void) acct_auto_close(dev); +#endif /* * Shrink dcache, then fsync. This guarantees that if the diff -u --recursive --new-file v2.1.100/linux/include/asm-alpha/delay.h linux/include/asm-alpha/delay.h --- v2.1.100/linux/include/asm-alpha/delay.h Fri Jun 2 03:51:16 1995 +++ linux/include/asm-alpha/delay.h Fri May 8 00:29:45 1998 @@ -35,13 +35,4 @@ __delay(usecs); } -/* - * 64-bit integers means we don't have to worry about overflow as - * on some other architectures.. - */ -extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c) -{ - return (a*b)/c; -} - #endif /* defined(__ALPHA_DELAY_H) */ diff -u --recursive --new-file v2.1.100/linux/include/asm-alpha/hardirq.h linux/include/asm-alpha/hardirq.h --- v2.1.100/linux/include/asm-alpha/hardirq.h Wed Apr 1 20:11:53 1998 +++ linux/include/asm-alpha/hardirq.h Fri May 8 00:31:10 1998 @@ -4,6 +4,7 @@ #include extern unsigned int local_irq_count[NR_CPUS]; +#define in_interrupt() (local_irq_count[smp_processor_id()] + local_bh_count[smp_processor_id()] != 0) #ifndef __SMP__ diff -u --recursive --new-file v2.1.100/linux/include/asm-alpha/md.h linux/include/asm-alpha/md.h --- v2.1.100/linux/include/asm-alpha/md.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/md.h Fri May 8 00:17:13 1998 @@ -0,0 +1,13 @@ +/* $Id: md.h,v 1.1 1997/12/15 15:11:48 jj Exp $ + * md.h: High speed xor_block operation for RAID4/5 + * + */ + +#ifndef __ASM_MD_H +#define __ASM_MD_H + +/* #define HAVE_ARCH_XORBLOCK */ + +#define MD_XORBLOCK_ALIGNMENT sizeof(long) + +#endif /* __ASM_MD_H */ diff -u --recursive --new-file v2.1.100/linux/include/asm-alpha/timex.h linux/include/asm-alpha/timex.h --- v2.1.100/linux/include/asm-alpha/timex.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/timex.h Thu May 7 23:53:35 1998 @@ -0,0 +1,11 @@ +/* + * linux/include/asm-alpha/timex.h + * + * ALPHA architecture timex specifications + */ +#ifndef _ASMALPHA_TIMEX_H +#define _ASMALPHA_TIMEX_H + +#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ + +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/a.out.h linux/include/asm-arm/arch-a5k/a.out.h --- v2.1.100/linux/include/asm-arm/arch-a5k/a.out.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/a.out.h Fri May 8 00:42:39 1998 @@ -0,0 +1,16 @@ +/* + * linux/include/asm-arm/arch-a5k/a.out.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_ARCH_A_OUT_H +#define __ASM_ARCH_A_OUT_H + +#ifdef __KERNEL__ +#define STACK_TOP (0x01a00000) +#define LIBRARY_START_TEXT (0x00c00000) +#endif + +#endif + diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/dma.h linux/include/asm-arm/arch-a5k/dma.h --- v2.1.100/linux/include/asm-arm/arch-a5k/dma.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/dma.h Fri May 8 00:42:39 1998 @@ -0,0 +1,101 @@ +#ifndef __ASM_ARCH_DMA_H +#define __ASM_ARCH_DMA_H + +#define MAX_DMA_ADDRESS 0x03000000 + +#ifdef KERNEL_ARCH_DMA + +static inline void arch_disable_dma (int dmanr) +{ + printk (dma_str, "arch_disable_dma", dmanr); +} + +static inline void arch_enable_dma (int dmanr) +{ + printk (dma_str, "arch_enable_dma", dmanr); +} + +static inline void arch_set_dma_addr (int dmanr, unsigned int addr) +{ + printk (dma_str, "arch_set_dma_addr", dmanr); +} + +static inline void arch_set_dma_count (int dmanr, unsigned int count) +{ + printk (dma_str, "arch_set_dma_count", dmanr); +} + +static inline void arch_set_dma_mode (int dmanr, char mode) +{ + printk (dma_str, "arch_set_dma_mode", dmanr); +} + +static inline int arch_dma_count (int dmanr) +{ + printk (dma_str, "arch_dma_count", dmanr); + return 0; +} + +#endif + +/* enable/disable a specific DMA channel */ +extern void enable_dma(unsigned int dmanr); + +static __inline__ void disable_dma(unsigned int dmanr) +{ + switch(dmanr) { + case 2: disable_irq(64); break; + default: printk (dma_str, "disable_dma", dmanr); break; + } +} + +/* Clear the 'DMA Pointer Flip Flop'. + * Write 0 for LSB/MSB, 1 for MSB/LSB access. + * Use this once to initialize the FF to a known state. + * After that, keep track of it. :-) + * --- In order to do that, the DMA routines below should --- + * --- only be used while interrupts are disabled! --- + */ +static __inline__ void clear_dma_ff(unsigned int dmanr) +{ + switch(dmanr) { + case 2: break; + default: printk (dma_str, "clear_dma_ff", dmanr); break; + } +} + +/* set mode (above) for a specific DMA channel */ +extern void set_dma_mode(unsigned int dmanr, char mode); + +/* Set only the page register bits of the transfer address. + * This is used for successive transfers when we know the contents of + * the lower 16 bits of the DMA current address register, but a 64k boundary + * may have been crossed. + */ +static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) +{ + printk (dma_str, "set_dma_page", dmanr); +} + + +/* Set transfer address & page bits for specific DMA channel. + * Assumes dma flipflop is clear. + */ +extern void set_dma_addr(unsigned int dmanr, unsigned int addr); + +/* Set transfer size for a specific DMA channel. + */ +extern void set_dma_count(unsigned int dmanr, unsigned int count); + +/* Get DMA residue count. After a DMA transfer, this + * should return zero. Reading this while a DMA transfer is + * still in progress will return unpredictable results. + * If called before the channel has been used, it may return 1. + * Otherwise, it returns the number of _bytes_ left to transfer. + * + * Assumes DMA flip-flop is clear. + */ +extern int get_dma_residue(unsigned int dmanr); + +#endif /* _ASM_ARCH_DMA_H */ + diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/hardware.h linux/include/asm-arm/arch-a5k/hardware.h --- v2.1.100/linux/include/asm-arm/arch-a5k/hardware.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/hardware.h Fri May 8 00:42:39 1998 @@ -0,0 +1,81 @@ +/* + * linux/include/asm-arm/arch-a5k/hardware.h + * + * Copyright (C) 1996 Russell King. + * + * This file contains the hardware definitions of the A5000 series machines. + */ + +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +/* + * What hardware must be present + */ +#define HAS_IOC +#define HAS_PCIO +#define HAS_MEMC +#define HAS_MEMC1A +#define HAS_VIDC + +/* + * Optional hardware + */ +#define HAS_EXPMASK + +#ifndef __ASSEMBLER__ + +/* + * for use with inb/outb + */ +#define VIDC_BASE 0x80100000 +#define IOCEC4IO_BASE 0x8009c000 +#define IOCECIO_BASE 0x80090000 +#define IOC_BASE 0x80080000 +#define MEMCECIO_BASE 0x80000000 + +/* + * IO definitions + */ +#define EXPMASK_BASE ((volatile unsigned char *)0x03360000) +#define IOEB_BASE ((volatile unsigned char *)0x03350050) +#define PCIO_FLOPPYDMABASE ((volatile unsigned char *)0x0302a000) +#define PCIO_BASE 0x03010000 + +/* + * Mapping areas + */ +#define IO_END 0x03ffffff +#define IO_BASE 0x03000000 +#define IO_SIZE (IO_END - IO_BASE) +#define IO_START 0x03000000 + +/* + * Screen mapping information + */ +#define SCREEN2_END 0x02078000 +#define SCREEN2_BASE 0x02000000 +#define SCREEN1_END SCREEN2_BASE +#define SCREEN1_BASE 0x01f88000 +#define SCREEN_START 0x02000000 + +/* + * RAM definitions + */ +#define MAPTOPHYS(a) (((unsigned long)a & 0x007fffff) + PAGE_OFFSET) +#define KERNTOPHYS(a) ((((unsigned long)(&a)) & 0x007fffff) + PAGE_OFFSET) +#define GET_MEMORY_END(p) (PAGE_OFFSET + (p->u1.s.page_size) * (p->u1.s.nr_pages)) +#define PARAMS_BASE (PAGE_OFFSET + 0x7c000) +#define KERNEL_BASE (PAGE_OFFSET + 0x80000) + +#else + +#define IOEB_BASE 0x03350050 +#define IOC_BASE 0x03200000 +#define PCIO_FLOPPYDMABASE 0x0302a000 +#define PCIO_BASE 0x03010000 +#define IO_BASE 0x03000000 + +#endif +#endif + diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/ide.h linux/include/asm-arm/arch-a5k/ide.h --- v2.1.100/linux/include/asm-arm/arch-a5k/ide.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/ide.h Fri May 8 00:42:39 1998 @@ -0,0 +1,44 @@ +/* + * linux/include/asm-arm/arch-a5k/ide.h + * + * Copyright (c) 1997 Russell King + */ + +static __inline__ int +ide_default_irq(ide_ioreg_t base) +{ + if (base == 0x1f0) + return 11; + return 0; +} + +static __inline__ ide_ioreg_t +ide_default_io_base(int index) +{ + if (index == 0) + return 0x1f0; + return 0; +} + +static __inline__ int +ide_default_stepping(int index) +{ + return 0; +} + +static __inline__ void +ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int stepping, int *irq) +{ + ide_ioreg_t port = base; + ide_ioreg_t ctrl = base + 0x206; + int i; + + i = 8; + while (i--) { + *p++ = port; + port += 1 << stepping; + } + *p++ = ctrl; + if (irq != NULL) + irq = 0; +} diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/io.h linux/include/asm-arm/arch-a5k/io.h --- v2.1.100/linux/include/asm-arm/arch-a5k/io.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/io.h Fri May 8 00:42:39 1998 @@ -0,0 +1,215 @@ +/* + * linux/include/asm-arm/arch-a5k/io.h + * + * Copyright (C) 1997 Russell King + * + * Modifications: + * 06-Dec-1997 RMK Created. + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +/* + * Virtual view <-> DMA view memory address translations + * virt_to_bus: Used to translate the virtual address to an + * address suitable to be passed to set_dma_addr + * bus_to_virt: Used to convert an address for DMA operations + * to an address that the kernel can use. + */ +#define virt_to_bus(x) ((unsigned long)(x)) +#define bus_to_virt(x) ((void *)(x)) + +/* + * This architecture does not require any delayed IO, and + * has the constant-optimised IO + */ +#undef ARCH_IO_DELAY + +/* + * We use two different types of addressing - PC style addresses, and ARM + * addresses. PC style accesses the PC hardware with the normal PC IO + * addresses, eg 0x3f8 for serial#1. ARM addresses are 0x80000000+ + * and are translated to the start of IO. Note that all addresses are + * shifted left! + */ +#define __PORT_PCIO(x) (!((x) & 0x80000000)) + +/* + * Dynamic IO functions - let the compiler + * optimize the expressions + */ +extern __inline__ void __outb (unsigned int value, unsigned int port) +{ + unsigned long temp; + __asm__ __volatile__( + "tst %2, #0x80000000\n\t" + "mov %0, %4\n\t" + "addeq %0, %0, %3\n\t" + "strb %1, [%0, %2, lsl #2]" + : "=&r" (temp) + : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) + : "cc"); +} + +extern __inline__ void __outw (unsigned int value, unsigned int port) +{ + unsigned long temp; + __asm__ __volatile__( + "tst %2, #0x80000000\n\t" + "mov %0, %4\n\t" + "addeq %0, %0, %3\n\t" + "str %1, [%0, %2, lsl #2]" + : "=&r" (temp) + : "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) + : "cc"); +} + +extern __inline__ void __outl (unsigned int value, unsigned int port) +{ + unsigned long temp; + __asm__ __volatile__( + "tst %2, #0x80000000\n\t" + "mov %0, %4\n\t" + "addeq %0, %0, %3\n\t" + "str %1, [%0, %2, lsl #2]" + : "=&r" (temp) + : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) + : "cc"); +} + +#define DECLARE_DYN_IN(sz,fnsuffix,instr) \ +extern __inline__ unsigned sz __in##fnsuffix (unsigned int port) \ +{ \ + unsigned long temp, value; \ + __asm__ __volatile__( \ + "tst %2, #0x80000000\n\t" \ + "mov %0, %4\n\t" \ + "addeq %0, %0, %3\n\t" \ + "ldr" ##instr## " %1, [%0, %2, lsl #2]" \ + : "=&r" (temp), "=r" (value) \ + : "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \ + : "cc"); \ + return (unsigned sz)value; \ +} + +extern __inline__ unsigned int __ioaddr (unsigned int port) \ +{ \ + if (__PORT_PCIO(port)) \ + return (unsigned int)(PCIO_BASE + (port << 2)); \ + else \ + return (unsigned int)(IO_BASE + (port << 2)); \ +} + +#define DECLARE_IO(sz,fnsuffix,instr) \ + DECLARE_DYN_IN(sz,fnsuffix,instr) + +DECLARE_IO(char,b,"b") +DECLARE_IO(short,w,"") +DECLARE_IO(long,l,"") + +#undef DECLARE_IO +#undef DECLARE_DYN_IN + +/* + * Constant address IO functions + * + * These have to be macros for the 'J' constraint to work - + * +/-4096 immediate operand. + */ +#define __outbc(value,port) \ +({ \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "strb %0, [%1, %2]" \ + : : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "strb %0, [%1, %2]" \ + : : "r" (value), "r" (IO_BASE), "r" ((port) << 2)); \ +}) + +#define __inbc(port) \ +({ \ + unsigned char result; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "ldrb %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "ldrb %0, [%1, %2]" \ + : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ + result; \ +}) + +#define __outwc(value,port) \ +({ \ + unsigned long v = value; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "str %0, [%1, %2]" \ + : : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "str %0, [%1, %2]" \ + : : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2)); \ +}) + +#define __inwc(port) \ +({ \ + unsigned short result; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ + result & 0xffff; \ +}) + +#define __outlc(v,p) __outwc((v),(p)) + +#define __inlc(port) \ +({ \ + unsigned long result; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ + result; \ +}) + +#define __ioaddrc(port) \ +({ \ + unsigned long addr; \ + if (__PORT_PCIO((port))) \ + addr = PCIO_BASE + ((port) << 2); \ + else \ + addr = IO_BASE + ((port) << 2); \ + addr; \ +}) + +/* + * Translated address IO functions + * + * IO address has already been translated to a virtual address + */ +#define outb_t(v,p) \ + (*(volatile unsigned char *)(p) = (v)) + +#define inb_t(p) \ + (*(volatile unsigned char *)(p)) + +#define outl_t(v,p) \ + (*(volatile unsigned long *)(p) = (v)) + +#define inl_t(p) \ + (*(volatile unsigned long *)(p)) + +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/irq.h linux/include/asm-arm/arch-a5k/irq.h --- v2.1.100/linux/include/asm-arm/arch-a5k/irq.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/irq.h Fri May 8 00:42:39 1998 @@ -0,0 +1,130 @@ +/* + * include/asm-arm/arch-a5k/irq.h + * + * Copyright (C) 1996 Russell King + * + * Changelog: + * 24-09-1996 RMK Created + * 10-10-1996 RMK Brought up to date with arch-sa110eval + * 22-10-1996 RMK Changed interrupt numbers & uses new inb/outb macros + * 11-01-1998 RMK Added mask_and_ack_irq + */ + +#define BUILD_IRQ(s,n,m) \ + void IRQ##n##_interrupt(void); \ + void fast_IRQ##n##_interrupt(void); \ + void bad_IRQ##n##_interrupt(void); \ + void probe_IRQ##n##_interrupt(void); + +/* + * The timer is a special interrupt + */ +#define IRQ5_interrupt timer_IRQ_interrupt + +#define IRQ_INTERRUPT(n) IRQ##n##_interrupt +#define FAST_INTERRUPT(n) fast_IRQ##n##_interrupt +#define BAD_INTERRUPT(n) bad_IRQ##n##_interrupt +#define PROBE_INTERRUPT(n) probe_IRQ##n##_interrupt + +#define X(x) (x)|0x01, (x)|0x02, (x)|0x04, (x)|0x08, (x)|0x10, (x)|0x20, (x)|0x40, (x)|0x80 +#define Z(x) (x), (x), (x), (x), (x), (x), (x), (x) + +static __inline__ void mask_and_ack_irq(unsigned int irq) +{ + static const int addrmasks[] = { + X((IOC_IRQMASKA - IOC_BASE)<<18 | (1 << 15)), + X((IOC_IRQMASKB - IOC_BASE)<<18), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0), + X((IOC_FIQMASK - IOC_BASE)<<18), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0) + }; + unsigned int temp1, temp2; + + __asm__ __volatile__( +" ldr %1, [%5, %3, lsl #2]\n" +" teq %1, #0\n" +" beq 2f\n" +" ldrb %0, [%2, %1, lsr #16]\n" +" bic %0, %0, %1\n" +" strb %0, [%2, %1, lsr #16]\n" +" tst %1, #0x8000\n" /* do we need an IRQ clear? */ +" strneb %1, [%2, %4]\n" +"2:" + : "=&r" (temp1), "=&r" (temp2) + : "r" (ioaddr(IOC_BASE)), "r" (irq), + "I" ((IOC_IRQCLRA - IOC_BASE) << 2), "r" (addrmasks)); +} + +#undef X +#undef Z + +static __inline__ void mask_irq(unsigned int irq) +{ + extern void ecard_disableirq (unsigned int); + extern void ecard_disablefiq (unsigned int); + unsigned char mask = 1 << (irq & 7); + + switch (irq >> 3) { + case 0: + outb(inb(IOC_IRQMASKA) & ~mask, IOC_IRQMASKA); + break; + case 1: + outb(inb(IOC_IRQMASKB) & ~mask, IOC_IRQMASKB); + break; + case 4: + ecard_disableirq (irq & 7); + break; + case 8: + outb(inb(IOC_FIQMASK) & ~mask, IOC_FIQMASK); + break; + case 12: + ecard_disablefiq (irq & 7); + } +} + +static __inline__ void unmask_irq(unsigned int irq) +{ + extern void ecard_enableirq (unsigned int); + extern void ecard_enablefiq (unsigned int); + unsigned char mask = 1 << (irq & 7); + + switch (irq >> 3) { + case 0: + outb(inb(IOC_IRQMASKA) | mask, IOC_IRQMASKA); + break; + case 1: + outb(inb(IOC_IRQMASKB) | mask, IOC_IRQMASKB); + break; + case 4: + ecard_enableirq (irq & 7); + break; + case 8: + outb(inb(IOC_FIQMASK) | mask, IOC_FIQMASK); + break; + case 12: + ecard_enablefiq (irq & 7); + } +} + +static __inline__ unsigned long get_enabled_irqs(void) +{ + return inb(IOC_IRQMASKA) | inb(IOC_IRQMASKB) << 8; +} + +static __inline__ void irq_init_irq(void) +{ + outb(0, IOC_IRQMASKA); + outb(0, IOC_IRQMASKB); + outb(0, IOC_FIQMASK); +} diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/irqs.h linux/include/asm-arm/arch-a5k/irqs.h --- v2.1.100/linux/include/asm-arm/arch-a5k/irqs.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/irqs.h Fri May 8 00:42:39 1998 @@ -0,0 +1,28 @@ +/* + * linux/include/asm-arm/arch-a5k/irqs.h + * + * Copyright (C) 1996 Russell King + */ + +#define IRQ_PRINTER 0 +#define IRQ_BATLOW 1 +#define IRQ_FLOPPYINDEX 2 +#define IRQ_VSYNCPULSE 3 +#define IRQ_POWERON 4 +#define IRQ_TIMER0 5 +#define IRQ_TIMER1 6 +#define IRQ_IMMEDIATE 7 +#define IRQ_EXPCARDFIQ 8 +#define IRQ_SOUNDCHANGE 9 +#define IRQ_SERIALPORT 10 +#define IRQ_HARDDISK 11 +#define IRQ_FLOPPYDISK 12 +#define IRQ_EXPANSIONCARD 13 +#define IRQ_KEYBOARDTX 14 +#define IRQ_KEYBOARDRX 15 + +#define FIQ_FLOPPYDATA 0 +#define FIQ_ECONET 2 +#define FIQ_SERIALPORT 4 +#define FIQ_EXPANSIONCARD 6 +#define FIQ_FORCE 7 diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/mmu.h linux/include/asm-arm/arch-a5k/mmu.h --- v2.1.100/linux/include/asm-arm/arch-a5k/mmu.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/mmu.h Fri May 8 00:42:39 1998 @@ -0,0 +1,15 @@ +/* + * linux/include/asm-arm/arch-a5k/mmu.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 22-11-1996 RMK Created + */ +#ifndef __ASM_ARCH_MMU_H +#define __ASM_ARCH_MMU_H + +#define __virt_to_phys(vpage) vpage +#define __phys_to_virt(ppage) ppage + +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/oldlatches.h linux/include/asm-arm/arch-a5k/oldlatches.h --- v2.1.100/linux/include/asm-arm/arch-a5k/oldlatches.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/oldlatches.h Fri May 8 00:42:39 1998 @@ -0,0 +1,9 @@ +/* + * Dummy oldlatches.h + * + * Copyright (C) 1996 Russell King + */ + +#ifdef __need_oldlatches +#error "Old latches not present in this (a5k) machine" +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/processor.h linux/include/asm-arm/arch-a5k/processor.h --- v2.1.100/linux/include/asm-arm/arch-a5k/processor.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/processor.h Fri May 8 00:42:39 1998 @@ -0,0 +1,35 @@ +/* + * linux/include/asm-arm/arch-a5k/processor.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 10-09-1996 RMK Created + */ + +#ifndef __ASM_ARCH_PROCESSOR_H +#define __ASM_ARCH_PROCESSOR_H + +/* + * Bus types + */ +#define EISA_bus 0 +#define EISA_bus__is_a_macro /* for versions in ksyms.c */ +#define MCA_bus 0 +#define MCA_bus__is_a_macro /* for versions in ksyms.c */ + +/* + * User space: 26MB + */ +#define TASK_SIZE (0x01a00000UL) + +/* This decides where the kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE(off) (TASK_SIZE / 3) +#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) + +#define INIT_MMAP \ +{ &init_mm, 0, 0x02000000, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } + +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/serial.h linux/include/asm-arm/arch-a5k/serial.h --- v2.1.100/linux/include/asm-arm/arch-a5k/serial.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/serial.h Fri May 8 00:42:39 1998 @@ -0,0 +1,40 @@ +/* + * linux/include/asm-arm/arch-a5k/serial.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 15-10-1996 RMK Created + */ +#ifndef __ASM_ARCH_SERIAL_H +#define __ASM_ARCH_SERIAL_H + +/* + * This assumes you have a 1.8432 MHz clock for your UART. + * + * It'd be nice if someone built a serial card with a 24.576 MHz + * clock, since the 16550A is capable of handling a top speed of 1.5 + * megabits/second; but this requires the faster clock. + */ +#define BASE_BAUD (1843200 / 16) + +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) + + /* UART CLK PORT IRQ FLAGS */ +#define RS_UARTS \ + { 0, BASE_BAUD, 0x3F8, 10, STD_COM_FLAGS }, /* ttyS0 */ \ + { 0, BASE_BAUD, 0x2F8, 10, STD_COM_FLAGS }, /* ttyS1 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS2 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS3 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS4 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS5 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS6 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS7 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS8 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS9 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS10 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS11 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS12 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS13 */ + +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/shmparam.h linux/include/asm-arm/arch-a5k/shmparam.h --- v2.1.100/linux/include/asm-arm/arch-a5k/shmparam.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/shmparam.h Fri May 8 00:42:39 1998 @@ -0,0 +1,5 @@ +/* + * linux/include/asm-arm/arch-a5k/shmparam.h + * + * Copyright (c) 1996 Russell King. + */ diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/system.h linux/include/asm-arm/arch-a5k/system.h --- v2.1.100/linux/include/asm-arm/arch-a5k/system.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/system.h Fri May 8 00:42:39 1998 @@ -0,0 +1,30 @@ +/* + * linux/include/asm-arm/arch-a5k/system.h + * + * Copyright (c) 1996 Russell King + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +extern __inline__ void arch_hard_reset (void) +{ + extern void ecard_reset (int card); + + /* + * Reset all expansion cards. + */ + ecard_reset (-1); + + /* + * copy branch instruction to reset location and call it + */ + *(unsigned long *)0 = *(unsigned long *)0x03800000; + ((void(*)(void))0)(); + + /* + * If that didn't work, loop endlessly + */ + while (1); +} + +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/time.h linux/include/asm-arm/arch-a5k/time.h --- v2.1.100/linux/include/asm-arm/arch-a5k/time.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/time.h Fri May 8 00:42:39 1998 @@ -0,0 +1,96 @@ +/* + * linux/include/asm-arm/arch-a5k/time.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 24-Sep-1996 RMK Created + * 10-Oct-1996 RMK Brought up to date with arch-sa110eval + * 04-Dec-1997 RMK Updated for new arch/arm/time.c + */ + +extern __inline__ unsigned long gettimeoffset (void) +{ + unsigned int count1, count2, status1, status2; + unsigned long offset = 0; + + status1 = IOC_IRQREQA; + barrier (); + outb (0, IOC_T0LATCH); + barrier (); + count1 = inb(IOC_T0CNTL) | (inb(IOC_T0CNTH) << 8); + barrier (); + status2 = inb(IOC_IRQREQA); + barrier (); + outb (0, IOC_T0LATCH); + barrier (); + count2 = inb(IOC_T0CNTL) | (inb(IOC_T0CNTH) << 8); + + if (count2 < count1) { + /* + * This means that we haven't just had an interrupt + * while reading into status2. + */ + if (status2 & (1 << 5)) + offset = tick; + count1 = count2; + } else if (count2 > count1) { + /* + * We have just had another interrupt while reading + * status2. + */ + offset += tick; + count1 = count2; + } + + count1 = LATCH - count1; + /* + * count1 = number of clock ticks since last interrupt + */ + offset += count1 * tick / LATCH; + return offset; +} + +/* + * No need to reset the timer at every irq + */ +#define reset_timer() 1 + +/* + * Updating of the RTC. We don't currently write the time to the + * CMOS clock. + */ +#define update_rtc() + +/* + * Set up timer interrupt, and return the current time in seconds. + */ +extern __inline__ unsigned long setup_timer (void) +{ + extern int iic_control (unsigned char, int, char *, int); + unsigned int year, mon, day, hour, min, sec; + char buf[8]; + + outb(LATCH & 255, IOC_T0LTCHL); + outb(LATCH >> 8, IOC_T0LTCHH); + outb(0, IOC_T0GO); + + iic_control (0xa0, 0xc0, buf, 1); + year = buf[0]; + if ((year += 1900) < 1970) + year += 100; + + iic_control (0xa0, 2, buf, 5); + mon = buf[4] & 0x1f; + day = buf[3] & 0x3f; + hour = buf[2]; + min = buf[1]; + sec = buf[0]; + BCD_TO_BIN(mon); + BCD_TO_BIN(day); + BCD_TO_BIN(hour); + BCD_TO_BIN(min); + BCD_TO_BIN(sec); + + return mktime(year, mon, day, hour, min, sec); +} diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/timex.h linux/include/asm-arm/arch-a5k/timex.h --- v2.1.100/linux/include/asm-arm/arch-a5k/timex.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/timex.h Fri May 8 00:42:39 1998 @@ -0,0 +1,13 @@ +/* + * linux/include/asm-arm/arch-a5k/timex.h + * + * A5000 architecture timex specifications + * + * Copyright (C) 1997, 1998 Russell King + */ + +/* + * On the RiscPC, the clock ticks at 2MHz. + */ +#define CLOCK_TICK_RATE 2000000 + diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/uncompress.h linux/include/asm-arm/arch-a5k/uncompress.h --- v2.1.100/linux/include/asm-arm/arch-a5k/uncompress.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/uncompress.h Fri May 8 00:42:39 1998 @@ -0,0 +1,104 @@ +/* + * linux/include/asm-arm/arch-a5k/uncompress.h + * + * Copyright (C) 1996 Russell King + */ +#define VIDMEM ((char *)0x02000000) + +#include "../arch/arm/drivers/char/font.h" + +int video_num_columns, video_num_lines, video_size_row; +int white, bytes_per_char_h; +extern unsigned long con_charconvtable[256]; + +struct param_struct { + unsigned long page_size; + unsigned long nr_pages; + unsigned long ramdisk_size; + unsigned long mountrootrdonly; + unsigned long rootdev; + unsigned long video_num_cols; + unsigned long video_num_rows; + unsigned long video_x; + unsigned long video_y; + unsigned long memc_control_reg; + unsigned char sounddefault; + unsigned char adfsdrives; + unsigned char bytes_per_char_h; + unsigned char bytes_per_char_v; + unsigned long unused[256/4-11]; +}; + +static struct param_struct *params = (struct param_struct *)0x0207c000; + +/* + * This does not append a newline + */ +static void puts(const char *s) +{ + extern void ll_write_char(char *, unsigned long); + int x,y; + unsigned char c; + char *ptr; + + x = params->video_x; + y = params->video_y; + + while ( ( c = *(unsigned char *)s++ ) != '\0' ) { + if ( c == '\n' ) { + x = 0; + if ( ++y >= video_num_lines ) { + y--; + } + } else { + ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h); + ll_write_char(ptr, c|(white<<8)); + if ( ++x >= video_num_columns ) { + x = 0; + if ( ++y >= video_num_lines ) { + y--; + } + } + } + } + + params->video_x = x; + params->video_y = y; +} + +static void error(char *x); + +/* + * Setup for decompression + */ +static void arch_decomp_setup(void) +{ + int i; + + video_num_lines = params->video_num_rows; + video_num_columns = params->video_num_cols; + bytes_per_char_h = params->bytes_per_char_h; + video_size_row = video_num_columns * bytes_per_char_h; + if (bytes_per_char_h == 4) + for (i = 0; i < 256; i++) + con_charconvtable[i] = + (i & 128 ? 1 << 0 : 0) | + (i & 64 ? 1 << 4 : 0) | + (i & 32 ? 1 << 8 : 0) | + (i & 16 ? 1 << 12 : 0) | + (i & 8 ? 1 << 16 : 0) | + (i & 4 ? 1 << 20 : 0) | + (i & 2 ? 1 << 24 : 0) | + (i & 1 ? 1 << 28 : 0); + else + for (i = 0; i < 16; i++) + con_charconvtable[i] = + (i & 8 ? 1 << 0 : 0) | + (i & 4 ? 1 << 8 : 0) | + (i & 2 ? 1 << 16 : 0) | + (i & 1 ? 1 << 24 : 0); + + white = bytes_per_char_h == 8 ? 0xfc : 7; + + if (params->nr_pages * params->page_size < 4096*1024) error("<4M of mem\n"); +} diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-arc/ide.h linux/include/asm-arm/arch-arc/ide.h --- v2.1.100/linux/include/asm-arm/arch-arc/ide.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-arc/ide.h Fri May 8 00:42:39 1998 @@ -11,13 +11,14 @@ */ #include +#include static __inline__ int ide_default_irq(ide_ioreg_t base) { #ifdef CONFIG_ARCH_A5K if (base == 0x1f0) - return 11; + return IRQ_HARDDISK; #endif return 0; } @@ -52,5 +53,5 @@ } *p++ = ctrl; if (irq != NULL) - irq = 0; + *irq = 0; } diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-arc/irqs.h linux/include/asm-arm/arch-arc/irqs.h --- v2.1.100/linux/include/asm-arm/arch-arc/irqs.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-arc/irqs.h Fri May 8 00:42:39 1998 @@ -47,3 +47,5 @@ #define FIQ_FORCE 7 #define IRQ_TIMER IRQ_TIMER0 + +#define irq_cannonicalize(i) (i) diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-arc/processor.h linux/include/asm-arm/arch-arc/processor.h --- v2.1.100/linux/include/asm-arm/arch-arc/processor.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-arc/processor.h Fri May 8 00:42:39 1998 @@ -26,7 +26,8 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE(off) (TASK_SIZE / 3) +#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) #define INIT_MMAP \ { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-arc/serial.h linux/include/asm-arm/arch-arc/serial.h --- v2.1.100/linux/include/asm-arm/arch-arc/serial.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-arc/serial.h Fri May 8 00:42:39 1998 @@ -25,7 +25,7 @@ #if defined(CONFIG_ARCH_A5K) /* UART CLK PORT IRQ FLAGS */ -#define RS_UARTS \ +#define SERIAL_PORT_DFNS \ { 0, BASE_BAUD, 0x3F8, 10, STD_COM_FLAGS }, /* ttyS0 */ \ { 0, BASE_BAUD, 0x2F8, 10, STD_COM_FLAGS }, /* ttyS1 */ \ { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS2 */ \ @@ -44,7 +44,7 @@ #elif defined(CONFIG_ARCH_ARC) /* UART CLK PORT IRQ FLAGS */ -#define RS_UARTS \ +#define SERIAL_PORT_DFNS \ { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS0 */ \ { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS1 */ \ { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS2 */ \ diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-arc/uncompress.h linux/include/asm-arm/arch-arc/uncompress.h --- v2.1.100/linux/include/asm-arm/arch-arc/uncompress.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-arc/uncompress.h Fri May 8 00:42:39 1998 @@ -52,7 +52,7 @@ } } else { ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h); - ll_write_char(ptr, c|(white<<8)); + ll_write_char(ptr, c|(white<<16)); if ( ++x >= video_num_columns ) { x = 0; if ( ++y >= video_num_lines ) { diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-ebsa110/irqs.h linux/include/asm-arm/arch-ebsa110/irqs.h --- v2.1.100/linux/include/asm-arm/arch-ebsa110/irqs.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-ebsa110/irqs.h Fri May 8 00:42:39 1998 @@ -14,3 +14,6 @@ #define IRQ_IMMEDIATE 7 #define IRQ_TIMER IRQ_TIMER0 + +#define irq_cannonicalize(i) (i) + diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-ebsa110/mmap.h linux/include/asm-arm/arch-ebsa110/mmap.h --- v2.1.100/linux/include/asm-arm/arch-ebsa110/mmap.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/mmap.h Fri May 8 00:42:39 1998 @@ -0,0 +1,10 @@ +/* + * linux/include/asm-arm/arch-ebsa110/mmap.h + * + * Copyright (C) 1996,1997,1998 Russell King + */ + +/* + * Use SRAM for cache flushing + */ +#define SAFE_ADDR 0x40000000 diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-ebsa110/processor.h linux/include/asm-arm/arch-ebsa110/processor.h --- v2.1.100/linux/include/asm-arm/arch-ebsa110/processor.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-ebsa110/processor.h Fri May 8 00:42:39 1998 @@ -23,7 +23,8 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE(off) (TASK_SIZE / 3) +#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) #define INIT_MMAP \ { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-ebsa110/serial.h linux/include/asm-arm/arch-ebsa110/serial.h --- v2.1.100/linux/include/asm-arm/arch-ebsa110/serial.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/arch-ebsa110/serial.h Fri May 8 00:42:39 1998 @@ -21,7 +21,7 @@ #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) /* UART CLK PORT IRQ FLAGS */ -#define RS_UARTS \ +#define SERIAL_PORT_DFNS \ { 0, BASE_BAUD, 0x3F8, 1, STD_COM_FLAGS }, /* ttyS0 */ \ { 0, BASE_BAUD, 0x2F8, 2, STD_COM_FLAGS }, /* ttyS1 */ \ { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS2 */ \ diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-ebsa285/irqs.h linux/include/asm-arm/arch-ebsa285/irqs.h --- v2.1.100/linux/include/asm-arm/arch-ebsa285/irqs.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-ebsa285/irqs.h Fri May 8 00:42:40 1998 @@ -43,3 +43,6 @@ * Now map them to the Linux interrupts */ #define IRQ_TIMER IRQ_TIMER1 + +#define irq_cannonicalize(i) (i) + diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-ebsa285/processor.h linux/include/asm-arm/arch-ebsa285/processor.h --- v2.1.100/linux/include/asm-arm/arch-ebsa285/processor.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-ebsa285/processor.h Fri May 8 00:42:40 1998 @@ -23,7 +23,8 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE(off) (TASK_SIZE / 3) +#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) #define INIT_MMAP \ { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/a.out.h linux/include/asm-arm/arch-nexuspci/a.out.h --- v2.1.100/linux/include/asm-arm/arch-nexuspci/a.out.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-nexuspci/a.out.h Fri May 8 00:42:40 1998 @@ -1,5 +1,5 @@ /* - * linux/include/asm-arm/arch-ebsa/a.out.h + * linux/include/asm-arm/arch-nexuspci/a.out.h * * Copyright (C) 1996 Russell King */ diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/dma.h linux/include/asm-arm/arch-nexuspci/dma.h --- v2.1.100/linux/include/asm-arm/arch-nexuspci/dma.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-nexuspci/dma.h Fri May 8 00:42:40 1998 @@ -1,17 +1,12 @@ /* * linux/include/asm-arm/arch-nexuspci/dma.h * - * Architecture DMA routines + * Architecture DMA routines - NexusPCI has no DMA, so this file is very + * simple. :-) * * Copyright (C) 1998 Philip Blundell */ -#ifndef __ASM_ARCH_DMA_H -#define __ASM_ARCH_DMA_H - -/* NexusPCI has no DMA */ - -#warning No DMA on this platform - -#endif /* _ASM_ARCH_DMA_H */ +/* Need this to keep happy. */ +typedef unsigned int dmamode_t; diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/hardware.h linux/include/asm-arm/arch-nexuspci/hardware.h --- v2.1.100/linux/include/asm-arm/arch-nexuspci/hardware.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-nexuspci/hardware.h Fri May 8 00:42:40 1998 @@ -1,11 +1,19 @@ /* * linux/include/asm-arm/arch-nexuspci/hardware.h * - * Copyright (C) 1997 Philip Blundell + * Copyright (C) 1998 Philip Blundell * * This file contains the hardware definitions of the Nexus PCI card. */ +/* Logical Physical + * 0xfff00000 0x10000000 SCC2691 DUART + * 0xffe00000 0x20000000 INTCONT + * 0xffd00000 0x30000000 Status + * 0xffc00000 0x60000000 PLX registers + * 0xfe000000 0x70000000 PCI I/O + */ + #ifndef __ASM_ARCH_HARDWARE_H #define __ASM_ARCH_HARDWARE_H @@ -13,29 +21,21 @@ * What hardware must be present */ -#ifndef __ASSEMBLER__ +#define HAS_PCIO +#define PCIO_BASE 0xfe000000 /* * Mapping areas */ #define IO_END 0xffffffff -#define IO_BASE 0xd0000000 +#define IO_BASE 0xfe000000 #define IO_SIZE (IO_END - IO_BASE) -#define IO_START 0xd0000000 /* * RAM definitions */ #define RAM_BASE 0x40000000 -#define MAPTOPHYS(a) ((unsigned long)(a) - PAGE_OFFSET + RAM_BASE) #define KERNTOPHYS(a) ((unsigned long)(&a)) -#define KERNEL_BASE (0xc0008000) #define SAFE_ADDR 0x40000000 -#else - -#define IO_BASE 0 - #endif -#endif - diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/io.h linux/include/asm-arm/arch-nexuspci/io.h --- v2.1.100/linux/include/asm-arm/arch-nexuspci/io.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/io.h Fri May 8 00:42:40 1998 @@ -0,0 +1,143 @@ +/* + * linux/include/asm-arm/arch-ebsa110/io.h + * + * Copyright (C) 1997,1998 Russell King + * + * Modifications: + * 06-Dec-1997 RMK Created. + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +/* + * This architecture does not require any delayed IO, and + * has the constant-optimised IO + */ +#undef ARCH_IO_DELAY + +/* + * Dynamic IO functions - let the compiler + * optimize the expressions + */ +#define DECLARE_DYN_OUT(fnsuffix,instr,typ) \ +extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port) \ +{ \ + __asm__ __volatile__( \ + "str" ##instr## " %0, [%1, %2]" \ + : \ + : "r" (value), "r" (PCIO_BASE), typ (port)); \ +} + +#define DECLARE_DYN_IN(sz,fnsuffix,instr,typ) \ +extern __inline__ unsigned sz __in##fnsuffix (unsigned int port) \ +{ \ + unsigned long value; \ + __asm__ __volatile__( \ + "ldr" ##instr## " %0, [%1, %2]" \ + : "=&r" (value) \ + : "r" (PCIO_BASE), typ (port)); \ + return (unsigned sz)value; \ +} + +extern __inline__ unsigned int __ioaddr (unsigned int port) \ +{ \ + return (unsigned int)(PCIO_BASE + port); \ +} + +#define DECLARE_IO(sz,fnsuffix,instr,typ) \ + DECLARE_DYN_OUT(fnsuffix,instr,typ) \ + DECLARE_DYN_IN(sz,fnsuffix,instr,typ) + +DECLARE_IO(char,b,"b","Jr") +DECLARE_IO(short,w,"h","r") +DECLARE_IO(long,l,"","Jr") + +#undef DECLARE_IO +#undef DECLARE_DYN_OUT +#undef DECLARE_DYN_IN + +/* + * Constant address IO functions + * + * These have to be macros for the 'J' constraint to work - + * +/-4096 immediate operand. + */ +#define __outbc(value,port) \ +({ \ + __asm__ __volatile__( \ + "strb %0, [%1, %2]" \ + : \ + : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \ +}) + +#define __inbc(port) \ +({ \ + unsigned char result; \ + __asm__ __volatile__( \ + "ldrb %0, [%1, %2]" \ + : "=r" (result) \ + : "r" (PCIO_BASE), "Jr" (port)); \ + result; \ +}) + +#define __outwc(value,port) \ +({ \ + __asm__ __volatile__( \ + "strh %0, [%1, %2]" \ + : \ + : "r" (value), "r" (PCIO_BASE), "r" (port)); \ +}) + +#define __inwc(port) \ +({ \ + unsigned short result; \ + __asm__ __volatile__( \ + "ldrh %0, [%1, %2]" \ + : "=r" (result) \ + : "r" (PCIO_BASE), "r" (port)); \ + result & 0xffff; \ +}) + +#define __outlc(value,port) \ +({ \ + __asm__ __volatile__( \ + "str %0, [%1, %2]" \ + : \ + : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \ +}) + +#define __inlc(port) \ +({ \ + unsigned long result; \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) \ + : "r" (PCIO_BASE), "Jr" (port)); \ + result; \ +}) + +#define __ioaddrc(port) \ +({ \ + unsigned long addr; \ + addr = PCIO_BASE + port; \ + addr; \ +}) + +/* + * Translated address IO functions + * + * IO address has already been translated to a virtual address + */ +#define outb_t(v,p) \ + (*(volatile unsigned char *)(p) = (v)) + +#define inb_t(p) \ + (*(volatile unsigned char *)(p)) + +#define outl_t(v,p) \ + (*(volatile unsigned long *)(p) = (v)) + +#define inl_t(p) \ + (*(volatile unsigned long *)(p)) + +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/irq.h linux/include/asm-arm/arch-nexuspci/irq.h --- v2.1.100/linux/include/asm-arm/arch-nexuspci/irq.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/arch-nexuspci/irq.h Fri May 8 00:42:40 1998 @@ -1,29 +1,27 @@ /* - * include/asm-arm/arch-ebsa110/irq.h + * include/asm-arm/arch-nexuspci/irq.h * - * Copyright (C) 1996,1997,1998 Russell King + * Copyright (C) 1998 Philip Blundell */ -#define IRQ_MCLR ((volatile unsigned char *)0xf3000000) -#define IRQ_MSET ((volatile unsigned char *)0xf2c00000) -#define IRQ_MASK ((volatile unsigned char *)0xf2c00000) +#define INT_RESET ((volatile unsigned char *)0xfff00000) +#define INT_ENABLE ((volatile unsigned char *)0xfff00000) +#define INT_DISABLE ((volatile unsigned char *)0xfff00000) static __inline__ void mask_and_ack_irq(unsigned int irq) { - if (irq < 8) - *IRQ_MCLR = 1 << irq; + INT_DISABLE[irq << 2] = 0; + INT_RESET[irq << 2] = 0; } static __inline__ void mask_irq(unsigned int irq) { - if (irq < 8) - *IRQ_MCLR = 1 << irq; + INT_DISABLE[irq << 2] = 0; } static __inline__ void unmask_irq(unsigned int irq) { - if (irq < 8) - *IRQ_MSET = 1 << irq; + INT_ENABLE[irq << 2] = 0; } static __inline__ unsigned long get_enabled_irqs(void) @@ -33,14 +31,8 @@ static __inline__ void irq_init_irq(void) { - unsigned long flags; - - save_flags_cli (flags); - *IRQ_MCLR = 0xff; - *IRQ_MSET = 0x55; - *IRQ_MSET = 0x00; - if (*IRQ_MASK != 0x55) - while (1); - *IRQ_MCLR = 0xff; /* clear all interrupt enables */ - restore_flags (flags); + unsigned int i; + /* Disable all interrupts initially. */ + for (i = 0; i < 8; i++) + mask_irq(i); } diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/irqs.h linux/include/asm-arm/arch-nexuspci/irqs.h --- v2.1.100/linux/include/asm-arm/arch-nexuspci/irqs.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-nexuspci/irqs.h Fri May 8 00:42:40 1998 @@ -14,3 +14,6 @@ /* timer is part of the DUART */ #define IRQ_TIMER IRQ_DUART + +#define irq_cannonicalize(i) (i) + diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/mmap.h linux/include/asm-arm/arch-nexuspci/mmap.h --- v2.1.100/linux/include/asm-arm/arch-nexuspci/mmap.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/mmap.h Fri May 8 00:42:40 1998 @@ -0,0 +1,10 @@ +/* + * linux/include/asm-arm/arch-ebsa110/mmap.h + * + * Copyright (C) 1996,1997,1998 Russell King + */ + +/* + * Use SRAM for cache flushing + */ +#define SAFE_ADDR 0x40000000 diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/mmu.h linux/include/asm-arm/arch-nexuspci/mmu.h --- v2.1.100/linux/include/asm-arm/arch-nexuspci/mmu.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/arch-nexuspci/mmu.h Fri May 8 00:42:40 1998 @@ -1,16 +1,26 @@ /* * linux/include/asm-arm/arch-nexuspci/mmu.h * - * Copyright (c) 1997 Philip Blundell. + * Copyright (c) 1997, 1998 Philip Blundell. * */ #ifndef __ASM_ARCH_MMU_H #define __ASM_ARCH_MMU_H /* - * On NexusPCI, the dram is contiguous + * On NexusPCI, the DRAM is contiguous */ #define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + 0x40000000) #define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - 0x40000000) +#define __virt_to_phys__is_a_macro +#define __phys_to_virt__is_a_macro + +/* + * These are exactly the same as the physical memory view. + */ +#define __virt_to_bus__is_a_macro +#define __virt_to_bus(x) __virt_to_phys(x) +#define __bus_to_virt__is_a_macro +#define __bus_to_virt(x) __phys_to_virt(x) #endif diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/processor.h linux/include/asm-arm/arch-nexuspci/processor.h --- v2.1.100/linux/include/asm-arm/arch-nexuspci/processor.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-nexuspci/processor.h Fri May 8 00:42:40 1998 @@ -24,7 +24,8 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE(off) (TASK_SIZE / 3) +#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) #define INIT_MMAP \ { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/serial.h linux/include/asm-arm/arch-nexuspci/serial.h --- v2.1.100/linux/include/asm-arm/arch-nexuspci/serial.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/serial.h Fri May 8 00:42:40 1998 @@ -0,0 +1,41 @@ +/* + * linux/include/asm-arm/arch-ebsa110/serial.h + * + * Copyright (c) 1996,1997,1998 Russell King. + * + * Changelog: + * 15-10-1996 RMK Created + */ +#ifndef __ASM_ARCH_SERIAL_H +#define __ASM_ARCH_SERIAL_H + +/* + * This assumes you have a 1.8432 MHz clock for your UART. + * + * It'd be nice if someone built a serial card with a 24.576 MHz + * clock, since the 16550A is capable of handling a top speed of 1.5 + * megabits/second; but this requires the faster clock. + */ +#define BASE_BAUD (1843200 / 16) + +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) + + /* UART CLK PORT IRQ FLAGS */ +#define RS_UARTS \ + { 0, BASE_BAUD, 0x3F8, 1, STD_COM_FLAGS }, /* ttyS0 */ \ + { 0, BASE_BAUD, 0x2F8, 2, STD_COM_FLAGS }, /* ttyS1 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS2 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS3 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS4 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS5 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS6 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS7 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS8 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS9 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS10 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS11 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS12 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS13 */ + +#endif + diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/shmparam.h linux/include/asm-arm/arch-nexuspci/shmparam.h --- v2.1.100/linux/include/asm-arm/arch-nexuspci/shmparam.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/arch-nexuspci/shmparam.h Fri May 8 00:42:40 1998 @@ -1,5 +1,5 @@ /* - * linux/include/asm-arm/arch-ebsa110/shmparam.h + * linux/include/asm-arm/arch-nexuspci/shmparam.h * * Copyright (c) 1996 Russell King. */ diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/system.h linux/include/asm-arm/arch-nexuspci/system.h --- v2.1.100/linux/include/asm-arm/arch-nexuspci/system.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/arch-nexuspci/system.h Fri May 8 00:42:40 1998 @@ -1,5 +1,5 @@ /* - * linux/include/asm-arm/arch-ebsa110/system.h + * linux/include/asm-arm/arch-nexuspci/system.h * * Copyright (c) 1996,1997,1998 Russell King. */ @@ -9,7 +9,7 @@ extern __inline__ void arch_hard_reset (void) { /* - * loop endlessly + * loop endlessly - the watchdog will reset us if it's enabled. */ cli(); while (1); diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/time.h linux/include/asm-arm/arch-nexuspci/time.h --- v2.1.100/linux/include/asm-arm/arch-nexuspci/time.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/arch-nexuspci/time.h Fri May 8 00:42:40 1998 @@ -7,6 +7,8 @@ * */ +#define update_rtc() + extern __inline__ unsigned long gettimeoffset (void) { return 0; diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/timex.h linux/include/asm-arm/arch-nexuspci/timex.h --- v2.1.100/linux/include/asm-arm/arch-nexuspci/timex.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/timex.h Fri May 8 00:42:40 1998 @@ -0,0 +1,8 @@ +/* + * linux/include/asm-arm/arch-nexuspci/timex.h + * + * NexusPCI StrongARM card timex specifications + * + * Copyright (C) 1998 Philip Blundell + */ + diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-rpc/ide.h linux/include/asm-arm/arch-rpc/ide.h --- v2.1.100/linux/include/asm-arm/arch-rpc/ide.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/arch-rpc/ide.h Fri May 8 00:42:40 1998 @@ -3,12 +3,13 @@ * * Copyright (c) 1997 Russell King */ +#include static __inline__ int ide_default_irq(ide_ioreg_t base) { if (base == 0x1f0) - return 9; + return IRQ_HARDDISK; return 0; } @@ -40,5 +41,5 @@ } *p++ = ctrl; if (irq != NULL) - irq = 0; + *irq = 0; } diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-rpc/irqs.h linux/include/asm-arm/arch-rpc/irqs.h --- v2.1.100/linux/include/asm-arm/arch-rpc/irqs.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-rpc/irqs.h Fri May 8 00:42:40 1998 @@ -1,5 +1,5 @@ /* - * linux/include/asm-arm/arch-a5k/irqs.h + * linux/include/asm-arm/arch-rpc/irqs.h * * Copyright (C) 1996 Russell King */ @@ -13,9 +13,8 @@ #define IRQ_TIMER1 6 #define IRQ_IMMEDIATE 7 #define IRQ_EXPCARDFIQ 8 -#define IRQ_SOUNDCHANGE 9 +#define IRQ_HARDDISK 9 #define IRQ_SERIALPORT 10 -#define IRQ_HARDDISK 11 #define IRQ_FLOPPYDISK 12 #define IRQ_EXPANSIONCARD 13 #define IRQ_KEYBOARDTX 14 @@ -35,3 +34,6 @@ #define FIQ_FORCE 7 #define IRQ_TIMER IRQ_TIMER0 + +#define irq_cannonicalize(i) (i) + diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-rpc/mmap.h linux/include/asm-arm/arch-rpc/mmap.h --- v2.1.100/linux/include/asm-arm/arch-rpc/mmap.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/mmap.h Fri May 8 00:42:40 1998 @@ -0,0 +1,48 @@ +/* + * linux/include/asm-arm/arch-rpc/mmap.h + * + * Copyright (C) 1996 Russell King + */ + +#define HAVE_MAP_VID_MEM +#define SAFE_ADDR 0x00000000 /* ROM */ + +unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update) +{ + static int updated = 0; + unsigned long address; + pgd_t *pgd; + + if (updated) + return 0; + updated = update; + + address = SCREEN_START | PMD_TYPE_SECT | PMD_DOMAIN(DOMAIN_KERNEL) | PMD_SECT_AP_WRITE; + pgd = swapper_pg_dir + (SCREEN2_BASE >> PGDIR_SHIFT); + pgd_val(pgd[0]) = address; + pgd_val(pgd[1]) = address + (1 << PGDIR_SHIFT); + + if (update) { + unsigned long pgtable = PAGE_ALIGN(kmem), *p; + int i; + + memzero ((void *)pgtable, 4096); + + pgd_val(pgd[-2]) = virt_to_phys(pgtable) | PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL); + pgd_val(pgd[-1]) = virt_to_phys(pgtable + PTRS_PER_PTE*4) | PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL); + p = (unsigned long *)pgtable; + + i = PTRS_PER_PTE * 2 - ((SCREEN1_END - log_start) >> PAGE_SHIFT); + address = SCREEN_START | PTE_TYPE_SMALL | PTE_AP_WRITE; + + while (i < PTRS_PER_PTE * 2) { + p[i++] = address; + address += PAGE_SIZE; + } + + flush_page_to_ram(pgtable); + + kmem = pgtable + PAGE_SIZE; + } + return kmem; +} diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-rpc/processor.h linux/include/asm-arm/arch-rpc/processor.h --- v2.1.100/linux/include/asm-arm/arch-rpc/processor.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-rpc/processor.h Fri May 8 00:42:40 1998 @@ -26,7 +26,8 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE(off) (TASK_SIZE / 3) +#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) #define INIT_MMAP \ { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-rpc/serial.h linux/include/asm-arm/arch-rpc/serial.h --- v2.1.100/linux/include/asm-arm/arch-rpc/serial.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/arch-rpc/serial.h Fri May 8 00:42:40 1998 @@ -21,7 +21,7 @@ #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) /* UART CLK PORT IRQ FLAGS */ -#define RS_UARTS \ +#define SERIAL_PORT_DFNS \ { 0, BASE_BAUD, 0x3F8, 10, STD_COM_FLAGS }, /* ttyS0 */ \ { 0, BASE_BAUD, 0x2F8, 10, STD_COM_FLAGS }, /* ttyS1 */ \ { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS2 */ \ diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/checksum.h linux/include/asm-arm/checksum.h --- v2.1.100/linux/include/asm-arm/checksum.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/checksum.h Fri May 8 00:42:40 1998 @@ -35,14 +35,19 @@ * better 64-bit) boundary */ -extern -unsigned int csum_partial_copy_from_user (const char *src, char *dst, int len, int sum, int *err_ptr); +unsigned int +csum_partial_copy_nocheck(const char *src, char *dst, int len, int sum); +unsigned int +csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *err_ptr); + +#if 0 /* * This combination is currently not used, but possible: */ -extern -unsigned int csum_partial_copy_to_user (const char *src, char *dst, int len, int sum, int *err_ptr); +unsigned int +csum_partial_copy_to_user(const char *src, char *dst, int len, int sum, int *err_ptr); +#endif /* * These are the old (and unsafe) way of doing checksums, a warning message will be @@ -51,7 +56,8 @@ * these functions should go away after some time. */ #define csum_partial_copy_fromuser csum_partial_copy -unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum); +unsigned int +csum_partial_copy(const char *src, char *dst, int len, int sum); /* * This is a version of ip_compute_csum() optimized for IP headers, @@ -62,8 +68,9 @@ * Note: the order that the LDM registers are loaded with respect to * the adc's doesn't matter. */ -static inline unsigned short ip_fast_csum(unsigned char * iph, - unsigned int ihl) { +static inline unsigned short +ip_fast_csum(unsigned char * iph, unsigned int ihl) +{ unsigned int sum, tmp1; __asm__ __volatile__(" @@ -92,63 +99,64 @@ } /* - * computes the checksum of the TCP/UDP pseudo-header - * returns a 16-bit checksum, already complemented - */ -static inline unsigned short int csum_tcpudp_magic(unsigned long saddr, - unsigned long daddr, - unsigned short len, - unsigned short proto, - unsigned int sum) { - __asm__ __volatile__(" - adds %0, %0, %1 - adcs %0, %0, %4 - adcs %0, %0, %5 - adc %0, %0, #0 - adds %0, %0, %0, lsl #16 - addcs %0, %0, #0x10000 - mvn %0, %0 - mov %0, %0, lsr #16 - " - : "=&r" (sum), "=&r" (saddr) - : "0" (daddr), "1"(saddr), "r"((ntohs(len)<<16)+proto*256), "r"(sum)); - return((unsigned short)sum); -} - -/* * Fold a partial checksum without adding pseudo headers */ -static inline unsigned int csum_fold(unsigned int sum) +static inline unsigned int +csum_fold(unsigned int sum) { - __asm__ __volatile__(" - adds %0, %0, %0, lsl #16 - addcs %0, %0, #0x10000 - mvn %0, %0 - mov %0, %0, lsr #16 - " + __asm__(" + adds %0, %0, %0, lsl #16 + addcs %0, %0, #0x10000" : "=r" (sum) : "0" (sum)); + return (~sum) >> 16; +} + +static inline unsigned long +csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len, + unsigned short proto, unsigned int sum) +{ + __asm__(" + adds %0, %0, %1 + adcs %0, %0, %2 + adcs %0, %0, %3 + adc %0, %0, #0" + : "=&r"(sum) + : "r" (daddr), "r" (saddr), "r" ((ntohs(len)<<16)+proto*256), "0" (sum)); return sum; } - +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +static inline unsigned short int +csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len, + unsigned short proto, unsigned int sum) +{ + return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); +} + /* * this routine is used for miscellaneous IP-like checksums, mainly * in icmp.c */ - -static inline unsigned short ip_compute_csum(unsigned char * buff, int len) { - unsigned int sum; - - __asm__ __volatile__(" - adds %0, %0, %0, lsl #16 - addcs %0, %0, #0x10000 - mvn %0, %0 - mov %0, %0, lsr #16 - " - : "=r"(sum) - : "0" (csum_partial(buff, len, 0))); - return(sum); +static inline unsigned short +ip_compute_csum(unsigned char * buff, int len) +{ + return csum_fold(csum_partial(buff, len, 0)); } +#define _HAVE_ARCH_IPV6_CSUM +extern unsigned long +__csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u32 len, + __u32 proto, unsigned int sum); + +extern __inline__ unsigned short int +csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u16 len, + unsigned short proto, unsigned int sum) +{ + return csum_fold(__csum_ipv6_magic(saddr, daddr, htonl((__u32)len), + htonl(proto), sum)); +} #endif diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/ecard.h linux/include/asm-arm/ecard.h --- v2.1.100/linux/include/asm-arm/ecard.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/ecard.h Fri May 8 00:42:40 1998 @@ -64,6 +64,8 @@ #define MANU_EESOX 0x0064 #define PROD_EESOX_SCSI2 0x008c +#define MANU_YELLOWSTONE 0x0096 +#define PROD_YELLOWSTONE_RAPIDE32 0x0120 #ifdef ECARD_C #define CONST diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/elf.h linux/include/asm-arm/elf.h --- v2.1.100/linux/include/asm-arm/elf.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/elf.h Fri May 8 00:42:40 1998 @@ -6,6 +6,7 @@ */ #include +#include typedef unsigned long elf_greg_t; @@ -48,7 +49,15 @@ specific libraries for optimization. This is more specific in intent than poking at uname or /proc/cpuinfo. */ -#define ELF_PLATFORM (NULL) +/* For now we just provide a fairly general string that describes the + processor family. This could be made more specific later if someone + implemented optimisations that require it. 26-bit CPUs give you + "arm2" for ARM2 (no SWP) and "arm3" for anything else (ARM1 isn't + supported). 32-bit CPUs give you "arm6" for anything based on an + ARM6 or ARM7 core and "sa1x" for anything based on a StrongARM-1 + core. */ + +#define ELF_PLATFORM (armidlist[armidindex].optname) #ifdef __KERNEL__ #define SET_PERSONALITY(ex,ibcs2) \ diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/ioctl.h linux/include/asm-arm/ioctl.h --- v2.1.100/linux/include/asm-arm/ioctl.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/ioctl.h Fri May 8 00:42:40 1998 @@ -1,4 +1,4 @@ -/* $Id: ioctl.h,v 1.5 1993/07/19 21:53:50 root Exp root $ +/* $Id: ioctl.h,v 1.1 1998/01/28 09:56:22 ecd Exp $ * * linux/ioctl.h for Linux by H.H. Bergman. */ diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/irq-no.h linux/include/asm-arm/irq-no.h --- v2.1.100/linux/include/asm-arm/irq-no.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/irq-no.h Fri May 8 00:42:40 1998 @@ -0,0 +1,11 @@ +/* + * linux/include/asm-arm/irq-no.h + * + * Machine independent interrupt numbers + */ + +#include + +#ifndef NR_IRQS +#define NR_IRQS 128 +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/linux_logo.h linux/include/asm-arm/linux_logo.h --- v2.1.100/linux/include/asm-arm/linux_logo.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/linux_logo.h Fri May 8 00:42:40 1998 @@ -0,0 +1,49 @@ +/* + * linux/include/asm-arm/linux_logo.h + * + * Copyright (C) 1998 Russell King + * + * Linux console driver logo definitions for ARM + */ + +#include +#include + +#define linux_logo_banner "ARM Linux version " UTS_RELEASE + +#define LINUX_LOGO_COLORS 0 + +unsigned char linux_logo_red[] __initdata = { }; +unsigned char linux_logo_green[] __initdata = { }; +unsigned char linux_logo_blue[] __initdata = { }; + +unsigned char linux_logo16_red[] __initdata = { }; +unsigned char linux_logo16_green[] __initdata = { }; +unsigned char linux_logo16_blue[] __initdata = { }; + +unsigned char linux_logo[] __initdata = { }; +unsigned char linux_logo16[] __initdata = { }; +unsigned char linux_logo_bw[] __initdata = { }; + +/* Painted by Johnny Stenback + * Modified by Russell King for ARM + */ +unsigned char *linux_serial_image __initdata = "\n" +" .u$e.\n" +" .$$$$$:S\n" +" $\"*$/\"*$$\n" +" $.`$ . ^F\n" +" 4k+#+T.$F\n" +" 4P+++\"$\"$\n" +" :R\"+ t$$B\n" +" ___# $$$\n" +" | | R$$k\n" +" dd. | Linux $!$\n" +" ddd | ARM $9$F\n" +" '!!!!!$ !!#!`\n" +" !!!!!* .!!!!!`\n" +"'!!!!!!!W..e$$!!!!!!` %s\n" +" \"~^^~ ^~~^\n" +"\n"; + +extern int (*console_show_logo)(void); diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/namei.h linux/include/asm-arm/namei.h --- v2.1.100/linux/include/asm-arm/namei.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/namei.h Fri May 8 00:42:40 1998 @@ -1,4 +1,4 @@ -/* $Id: namei.h,v 1.1 1996/12/13 14:48:21 jj Exp $ +/* $Id: namei.h,v 1.1 1998/01/28 09:56:37 ecd Exp $ * linux/include/asm-i386/namei.h * * Included from linux/fs/namei.c diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/page.h linux/include/asm-arm/page.h --- v2.1.100/linux/include/asm-arm/page.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/page.h Fri May 8 00:42:40 1998 @@ -6,6 +6,8 @@ #ifdef __KERNEL__ +#define get_user_page(vaddr) __get_free_page(GFP_KERNEL) +#define free_user_page(page, addr) free_page(addr) #define clear_page(page) memzero((void *)(page), PAGE_SIZE) #define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE) diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/posix_types.h linux/include/asm-arm/posix_types.h --- v2.1.100/linux/include/asm-arm/posix_types.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/posix_types.h Fri May 8 00:42:40 1998 @@ -9,51 +9,61 @@ #ifndef __ARCH_ARM_POSIX_TYPES_H #define __ARCH_ARM_POSIX_TYPES_H +#include + /* * This file is generally used by user-level software, so you need to * be a little careful about namespace pollution etc. Also, we cannot * assume GCC is being used. */ -typedef unsigned short __kernel_dev_t; -typedef unsigned long __kernel_ino_t; -typedef unsigned short __kernel_mode_t; -typedef unsigned short __kernel_nlink_t; -typedef long __kernel_off_t; -typedef int __kernel_pid_t; -typedef unsigned short __kernel_ipc_pid_t; -typedef unsigned short __kernel_uid_t; -typedef unsigned short __kernel_gid_t; -typedef unsigned int __kernel_size_t; -typedef int __kernel_ssize_t; -typedef int __kernel_ptrdiff_t; -typedef long __kernel_time_t; -typedef long __kernel_suseconds_t; -typedef long __kernel_clock_t; -typedef int __kernel_daddr_t; -typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +#ifdef CONFIG_BINUTILS_NEW +typedef long unsigned int __kernel_size_t; +#else +typedef unsigned int __kernel_size_t; +#endif +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; #ifdef __GNUC__ -typedef long long __kernel_loff_t; +typedef long long __kernel_loff_t; #endif typedef struct { +#if defined(__KERNEL__) || defined(__USE_ALL) int val[2]; +#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */ + int __val[2]; +#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */ } __kernel_fsid_t; -#undef __FD_SET +#undef __FD_SET #define __FD_SET(fd, fdsetp) \ (((fd_set *)fdsetp)->fds_bits[fd >> 5] |= (1<<(fd & 31))) -#undef __FD_CLR +#undef __FD_CLR #define __FD_CLR(fd, fdsetp) \ (((fd_set *)fdsetp)->fds_bits[fd >> 5] &= ~(1<<(fd & 31))) -#undef __FD_ISSET +#undef __FD_ISSET #define __FD_ISSET(fd, fdsetp) \ ((((fd_set *)fdsetp)->fds_bits[fd >> 5] & (1<<(fd & 31))) != 0) -#undef __FD_ZERO +#undef __FD_ZERO #define __FD_ZERO(fdsetp) \ (memset (fdsetp, 0, sizeof (*(fd_set *)fdsetp))) diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/proc-armo/mm-init.h linux/include/asm-arm/proc-armo/mm-init.h --- v2.1.100/linux/include/asm-arm/proc-armo/mm-init.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/proc-armo/mm-init.h Fri May 8 00:42:40 1998 @@ -8,8 +8,8 @@ * some more work to get it to fit into our separate processor and * architecture structure. */ - -static unsigned long phys_screen_end; +extern unsigned long phys_screen_end; +extern unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update); int page_nr; #define setup_processor_functions() @@ -18,76 +18,6 @@ static inline void setup_swapper_dir (int index, pte_t *ptep) { set_pmd (pmd_offset (swapper_pg_dir + index, 0), mk_pmd (ptep)); -} - -/* - * This routine needs more work to make it dynamically release/allocate mem! - */ -unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update) -{ - static int updated = 0; - - if (updated) - return 0; - - updated = update; - - if (update) { - unsigned long address = log_start, offset; - pgd_t *pgdp; - - kmem = (kmem + 3) & ~3; - - pgdp = pgd_offset (&init_mm, address); /* +31 */ - offset = SCREEN_START; - while (address < SCREEN1_END) { - unsigned long addr_pmd, end_pmd; - pmd_t *pmdp; - - /* if (pgd_none (*pgdp)) alloc pmd */ - pmdp = pmd_offset (pgdp, address); /* +0 */ - addr_pmd = address & ~PGDIR_MASK; /* 088000 */ - end_pmd = addr_pmd + SCREEN1_END - address; /* 100000 */ - if (end_pmd > PGDIR_SIZE) - end_pmd = PGDIR_SIZE; - - do { - unsigned long addr_pte, end_pte; - pte_t *ptep; - - if (pmd_none (*pmdp)) { - pte_t *new_pte = (pte_t *)kmem; - kmem += PTRS_PER_PTE * BYTES_PER_PTR; - memzero (new_pte, PTRS_PER_PTE * BYTES_PER_PTR); - set_pmd (pmdp, mk_pmd(new_pte)); - } - - ptep = pte_offset (pmdp, addr_pmd); /* +11 */ - addr_pte = addr_pmd & ~PMD_MASK; /* 088000 */ - end_pte = addr_pte + end_pmd - addr_pmd; /* 100000 */ - if (end_pte > PMD_SIZE) - end_pte = PMD_SIZE; - - do { - set_pte (ptep, mk_pte(offset, PAGE_KERNEL)); - addr_pte += PAGE_SIZE; - offset += PAGE_SIZE; - ptep++; - } while (addr_pte < end_pte); - - pmdp++; - addr_pmd = (addr_pmd + PMD_SIZE) & PMD_MASK; - } while (addr_pmd < end_pmd); - - address = (address + PGDIR_SIZE) & PGDIR_MASK; - pgdp ++; - } - - phys_screen_end = offset; - flush_tlb_all (); - update_mm_cache_all (); - } - return kmem; } static inline unsigned long setup_pagetables(unsigned long start_mem, unsigned long end_mem) diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/proc-armo/page.h linux/include/asm-arm/proc-armo/page.h --- v2.1.100/linux/include/asm-arm/proc-armo/page.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/proc-armo/page.h Fri May 8 00:42:40 1998 @@ -7,8 +7,16 @@ #ifndef __ASM_PROC_PAGE_H #define __ASM_PROC_PAGE_H -/* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT 15 +#include + +/* PAGE_SHIFT determines the page size. This is configurable. */ +#if defined(CONFIG_PAGESIZE_8) +#define PAGE_SHIFT 13 /* 8K */ +#elif defined(CONFIG_PAGESIZE_16) +#define PAGE_SHIFT 14 /* 16K */ +#else /* default */ +#define PAGE_SHIFT 15 /* 32K */ +#endif #define PAGE_SIZE (1UL << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE-1)) diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/proc-armo/pgtable.h linux/include/asm-arm/proc-armo/pgtable.h --- v2.1.100/linux/include/asm-arm/proc-armo/pgtable.h Wed Apr 8 19:36:28 1998 +++ linux/include/asm-arm/proc-armo/pgtable.h Fri May 8 00:42:40 1998 @@ -41,7 +41,7 @@ /* * We have a mem map cache... */ -extern __inline__ void update_mm_cache_all(void) +extern __inline__ void update_memc_all(void) { struct task_struct *p; @@ -54,7 +54,7 @@ processor.u.armv2._remap_memc (current); } -extern __inline__ void update_mm_cache_task(struct task_struct *tsk) +extern __inline__ void update_memc_task(struct task_struct *tsk) { processor.u.armv2._update_map(tsk); @@ -62,7 +62,7 @@ processor.u.armv2._remap_memc (tsk); } -extern __inline__ void update_mm_cache_mm(struct mm_struct *mm) +extern __inline__ void update_memc_mm(struct mm_struct *mm) { struct task_struct *p; @@ -77,7 +77,7 @@ processor.u.armv2._remap_memc (current); } -extern __inline__ void update_mm_cache_mm_addr(struct mm_struct *mm, unsigned long addr, pte_t pte) +extern __inline__ void update_memc_addr(struct mm_struct *mm, unsigned long addr, pte_t pte) { struct task_struct *p; @@ -117,7 +117,6 @@ #define PTRS_PER_PTE 32 #define PTRS_PER_PMD 1 #define PTRS_PER_PGD 32 -#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SHIFT) /* Just any arbitrary offset to the start of the vmalloc VM area: the * current 8MB value just means that there will be a 8MB "hole" after the @@ -407,7 +406,8 @@ { } -extern void __bad_pte(pmd_t *pmd); +extern void __bad_pmd(pmd_t *pmd); +extern void __bad_pmd_kernel(pmd_t *pmd); #define pte_free_kernel(pte) free_pte_fast(pte) #define pte_free(pte) free_pte_fast(pte) @@ -427,7 +427,7 @@ return page + address; } if (pmd_bad (*pmd)) { - __bad_pte(pmd); + __bad_pmd(pmd); return NULL; } return (pte_t *) pmd_page(*pmd) + address; @@ -450,6 +450,7 @@ #define pmd_alloc_kernel pmd_alloc #define pte_alloc_kernel pte_alloc +#if 0 extern __inline__ void set_pgdir(unsigned long address, pgd_t entry) { struct task_struct * p; @@ -463,8 +464,9 @@ } read_unlock(&tasklist_lock); for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd) - pgd[address >> PGDIR_SHIFT)] = entry; + pgd[address >> PGDIR_SHIFT] = entry; } +#endif extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/proc-armo/uaccess.h linux/include/asm-arm/proc-armo/uaccess.h --- v2.1.100/linux/include/asm-arm/proc-armo/uaccess.h Tue Jan 20 16:39:43 1998 +++ linux/include/asm-arm/proc-armo/uaccess.h Fri May 8 00:42:40 1998 @@ -33,7 +33,7 @@ #define __range_ok(addr,size) ({ \ unsigned long flag, sum; \ - __asm__ __volatile__("adds %1, %2, %3; cmpls %1, %0; movls %0, #0" \ + __asm__ __volatile__("subs %1, %0, %3; cmpcs %1, %2; movcs %0, #0" \ : "=&r" (flag), "=&r" (sum) \ : "r" (addr), "Ir" (size), "0" (current->addr_limit) \ : "cc"); \ diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/proc-armv/pgtable.h linux/include/asm-arm/proc-armv/pgtable.h --- v2.1.100/linux/include/asm-arm/proc-armv/pgtable.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/proc-armv/pgtable.h Fri May 8 00:42:40 1998 @@ -45,12 +45,12 @@ processor.u.armv3v4._flush_icache_area((_start), (_end)) /* - * We don't have a mem map cache... + * We don't have a MEMC chip... */ -#define update_mm_cache_all() do { } while (0) -#define update_mm_cache_task(tsk) do { } while (0) -#define update_mm_cache_mm(mm) do { } while (0) -#define update_mm_cache_mm_addr(mm,addr,pte) do { } while (0) +#define update_memc_all() do { } while (0) +#define update_memc_task(tsk) do { } while (0) +#define update_memc_mm(mm) do { } while (0) +#define update_memc_addr(mm,addr,pte) do { } while (0) /* * This flushes back any buffered write data. We have to clean and flush the entries @@ -133,7 +133,6 @@ #define PTRS_PER_PTE 256 #define PTRS_PER_PMD 1 #define PTRS_PER_PGD 4096 -#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) /* Just any arbitrary offset to the start of the vmalloc VM area: the * current 8MB value just means that there will be a 8MB "hole" after the diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/processor.h linux/include/asm-arm/processor.h --- v2.1.100/linux/include/asm-arm/processor.h Tue Jan 20 16:39:43 1998 +++ linux/include/asm-arm/processor.h Fri May 8 00:42:40 1998 @@ -42,8 +42,18 @@ EXTRA_THREAD_STRUCT_INIT \ } +/* Forward declaration, a strange C thing */ +struct mm_struct; + /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); + +/* Copy and release all segment info associated with a VM */ +extern void copy_segments(int nr, struct task_struct *p, struct mm_struct * mm); +extern void release_segments(struct mm_struct * mm); + +#define copy_segments(nr, tsk, mm) do { } while (0) +#define release_segments(mm) do { } while (0) #define init_task (init_task_union.task) #define init_stack (init_task_union.stack) diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/procinfo.h linux/include/asm-arm/procinfo.h --- v2.1.100/linux/include/asm-arm/procinfo.h Tue Jan 20 16:39:43 1998 +++ linux/include/asm-arm/procinfo.h Fri May 8 00:42:40 1998 @@ -18,13 +18,17 @@ #ifndef __ASSEMBLER__ struct armversions { - unsigned long id; - unsigned long mask; - unsigned long features; - const char *manu; - const char *name; - const struct processor *proc; + unsigned long id; /* Processor ID */ + unsigned long mask; /* Processor ID mask */ + unsigned long features; /* Features (see above) */ + const char *manu; /* Manufacturer */ + const char *name; /* Processor name */ + const struct processor *proc; /* Processor-specific ASM */ + const char *optname; /* Optimisation name */ }; + +extern struct armversions armidlist[]; +extern int armidindex; #endif diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/stat.h linux/include/asm-arm/stat.h --- v2.1.100/linux/include/asm-arm/stat.h Wed Apr 8 19:36:28 1998 +++ linux/include/asm-arm/stat.h Fri May 8 00:42:40 1998 @@ -38,6 +38,7 @@ unsigned long __unused5; }; +#if 0 typedef struct { unsigned int minor; unsigned int major; @@ -73,5 +74,5 @@ #define __XSTAT_VER_TYPEMASK 0xff00 #define __XMKNOD_VER_1 1 - +#endif #endif diff -u --recursive --new-file v2.1.100/linux/include/asm-i386/hardirq.h linux/include/asm-i386/hardirq.h --- v2.1.100/linux/include/asm-i386/hardirq.h Fri Jan 30 15:50:57 1998 +++ linux/include/asm-i386/hardirq.h Fri May 8 00:31:10 1998 @@ -5,6 +5,12 @@ extern unsigned int local_irq_count[NR_CPUS]; +/* + * Are we in an interrupt context? Either doing bottom half + * or hardware interrupt processing? + */ +#define in_interrupt() (local_irq_count[smp_processor_id()] + local_bh_count[smp_processor_id()] != 0) + #ifndef __SMP__ #define hardirq_trylock(cpu) (local_irq_count[cpu] == 0) diff -u --recursive --new-file v2.1.100/linux/include/asm-i386/md.h linux/include/asm-i386/md.h --- v2.1.100/linux/include/asm-i386/md.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-i386/md.h Fri May 8 00:17:13 1998 @@ -0,0 +1,13 @@ +/* $Id: md.h,v 1.1 1997/12/15 15:11:57 jj Exp $ + * md.h: High speed xor_block operation for RAID4/5 + * + */ + +#ifndef __ASM_MD_H +#define __ASM_MD_H + +/* #define HAVE_ARCH_XORBLOCK */ + +#define MD_XORBLOCK_ALIGNMENT sizeof(long) + +#endif /* __ASM_MD_H */ diff -u --recursive --new-file v2.1.100/linux/include/asm-i386/smp.h linux/include/asm-i386/smp.h --- v2.1.100/linux/include/asm-i386/smp.h Sat May 2 14:19:54 1998 +++ linux/include/asm-i386/smp.h Fri May 8 00:45:50 1998 @@ -184,6 +184,7 @@ extern void smp_callin(void); extern void smp_boot_cpus(void); extern void smp_store_cpu_info(int id); /* Store per cpu info (like the initial udelay numbers */ +extern void smp_message_pass(int target, int msg, unsigned long data, int wait); extern volatile unsigned long smp_proc_in_lock[NR_CPUS]; /* for computing process time */ extern volatile int smp_process_available; diff -u --recursive --new-file v2.1.100/linux/include/asm-i386/timex.h linux/include/asm-i386/timex.h --- v2.1.100/linux/include/asm-i386/timex.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-i386/timex.h Thu May 7 23:53:35 1998 @@ -0,0 +1,15 @@ +/* + * linux/include/asm-i386/timex.h + * + * i386 architecture timex specifications + */ +#ifndef _ASMi386_TIMEX_H +#define _ASMi386_TIMEX_H + +#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ +#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */ +#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \ + (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \ + << (SHIFT_SCALE-SHIFT_HZ)) / HZ) + +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/adb.h linux/include/asm-m68k/adb.h --- v2.1.100/linux/include/asm-m68k/adb.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/adb.h Fri May 8 00:15:22 1998 @@ -0,0 +1,75 @@ +/* + * Definitions for talking to ADB and CUDA. The CUDA is a microcontroller + * which controls the ADB, system power, RTC, and various other things on + * later Macintoshes + * + * Copyright (C) 1996 Paul Mackerras. + */ + +/* First byte sent to or received from CUDA */ +#define ADB_PACKET 0 +#define CUDA_PACKET 1 +#define ERROR_PACKET 2 +#define TIMER_PACKET 3 +#define POWER_PACKET 4 +#define MACIIC_PACKET 5 + +/* ADB commands (2nd byte) */ +#define ADB_BUSRESET 0 +#define ADB_FLUSH(id) (1 + ((id) << 4)) +#define ADB_WRITEREG(id, reg) (8 + (reg) + ((id) << 4)) +#define ADB_READREG(id, reg) (0xc + (reg) + ((id) << 4)) + +/* ADB default device IDs (upper 4 bits of 2nd byte) */ +#define ADB_DONGLE 1 /* "software execution control" devices */ +#define ADB_KEYBOARD 2 +#define ADB_MOUSE 3 +#define ADB_TABLET 4 +#define ADB_MODEM 5 +#define ADB_MISC 7 /* maybe a monitor */ + +/* CUDA commands (2nd byte) */ +#define CUDA_WARM_START 0 +#define CUDA_AUTOPOLL 1 +#define CUDA_GET_6805_ADDR 2 +#define CUDA_GET_TIME 3 +#define CUDA_GET_PRAM 7 +#define CUDA_SET_6805_ADDR 8 +#define CUDA_SET_TIME 9 +#define CUDA_POWERDOWN 0xa +#define CUDA_POWERUP_TIME 0xb +#define CUDA_SET_PRAM 0xc +#define CUDA_MS_RESET 0xd +#define CUDA_SEND_DFAC 0xe +#define CUDA_RESET_SYSTEM 0x11 +#define CUDA_SET_IPL 0x12 +#define CUDA_SET_AUTO_RATE 0x14 +#define CUDA_GET_AUTO_RATE 0x16 +#define CUDA_SET_DEVICE_LIST 0x19 +#define CUDA_GET_DEVICE_LIST 0x1a +#define CUDA_GET_SET_IIC 0x22 + +#ifdef __KERNEL__ + +struct adb_request { + unsigned char data[16]; + int nbytes; + unsigned char reply[16]; + int reply_len; + unsigned char reply_expected; + unsigned char sent; + unsigned char got_reply; + void (*done)(struct adb_request *); + void *arg; + struct adb_request *next; +}; + +void via_adb_init(void); +int adb_request(struct adb_request *req, + void (*done)(struct adb_request *), int nbytes, ...); +int adb_send_request(struct adb_request *req); +void adb_poll(void); +int adb_register(int default_id, + void (*handler)(unsigned char *, int, struct pt_regs *)); + +#endif /* __KERNEL */ diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/linux_logo.h linux/include/asm-m68k/linux_logo.h --- v2.1.100/linux/include/asm-m68k/linux_logo.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/linux_logo.h Fri May 8 00:15:22 1998 @@ -0,0 +1,69 @@ +/* $Id: linux_logo.h,v 1.1 1997/04/16 17:51:24 jj Exp $ + * include/asm-m68k/linux_logo.h: This is a linux logo + * to be displayed on boot. + * + * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu) + * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * + * You can put anything here, but: + * LINUX_LOGO_COLORS has to be less than 224 + * image size has to be 80x80 + * values have to start from 0x20 + * (i.e. RGB(linux_logo_red[0], + * linux_logo_green[0], + * linux_logo_blue[0]) is color 0x20) + * BW image has to be 80x80 as well, with MS bit + * on the left + * Serial_console ascii image can be any size, + * but should contain %s to display the version + */ + +#include +#include + +#define linux_logo_banner "Linux/m68k version " UTS_RELEASE + +#define LINUX_LOGO_COLORS 221 + +#ifdef INCLUDE_LINUX_LOGO_DATA + +#define INCLUDE_LINUX_LOGO16 +#include + +/* Painted by Johnny Stenback */ + +unsigned char *linux_serial_image __initdata = "\n" +" .u$e.\n" +" .$$$$$:S\n" +" $\"*$/\"*$$\n" +" $.`$ . ^F\n" +" 4k+#+T.$F\n" +" 4P+++\"$\"$\n" +" :R\"+ t$$B\n" +" ___# $$$\n" +" | | R$$k\n" +" dd. | Linux $!$\n" +" ddd | m68k $9$F\n" +" '!!!!!$ !!#!`\n" +" !!!!!* .!!!!!`\n" +"'!!!!!!!W..e$$!!!!!!` %s\n" +" \"~^^~ ^~~^\n" +"\n"; + +#else + +/* prototypes only */ +extern unsigned char linux_logo_red[]; +extern unsigned char linux_logo_green[]; +extern unsigned char linux_logo_blue[]; +extern unsigned char linux_logo[]; +extern unsigned char linux_logo_bw[]; +extern unsigned char linux_logo16_red[]; +extern unsigned char linux_logo16_green[]; +extern unsigned char linux_logo16_blue[]; +extern unsigned char linux_logo16[]; +extern unsigned char *linux_serial_image; + +extern int (*console_show_logo)(void); + +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/macintosh.h linux/include/asm-m68k/macintosh.h --- v2.1.100/linux/include/asm-m68k/macintosh.h Tue Feb 17 13:12:49 1998 +++ linux/include/asm-m68k/macintosh.h Fri May 8 00:15:22 1998 @@ -56,6 +56,8 @@ #define MAC_ADB_II 1 #define MAC_ADB_IISI 2 #define MAC_ADB_CUDA 3 +#define MAC_ADB_PB1 4 +#define MAC_ADB_PB2 5 #define MAC_VIA_II 1 #define MAC_VIA_IIci 2 @@ -93,7 +95,7 @@ #define MAC_MODEL_IIFX 13 /* And well numbered it is too */ #define MAC_MODEL_IISI 18 #define MAC_MODEL_Q900 20 -#define MAC_MODEL_PB170 25 +#define MAC_MODEL_PB170 21 #define MAC_MODEL_Q700 22 #define MAC_MODEL_CLII 23 #define MAC_MODEL_PB140 25 @@ -109,6 +111,7 @@ #define MAC_MODEL_LCII 37 /* aka: P400/405/410/430 */ #define MAC_MODEL_PB250 38 #define MAC_MODEL_IIVI 44 +#define MAC_MODEL_P600 45 #define MAC_MODEL_IIVX 48 #define MAC_MODEL_CCL 49 #define MAC_MODEL_PB165C 50 @@ -123,6 +126,7 @@ #define MAC_MODEL_PB270C 77 #define MAC_MODEL_Q840 78 #define MAC_MODEL_P550 80 +#define MAC_MODEL_CCLII 83 #define MAC_MODEL_PB165 84 #define MAC_MODEL_PB190 85 #define MAC_MODEL_TV 88 diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/macints.h linux/include/asm-m68k/macints.h --- v2.1.100/linux/include/asm-m68k/macints.h Tue Feb 17 13:12:49 1998 +++ linux/include/asm-m68k/macints.h Fri May 8 00:15:22 1998 @@ -143,7 +143,7 @@ void mac_turnoff_irq( unsigned irq ); void mac_clear_pending_irq( unsigned irq ); int mac_irq_pending( unsigned irq ); -int nubus_request_irq(int slot, void (*handler)(int,void *,struct pt_regs *)); +int nubus_request_irq(int slot, void *dev_id, void (*handler)(int,void *,struct pt_regs *)); int nubus_free_irq(int slot); unsigned long mac_register_nubus_int( void ); diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/md.h linux/include/asm-m68k/md.h --- v2.1.100/linux/include/asm-m68k/md.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/md.h Fri May 8 00:15:22 1998 @@ -0,0 +1,13 @@ +/* $Id: md.h,v 1.1 1997/12/15 15:12:04 jj Exp $ + * md.h: High speed xor_block operation for RAID4/5 + * + */ + +#ifndef __ASM_MD_H +#define __ASM_MD_H + +/* #define HAVE_ARCH_XORBLOCK */ + +#define MD_XORBLOCK_ALIGNMENT sizeof(long) + +#endif /* __ASM_MD_H */ diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/page.h linux/include/asm-m68k/page.h --- v2.1.100/linux/include/asm-m68k/page.h Wed Apr 23 19:01:27 1997 +++ linux/include/asm-m68k/page.h Fri May 8 00:15:22 1998 @@ -12,6 +12,9 @@ #define STRICT_MM_TYPECHECKS +#define get_user_page(vaddr) __get_free_page(GFP_KERNEL) +#define free_user_page(page, addr) free_page(addr) + /* * We don't need to check for alignment etc. */ diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/pgtable.h linux/include/asm-m68k/pgtable.h --- v2.1.100/linux/include/asm-m68k/pgtable.h Tue Feb 17 13:12:49 1998 +++ linux/include/asm-m68k/pgtable.h Fri May 8 00:15:22 1998 @@ -5,6 +5,8 @@ #ifndef __ASSEMBLY__ +#include /* For TASK_SIZE */ + /* * This file contains the functions and defines necessary to modify and use * the m68k page table tree. @@ -263,6 +265,7 @@ #define PTRS_PER_PTE 1024 #define PTRS_PER_PMD 8 #define PTRS_PER_PGD 128 +#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) /* the no. of pointers that fit on a page: this will go away */ #define PTRS_PER_PAGE (PAGE_SIZE/sizeof(void*)) @@ -584,40 +587,94 @@ } } +extern struct pgtable_cache_struct { + unsigned long *pte_cache; + unsigned long pgtable_cache_sz; +} quicklists; +#define pgd_quicklist ((unsigned long *)0) +#define pmd_quicklist ((unsigned long *)0) +#define pte_quicklist (quicklists.pte_cache) +#define pgtable_cache_size (quicklists.pgtable_cache_sz) + +/* We don't use pgd cache yet, so this is a dummy routine */ +extern __inline__ pgd_t *get_pgd_fast(void) +{ + return (pgd_t *)0; +} + +extern __inline__ void free_pgd_fast(pgd_t *pgd) +{ +} + +extern __inline__ void free_pgd_slow(pgd_t *pgd) +{ +} + +/* We don't use pmd cache yet, so this is a dummy routine */ +extern __inline__ pmd_t *get_pmd_fast(void) +{ + return (pmd_t *)0; +} + +extern __inline__ void free_pmd_fast(pmd_t *pmd) +{ +} + +extern __inline__ void free_pmd_slow(pmd_t *pmd) +{ +} + +extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted); + +extern __inline__ pte_t *get_pte_fast(void) +{ + unsigned long *ret; + + if((ret = (unsigned long *)pte_quicklist) != NULL) { + pte_quicklist = (unsigned long *)(*ret); + ret[0] = ret[1]; + pgtable_cache_size--; + } + return (pte_t *)ret; +} + +extern __inline__ void free_pte_fast(pte_t *pte) +{ + *(unsigned long *)pte = (unsigned long) pte_quicklist; + pte_quicklist = (unsigned long *) pte; + pgtable_cache_size++; +} + +extern __inline__ void free_pte_slow(pte_t *pte) +{ + cache_page((unsigned long)pte); + free_page((unsigned long)pte); +} + +extern void __bad_pte(pmd_t *pmd); extern const char PgtabStr_bad_pmd[]; extern const char PgtabStr_bad_pgd[]; extern const char PgtabStr_bad_pmdk[]; extern const char PgtabStr_bad_pgdk[]; -extern inline void pte_free(pte_t * pte) -{ - cache_page((unsigned long)pte); - free_page((unsigned long) pte); -} +#define pte_free free_pte_fast +#define pte_free_kernel free_pte_fast +#define pte_alloc_kernel pte_alloc extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address) { address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); if (pmd_none(*pmd)) { - pte_t * page = (pte_t *)__get_free_page(GFP_KERNEL); - if (pmd_none(*pmd)) { - if (page) { - memset((void *) page, 0, PAGE_SIZE); - flush_page_to_ram((unsigned long)page); - flush_tlb_kernel_page((unsigned long)page); - nocache_page((unsigned long)page); - pmd_set(pmd,page); - return page + address; - } - pmd_set(pmd, BAD_PAGETABLE); - return NULL; - } - free_page((unsigned long)page); + pte_t * page = (pte_t *)get_pte_fast(); + + if (!page) + return get_pte_slow(pmd, address); + pmd_set(pmd,page); + return page + address; } if (pmd_bad(*pmd)) { - printk(PgtabStr_bad_pmd, pmd_val(*pmd)); - pmd_set(pmd, BAD_PAGETABLE); + __bad_pte(pmd); return NULL; } return (pte_t *) pmd_page(*pmd) + address; @@ -656,37 +713,6 @@ return (pmd_t *) pgd_page(*pgd) + address; } -extern inline void pte_free_kernel(pte_t * pte) -{ - cache_page((unsigned long)pte); - free_page((unsigned long) pte); -} - -extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address) -{ - address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); - if (pmd_none(*pmd)) { - pte_t * page = (pte_t *) get_free_page(GFP_KERNEL); - if (pmd_none(*pmd)) { - if (page) { - flush_tlb_kernel_page((unsigned long)page); - nocache_page((unsigned long)page); - pmd_set(pmd, page); - return page + address; - } - pmd_set(pmd, BAD_PAGETABLE); - return NULL; - } - free_page((unsigned long) page); - } - if (pmd_bad(*pmd)) { - printk(PgtabStr_bad_pmdk, pmd_val(*pmd)); - pmd_set(pmd, BAD_PAGETABLE); - return NULL; - } - return (pte_t *) pmd_page(*pmd) + address; -} - extern inline void pmd_free_kernel(pmd_t * pmd) { free_kpointer_table(pmd); @@ -722,7 +748,21 @@ extern inline pgd_t * pgd_alloc(void) { - return (pgd_t *)get_pointer_table (); + pgd_t *ret = (pgd_t *)get_pointer_table (); + + if (ret) { + pgd_t * init; + + init = pgd_offset(&init_mm, 0); + memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, + (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof (pgd_t)); + } + return ret; +} + +extern inline void set_pgdir(unsigned long address, pgd_t entry) +{ + /* Nothing to do on m68k */ } /* @@ -777,9 +817,13 @@ #define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << PAGE_SHIFT)) #endif -#endif /* __ASSEMBLY__ */ - #define module_map vmalloc #define module_unmap vfree +#define module_shrink vshrink + +/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ +#define PageSkip(page) (0) + +#endif /* __ASSEMBLY__ */ #endif /* _M68K_PGTABLE_H */ diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/processor.h linux/include/asm-m68k/processor.h --- v2.1.100/linux/include/asm-m68k/processor.h Tue Feb 17 13:12:49 1998 +++ linux/include/asm-m68k/processor.h Fri May 8 00:15:22 1998 @@ -19,7 +19,8 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE 0xC0000000UL +#define TASK_UNMAPPED_BASE(off) 0xC0000000UL +#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) /* * Bus types @@ -93,6 +94,9 @@ else return sw->retpc; } + +#define copy_segments(nr, tsk, mm) do { } while (0) +#define release_segments(mm) do { } while (0) /* Allocation and freeing of basic task resources. */ #define alloc_task_struct() \ diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/stat.h linux/include/asm-m68k/stat.h --- v2.1.100/linux/include/asm-m68k/stat.h Fri Nov 22 05:56:36 1996 +++ linux/include/asm-m68k/stat.h Fri May 8 00:15:22 1998 @@ -38,4 +38,40 @@ unsigned long __unused5; }; +typedef struct { + unsigned int major; + unsigned int minor; +} __new_dev_t; + +struct stat64 { + __new_dev_t st_dev; + __u64 st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + __new_dev_t st_rdev; + __s64 st_size; + __u64 st_blocks; + unsigned long st_atime; + unsigned long __unused1; + unsigned long st_mtime; + unsigned long __unused2; + unsigned long st_ctime; + unsigned long __unused3; + unsigned long st_blksize; + unsigned long __unused4; +}; + +#define __XSTAT_VER_1 1 +#define __XSTAT_VER_2 2 +#define __XSTAT_VER_MASK 0xff + +#define __XSTAT_VER_XSTAT 0x000 +#define __XSTAT_VER_LXSTAT 0x100 +#define __XSTAT_VER_FXSTAT 0x200 +#define __XSTAT_VER_TYPEMASK 0xff00 + +#define __XMKNOD_VER_1 1 + #endif /* _M68K_STAT_H */ diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/timex.h linux/include/asm-m68k/timex.h --- v2.1.100/linux/include/asm-m68k/timex.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/timex.h Thu May 7 23:53:35 1998 @@ -0,0 +1,15 @@ +/* + * linux/include/asm-m68k/timex.h + * + * m68k architecture timex specifications + */ +#ifndef _ASMm68k_TIMEX_H +#define _ASMm68k_TIMEX_H + +#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ +#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */ +#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \ + (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \ + << (SHIFT_SCALE-SHIFT_HZ)) / HZ) + +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/xstat.h linux/include/asm-m68k/xstat.h --- v2.1.100/linux/include/asm-m68k/xstat.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/xstat.h Fri May 8 00:15:22 1998 @@ -0,0 +1,35 @@ +/* $Id: xstat.h,v 1.1 1998/02/06 12:51:30 jj Exp $ + * xstat.h: sys_xstat/xmknod architecture dependent stuff. + * + * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + */ + +extern __inline__ int cp_xstat(struct inode *inode, struct stat64 *s, unsigned long blocks, int blksize) +{ + struct stat64 tmp; + + memset (&tmp, 0, sizeof(tmp)); + tmp.st_dev.major = MAJOR(inode->i_dev); + tmp.st_dev.minor = MINOR(inode->i_dev); + tmp.st_ino = inode->i_ino; + tmp.st_mode = inode->i_mode; + tmp.st_nlink = inode->i_nlink; + tmp.st_uid = inode->i_uid; + tmp.st_gid = inode->i_gid; + tmp.st_rdev.major = MAJOR(inode->i_rdev); + tmp.st_rdev.minor = MINOR(inode->i_rdev); + tmp.st_size = inode->i_size; + tmp.st_blksize = blksize; + tmp.st_blocks = blocks; + tmp.st_atime = inode->i_atime; + tmp.st_mtime = inode->i_mtime; + tmp.st_ctime = inode->i_ctime; + return copy_to_user(s,&tmp,sizeof(tmp)); +} + +extern __inline__ int get_user_new_dev_t(kdev_t *kdev, __new_dev_t *udev) { + __new_dev_t ndev; + if (copy_from_user (&ndev, udev, sizeof(__new_dev_t))) return -EFAULT; + *kdev = MKDEV(ndev.major, ndev.minor); + return 0; +} diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/asmmacro.h linux/include/asm-mips/asmmacro.h --- v2.1.100/linux/include/asm-mips/asmmacro.h Wed Dec 10 10:31:10 1997 +++ linux/include/asm-mips/asmmacro.h Fri May 8 00:13:26 1998 @@ -1,89 +1,161 @@ -/* $Id: asmmacro.h,v 1.1.1.1 1997/06/01 03:17:13 ralf Exp $ +/* * asmmacro.h: Assembler macros to make things easier to read. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1998 Ralf Baechle + * + * $Id: asmmacro.h,v 1.2 1998/05/01 01:35:44 ralf Exp $ */ - #ifndef __MIPS_ASMMACRO_H #define __MIPS_ASMMACRO_H #include -#define FPU_SAVE_16ODD(thread) \ - swc1 $f1, (THREAD_FPU + 0x08)(thread); \ - swc1 $f3, (THREAD_FPU + 0x18)(thread); \ - swc1 $f5, (THREAD_FPU + 0x28)(thread); \ - swc1 $f7, (THREAD_FPU + 0x38)(thread); \ - swc1 $f9, (THREAD_FPU + 0x48)(thread); \ - swc1 $f11, (THREAD_FPU + 0x58)(thread); \ - swc1 $f13, (THREAD_FPU + 0x68)(thread); \ - swc1 $f15, (THREAD_FPU + 0x78)(thread); \ - swc1 $f17, (THREAD_FPU + 0x88)(thread); \ - swc1 $f19, (THREAD_FPU + 0x98)(thread); \ - swc1 $f21, (THREAD_FPU + 0xa8)(thread); \ - swc1 $f23, (THREAD_FPU + 0xb8)(thread); \ - swc1 $f25, (THREAD_FPU + 0xc8)(thread); \ - swc1 $f27, (THREAD_FPU + 0xd8)(thread); \ - swc1 $f29, (THREAD_FPU + 0xe8)(thread); \ - swc1 $f31, (THREAD_FPU + 0xf8)(thread); - - -#define FPU_RESTORE_16ODD(thread) \ - lwc1 $f1, (THREAD_FPU + 0x08)(thread); \ - lwc1 $f3, (THREAD_FPU + 0x18)(thread); \ - lwc1 $f5, (THREAD_FPU + 0x28)(thread); \ - lwc1 $f7, (THREAD_FPU + 0x38)(thread); \ - lwc1 $f9, (THREAD_FPU + 0x48)(thread); \ - lwc1 $f11, (THREAD_FPU + 0x58)(thread); \ - lwc1 $f13, (THREAD_FPU + 0x68)(thread); \ - lwc1 $f15, (THREAD_FPU + 0x78)(thread); \ - lwc1 $f17, (THREAD_FPU + 0x88)(thread); \ - lwc1 $f19, (THREAD_FPU + 0x98)(thread); \ - lwc1 $f21, (THREAD_FPU + 0xa8)(thread); \ - lwc1 $f23, (THREAD_FPU + 0xb8)(thread); \ - lwc1 $f25, (THREAD_FPU + 0xc8)(thread); \ - lwc1 $f27, (THREAD_FPU + 0xd8)(thread); \ - lwc1 $f29, (THREAD_FPU + 0xe8)(thread); \ - lwc1 $f31, (THREAD_FPU + 0xf8)(thread); - #define FPU_SAVE_16EVEN(thread, tmp) \ cfc1 tmp, fcr31; \ + sdc1 $f2, (THREAD_FPU + 0x010)(thread); \ + sdc1 $f4, (THREAD_FPU + 0x020)(thread); \ + sdc1 $f6, (THREAD_FPU + 0x030)(thread); \ + sdc1 $f8, (THREAD_FPU + 0x040)(thread); \ + sdc1 $f10, (THREAD_FPU + 0x050)(thread); \ + sdc1 $f12, (THREAD_FPU + 0x060)(thread); \ + sdc1 $f14, (THREAD_FPU + 0x070)(thread); \ + sdc1 $f16, (THREAD_FPU + 0x080)(thread); \ + sdc1 $f18, (THREAD_FPU + 0x090)(thread); \ + sdc1 $f20, (THREAD_FPU + 0x0a0)(thread); \ + sdc1 $f22, (THREAD_FPU + 0x0b0)(thread); \ + sdc1 $f24, (THREAD_FPU + 0x0c0)(thread); \ + sdc1 $f26, (THREAD_FPU + 0x0d0)(thread); \ + sdc1 $f28, (THREAD_FPU + 0x0e0)(thread); \ + sdc1 $f30, (THREAD_FPU + 0x0f0)(thread); \ + sw tmp, (THREAD_FPU + 0x100)(thread) + +#define FPU_SAVE_16ODD(thread) \ + sdc1 $f1, (THREAD_FPU + 0x08)(thread); \ + sdc1 $f3, (THREAD_FPU + 0x18)(thread); \ + sdc1 $f5, (THREAD_FPU + 0x28)(thread); \ + sdc1 $f7, (THREAD_FPU + 0x38)(thread); \ + sdc1 $f9, (THREAD_FPU + 0x48)(thread); \ + sdc1 $f11, (THREAD_FPU + 0x58)(thread); \ + sdc1 $f13, (THREAD_FPU + 0x68)(thread); \ + sdc1 $f15, (THREAD_FPU + 0x78)(thread); \ + sdc1 $f17, (THREAD_FPU + 0x88)(thread); \ + sdc1 $f19, (THREAD_FPU + 0x98)(thread); \ + sdc1 $f21, (THREAD_FPU + 0xa8)(thread); \ + sdc1 $f23, (THREAD_FPU + 0xb8)(thread); \ + sdc1 $f25, (THREAD_FPU + 0xc8)(thread); \ + sdc1 $f27, (THREAD_FPU + 0xd8)(thread); \ + sdc1 $f29, (THREAD_FPU + 0xe8)(thread); \ + sdc1 $f31, (THREAD_FPU + 0xf8)(thread) + +#define FPU_SAVE(thread,tmp) \ + cfc1 tmp, fcr31; \ + swc1 $f0, (THREAD_FPU + 0x000)(thread); \ + swc1 $f1, (THREAD_FPU + 0x008)(thread); \ swc1 $f2, (THREAD_FPU + 0x010)(thread); \ + swc1 $f3, (THREAD_FPU + 0x018)(thread); \ swc1 $f4, (THREAD_FPU + 0x020)(thread); \ + swc1 $f5, (THREAD_FPU + 0x028)(thread); \ swc1 $f6, (THREAD_FPU + 0x030)(thread); \ + swc1 $f7, (THREAD_FPU + 0x038)(thread); \ swc1 $f8, (THREAD_FPU + 0x040)(thread); \ + swc1 $f9, (THREAD_FPU + 0x048)(thread); \ swc1 $f10, (THREAD_FPU + 0x050)(thread); \ + swc1 $f11, (THREAD_FPU + 0x058)(thread); \ swc1 $f12, (THREAD_FPU + 0x060)(thread); \ + swc1 $f13, (THREAD_FPU + 0x068)(thread); \ swc1 $f14, (THREAD_FPU + 0x070)(thread); \ + swc1 $f15, (THREAD_FPU + 0x078)(thread); \ swc1 $f16, (THREAD_FPU + 0x080)(thread); \ + swc1 $f17, (THREAD_FPU + 0x088)(thread); \ swc1 $f18, (THREAD_FPU + 0x090)(thread); \ + swc1 $f19, (THREAD_FPU + 0x098)(thread); \ swc1 $f20, (THREAD_FPU + 0x0a0)(thread); \ + swc1 $f21, (THREAD_FPU + 0x0a8)(thread); \ swc1 $f22, (THREAD_FPU + 0x0b0)(thread); \ + swc1 $f23, (THREAD_FPU + 0x0b8)(thread); \ swc1 $f24, (THREAD_FPU + 0x0c0)(thread); \ + swc1 $f25, (THREAD_FPU + 0x0c8)(thread); \ swc1 $f26, (THREAD_FPU + 0x0d0)(thread); \ + swc1 $f27, (THREAD_FPU + 0x0d8)(thread); \ swc1 $f28, (THREAD_FPU + 0x0e0)(thread); \ + swc1 $f29, (THREAD_FPU + 0x0e8)(thread); \ swc1 $f30, (THREAD_FPU + 0x0f0)(thread); \ - sw tmp, (THREAD_FPU + 0x100)(thread); - + swc1 $f31, (THREAD_FPU + 0x0f8)(thread); \ + sw tmp, (THREAD_FPU + 0x100)(thread) #define FPU_RESTORE_16EVEN(thread, tmp) \ lw tmp, (THREAD_FPU + 0x100)(thread); \ + ldc1 $f2, (THREAD_FPU + 0x010)(thread); \ + ldc1 $f4, (THREAD_FPU + 0x020)(thread); \ + ldc1 $f6, (THREAD_FPU + 0x030)(thread); \ + ldc1 $f8, (THREAD_FPU + 0x040)(thread); \ + ldc1 $f10, (THREAD_FPU + 0x050)(thread); \ + ldc1 $f12, (THREAD_FPU + 0x060)(thread); \ + ldc1 $f14, (THREAD_FPU + 0x070)(thread); \ + ldc1 $f16, (THREAD_FPU + 0x080)(thread); \ + ldc1 $f18, (THREAD_FPU + 0x090)(thread); \ + ldc1 $f20, (THREAD_FPU + 0x0a0)(thread); \ + ldc1 $f22, (THREAD_FPU + 0x0b0)(thread); \ + ldc1 $f24, (THREAD_FPU + 0x0c0)(thread); \ + ldc1 $f26, (THREAD_FPU + 0x0d0)(thread); \ + ldc1 $f28, (THREAD_FPU + 0x0e0)(thread); \ + ldc1 $f30, (THREAD_FPU + 0x0f0)(thread); \ + ctc1 tmp, fcr31 + +#define FPU_RESTORE_16ODD(thread) \ + ldc1 $f1, (THREAD_FPU + 0x08)(thread); \ + ldc1 $f3, (THREAD_FPU + 0x18)(thread); \ + ldc1 $f5, (THREAD_FPU + 0x28)(thread); \ + ldc1 $f7, (THREAD_FPU + 0x38)(thread); \ + ldc1 $f9, (THREAD_FPU + 0x48)(thread); \ + ldc1 $f11, (THREAD_FPU + 0x58)(thread); \ + ldc1 $f13, (THREAD_FPU + 0x68)(thread); \ + ldc1 $f15, (THREAD_FPU + 0x78)(thread); \ + ldc1 $f17, (THREAD_FPU + 0x88)(thread); \ + ldc1 $f19, (THREAD_FPU + 0x98)(thread); \ + ldc1 $f21, (THREAD_FPU + 0xa8)(thread); \ + ldc1 $f23, (THREAD_FPU + 0xb8)(thread); \ + ldc1 $f25, (THREAD_FPU + 0xc8)(thread); \ + ldc1 $f27, (THREAD_FPU + 0xd8)(thread); \ + ldc1 $f29, (THREAD_FPU + 0xe8)(thread); \ + ldc1 $f31, (THREAD_FPU + 0xf8)(thread) + +#define FPU_RESTORE(thread,tmp) \ + lw tmp, (THREAD_FPU + 0x100)(thread); \ + lwc1 $f0, (THREAD_FPU + 0x000)(thread); \ + lwc1 $f1, (THREAD_FPU + 0x008)(thread); \ lwc1 $f2, (THREAD_FPU + 0x010)(thread); \ + lwc1 $f3, (THREAD_FPU + 0x018)(thread); \ lwc1 $f4, (THREAD_FPU + 0x020)(thread); \ + lwc1 $f5, (THREAD_FPU + 0x028)(thread); \ lwc1 $f6, (THREAD_FPU + 0x030)(thread); \ + lwc1 $f7, (THREAD_FPU + 0x038)(thread); \ lwc1 $f8, (THREAD_FPU + 0x040)(thread); \ + lwc1 $f9, (THREAD_FPU + 0x048)(thread); \ lwc1 $f10, (THREAD_FPU + 0x050)(thread); \ + lwc1 $f11, (THREAD_FPU + 0x058)(thread); \ lwc1 $f12, (THREAD_FPU + 0x060)(thread); \ + lwc1 $f13, (THREAD_FPU + 0x068)(thread); \ lwc1 $f14, (THREAD_FPU + 0x070)(thread); \ + lwc1 $f15, (THREAD_FPU + 0x078)(thread); \ lwc1 $f16, (THREAD_FPU + 0x080)(thread); \ + lwc1 $f17, (THREAD_FPU + 0x088)(thread); \ lwc1 $f18, (THREAD_FPU + 0x090)(thread); \ + lwc1 $f19, (THREAD_FPU + 0x098)(thread); \ lwc1 $f20, (THREAD_FPU + 0x0a0)(thread); \ + lwc1 $f21, (THREAD_FPU + 0x0a8)(thread); \ lwc1 $f22, (THREAD_FPU + 0x0b0)(thread); \ + lwc1 $f23, (THREAD_FPU + 0x0b8)(thread); \ lwc1 $f24, (THREAD_FPU + 0x0c0)(thread); \ + lwc1 $f25, (THREAD_FPU + 0x0c8)(thread); \ lwc1 $f26, (THREAD_FPU + 0x0d0)(thread); \ + lwc1 $f27, (THREAD_FPU + 0x0d8)(thread); \ lwc1 $f28, (THREAD_FPU + 0x0e0)(thread); \ + lwc1 $f29, (THREAD_FPU + 0x0e8)(thread); \ lwc1 $f30, (THREAD_FPU + 0x0f0)(thread); \ - ctc1 tmp, fcr31; + lwc1 $f31, (THREAD_FPU + 0x0f8)(thread); \ + ctc1 tmp, fcr31 #define CPU_SAVE_NONSCRATCH(thread) \ sw s0, THREAD_REG16(thread); \ @@ -94,9 +166,8 @@ sw s5, THREAD_REG21(thread); \ sw s6, THREAD_REG22(thread); \ sw s7, THREAD_REG23(thread); \ - sw gp, THREAD_REG28(thread); \ sw sp, THREAD_REG29(thread); \ - sw fp, THREAD_REG30(thread); + sw fp, THREAD_REG30(thread) #define CPU_RESTORE_NONSCRATCH(thread) \ lw s0, THREAD_REG16(thread); \ @@ -107,9 +178,8 @@ lw s5, THREAD_REG21(thread); \ lw s6, THREAD_REG22(thread); \ lw s7, THREAD_REG23(thread); \ - lw gp, THREAD_REG28(thread); \ lw sp, THREAD_REG29(thread); \ lw fp, THREAD_REG30(thread); \ - lw ra, THREAD_REG31(thread); + lw ra, THREAD_REG31(thread) #endif /* !(__MIPS_ASMMACRO_H) */ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/atomic.h linux/include/asm-mips/atomic.h --- v2.1.100/linux/include/asm-mips/atomic.h Tue Dec 16 12:45:55 1997 +++ linux/include/asm-mips/atomic.h Fri May 8 00:13:26 1998 @@ -9,9 +9,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996 by Ralf Baechle + * Copyright (C) 1996, 1997 by Ralf Baechle * - * $Id: atomic.h,v 1.2 1997/06/20 03:05:12 ralf Exp $ + * $Id: atomic.h,v 1.4 1998/05/01 01:35:45 ralf Exp $ */ #ifndef __ASM_MIPS_ATOMIC_H #define __ASM_MIPS_ATOMIC_H diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/bcache.h linux/include/asm-mips/bcache.h --- v2.1.100/linux/include/asm-mips/bcache.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/bcache.h Fri May 8 00:13:26 1998 @@ -0,0 +1,22 @@ +/* + * include/asm-mips/bcache.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1997 by Ralf Baechle + * + * $Id: bcache.h,v 1.1 1998/05/01 01:35:46 ralf Exp $ + */ +struct bcache_ops { + void (*bc_enable)(void); + void (*bc_disable)(void); + void (*bc_wback_inv)(unsigned long page, unsigned long size); + void (*bc_inv)(unsigned long page, unsigned long size); +}; + +extern void indy_sc_init(void); +extern void sni_pcimt_sc_init(void); + +extern struct bcache_ops *bcops; diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/bootinfo.h linux/include/asm-mips/bootinfo.h --- v2.1.100/linux/include/asm-mips/bootinfo.h Tue Dec 16 12:45:55 1997 +++ linux/include/asm-mips/bootinfo.h Fri May 8 00:13:26 1998 @@ -8,7 +8,7 @@ * License. See the file COPYING in the main directory of this archive * for more details. * - * $Id: bootinfo.h,v 1.3 1997/09/19 08:37:44 ralf Exp $ + * $Id: bootinfo.h,v 1.7 1998/05/01 01:35:46 ralf Exp $ */ #ifndef __ASM_MIPS_BOOTINFO_H #define __ASM_MIPS_BOOTINFO_H @@ -26,9 +26,10 @@ #define MACH_GROUP_SNI_RM 4 /* Siemens Nixdorf RM series */ #define MACH_GROUP_ACN 5 #define MACH_GROUP_SGI 6 /* Silicon Graphics workstations and servers */ +#define MACH_GROUP_RESERVED 7 /* No Such Architecture */ #define GROUP_NAMES { "unknown", "Jazz", "Digital", "ARC", \ - "SNI", "ACN", "SGI" } + "SNI", "ACN", "SGI", "NSA" } /* * Valid machtype values for group unknown (low order halfword of mips_machtype) @@ -81,8 +82,6 @@ * Valid machtype for group SGI */ #define MACH_SGI_INDY 0 /* R4?K and R5K Indy workstaions */ - -#define GROUP_SGI_NAMES { "Indy" } #define GROUP_SGI_NAMES { "Indy" } diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/branch.h linux/include/asm-mips/branch.h --- v2.1.100/linux/include/asm-mips/branch.h Thu Jun 26 12:33:39 1997 +++ linux/include/asm-mips/branch.h Fri May 8 00:13:26 1998 @@ -5,7 +5,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 1997 by Ralf Baechle + * Copyright (C) 1996, 1997, 1998 by Ralf Baechle + * + * $Id: branch.h,v 1.2 1998/05/04 09:18:56 ralf Exp $ */ #include @@ -15,12 +17,13 @@ } extern int __compute_return_epc(struct pt_regs *regs); + extern inline int compute_return_epc(struct pt_regs *regs) { - if (delay_slot(regs)) { - return __compute_return_epc(regs); + if (!delay_slot(regs)) { + regs->cp0_epc += 4; + return 0; } - regs->cp0_epc += 4; - return 0; + return __compute_return_epc(regs); } diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/bugs.h linux/include/asm-mips/bugs.h --- v2.1.100/linux/include/asm-mips/bugs.h Tue Dec 16 12:45:55 1997 +++ linux/include/asm-mips/bugs.h Fri May 8 00:13:26 1998 @@ -4,7 +4,7 @@ * Copyright (C) 1995 Waldorf Electronics * Copyright (C) 1997 Ralf Baechle * - * $Id: bugs.h,v 1.2 1997/09/07 04:13:53 ralf Exp $ + * $Id: bugs.h,v 1.4 1998/05/01 01:35:47 ralf Exp $ */ #include diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/cpu.h linux/include/asm-mips/cpu.h --- v2.1.100/linux/include/asm-mips/cpu.h Wed Dec 10 10:31:10 1997 +++ linux/include/asm-mips/cpu.h Fri May 8 00:13:26 1998 @@ -1,4 +1,4 @@ -/* $Id: cpu.h,v 1.1.1.1 1997/06/01 03:17:12 ralf Exp $ +/* $Id: cpu.h,v 1.2 1998/05/01 01:35:49 ralf Exp $ * cpu.h: Values of the PRId register used to match up * various MIPS cpu types. * diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/current.h linux/include/asm-mips/current.h --- v2.1.100/linux/include/asm-mips/current.h Thu Jun 26 12:33:39 1997 +++ linux/include/asm-mips/current.h Fri May 8 00:13:26 1998 @@ -3,33 +3,13 @@ #ifdef __LANGUAGE_C__ -static inline struct task_struct *__get_current(void) -{ - struct task_struct *__current; - - __asm__("ori\t%0,$29,%1\n\t" - "xori\t%0,%1" - :"=r" (__current) - :"ir" (8191UL)); - - return __current; -} - -#define current __get_current() +/* MIPS rules... */ +register struct task_struct *current asm("$28"); #endif /* __LANGUAGE_C__ */ #ifdef __LANGUAGE_ASSEMBLY__ /* - * Get current task pointer - */ -#define GET_CURRENT(reg) \ - lui reg, %hi(kernelsp); \ - lw reg, %lo(kernelsp)(reg); \ - ori reg, 8191; \ - xori reg, 8191 - -/* * Special variant for use by exception handlers when the stack pointer * is not loaded. */ @@ -41,7 +21,6 @@ .set pop; \ ori reg, 8191; \ xori reg, 8191 - #endif diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/elf.h linux/include/asm-mips/elf.h --- v2.1.100/linux/include/asm-mips/elf.h Tue Dec 16 12:46:01 1997 +++ linux/include/asm-mips/elf.h Fri May 8 00:13:26 1998 @@ -1,5 +1,5 @@ /* - * $Id: elf.h,v 1.4 1997/12/16 05:36:40 ralf Exp $ + * $Id: elf.h,v 1.10 1998/05/01 01:35:51 ralf Exp $ */ #ifndef __ASM_MIPS_ELF_H #define __ASM_MIPS_ELF_H @@ -38,6 +38,21 @@ memcpy((char *) &_dest, (char *) _regs, \ sizeof(struct pt_regs)); +/* This yields a mask that user programs can use to figure out what + instruction set this cpu supports. This could be done in userspace, + but it's not easy, and we've already done it here. */ + +#define ELF_HWCAP (0) + +/* This yields a string that ld.so will use to load implementation + specific libraries for optimization. This is more specific in + intent than poking at uname or /proc/cpuinfo. + + For the moment, we have only optimizations for the Intel generations, + but that could change... */ + +#define ELF_PLATFORM (NULL) + /* See comments in asm-alpha/elf.h, this is the same thing * on the MIPS. */ @@ -49,5 +64,10 @@ that it will "exec", and that there is sufficient room for the brk. */ #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) + +#ifdef __KERNEL__ +#define SET_PERSONALITY(ex,ibcs2) \ + current->personality = (ibcs2 ? PER_SVR4 : PER_LINUX) +#endif #endif /* __ASM_MIPS_ELF_H */ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/errno.h linux/include/asm-mips/errno.h --- v2.1.100/linux/include/asm-mips/errno.h Thu Jun 26 12:33:39 1997 +++ linux/include/asm-mips/errno.h Fri May 8 00:13:26 1998 @@ -156,4 +156,7 @@ #define EDQUOT 1133 /* Quota exceeded */ #define ENFSREMOTE 1134 /* ??? */ +/* The biggest error number defined here or in . */ +#define EMAXERRNO 1134 + #endif /* __ASM_MIPS_ERRNO_H */ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/floppy.h linux/include/asm-mips/floppy.h --- v2.1.100/linux/include/asm-mips/floppy.h Tue Dec 16 12:46:01 1997 +++ linux/include/asm-mips/floppy.h Fri May 8 00:13:26 1998 @@ -7,7 +7,7 @@ * * Copyright (C) 1995, 1996, 1997 Ralf Baechle * - * $Id: floppy.h,v 1.3 1997/09/07 03:59:02 ralf Exp $ + * $Id: floppy.h,v 1.14 1998/05/01 01:35:52 ralf Exp $ */ #ifndef __ASM_MIPS_FLOPPY_H #define __ASM_MIPS_FLOPPY_H diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/hardirq.h linux/include/asm-mips/hardirq.h --- v2.1.100/linux/include/asm-mips/hardirq.h Thu Jun 26 12:33:39 1997 +++ linux/include/asm-mips/hardirq.h Fri May 8 00:13:26 1998 @@ -4,7 +4,6 @@ #include extern unsigned int local_irq_count[NR_CPUS]; -#define in_interrupt() (local_irq_count[smp_processor_id()] != 0) #ifndef __SMP__ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/ide.h linux/include/asm-mips/ide.h --- v2.1.100/linux/include/asm-mips/ide.h Thu May 7 22:51:54 1998 +++ linux/include/asm-mips/ide.h Fri May 8 00:13:26 1998 @@ -21,40 +21,36 @@ #define ide__sti() __sti() +struct ide_ops { + int (*ide_default_irq)(ide_ioreg_t base); + ide_ioreg_t (*ide_default_io_base)(int index); + void (*ide_init_hwif_ports)(ide_ioreg_t *p, ide_ioreg_t base, int *irq); + int (*ide_request_irq)(unsigned int irq, void (*handler)(int, void *, + struct pt_regs *), unsigned long flags, + const char *device, void *dev_id); + void (*ide_free_irq)(unsigned int irq, void *dev_id); + int (*ide_check_region) (ide_ioreg_t from, unsigned int extent); + void (*ide_request_region)(ide_ioreg_t from, unsigned int extent, + const char *name); + void (*ide_release_region)(ide_ioreg_t from, unsigned int extent); +}; + +extern struct ide_ops *ide_ops; + static __inline__ int ide_default_irq(ide_ioreg_t base) { - switch (base) { - case 0x1f0: return 14; - case 0x170: return 15; - case 0x1e8: return 11; - case 0x168: return 10; - default: - return 0; - } + return ide_ops->ide_default_irq(base); } static __inline__ ide_ioreg_t ide_default_io_base(int index) { - switch (index) { - case 0: return 0x1f0; - case 1: return 0x170; - case 2: return 0x1e8; - case 3: return 0x168; - default: - return 0; - } -} - -static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq) -{ - ide_ioreg_t port = base; - int i = 8; - - while (i--) - *p++ = port++; - *p++ = base + 0x206; - if (irq != NULL) - *irq = 0; + return ide_ops->ide_default_io_base(index); +} + +static __inline__ void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, + int *irq) +{ + ide_ops->ide_init_hwif_ports(p, base, irq); } typedef union { @@ -68,38 +64,41 @@ } b; } select_t; -static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), +static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int,void *, struct pt_regs *), unsigned long flags, const char *device, void *dev_id) { - return request_irq(irq, handler, flags, device, dev_id); -} + return ide_ops->ide_request_irq(irq, handler, flags, device, dev_id); +} static __inline__ void ide_free_irq(unsigned int irq, void *dev_id) { - free_irq(irq, dev_id); + ide_ops->ide_free_irq(irq, dev_id); } static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent) { - return check_region(from, extent); + return ide_ops->ide_check_region(from, extent); } -static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name) +static __inline__ void ide_request_region(ide_ioreg_t from, + unsigned int extent, const char *name) { - request_region(from, extent, name); + ide_ops->ide_request_region(from, extent, name); } -static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent) +static __inline__ void ide_release_region(ide_ioreg_t from, + unsigned int extent) { - release_region(from, extent); + ide_ops->ide_release_region(from, extent); } /* * The following are not needed for the non-m68k ports */ -static __inline__ int ide_ack_intr (ide_ioreg_t status_port, ide_ioreg_t irq_port) +static __inline__ int ide_ack_intr (ide_ioreg_t status_port, + ide_ioreg_t irq_port) { - return(1); + return 1; } static __inline__ void ide_fix_driveid(struct hd_driveid *id) @@ -110,7 +109,10 @@ { } -static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data) +static __inline__ void ide_get_lock (int *ide_lock, + void (*handler)(int, void *, + struct pt_regs *), + void *data) { } diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/init.h linux/include/asm-mips/init.h --- v2.1.100/linux/include/asm-mips/init.h Thu Jun 26 12:33:39 1997 +++ linux/include/asm-mips/init.h Fri May 8 00:13:26 1998 @@ -1,14 +1,30 @@ -#ifndef __ASM_MIPS_INIT_H -#define __ASM_MIPS_INIT_H +/* + * include/asm-mips/init.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * $Id: init.h,v 1.3 1998/05/01 01:35:53 ralf Exp $ + */ +#ifndef __MIPS_INIT_H +#define __MIPS_INIT_H -/* Throwing the initialization code and data out is not supported yet... */ +#define __init __attribute__ ((__section__ (".text.init"))) +#define __initdata __attribute__ ((__section__ (".data.init"))) +#define __initfunc(__arginit) \ + __arginit __init; \ + __arginit + +#if __GNUC__ >= 2 && __GNUC_MINOR__ >= 8 +#define __initlocaldata __initdata +#else +#define __initlocaldata +#endif -#define __init -#define __initdata -#define __initfunc(__arginit) __arginit /* For assembly routines */ -#define __INIT -#define __FINIT -#define __INITDATA +#define __INIT .section .text.init,"ax" +#define __FINIT .previous +#define __INITDATA .section .data.init,"a" -#endif /* __ASM_MIPS_INIT_H */ +#endif /* __MIPS_INIT_H */ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/inventory.h linux/include/asm-mips/inventory.h --- v2.1.100/linux/include/asm-mips/inventory.h Mon Feb 23 18:12:11 1998 +++ linux/include/asm-mips/inventory.h Fri May 8 00:13:26 1998 @@ -1,5 +1,5 @@ /* - * $Id: inventory.h,v 1.2 1997/12/06 23:55:49 ralf Exp $ + * $Id: inventory.h,v 1.2 1998/05/01 01:35:54 ralf Exp $ */ #ifndef __ASM_MIPS_INVENTORY_H #define __ASM_MIPS_INVENTORY_H diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/io.h linux/include/asm-mips/io.h --- v2.1.100/linux/include/asm-mips/io.h Tue Dec 16 12:46:07 1997 +++ linux/include/asm-mips/io.h Fri May 8 00:13:26 1998 @@ -42,16 +42,6 @@ extern unsigned long mips_io_port_base; /* - * On MIPS I/O ports are memory mapped, so we access them using normal - * load/store instructions. mips_io_port_base is the virtual address to - * which all ports are being mapped. For sake of efficiency some code - * assumes that this is an address that can be loaded with a single lui - * instruction, so the lower 16 bits must be zero. Should be true on - * on any sane architecture; generic code does not use this assumption. - */ -extern unsigned long mips_io_port_base; - -/* * Thanks to James van Artsdalen for a better timing-fix than * the two short jumps: using outb's to a nonexistent port seems * to guarantee better timings even on fast machines. @@ -381,5 +371,22 @@ ((__builtin_constant_p((port)) && (port) < 32768) ? \ __inslc((port),(addr),(count)) : \ __insl((port),(addr),(count))) + +/* + * The caches on some architectures aren't dma-coherent and have need to + * handle this in software. There are two types of operations that + * can be applied to dma buffers. + * + * - dma_cache_wback_inv(start, size) makes caches and coherent by + * writing the content of the caches back to memory, if necessary. + * The function also invalidates the affected part of the caches as + * necessary before DMA transfers from outside to memory. + * - dma_cache_inv(start, size) invalidates the affected parts of the + * caches. Dirty lines of the caches may be written back or simply + * be discarded. This operation is necessary before dma operations + * to the memory. + */ +extern void (*dma_cache_wback_inv)(unsigned long start, unsigned long size); +extern void (*dma_cache_inv)(unsigned long start, unsigned long size); #endif /* __ASM_MIPS_IO_H */ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/ioctls.h linux/include/asm-mips/ioctls.h --- v2.1.100/linux/include/asm-mips/ioctls.h Tue Feb 17 13:12:49 1998 +++ linux/include/asm-mips/ioctls.h Fri May 8 00:13:26 1998 @@ -98,7 +98,7 @@ #define TIOCTTYGSTRUCT 0x5487 /* For debugging only */ #define TIOCSBRK 0x5427 /* BSD compatibility */ #define TIOCCBRK 0x5428 /* BSD compatibility */ -#define TIOCGSID 0x5429 /* Return the session ID of FD */ +#define TIOCGSID 0x7416 /* Return the session ID of FD */ #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/irq.h linux/include/asm-mips/irq.h --- v2.1.100/linux/include/asm-mips/irq.h Tue Dec 16 12:46:08 1997 +++ linux/include/asm-mips/irq.h Fri May 8 00:13:26 1998 @@ -33,13 +33,4 @@ #define irq_exit(cpu, irq) (--local_irq_count[cpu]) #endif -extern unsigned int local_irq_count[]; - -#ifdef __SMP__ -#error Send superfluous SMP boxes to ralf@uni-koblenz.de -#else -#define irq_enter(cpu, irq) (++local_irq_count[cpu]) -#define irq_exit(cpu, irq) (--local_irq_count[cpu]) -#endif - #endif /* __ASM_MIPS_IRQ_H */ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/jazz.h linux/include/asm-mips/jazz.h --- v2.1.100/linux/include/asm-mips/jazz.h Tue Dec 16 12:46:08 1997 +++ linux/include/asm-mips/jazz.h Fri May 8 00:13:26 1998 @@ -9,7 +9,7 @@ * * This file is a mess. It really needs some reorganisation! * - * $Id: jazz.h,v 1.5 1997/12/01 21:26:48 ralf Exp $ + * $Id: jazz.h,v 1.6 1998/05/01 01:35:56 ralf Exp $ */ #ifndef __ASM_MIPS_JAZZ_H #define __ASM_MIPS_JAZZ_H diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/jazzdma.h linux/include/asm-mips/jazzdma.h --- v2.1.100/linux/include/asm-mips/jazzdma.h Tue Dec 16 12:46:09 1997 +++ linux/include/asm-mips/jazzdma.h Fri May 8 00:13:26 1998 @@ -1,5 +1,7 @@ /* * Helpfile for jazzdma.c -- Mips Jazz R4030 DMA controller support + * + * $Id: jazzdma.h,v 1.6 1998/05/01 01:35:57 ralf Exp $ */ #ifndef __ASM_MIPS_JAZZDMA_H #define __ASM_MIPS_JAZZDMA_H @@ -21,6 +23,7 @@ void vdma_set_addr(int channel, long addr); void vdma_set_count(int channel, int count); int vdma_get_residue(int channel); +int vdma_get_enable(int channel); /* * some definitions used by the driver functions diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/keyboard.h linux/include/asm-mips/keyboard.h --- v2.1.100/linux/include/asm-mips/keyboard.h Tue Dec 16 12:46:09 1997 +++ linux/include/asm-mips/keyboard.h Fri May 8 00:13:26 1998 @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * $Id: keyboard.h,v 1.8 1997/12/02 05:51:14 ralf Exp $ + * $Id: keyboard.h,v 1.7 1998/05/01 01:35:57 ralf Exp $ */ #ifndef __ASM_MIPS_KEYBOARD_H #define __ASM_MIPS_KEYBOARD_H diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/md.h linux/include/asm-mips/md.h --- v2.1.100/linux/include/asm-mips/md.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/md.h Fri May 8 00:13:26 1998 @@ -0,0 +1,13 @@ +/* $Id: md.h,v 1.1 1997/12/15 15:12:09 jj Exp $ + * md.h: High speed xor_block operation for RAID4/5 + * + */ + +#ifndef __ASM_MD_H +#define __ASM_MD_H + +/* #define HAVE_ARCH_XORBLOCK */ + +#define MD_XORBLOCK_ALIGNMENT sizeof(long) + +#endif /* __ASM_MD_H */ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/mipsregs.h linux/include/asm-mips/mipsregs.h --- v2.1.100/linux/include/asm-mips/mipsregs.h Tue Dec 16 12:46:10 1997 +++ linux/include/asm-mips/mipsregs.h Fri May 8 00:13:26 1998 @@ -8,7 +8,7 @@ * Copyright (C) 1994, 1995, 1996, 1997 by Ralf Baechle * Modified for further R[236]000 support by Paul M. Antoine, 1996. * - * $Id: mipsregs.h,v 1.4 1997/09/20 19:02:46 root Exp $ + * $Id: mipsregs.h,v 1.6 1998/05/01 01:35:58 ralf Exp $ */ #ifndef __ASM_MIPS_MIPSREGS_H #define __ASM_MIPS_MIPSREGS_H diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/namei.h linux/include/asm-mips/namei.h --- v2.1.100/linux/include/asm-mips/namei.h Tue Dec 16 12:46:10 1997 +++ linux/include/asm-mips/namei.h Fri May 8 00:13:26 1998 @@ -3,7 +3,7 @@ * * Included from linux/fs/namei.c * - * $Id: namei.h,v 1.6 1997/09/18 07:59:31 root Exp $ + * $Id: namei.h,v 1.9 1998/05/01 01:35:59 ralf Exp $ */ #ifndef __ASM_MIPS_NAMEI_H #define __ASM_MIPS_NAMEI_H diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/ng1.h linux/include/asm-mips/ng1.h --- v2.1.100/linux/include/asm-mips/ng1.h Tue Mar 10 10:03:34 1998 +++ linux/include/asm-mips/ng1.h Fri May 8 00:13:26 1998 @@ -46,3 +46,5 @@ unsigned char green [256]; unsigned char blue [256]; }; + + diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/offset.h linux/include/asm-mips/offset.h --- v2.1.100/linux/include/asm-mips/offset.h Tue Dec 16 12:46:10 1997 +++ linux/include/asm-mips/offset.h Fri May 8 00:13:26 1998 @@ -38,52 +38,48 @@ #define PT_R31 148 #define PT_LO 152 #define PT_HI 156 -#define PT_OR2 160 -#define PT_OR7 164 -#define PT_EPC 168 -#define PT_BVADDR 172 -#define PT_STATUS 176 -#define PT_CAUSE 180 -#define PT_SIZE 184 +#define PT_EPC 160 +#define PT_BVADDR 164 +#define PT_STATUS 168 +#define PT_CAUSE 172 +#define PT_SIZE 176 /* MIPS task_struct offsets. */ #define TASK_STATE 0 -#define TASK_COUNTER 4 -#define TASK_PRIORITY 8 -#define TASK_SIGNAL 12 -#define TASK_BLOCKED 16 -#define TASK_FLAGS 20 -#define TASK_MM 920 +#define TASK_COUNTER 52 +#define TASK_PRIORITY 56 +#define TASK_FLAGS 4 +#define TASK_SIGPENDING 8 +#define TASK_MM 928 /* MIPS specific thread_struct offsets. */ -#define THREAD_REG16 552 -#define THREAD_REG17 556 -#define THREAD_REG18 560 -#define THREAD_REG19 564 -#define THREAD_REG20 568 -#define THREAD_REG21 572 -#define THREAD_REG22 576 -#define THREAD_REG23 580 -#define THREAD_REG28 584 -#define THREAD_REG29 588 -#define THREAD_REG30 592 -#define THREAD_REG31 596 -#define THREAD_STATUS 600 -#define THREAD_FPU 608 -#define THREAD_BVADDR 872 -#define THREAD_ECODE 876 -#define THREAD_TRAPNO 880 -#define THREAD_KSP 884 -#define THREAD_PGDIR 888 -#define THREAD_MFLAGS 892 -#define THREAD_CURDS 896 -#define THREAD_TRAMP 900 -#define THREAD_OLDCTX 904 +#define THREAD_REG16 568 +#define THREAD_REG17 572 +#define THREAD_REG18 576 +#define THREAD_REG19 580 +#define THREAD_REG20 584 +#define THREAD_REG21 588 +#define THREAD_REG22 592 +#define THREAD_REG23 596 +#define THREAD_REG29 600 +#define THREAD_REG30 604 +#define THREAD_REG31 608 +#define THREAD_STATUS 612 +#define THREAD_FPU 616 +#define THREAD_BVADDR 880 +#define THREAD_BUADDR 884 +#define THREAD_ECODE 888 +#define THREAD_TRAPNO 892 +#define THREAD_PGDIR 896 +#define THREAD_MFLAGS 900 +#define THREAD_CURDS 904 +#define THREAD_TRAMP 908 +#define THREAD_OLDCTX 912 /* Linux mm_struct offsets. */ #define MM_COUNT 12 #define MM_PGD 8 -#define MM_CONTEXT 28 +#define MM_CONTEXT 32 /* Linux sigcontext offsets. */ #define SC_REGMASK 0 diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/page.h linux/include/asm-mips/page.h --- v2.1.100/linux/include/asm-mips/page.h Thu Jun 26 12:33:40 1997 +++ linux/include/asm-mips/page.h Fri May 8 00:13:26 1998 @@ -21,6 +21,8 @@ #ifndef __LANGUAGE_ASSEMBLY__ +#define get_user_page(vaddr) __get_free_page(GFP_KERNEL) +#define free_user_page(page, addr) free_page(addr) extern void (*clear_page)(unsigned long page); extern void (*copy_page)(unsigned long to, unsigned long from); diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/pci.h linux/include/asm-mips/pci.h --- v2.1.100/linux/include/asm-mips/pci.h Tue Dec 16 12:46:10 1997 +++ linux/include/asm-mips/pci.h Fri May 8 00:13:26 1998 @@ -5,7 +5,7 @@ * * Declarations for the MIPS specific implementation of the PCI BIOS32 services. * - * $Id: pci.h,v 1.2 1997/09/20 21:16:37 ralf Exp $ + * $Id: pci.h,v 1.3 1998/05/01 01:36:00 ralf Exp $ */ #ifndef __ASM_MIPS_PCI_H #define __ASM_MIPS_PCI_H diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/pgtable.h linux/include/asm-mips/pgtable.h --- v2.1.100/linux/include/asm-mips/pgtable.h Tue Dec 16 12:46:11 1997 +++ linux/include/asm-mips/pgtable.h Fri May 8 00:13:26 1998 @@ -26,12 +26,6 @@ extern void (*flush_page_to_ram)(unsigned long page); #define flush_icache_range(start, end) flush_cache_all() -/* - * Prototype of the DMA related cacheflushing stuff. - */ -extern void (*flush_cache_pre_dma_out)(unsigned long start, unsigned long size); -extern void (*flush_cache_post_dma_in)(unsigned long start, unsigned long size); - /* TLB flushing: * * - flush_tlb_all() flushes all processes TLB entries @@ -127,8 +121,7 @@ #define _PAGE_CHG_MASK (PAGE_MASK | __READABLE | __WRITEABLE | _CACHE_MASK) -#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ - _CACHE_CACHABLE_NONCOHERENT) +#define PAGE_NONE __pgprot(0) #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ _CACHE_CACHABLE_NONCOHERENT) #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_READ | \ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/prctl.h linux/include/asm-mips/prctl.h --- v2.1.100/linux/include/asm-mips/prctl.h Tue Mar 10 10:03:35 1998 +++ linux/include/asm-mips/prctl.h Fri May 8 00:13:26 1998 @@ -3,7 +3,7 @@ * * The IRIX kernel maps a page at PRDA_ADDRESS with the * contents of prda and fills it the bits on prda_sys. - * $Id: prctl.h,v 1.1 1997/12/02 02:28:28 ralf Exp $ + * $Id: prctl.h,v 1.2 1998/05/01 01:36:02 ralf Exp $ */ #ifndef __PRCTL_H__ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/processor.h linux/include/asm-mips/processor.h --- v2.1.100/linux/include/asm-mips/processor.h Fri Jan 16 20:32:53 1998 +++ linux/include/asm-mips/processor.h Fri May 8 00:13:26 1998 @@ -5,7 +5,7 @@ * written by Ralf Baechle * Modified further for R[236]000 compatibility by Paul M. Antoine * - * $Id: processor.h,v 1.5 1997/12/01 16:48:39 ralf Exp $ + * $Id: processor.h,v 1.20 1998/05/04 09:18:59 ralf Exp $ */ #ifndef __ASM_MIPS_PROCESSOR_H #define __ASM_MIPS_PROCESSOR_H @@ -51,7 +51,8 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE(off) (TASK_SIZE / 3) +#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) /* * Size of io_bitmap in longwords: 32 is ports 0-0x3ff. @@ -90,21 +91,21 @@ */ struct thread_struct { /* Saved main processor registers. */ - unsigned long reg16 __attribute__ ((aligned (8))); + unsigned long reg16; unsigned long reg17, reg18, reg19, reg20, reg21, reg22, reg23; - unsigned long reg28, reg29, reg30, reg31; + unsigned long reg29, reg30, reg31; /* Saved cp0 stuff. */ unsigned long cp0_status; /* Saved fpu/fpu emulator stuff. */ - union mips_fpu_union fpu __attribute__ ((aligned (8))); + union mips_fpu_union fpu; /* Other stuff associated with the thread. */ - unsigned long cp0_badvaddr; + unsigned long cp0_badvaddr; /* Last user fault */ + unsigned long cp0_baduaddr; /* Last kernel fault accessing USEG */ unsigned long error_code; unsigned long trap_no; - unsigned long ksp; /* Top of kernel stack */ unsigned long pg_dir; /* used in tlb refill */ #define MF_FIXADE 1 /* Fix address errors in software */ #define MF_LOGADE 2 /* Log address errors to syslog */ @@ -124,7 +125,7 @@ * saved main processor registers \ */ \ 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, \ + 0, 0, 0, \ /* \ * saved cp0 stuff \ */ \ @@ -136,12 +137,11 @@ /* \ * Other stuff associated with the process \ */ \ - 0, 0, 0, (unsigned long)&init_task_union + KERNEL_STACK_SIZE - 32, \ - (unsigned long) swapper_pg_dir, \ + 0, 0, 0, 0, (unsigned long) swapper_pg_dir, \ /* \ * For now the default is to fix address errors \ */ \ - MF_FIXADE, 0, 0, 0 \ + MF_FIXADE, { 0 }, 0, 0 \ } #ifdef __KERNEL__ @@ -167,16 +167,12 @@ return ((unsigned long*)t->reg29)[17]; } +extern int (*user_mode)(struct pt_regs *); + /* * Do necessary setup to start up a newly executed thread. */ extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp); - -/* - * Does the process account for user or for system time? - */ -extern int (*running_in_user_mode)(void); -#define USES_USER_TIME(regs) running_in_user_mode() /* Allocation and freeing of basic task resources. */ /* diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/ptrace.h linux/include/asm-mips/ptrace.h --- v2.1.100/linux/include/asm-mips/ptrace.h Thu Jun 26 12:33:40 1997 +++ linux/include/asm-mips/ptrace.h Fri May 8 00:13:26 1998 @@ -30,8 +30,6 @@ /* Other saved registers. */ unsigned long lo; unsigned long hi; - unsigned long orig_reg2; - unsigned long orig_reg7; /* * saved cp0 registers diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/r4kcache.h linux/include/asm-mips/r4kcache.h --- v2.1.100/linux/include/asm-mips/r4kcache.h Tue Dec 16 12:46:12 1997 +++ linux/include/asm-mips/r4kcache.h Fri May 8 00:13:26 1998 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r4kcache.h,v 1.5 1997/12/01 16:47:05 ralf Exp $ + * $Id: r4kcache.h,v 1.5 1998/05/01 01:36:03 ralf Exp $ * * FIXME: Handle split L2 caches. */ @@ -104,32 +104,6 @@ "i" (Hit_Invalidate_SD)); } -extern inline void invalidate_dcache_line(unsigned long addr) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - ".set mips3\n\t" - "cache %1, (%0)\n\t" - ".set mips0\n\t" - ".set reorder" - : - : "r" (addr), - "i" (Hit_Invalidate_D)); -} - -extern inline void invalidate_scache_line(unsigned long addr) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - ".set mips3\n\t" - "cache %1, (%0)\n\t" - ".set mips0\n\t" - ".set reorder" - : - : "r" (addr), - "i" (Hit_Invalidate_SD)); -} - extern inline void flush_scache_line(unsigned long addr) { __asm__ __volatile__( @@ -178,40 +152,31 @@ "i" (Hit_Writeback_D)); } -/* - * The next two are for badland addresses like signal trampolines. - */ -extern inline void protected_flush_icache_line(unsigned long addr) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - ".set mips3\n" - "1:\tcache %1,(%0)\n" - "2:\t.set mips0\n\t" - ".set reorder\n\t" - ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,2b\n\t" - ".previous" - : - : "r" (addr), - "i" (Hit_Invalidate_I)); -} - -extern inline void protected_writeback_dcache_line(unsigned long addr) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - ".set mips3\n" - "1:\tcache %1,(%0)\n" - "2:\t.set mips0\n\t" - ".set reorder\n\t" - ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,2b\n\t" - ".previous" - : - : "r" (addr), - "i" (Hit_Writeback_D)); -} +#define cache16_unroll32(base,op) \ + __asm__ __volatile__(" \ + .set noreorder; \ + .set mips3; \ + cache %1, 0x000(%0); cache %1, 0x010(%0); \ + cache %1, 0x020(%0); cache %1, 0x030(%0); \ + cache %1, 0x040(%0); cache %1, 0x050(%0); \ + cache %1, 0x060(%0); cache %1, 0x070(%0); \ + cache %1, 0x080(%0); cache %1, 0x090(%0); \ + cache %1, 0x0a0(%0); cache %1, 0x0b0(%0); \ + cache %1, 0x0c0(%0); cache %1, 0x0d0(%0); \ + cache %1, 0x0e0(%0); cache %1, 0x0f0(%0); \ + cache %1, 0x100(%0); cache %1, 0x110(%0); \ + cache %1, 0x120(%0); cache %1, 0x130(%0); \ + cache %1, 0x140(%0); cache %1, 0x150(%0); \ + cache %1, 0x160(%0); cache %1, 0x170(%0); \ + cache %1, 0x180(%0); cache %1, 0x190(%0); \ + cache %1, 0x1a0(%0); cache %1, 0x1b0(%0); \ + cache %1, 0x1c0(%0); cache %1, 0x1d0(%0); \ + cache %1, 0x1e0(%0); cache %1, 0x1f0(%0); \ + .set mips0; \ + .set reorder" \ + : \ + : "r" (base), \ + "i" (op)); extern inline void blast_dcache16(void) { @@ -219,30 +184,7 @@ unsigned long end = (start + dcache_size); while(start < end) { - __asm__ __volatile__(" - .set noreorder - .set mips3 - cache %1, 0x000(%0); cache %1, 0x010(%0) - cache %1, 0x020(%0); cache %1, 0x030(%0) - cache %1, 0x040(%0); cache %1, 0x050(%0) - cache %1, 0x060(%0); cache %1, 0x070(%0) - cache %1, 0x080(%0); cache %1, 0x090(%0) - cache %1, 0x0a0(%0); cache %1, 0x0b0(%0) - cache %1, 0x0c0(%0); cache %1, 0x0d0(%0) - cache %1, 0x0e0(%0); cache %1, 0x0f0(%0) - cache %1, 0x100(%0); cache %1, 0x110(%0) - cache %1, 0x120(%0); cache %1, 0x130(%0) - cache %1, 0x140(%0); cache %1, 0x150(%0) - cache %1, 0x160(%0); cache %1, 0x170(%0) - cache %1, 0x180(%0); cache %1, 0x190(%0) - cache %1, 0x1a0(%0); cache %1, 0x1b0(%0) - cache %1, 0x1c0(%0); cache %1, 0x1d0(%0) - cache %1, 0x1e0(%0); cache %1, 0x1f0(%0) - .set mips0 - .set reorder" - : - : "r" (start), - "i" (Index_Writeback_Inv_D)); + cache16_unroll32(start,Index_Writeback_Inv_D); start += 0x200; } } @@ -253,79 +195,8 @@ unsigned long end = (start + PAGE_SIZE); while(start < end) { - __asm__ __volatile__(" - .set noreorder - .set mips3 - cache %1, 0x000(%0); cache %1, 0x010(%0) - cache %1, 0x020(%0); cache %1, 0x030(%0) - cache %1, 0x040(%0); cache %1, 0x050(%0) - cache %1, 0x060(%0); cache %1, 0x070(%0) - cache %1, 0x080(%0); cache %1, 0x090(%0) - cache %1, 0x0a0(%0); cache %1, 0x0b0(%0) - cache %1, 0x0c0(%0); cache %1, 0x0d0(%0) - cache %1, 0x0e0(%0); cache %1, 0x0f0(%0) - cache %1, 0x100(%0); cache %1, 0x110(%0) - cache %1, 0x120(%0); cache %1, 0x130(%0) - cache %1, 0x140(%0); cache %1, 0x150(%0) - cache %1, 0x160(%0); cache %1, 0x170(%0) - cache %1, 0x180(%0); cache %1, 0x190(%0) - cache %1, 0x1a0(%0); cache %1, 0x1b0(%0) - cache %1, 0x1c0(%0); cache %1, 0x1d0(%0) - cache %1, 0x1e0(%0); cache %1, 0x1f0(%0) - cache %1, 0x200(%0); cache %1, 0x210(%0) - cache %1, 0x220(%0); cache %1, 0x230(%0) - cache %1, 0x240(%0); cache %1, 0x250(%0) - cache %1, 0x260(%0); cache %1, 0x270(%0) - cache %1, 0x280(%0); cache %1, 0x290(%0) - cache %1, 0x2a0(%0); cache %1, 0x2b0(%0) - cache %1, 0x2c0(%0); cache %1, 0x2d0(%0) - cache %1, 0x2e0(%0); cache %1, 0x2f0(%0) - cache %1, 0x300(%0); cache %1, 0x310(%0) - cache %1, 0x320(%0); cache %1, 0x330(%0) - cache %1, 0x340(%0); cache %1, 0x350(%0) - cache %1, 0x360(%0); cache %1, 0x370(%0) - cache %1, 0x380(%0); cache %1, 0x390(%0) - cache %1, 0x3a0(%0); cache %1, 0x3b0(%0) - cache %1, 0x3c0(%0); cache %1, 0x3d0(%0) - cache %1, 0x3e0(%0); cache %1, 0x3f0(%0) - cache %1, 0x400(%0); cache %1, 0x410(%0) - cache %1, 0x420(%0); cache %1, 0x430(%0) - cache %1, 0x440(%0); cache %1, 0x450(%0) - cache %1, 0x460(%0); cache %1, 0x470(%0) - cache %1, 0x480(%0); cache %1, 0x490(%0) - cache %1, 0x4a0(%0); cache %1, 0x4b0(%0) - cache %1, 0x4c0(%0); cache %1, 0x4d0(%0) - cache %1, 0x4e0(%0); cache %1, 0x4f0(%0) - cache %1, 0x500(%0); cache %1, 0x510(%0) - cache %1, 0x520(%0); cache %1, 0x530(%0) - cache %1, 0x540(%0); cache %1, 0x550(%0) - cache %1, 0x560(%0); cache %1, 0x570(%0) - cache %1, 0x580(%0); cache %1, 0x590(%0) - cache %1, 0x5a0(%0); cache %1, 0x5b0(%0) - cache %1, 0x5c0(%0); cache %1, 0x5d0(%0) - cache %1, 0x5e0(%0); cache %1, 0x5f0(%0) - cache %1, 0x600(%0); cache %1, 0x610(%0) - cache %1, 0x620(%0); cache %1, 0x630(%0) - cache %1, 0x640(%0); cache %1, 0x650(%0) - cache %1, 0x660(%0); cache %1, 0x670(%0) - cache %1, 0x680(%0); cache %1, 0x690(%0) - cache %1, 0x6a0(%0); cache %1, 0x6b0(%0) - cache %1, 0x6c0(%0); cache %1, 0x6d0(%0) - cache %1, 0x6e0(%0); cache %1, 0x6f0(%0) - cache %1, 0x700(%0); cache %1, 0x710(%0) - cache %1, 0x720(%0); cache %1, 0x730(%0) - cache %1, 0x740(%0); cache %1, 0x750(%0) - cache %1, 0x760(%0); cache %1, 0x770(%0) - cache %1, 0x780(%0); cache %1, 0x790(%0) - cache %1, 0x7a0(%0); cache %1, 0x7b0(%0) - cache %1, 0x7c0(%0); cache %1, 0x7d0(%0) - cache %1, 0x7e0(%0); cache %1, 0x7f0(%0) - .set mips0 - .set reorder" - : - : "r" (start), - "i" (Hit_Writeback_Inv_D)); - start += 0x800; + cache16_unroll32(start,Hit_Writeback_Inv_D); + start += 0x200; } } @@ -335,571 +206,184 @@ unsigned long end = (start + PAGE_SIZE); while(start < end) { - __asm__ __volatile__(" - .set noreorder - .set mips3 - cache %1, 0x000(%0); cache %1, 0x010(%0) - cache %1, 0x020(%0); cache %1, 0x030(%0) - cache %1, 0x040(%0); cache %1, 0x050(%0) - cache %1, 0x060(%0); cache %1, 0x070(%0) - cache %1, 0x080(%0); cache %1, 0x090(%0) - cache %1, 0x0a0(%0); cache %1, 0x0b0(%0) - cache %1, 0x0c0(%0); cache %1, 0x0d0(%0) - cache %1, 0x0e0(%0); cache %1, 0x0f0(%0) - cache %1, 0x100(%0); cache %1, 0x110(%0) - cache %1, 0x120(%0); cache %1, 0x130(%0) - cache %1, 0x140(%0); cache %1, 0x150(%0) - cache %1, 0x160(%0); cache %1, 0x170(%0) - cache %1, 0x180(%0); cache %1, 0x190(%0) - cache %1, 0x1a0(%0); cache %1, 0x1b0(%0) - cache %1, 0x1c0(%0); cache %1, 0x1d0(%0) - cache %1, 0x1e0(%0); cache %1, 0x1f0(%0) - cache %1, 0x200(%0); cache %1, 0x210(%0) - cache %1, 0x220(%0); cache %1, 0x230(%0) - cache %1, 0x240(%0); cache %1, 0x250(%0) - cache %1, 0x260(%0); cache %1, 0x270(%0) - cache %1, 0x280(%0); cache %1, 0x290(%0) - cache %1, 0x2a0(%0); cache %1, 0x2b0(%0) - cache %1, 0x2c0(%0); cache %1, 0x2d0(%0) - cache %1, 0x2e0(%0); cache %1, 0x2f0(%0) - cache %1, 0x300(%0); cache %1, 0x310(%0) - cache %1, 0x320(%0); cache %1, 0x330(%0) - cache %1, 0x340(%0); cache %1, 0x350(%0) - cache %1, 0x360(%0); cache %1, 0x370(%0) - cache %1, 0x380(%0); cache %1, 0x390(%0) - cache %1, 0x3a0(%0); cache %1, 0x3b0(%0) - cache %1, 0x3c0(%0); cache %1, 0x3d0(%0) - cache %1, 0x3e0(%0); cache %1, 0x3f0(%0) - cache %1, 0x400(%0); cache %1, 0x410(%0) - cache %1, 0x420(%0); cache %1, 0x430(%0) - cache %1, 0x440(%0); cache %1, 0x450(%0) - cache %1, 0x460(%0); cache %1, 0x470(%0) - cache %1, 0x480(%0); cache %1, 0x490(%0) - cache %1, 0x4a0(%0); cache %1, 0x4b0(%0) - cache %1, 0x4c0(%0); cache %1, 0x4d0(%0) - cache %1, 0x4e0(%0); cache %1, 0x4f0(%0) - cache %1, 0x500(%0); cache %1, 0x510(%0) - cache %1, 0x520(%0); cache %1, 0x530(%0) - cache %1, 0x540(%0); cache %1, 0x550(%0) - cache %1, 0x560(%0); cache %1, 0x570(%0) - cache %1, 0x580(%0); cache %1, 0x590(%0) - cache %1, 0x5a0(%0); cache %1, 0x5b0(%0) - cache %1, 0x5c0(%0); cache %1, 0x5d0(%0) - cache %1, 0x5e0(%0); cache %1, 0x5f0(%0) - cache %1, 0x600(%0); cache %1, 0x610(%0) - cache %1, 0x620(%0); cache %1, 0x630(%0) - cache %1, 0x640(%0); cache %1, 0x650(%0) - cache %1, 0x660(%0); cache %1, 0x670(%0) - cache %1, 0x680(%0); cache %1, 0x690(%0) - cache %1, 0x6a0(%0); cache %1, 0x6b0(%0) - cache %1, 0x6c0(%0); cache %1, 0x6d0(%0) - cache %1, 0x6e0(%0); cache %1, 0x6f0(%0) - cache %1, 0x700(%0); cache %1, 0x710(%0) - cache %1, 0x720(%0); cache %1, 0x730(%0) - cache %1, 0x740(%0); cache %1, 0x750(%0) - cache %1, 0x760(%0); cache %1, 0x770(%0) - cache %1, 0x780(%0); cache %1, 0x790(%0) - cache %1, 0x7a0(%0); cache %1, 0x7b0(%0) - cache %1, 0x7c0(%0); cache %1, 0x7d0(%0) - cache %1, 0x7e0(%0); cache %1, 0x7f0(%0) - .set mips0 - .set reorder" - : - : "r" (start), - "i" (Index_Writeback_Inv_D)); - start += 0x800; + cache16_unroll32(start,Index_Writeback_Inv_D); + start += 0x200; } } -extern inline void blast_dcache32(void) +extern inline void blast_icache16(void) { unsigned long start = KSEG0; - unsigned long end = (start + dcache_size); + unsigned long end = (start + icache_size); while(start < end) { - __asm__ __volatile__(" - .set noreorder - .set mips3 - cache %1, 0x000(%0); cache %1, 0x020(%0) - cache %1, 0x040(%0); cache %1, 0x060(%0) - cache %1, 0x080(%0); cache %1, 0x0a0(%0) - cache %1, 0x0c0(%0); cache %1, 0x0e0(%0) - cache %1, 0x100(%0); cache %1, 0x120(%0) - cache %1, 0x140(%0); cache %1, 0x160(%0) - cache %1, 0x180(%0); cache %1, 0x1a0(%0) - cache %1, 0x1c0(%0); cache %1, 0x1e0(%0) - cache %1, 0x200(%0); cache %1, 0x220(%0) - cache %1, 0x240(%0); cache %1, 0x260(%0) - cache %1, 0x280(%0); cache %1, 0x2a0(%0) - cache %1, 0x2c0(%0); cache %1, 0x2e0(%0) - cache %1, 0x300(%0); cache %1, 0x320(%0) - cache %1, 0x340(%0); cache %1, 0x360(%0) - cache %1, 0x380(%0); cache %1, 0x3a0(%0) - cache %1, 0x3c0(%0); cache %1, 0x3e0(%0) - cache %1, 0x400(%0); cache %1, 0x420(%0) - cache %1, 0x440(%0); cache %1, 0x460(%0) - cache %1, 0x480(%0); cache %1, 0x4a0(%0) - cache %1, 0x4c0(%0); cache %1, 0x4e0(%0) - cache %1, 0x500(%0); cache %1, 0x520(%0) - cache %1, 0x540(%0); cache %1, 0x560(%0) - cache %1, 0x580(%0); cache %1, 0x5a0(%0) - cache %1, 0x5c0(%0); cache %1, 0x5e0(%0) - cache %1, 0x600(%0); cache %1, 0x620(%0) - cache %1, 0x640(%0); cache %1, 0x660(%0) - cache %1, 0x680(%0); cache %1, 0x6a0(%0) - cache %1, 0x6c0(%0); cache %1, 0x6e0(%0) - cache %1, 0x700(%0); cache %1, 0x720(%0) - cache %1, 0x740(%0); cache %1, 0x760(%0) - cache %1, 0x780(%0); cache %1, 0x7a0(%0) - cache %1, 0x7c0(%0); cache %1, 0x7e0(%0) - .set mips0 - .set reorder" - : - : "r" (start), - "i" (Index_Writeback_Inv_D)); - start += 0x400; + cache16_unroll32(start,Index_Invalidate_I); + start += 0x200; } } -/* - * Call this function only with interrupts disabled or R4600 V2.0 may blow - * you up. - * - * R4600 v2.0 bug: "The CACHE instructions Hit_Writeback_Inv_D, - * Hit_Writeback_D, Hit_Invalidate_D and Create_Dirty_Excl_D will only - * operate correctly if the internal data cache refill buffer is empty. These - * CACHE instructions should be separated from any potential data cache miss - * by a load instruction to an uncached address to empty the response buffer." - * (Revision 2.0 device errata from IDT available on http://www.idt.com/ - * in .pdf format.) - */ -extern inline void blast_dcache32_page(unsigned long page) +extern inline void blast_icache16_page(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); - /* - * Sigh ... workaround for R4600 v1.7 bug. Explanation see above. - */ - *(volatile unsigned long *)KSEG1; - - __asm__ __volatile__("nop;nop;nop;nop"); while(start < end) { - __asm__ __volatile__(" - .set noreorder - .set mips3 - cache %1, 0x000(%0); cache %1, 0x020(%0) - cache %1, 0x040(%0); cache %1, 0x060(%0) - cache %1, 0x080(%0); cache %1, 0x0a0(%0) - cache %1, 0x0c0(%0); cache %1, 0x0e0(%0) - cache %1, 0x100(%0); cache %1, 0x120(%0) - cache %1, 0x140(%0); cache %1, 0x160(%0) - cache %1, 0x180(%0); cache %1, 0x1a0(%0) - cache %1, 0x1c0(%0); cache %1, 0x1e0(%0) - cache %1, 0x200(%0); cache %1, 0x220(%0) - cache %1, 0x240(%0); cache %1, 0x260(%0) - cache %1, 0x280(%0); cache %1, 0x2a0(%0) - cache %1, 0x2c0(%0); cache %1, 0x2e0(%0) - cache %1, 0x300(%0); cache %1, 0x320(%0) - cache %1, 0x340(%0); cache %1, 0x360(%0) - cache %1, 0x380(%0); cache %1, 0x3a0(%0) - cache %1, 0x3c0(%0); cache %1, 0x3e0(%0) - cache %1, 0x400(%0); cache %1, 0x420(%0) - cache %1, 0x440(%0); cache %1, 0x460(%0) - cache %1, 0x480(%0); cache %1, 0x4a0(%0) - cache %1, 0x4c0(%0); cache %1, 0x4e0(%0) - cache %1, 0x500(%0); cache %1, 0x520(%0) - cache %1, 0x540(%0); cache %1, 0x560(%0) - cache %1, 0x580(%0); cache %1, 0x5a0(%0) - cache %1, 0x5c0(%0); cache %1, 0x5e0(%0) - cache %1, 0x600(%0); cache %1, 0x620(%0) - cache %1, 0x640(%0); cache %1, 0x660(%0) - cache %1, 0x680(%0); cache %1, 0x6a0(%0) - cache %1, 0x6c0(%0); cache %1, 0x6e0(%0) - cache %1, 0x700(%0); cache %1, 0x720(%0) - cache %1, 0x740(%0); cache %1, 0x760(%0) - cache %1, 0x780(%0); cache %1, 0x7a0(%0) - cache %1, 0x7c0(%0); cache %1, 0x7e0(%0) - .set mips0 - .set reorder" - : - : "r" (start), - "i" (Hit_Writeback_Inv_D)); - start += 0x800; + cache16_unroll32(start,Hit_Invalidate_I); + start += 0x200; } } -extern inline void blast_dcache32_page_indexed(unsigned long page) +extern inline void blast_icache16_page_indexed(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); while(start < end) { - __asm__ __volatile__(" - .set noreorder - .set mips3 - cache %1, 0x000(%0); cache %1, 0x020(%0) - cache %1, 0x040(%0); cache %1, 0x060(%0) - cache %1, 0x080(%0); cache %1, 0x0a0(%0) - cache %1, 0x0c0(%0); cache %1, 0x0e0(%0) - cache %1, 0x100(%0); cache %1, 0x120(%0) - cache %1, 0x140(%0); cache %1, 0x160(%0) - cache %1, 0x180(%0); cache %1, 0x1a0(%0) - cache %1, 0x1c0(%0); cache %1, 0x1e0(%0) - cache %1, 0x200(%0); cache %1, 0x220(%0) - cache %1, 0x240(%0); cache %1, 0x260(%0) - cache %1, 0x280(%0); cache %1, 0x2a0(%0) - cache %1, 0x2c0(%0); cache %1, 0x2e0(%0) - cache %1, 0x300(%0); cache %1, 0x320(%0) - cache %1, 0x340(%0); cache %1, 0x360(%0) - cache %1, 0x380(%0); cache %1, 0x3a0(%0) - cache %1, 0x3c0(%0); cache %1, 0x3e0(%0) - cache %1, 0x400(%0); cache %1, 0x420(%0) - cache %1, 0x440(%0); cache %1, 0x460(%0) - cache %1, 0x480(%0); cache %1, 0x4a0(%0) - cache %1, 0x4c0(%0); cache %1, 0x4e0(%0) - cache %1, 0x500(%0); cache %1, 0x520(%0) - cache %1, 0x540(%0); cache %1, 0x560(%0) - cache %1, 0x580(%0); cache %1, 0x5a0(%0) - cache %1, 0x5c0(%0); cache %1, 0x5e0(%0) - cache %1, 0x600(%0); cache %1, 0x620(%0) - cache %1, 0x640(%0); cache %1, 0x660(%0) - cache %1, 0x680(%0); cache %1, 0x6a0(%0) - cache %1, 0x6c0(%0); cache %1, 0x6e0(%0) - cache %1, 0x700(%0); cache %1, 0x720(%0) - cache %1, 0x740(%0); cache %1, 0x760(%0) - cache %1, 0x780(%0); cache %1, 0x7a0(%0) - cache %1, 0x7c0(%0); cache %1, 0x7e0(%0) - .set mips0 - .set reorder" - : - : "r" (start), - "i" (Index_Writeback_Inv_D)); - start += 0x800; + cache16_unroll32(start,Index_Invalidate_I); + start += 0x200; } } -extern inline void blast_icache16(void) +extern inline void blast_scache16(void) { unsigned long start = KSEG0; - unsigned long end = (start + icache_size); + unsigned long end = KSEG0 + scache_size; while(start < end) { - __asm__ __volatile__(" - .set noreorder - .set mips3 - cache %1, 0x000(%0); cache %1, 0x010(%0) - cache %1, 0x020(%0); cache %1, 0x030(%0) - cache %1, 0x040(%0); cache %1, 0x050(%0) - cache %1, 0x060(%0); cache %1, 0x070(%0) - cache %1, 0x080(%0); cache %1, 0x090(%0) - cache %1, 0x0a0(%0); cache %1, 0x0b0(%0) - cache %1, 0x0c0(%0); cache %1, 0x0d0(%0) - cache %1, 0x0e0(%0); cache %1, 0x0f0(%0) - cache %1, 0x100(%0); cache %1, 0x110(%0) - cache %1, 0x120(%0); cache %1, 0x130(%0) - cache %1, 0x140(%0); cache %1, 0x150(%0) - cache %1, 0x160(%0); cache %1, 0x170(%0) - cache %1, 0x180(%0); cache %1, 0x190(%0) - cache %1, 0x1a0(%0); cache %1, 0x1b0(%0) - cache %1, 0x1c0(%0); cache %1, 0x1d0(%0) - cache %1, 0x1e0(%0); cache %1, 0x1f0(%0) - .set mips0 - .set reorder" - : - : "r" (start), - "i" (Index_Invalidate_I)); + cache16_unroll32(start,Index_Writeback_Inv_SD); start += 0x200; } } -extern inline void blast_icache16_page(unsigned long page) +extern inline void blast_scache16_page(unsigned long page) { unsigned long start = page; - unsigned long end = (start + PAGE_SIZE); + unsigned long end = page + PAGE_SIZE; while(start < end) { - __asm__ __volatile__(" - .set noreorder - .set mips3 - cache %1, 0x000(%0); cache %1, 0x010(%0) - cache %1, 0x020(%0); cache %1, 0x030(%0) - cache %1, 0x040(%0); cache %1, 0x050(%0) - cache %1, 0x060(%0); cache %1, 0x070(%0) - cache %1, 0x080(%0); cache %1, 0x090(%0) - cache %1, 0x0a0(%0); cache %1, 0x0b0(%0) - cache %1, 0x0c0(%0); cache %1, 0x0d0(%0) - cache %1, 0x0e0(%0); cache %1, 0x0f0(%0) - cache %1, 0x100(%0); cache %1, 0x110(%0) - cache %1, 0x120(%0); cache %1, 0x130(%0) - cache %1, 0x140(%0); cache %1, 0x150(%0) - cache %1, 0x160(%0); cache %1, 0x170(%0) - cache %1, 0x180(%0); cache %1, 0x190(%0) - cache %1, 0x1a0(%0); cache %1, 0x1b0(%0) - cache %1, 0x1c0(%0); cache %1, 0x1d0(%0) - cache %1, 0x1e0(%0); cache %1, 0x1f0(%0) - cache %1, 0x200(%0); cache %1, 0x210(%0) - cache %1, 0x220(%0); cache %1, 0x230(%0) - cache %1, 0x240(%0); cache %1, 0x250(%0) - cache %1, 0x260(%0); cache %1, 0x270(%0) - cache %1, 0x280(%0); cache %1, 0x290(%0) - cache %1, 0x2a0(%0); cache %1, 0x2b0(%0) - cache %1, 0x2c0(%0); cache %1, 0x2d0(%0) - cache %1, 0x2e0(%0); cache %1, 0x2f0(%0) - cache %1, 0x300(%0); cache %1, 0x310(%0) - cache %1, 0x320(%0); cache %1, 0x330(%0) - cache %1, 0x340(%0); cache %1, 0x350(%0) - cache %1, 0x360(%0); cache %1, 0x370(%0) - cache %1, 0x380(%0); cache %1, 0x390(%0) - cache %1, 0x3a0(%0); cache %1, 0x3b0(%0) - cache %1, 0x3c0(%0); cache %1, 0x3d0(%0) - cache %1, 0x3e0(%0); cache %1, 0x3f0(%0) - cache %1, 0x400(%0); cache %1, 0x410(%0) - cache %1, 0x420(%0); cache %1, 0x430(%0) - cache %1, 0x440(%0); cache %1, 0x450(%0) - cache %1, 0x460(%0); cache %1, 0x470(%0) - cache %1, 0x480(%0); cache %1, 0x490(%0) - cache %1, 0x4a0(%0); cache %1, 0x4b0(%0) - cache %1, 0x4c0(%0); cache %1, 0x4d0(%0) - cache %1, 0x4e0(%0); cache %1, 0x4f0(%0) - cache %1, 0x500(%0); cache %1, 0x510(%0) - cache %1, 0x520(%0); cache %1, 0x530(%0) - cache %1, 0x540(%0); cache %1, 0x550(%0) - cache %1, 0x560(%0); cache %1, 0x570(%0) - cache %1, 0x580(%0); cache %1, 0x590(%0) - cache %1, 0x5a0(%0); cache %1, 0x5b0(%0) - cache %1, 0x5c0(%0); cache %1, 0x5d0(%0) - cache %1, 0x5e0(%0); cache %1, 0x5f0(%0) - cache %1, 0x600(%0); cache %1, 0x610(%0) - cache %1, 0x620(%0); cache %1, 0x630(%0) - cache %1, 0x640(%0); cache %1, 0x650(%0) - cache %1, 0x660(%0); cache %1, 0x670(%0) - cache %1, 0x680(%0); cache %1, 0x690(%0) - cache %1, 0x6a0(%0); cache %1, 0x6b0(%0) - cache %1, 0x6c0(%0); cache %1, 0x6d0(%0) - cache %1, 0x6e0(%0); cache %1, 0x6f0(%0) - cache %1, 0x700(%0); cache %1, 0x710(%0) - cache %1, 0x720(%0); cache %1, 0x730(%0) - cache %1, 0x740(%0); cache %1, 0x750(%0) - cache %1, 0x760(%0); cache %1, 0x770(%0) - cache %1, 0x780(%0); cache %1, 0x790(%0) - cache %1, 0x7a0(%0); cache %1, 0x7b0(%0) - cache %1, 0x7c0(%0); cache %1, 0x7d0(%0) - cache %1, 0x7e0(%0); cache %1, 0x7f0(%0) - .set mips0 - .set reorder" - : - : "r" (start), - "i" (Hit_Invalidate_I)); - start += 0x800; + cache16_unroll32(start,Hit_Writeback_Inv_SD); + start += 0x200; } } -extern inline void blast_icache16_page_indexed(unsigned long page) +extern inline void blast_scache16_page_indexed(unsigned long page) { unsigned long start = page; - unsigned long end = (start + PAGE_SIZE); + unsigned long end = page + PAGE_SIZE; while(start < end) { - __asm__ __volatile__(" -.set noreorder -.set mips3 -cache 0, 0x000(%0); cache 0, 0x010(%0); cache 0, 0x020(%0); cache 0, 0x030(%0) -cache 0, 0x040(%0); cache 0, 0x050(%0); cache 0, 0x060(%0); cache 0, 0x070(%0) -cache 0, 0x080(%0); cache 0, 0x090(%0); cache 0, 0x0a0(%0); cache 0, 0x0b0(%0) -cache 0, 0x0c0(%0); cache 0, 0x0d0(%0); cache 0, 0x0e0(%0); cache 0, 0x0f0(%0) -cache 0, 0x100(%0); cache 0, 0x110(%0); cache 0, 0x120(%0); cache 0, 0x130(%0) -cache 0, 0x140(%0); cache 0, 0x150(%0); cache 0, 0x160(%0); cache 0, 0x170(%0) -cache 0, 0x180(%0); cache 0, 0x190(%0); cache 0, 0x1a0(%0); cache 0, 0x1b0(%0) -cache 0, 0x1c0(%0); cache 0, 0x1d0(%0); cache 0, 0x1e0(%0); cache 0, 0x1f0(%0) -cache 0, 0x200(%0); cache 0, 0x210(%0); cache 0, 0x220(%0); cache 0, 0x230(%0) -cache 0, 0x240(%0); cache 0, 0x250(%0); cache 0, 0x260(%0); cache 0, 0x270(%0) -cache 0, 0x280(%0); cache 0, 0x290(%0); cache 0, 0x2a0(%0); cache 0, 0x2b0(%0) -cache 0, 0x2c0(%0); cache 0, 0x2d0(%0); cache 0, 0x2e0(%0); cache 0, 0x2f0(%0) -cache 0, 0x300(%0); cache 0, 0x310(%0); cache 0, 0x320(%0); cache 0, 0x330(%0) -cache 0, 0x340(%0); cache 0, 0x350(%0); cache 0, 0x360(%0); cache 0, 0x370(%0) -cache 0, 0x380(%0); cache 0, 0x390(%0); cache 0, 0x3a0(%0); cache 0, 0x3b0(%0) -cache 0, 0x3c0(%0); cache 0, 0x3d0(%0); cache 0, 0x3e0(%0); cache 0, 0x3f0(%0) -cache 0, 0x400(%0); cache 0, 0x410(%0); cache 0, 0x420(%0); cache 0, 0x430(%0) -cache 0, 0x440(%0); cache 0, 0x450(%0); cache 0, 0x460(%0); cache 0, 0x470(%0) -cache 0, 0x480(%0); cache 0, 0x490(%0); cache 0, 0x4a0(%0); cache 0, 0x4b0(%0) -cache 0, 0x4c0(%0); cache 0, 0x4d0(%0); cache 0, 0x4e0(%0); cache 0, 0x4f0(%0) -cache 0, 0x500(%0); cache 0, 0x510(%0); cache 0, 0x520(%0); cache 0, 0x530(%0) -cache 0, 0x540(%0); cache 0, 0x550(%0); cache 0, 0x560(%0); cache 0, 0x570(%0) -cache 0, 0x580(%0); cache 0, 0x590(%0); cache 0, 0x5a0(%0); cache 0, 0x5b0(%0) -cache 0, 0x5c0(%0); cache 0, 0x5d0(%0); cache 0, 0x5e0(%0); cache 0, 0x5f0(%0) -cache 0, 0x600(%0); cache 0, 0x610(%0); cache 0, 0x620(%0); cache 0, 0x630(%0) -cache 0, 0x640(%0); cache 0, 0x650(%0); cache 0, 0x660(%0); cache 0, 0x670(%0) -cache 0, 0x680(%0); cache 0, 0x690(%0); cache 0, 0x6a0(%0); cache 0, 0x6b0(%0) -cache 0, 0x6c0(%0); cache 0, 0x6d0(%0); cache 0, 0x6e0(%0); cache 0, 0x6f0(%0) -cache 0, 0x700(%0); cache 0, 0x710(%0); cache 0, 0x720(%0); cache 0, 0x730(%0) -cache 0, 0x740(%0); cache 0, 0x750(%0); cache 0, 0x760(%0); cache 0, 0x770(%0) -cache 0, 0x780(%0); cache 0, 0x790(%0); cache 0, 0x7a0(%0); cache 0, 0x7b0(%0) -cache 0, 0x7c0(%0); cache 0, 0x7d0(%0); cache 0, 0x7e0(%0); cache 0, 0x7f0(%0) -.set mips0 -.set reorder - " : : "r" (start)); - start += 0x800; + cache16_unroll32(start,Index_Writeback_Inv_SD); + start += 0x200; } } -extern inline void blast_icache32(void) +#define cache32_unroll32(base,op) \ + __asm__ __volatile__(" \ + .set noreorder; \ + .set mips3; \ + cache %1, 0x000(%0); cache %1, 0x020(%0); \ + cache %1, 0x040(%0); cache %1, 0x060(%0); \ + cache %1, 0x080(%0); cache %1, 0x0a0(%0); \ + cache %1, 0x0c0(%0); cache %1, 0x0e0(%0); \ + cache %1, 0x100(%0); cache %1, 0x120(%0); \ + cache %1, 0x140(%0); cache %1, 0x160(%0); \ + cache %1, 0x180(%0); cache %1, 0x1a0(%0); \ + cache %1, 0x1c0(%0); cache %1, 0x1e0(%0); \ + cache %1, 0x200(%0); cache %1, 0x220(%0); \ + cache %1, 0x240(%0); cache %1, 0x260(%0); \ + cache %1, 0x280(%0); cache %1, 0x2a0(%0); \ + cache %1, 0x2c0(%0); cache %1, 0x2e0(%0); \ + cache %1, 0x300(%0); cache %1, 0x320(%0); \ + cache %1, 0x340(%0); cache %1, 0x360(%0); \ + cache %1, 0x380(%0); cache %1, 0x3a0(%0); \ + cache %1, 0x3c0(%0); cache %1, 0x3e0(%0); \ + .set mips0; \ + .set reorder" \ + : \ + : "r" (base), \ + "i" (op)); + +extern inline void blast_dcache32(void) { unsigned long start = KSEG0; - unsigned long end = (start + icache_size); + unsigned long end = (start + dcache_size); while(start < end) { - __asm__ __volatile__(" -.set noreorder -.set mips3 -cache 0, 0x000(%0); cache 0, 0x020(%0); cache 0, 0x040(%0); cache 0, 0x060(%0); -cache 0, 0x080(%0); cache 0, 0x0a0(%0); cache 0, 0x0c0(%0); cache 0, 0x0e0(%0); -cache 0, 0x100(%0); cache 0, 0x120(%0); cache 0, 0x140(%0); cache 0, 0x160(%0); -cache 0, 0x180(%0); cache 0, 0x1a0(%0); cache 0, 0x1c0(%0); cache 0, 0x1e0(%0); -cache 0, 0x200(%0); cache 0, 0x220(%0); cache 0, 0x240(%0); cache 0, 0x260(%0); -cache 0, 0x280(%0); cache 0, 0x2a0(%0); cache 0, 0x2c0(%0); cache 0, 0x2e0(%0); -cache 0, 0x300(%0); cache 0, 0x320(%0); cache 0, 0x340(%0); cache 0, 0x360(%0); -cache 0, 0x380(%0); cache 0, 0x3a0(%0); cache 0, 0x3c0(%0); cache 0, 0x3e0(%0); -.set mips0 -.set reorder - " : : "r" (start)); + cache32_unroll32(start,Index_Writeback_Inv_D); start += 0x400; } } -extern inline void blast_icache32_page(unsigned long page) +/* + * Call this function only with interrupts disabled or R4600 V2.0 may blow + * up on you. + * + * R4600 v2.0 bug: "The CACHE instructions Hit_Writeback_Inv_D, + * Hit_Writeback_D, Hit_Invalidate_D and Create_Dirty_Excl_D will only + * operate correctly if the internal data cache refill buffer is empty. These + * CACHE instructions should be separated from any potential data cache miss + * by a load instruction to an uncached address to empty the response buffer." + * (Revision 2.0 device errata from IDT available on http://www.idt.com/ + * in .pdf format.) + */ +extern inline void blast_dcache32_page(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); + /* + * Sigh ... workaround for R4600 v1.7 bug. Explanation see above. + */ + *(volatile unsigned long *)KSEG1; + + __asm__ __volatile__("nop;nop;nop;nop"); while(start < end) { - __asm__ __volatile__(" -.set noreorder -.set mips3 -cache 16, 0x000(%0); cache 16, 0x020(%0); cache 16, 0x040(%0); cache 16, 0x060(%0); -cache 16, 0x080(%0); cache 16, 0x0a0(%0); cache 16, 0x0c0(%0); cache 16, 0x0e0(%0); -cache 16, 0x100(%0); cache 16, 0x120(%0); cache 16, 0x140(%0); cache 16, 0x160(%0); -cache 16, 0x180(%0); cache 16, 0x1a0(%0); cache 16, 0x1c0(%0); cache 16, 0x1e0(%0); -cache 16, 0x200(%0); cache 16, 0x220(%0); cache 16, 0x240(%0); cache 16, 0x260(%0); -cache 16, 0x280(%0); cache 16, 0x2a0(%0); cache 16, 0x2c0(%0); cache 16, 0x2e0(%0); -cache 16, 0x300(%0); cache 16, 0x320(%0); cache 16, 0x340(%0); cache 16, 0x360(%0); -cache 16, 0x380(%0); cache 16, 0x3a0(%0); cache 16, 0x3c0(%0); cache 16, 0x3e0(%0); -cache 16, 0x400(%0); cache 16, 0x420(%0); cache 16, 0x440(%0); cache 16, 0x460(%0); -cache 16, 0x480(%0); cache 16, 0x4a0(%0); cache 16, 0x4c0(%0); cache 16, 0x4e0(%0); -cache 16, 0x500(%0); cache 16, 0x520(%0); cache 16, 0x540(%0); cache 16, 0x560(%0); -cache 16, 0x580(%0); cache 16, 0x5a0(%0); cache 16, 0x5c0(%0); cache 16, 0x5e0(%0); -cache 16, 0x600(%0); cache 16, 0x620(%0); cache 16, 0x640(%0); cache 16, 0x660(%0); -cache 16, 0x680(%0); cache 16, 0x6a0(%0); cache 16, 0x6c0(%0); cache 16, 0x6e0(%0); -cache 16, 0x700(%0); cache 16, 0x720(%0); cache 16, 0x740(%0); cache 16, 0x760(%0); -cache 16, 0x780(%0); cache 16, 0x7a0(%0); cache 16, 0x7c0(%0); cache 16, 0x7e0(%0); -.set mips0 -.set reorder - " : : "r" (start)); - start += 0x800; + cache32_unroll32(start,Hit_Writeback_Inv_D); + start += 0x400; } } -extern inline void blast_icache32_page_indexed(unsigned long page) +extern inline void blast_dcache32_page_indexed(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); while(start < end) { - __asm__ __volatile__(" -.set noreorder -.set mips3 -cache 0, 0x000(%0); cache 0, 0x020(%0); cache 0, 0x040(%0); cache 0, 0x060(%0); -cache 0, 0x080(%0); cache 0, 0x0a0(%0); cache 0, 0x0c0(%0); cache 0, 0x0e0(%0); -cache 0, 0x100(%0); cache 0, 0x120(%0); cache 0, 0x140(%0); cache 0, 0x160(%0); -cache 0, 0x180(%0); cache 0, 0x1a0(%0); cache 0, 0x1c0(%0); cache 0, 0x1e0(%0); -cache 0, 0x200(%0); cache 0, 0x220(%0); cache 0, 0x240(%0); cache 0, 0x260(%0); -cache 0, 0x280(%0); cache 0, 0x2a0(%0); cache 0, 0x2c0(%0); cache 0, 0x2e0(%0); -cache 0, 0x300(%0); cache 0, 0x320(%0); cache 0, 0x340(%0); cache 0, 0x360(%0); -cache 0, 0x380(%0); cache 0, 0x3a0(%0); cache 0, 0x3c0(%0); cache 0, 0x3e0(%0); -cache 0, 0x400(%0); cache 0, 0x420(%0); cache 0, 0x440(%0); cache 0, 0x460(%0); -cache 0, 0x480(%0); cache 0, 0x4a0(%0); cache 0, 0x4c0(%0); cache 0, 0x4e0(%0); -cache 0, 0x500(%0); cache 0, 0x520(%0); cache 0, 0x540(%0); cache 0, 0x560(%0); -cache 0, 0x580(%0); cache 0, 0x5a0(%0); cache 0, 0x5c0(%0); cache 0, 0x5e0(%0); -cache 0, 0x600(%0); cache 0, 0x620(%0); cache 0, 0x640(%0); cache 0, 0x660(%0); -cache 0, 0x680(%0); cache 0, 0x6a0(%0); cache 0, 0x6c0(%0); cache 0, 0x6e0(%0); -cache 0, 0x700(%0); cache 0, 0x720(%0); cache 0, 0x740(%0); cache 0, 0x760(%0); -cache 0, 0x780(%0); cache 0, 0x7a0(%0); cache 0, 0x7c0(%0); cache 0, 0x7e0(%0); -.set mips0 -.set reorder - " : : "r" (start)); - start += 0x800; + cache32_unroll32(start,Index_Writeback_Inv_D); + start += 0x400; } } -extern inline void blast_scache16(void) +extern inline void blast_icache32(void) { unsigned long start = KSEG0; - unsigned long end = KSEG0 + scache_size; + unsigned long end = (start + icache_size); while(start < end) { - __asm__ __volatile__(" -.set noreorder -.set mips3 -cache 3, 0x000(%0); cache 3, 0x010(%0); cache 3, 0x020(%0); cache 3, 0x030(%0) -cache 3, 0x040(%0); cache 3, 0x050(%0); cache 3, 0x060(%0); cache 3, 0x070(%0) -cache 3, 0x080(%0); cache 3, 0x090(%0); cache 3, 0x0a0(%0); cache 3, 0x0b0(%0) -cache 3, 0x0c0(%0); cache 3, 0x0d0(%0); cache 3, 0x0e0(%0); cache 3, 0x0f0(%0) -cache 3, 0x100(%0); cache 3, 0x110(%0); cache 3, 0x120(%0); cache 3, 0x130(%0) -cache 3, 0x140(%0); cache 3, 0x150(%0); cache 3, 0x160(%0); cache 3, 0x170(%0) -cache 3, 0x180(%0); cache 3, 0x190(%0); cache 3, 0x1a0(%0); cache 3, 0x1b0(%0) -cache 3, 0x1c0(%0); cache 3, 0x1d0(%0); cache 3, 0x1e0(%0); cache 3, 0x1f0(%0) -.set mips0 -.set reorder - " : : "r" (start)); - start += 0x200; + cache32_unroll32(start,Index_Invalidate_I); + start += 0x400; } } -extern inline void blast_scache16_page(unsigned long page) +extern inline void blast_icache32_page(unsigned long page) { unsigned long start = page; - unsigned long end = page + PAGE_SIZE; + unsigned long end = (start + PAGE_SIZE); while(start < end) { - __asm__ __volatile__(" -.set noreorder -.set mips3 -cache 23, 0x000(%0); cache 23, 0x010(%0); cache 23, 0x020(%0); cache 23, 0x030(%0) -cache 23, 0x040(%0); cache 23, 0x050(%0); cache 23, 0x060(%0); cache 23, 0x070(%0) -cache 23, 0x080(%0); cache 23, 0x090(%0); cache 23, 0x0a0(%0); cache 23, 0x0b0(%0) -cache 23, 0x0c0(%0); cache 23, 0x0d0(%0); cache 23, 0x0e0(%0); cache 23, 0x0f0(%0) -cache 23, 0x100(%0); cache 23, 0x110(%0); cache 23, 0x120(%0); cache 23, 0x130(%0) -cache 23, 0x140(%0); cache 23, 0x150(%0); cache 23, 0x160(%0); cache 23, 0x170(%0) -cache 23, 0x180(%0); cache 23, 0x190(%0); cache 23, 0x1a0(%0); cache 23, 0x1b0(%0) -cache 23, 0x1c0(%0); cache 23, 0x1d0(%0); cache 23, 0x1e0(%0); cache 23, 0x1f0(%0) -.set mips0 -.set reorder - " : : "r" (start)); - start += 0x200; + cache32_unroll32(start,Hit_Invalidate_I); + start += 0x400; } } -extern inline void blast_scache16_page_indexed(unsigned long page) +extern inline void blast_icache32_page_indexed(unsigned long page) { unsigned long start = page; - unsigned long end = page + PAGE_SIZE; + unsigned long end = (start + PAGE_SIZE); while(start < end) { - __asm__ __volatile__(" -.set noreorder -.set mips3 -cache 3, 0x000(%0); cache 3, 0x010(%0); cache 3, 0x020(%0); cache 3, 0x030(%0) -cache 3, 0x040(%0); cache 3, 0x050(%0); cache 3, 0x060(%0); cache 3, 0x070(%0) -cache 3, 0x080(%0); cache 3, 0x090(%0); cache 3, 0x0a0(%0); cache 3, 0x0b0(%0) -cache 3, 0x0c0(%0); cache 3, 0x0d0(%0); cache 3, 0x0e0(%0); cache 3, 0x0f0(%0) -cache 3, 0x100(%0); cache 3, 0x110(%0); cache 3, 0x120(%0); cache 3, 0x130(%0) -cache 3, 0x140(%0); cache 3, 0x150(%0); cache 3, 0x160(%0); cache 3, 0x170(%0) -cache 3, 0x180(%0); cache 3, 0x190(%0); cache 3, 0x1a0(%0); cache 3, 0x1b0(%0) -cache 3, 0x1c0(%0); cache 3, 0x1d0(%0); cache 3, 0x1e0(%0); cache 3, 0x1f0(%0) -.set mips0 -.set reorder - " : : "r" (start)); - start += 0x200; + cache32_unroll32(start,Index_Invalidate_I); + start += 0x400; } } @@ -909,20 +393,7 @@ unsigned long end = KSEG0 + scache_size; while(start < end) { - __asm__ __volatile__(" -.set noreorder -.set mips3 -cache 3, 0x000(%0); cache 3, 0x020(%0); cache 3, 0x040(%0); cache 3, 0x060(%0); -cache 3, 0x080(%0); cache 3, 0x0a0(%0); cache 3, 0x0c0(%0); cache 3, 0x0e0(%0); -cache 3, 0x100(%0); cache 3, 0x120(%0); cache 3, 0x140(%0); cache 3, 0x160(%0); -cache 3, 0x180(%0); cache 3, 0x1a0(%0); cache 3, 0x1c0(%0); cache 3, 0x1e0(%0); -cache 3, 0x200(%0); cache 3, 0x220(%0); cache 3, 0x240(%0); cache 3, 0x260(%0); -cache 3, 0x280(%0); cache 3, 0x2a0(%0); cache 3, 0x2c0(%0); cache 3, 0x2e0(%0); -cache 3, 0x300(%0); cache 3, 0x320(%0); cache 3, 0x340(%0); cache 3, 0x360(%0); -cache 3, 0x380(%0); cache 3, 0x3a0(%0); cache 3, 0x3c0(%0); cache 3, 0x3e0(%0); -.set mips0 -.set reorder - " : : "r" (start)); + cache32_unroll32(start,Index_Writeback_Inv_SD); start += 0x400; } } @@ -933,20 +404,7 @@ unsigned long end = page + PAGE_SIZE; while(start < end) { - __asm__ __volatile__(" -.set noreorder -.set mips3 -cache 23, 0x000(%0); cache 23, 0x020(%0); cache 23, 0x040(%0); cache 23, 0x060(%0); -cache 23, 0x080(%0); cache 23, 0x0a0(%0); cache 23, 0x0c0(%0); cache 23, 0x0e0(%0); -cache 23, 0x100(%0); cache 23, 0x120(%0); cache 23, 0x140(%0); cache 23, 0x160(%0); -cache 23, 0x180(%0); cache 23, 0x1a0(%0); cache 23, 0x1c0(%0); cache 23, 0x1e0(%0); -cache 23, 0x200(%0); cache 23, 0x220(%0); cache 23, 0x240(%0); cache 23, 0x260(%0); -cache 23, 0x280(%0); cache 23, 0x2a0(%0); cache 23, 0x2c0(%0); cache 23, 0x2e0(%0); -cache 23, 0x300(%0); cache 23, 0x320(%0); cache 23, 0x340(%0); cache 23, 0x360(%0); -cache 23, 0x380(%0); cache 23, 0x3a0(%0); cache 23, 0x3c0(%0); cache 23, 0x3e0(%0); -.set mips0 -.set reorder - " : : "r" (start)); + cache32_unroll32(start,Hit_Writeback_Inv_SD); start += 0x400; } } @@ -957,54 +415,44 @@ unsigned long end = page + PAGE_SIZE; while(start < end) { - __asm__ __volatile__(" -.set noreorder -.set mips3 -cache 3, 0x000(%0); cache 3, 0x020(%0); cache 3, 0x040(%0); cache 3, 0x060(%0); -cache 3, 0x080(%0); cache 3, 0x0a0(%0); cache 3, 0x0c0(%0); cache 3, 0x0e0(%0); -cache 3, 0x100(%0); cache 3, 0x120(%0); cache 3, 0x140(%0); cache 3, 0x160(%0); -cache 3, 0x180(%0); cache 3, 0x1a0(%0); cache 3, 0x1c0(%0); cache 3, 0x1e0(%0); -cache 3, 0x200(%0); cache 3, 0x220(%0); cache 3, 0x240(%0); cache 3, 0x260(%0); -cache 3, 0x280(%0); cache 3, 0x2a0(%0); cache 3, 0x2c0(%0); cache 3, 0x2e0(%0); -cache 3, 0x300(%0); cache 3, 0x320(%0); cache 3, 0x340(%0); cache 3, 0x360(%0); -cache 3, 0x380(%0); cache 3, 0x3a0(%0); cache 3, 0x3c0(%0); cache 3, 0x3e0(%0); -.set mips0 -.set reorder - " : : "r" (start)); + cache32_unroll32(start,Index_Writeback_Inv_SD); start += 0x400; } } +#define cache64_unroll32(base,op) \ + __asm__ __volatile__(" \ + .set noreorder; \ + .set mips3; \ + cache %1, 0x000(%0); cache %1, 0x040(%0); \ + cache %1, 0x080(%0); cache %1, 0x0c0(%0); \ + cache %1, 0x100(%0); cache %1, 0x140(%0); \ + cache %1, 0x180(%0); cache %1, 0x1c0(%0); \ + cache %1, 0x200(%0); cache %1, 0x240(%0); \ + cache %1, 0x280(%0); cache %1, 0x2c0(%0); \ + cache %1, 0x300(%0); cache %1, 0x340(%0); \ + cache %1, 0x380(%0); cache %1, 0x3c0(%0); \ + cache %1, 0x400(%0); cache %1, 0x440(%0); \ + cache %1, 0x480(%0); cache %1, 0x4c0(%0); \ + cache %1, 0x500(%0); cache %1, 0x540(%0); \ + cache %1, 0x580(%0); cache %1, 0x5c0(%0); \ + cache %1, 0x600(%0); cache %1, 0x640(%0); \ + cache %1, 0x680(%0); cache %1, 0x6c0(%0); \ + cache %1, 0x700(%0); cache %1, 0x740(%0); \ + cache %1, 0x780(%0); cache %1, 0x7c0(%0); \ + .set mips0; \ + .set reorder" \ + : \ + : "r" (base), \ + "i" (op)); + extern inline void blast_scache64(void) { unsigned long start = KSEG0; unsigned long end = KSEG0 + scache_size; while(start < end) { - __asm__ __volatile__(" - .set noreorder - .set mips3 - cache %1, 0x000(%0); cache %1, 0x040(%0) - cache %1, 0x080(%0); cache %1, 0x0c0(%0) - cache %1, 0x100(%0); cache %1, 0x140(%0) - cache %1, 0x180(%0); cache %1, 0x1c0(%0) - cache %1, 0x200(%0); cache %1, 0x240(%0) - cache %1, 0x280(%0); cache %1, 0x2c0(%0) - cache %1, 0x300(%0); cache %1, 0x340(%0) - cache %1, 0x380(%0); cache %1, 0x3c0(%0) - cache %1, 0x400(%0); cache %1, 0x440(%0) - cache %1, 0x480(%0); cache %1, 0x4c0(%0) - cache %1, 0x500(%0); cache %1, 0x540(%0) - cache %1, 0x580(%0); cache %1, 0x5c0(%0) - cache %1, 0x600(%0); cache %1, 0x640(%0) - cache %1, 0x680(%0); cache %1, 0x6c0(%0) - cache %1, 0x700(%0); cache %1, 0x740(%0) - cache %1, 0x780(%0); cache %1, 0x7c0(%0) - .set mips0 - .set reorder" - : - : "r" (start), - "i" (Index_Writeback_Inv_SD)); + cache64_unroll32(start,Index_Writeback_Inv_SD); start += 0x800; } } @@ -1015,30 +463,7 @@ unsigned long end = page + PAGE_SIZE; while(start < end) { - __asm__ __volatile__(" - .set noreorder - .set mips3 - cache %1, 0x000(%0); cache %1, 0x040(%0) - cache %1, 0x080(%0); cache %1, 0x0c0(%0) - cache %1, 0x100(%0); cache %1, 0x140(%0) - cache %1, 0x180(%0); cache %1, 0x1c0(%0) - cache %1, 0x200(%0); cache %1, 0x240(%0) - cache %1, 0x280(%0); cache %1, 0x2c0(%0) - cache %1, 0x300(%0); cache %1, 0x340(%0) - cache %1, 0x380(%0); cache %1, 0x3c0(%0) - cache %1, 0x400(%0); cache %1, 0x440(%0) - cache %1, 0x480(%0); cache %1, 0x4c0(%0) - cache %1, 0x500(%0); cache %1, 0x540(%0) - cache %1, 0x580(%0); cache %1, 0x5c0(%0) - cache %1, 0x600(%0); cache %1, 0x640(%0) - cache %1, 0x680(%0); cache %1, 0x6c0(%0) - cache %1, 0x700(%0); cache %1, 0x740(%0) - cache %1, 0x780(%0); cache %1, 0x7c0(%0) - .set mips0 - .set reorder" - : - : "r" (start), - "i" (Hit_Writeback_Inv_D)); + cache64_unroll32(start,Hit_Writeback_Inv_SD); start += 0x800; } } @@ -1049,122 +474,56 @@ unsigned long end = page + PAGE_SIZE; while(start < end) { - __asm__ __volatile__(" - .set noreorder - .set mips3 - cache %1, 0x000(%0); cache %1, 0x040(%0) - cache %1, 0x080(%0); cache %1, 0x0c0(%0) - cache %1, 0x100(%0); cache %1, 0x140(%0) - cache %1, 0x180(%0); cache %1, 0x1c0(%0) - cache %1, 0x200(%0); cache %1, 0x240(%0) - cache %1, 0x280(%0); cache %1, 0x2c0(%0) - cache %1, 0x300(%0); cache %1, 0x340(%0) - cache %1, 0x380(%0); cache %1, 0x3c0(%0) - cache %1, 0x400(%0); cache %1, 0x440(%0) - cache %1, 0x480(%0); cache %1, 0x4c0(%0) - cache %1, 0x500(%0); cache %1, 0x540(%0) - cache %1, 0x580(%0); cache %1, 0x5c0(%0) - cache %1, 0x600(%0); cache %1, 0x640(%0) - cache %1, 0x680(%0); cache %1, 0x6c0(%0) - cache %1, 0x700(%0); cache %1, 0x740(%0) - cache %1, 0x780(%0); cache %1, 0x7c0(%0) - .set mips0 - .set reorder" - : - : "r" (start), - "i" (Index_Writeback_Inv_SD)); + cache64_unroll32(start,Index_Writeback_Inv_SD); start += 0x800; } } +#define cache128_unroll32(base,op) \ + __asm__ __volatile__(" \ + .set noreorder; \ + .set mips3; \ + cache %1, 0x000(%0); cache %1, 0x080(%0); \ + cache %1, 0x100(%0); cache %1, 0x180(%0); \ + cache %1, 0x200(%0); cache %1, 0x280(%0); \ + cache %1, 0x300(%0); cache %1, 0x380(%0); \ + cache %1, 0x400(%0); cache %1, 0x480(%0); \ + cache %1, 0x500(%0); cache %1, 0x580(%0); \ + cache %1, 0x600(%0); cache %1, 0x680(%0); \ + cache %1, 0x700(%0); cache %1, 0x780(%0); \ + cache %1, 0x800(%0); cache %1, 0x880(%0); \ + cache %1, 0x900(%0); cache %1, 0x980(%0); \ + cache %1, 0xa00(%0); cache %1, 0xa80(%0); \ + cache %1, 0xb00(%0); cache %1, 0xb80(%0); \ + cache %1, 0xc00(%0); cache %1, 0xc80(%0); \ + cache %1, 0xd00(%0); cache %1, 0xd80(%0); \ + cache %1, 0xe00(%0); cache %1, 0xe80(%0); \ + cache %1, 0xf00(%0); cache %1, 0xf80(%0); \ + .set mips0; \ + .set reorder" \ + : \ + : "r" (base), \ + "i" (op)); + extern inline void blast_scache128(void) { unsigned long start = KSEG0; unsigned long end = KSEG0 + scache_size; while(start < end) { - __asm__ __volatile__(" - .set noreorder - .set mips3 - cache %1, 0x000(%0); cache %1, 0x080(%0) - cache %1, 0x100(%0); cache %1, 0x180(%0) - cache %1, 0x200(%0); cache %1, 0x280(%0) - cache %1, 0x300(%0); cache %1, 0x380(%0) - cache %1, 0x400(%0); cache %1, 0x480(%0) - cache %1, 0x500(%0); cache %1, 0x580(%0) - cache %1, 0x600(%0); cache %1, 0x680(%0) - cache %1, 0x700(%0); cache %1, 0x780(%0) - cache %1, 0x800(%0); cache %1, 0x880(%0) - cache %1, 0x900(%0); cache %1, 0x980(%0) - cache %1, 0xa00(%0); cache %1, 0xa80(%0) - cache %1, 0xb00(%0); cache %1, 0xb80(%0) - cache %1, 0xc00(%0); cache %1, 0xc80(%0) - cache %1, 0xd00(%0); cache %1, 0xd80(%0) - cache %1, 0xe00(%0); cache %1, 0xe80(%0) - cache %1, 0xf00(%0); cache %1, 0xf80(%0) - .set mips0 - .set reorder" - : - : "r" (start), - "i" (Index_Writeback_Inv_SD)); + cache128_unroll32(start,Index_Writeback_Inv_SD); start += 0x1000; } } extern inline void blast_scache128_page(unsigned long page) { - __asm__ __volatile__(" - .set noreorder - .set mips3 - cache %1, 0x000(%0); cache %1, 0x080(%0) - cache %1, 0x100(%0); cache %1, 0x180(%0) - cache %1, 0x200(%0); cache %1, 0x280(%0) - cache %1, 0x300(%0); cache %1, 0x380(%0) - cache %1, 0x400(%0); cache %1, 0x480(%0) - cache %1, 0x500(%0); cache %1, 0x580(%0) - cache %1, 0x600(%0); cache %1, 0x680(%0) - cache %1, 0x700(%0); cache %1, 0x780(%0) - cache %1, 0x800(%0); cache %1, 0x880(%0) - cache %1, 0x900(%0); cache %1, 0x980(%0) - cache %1, 0xa00(%0); cache %1, 0xa80(%0) - cache %1, 0xb00(%0); cache %1, 0xb80(%0) - cache %1, 0xc00(%0); cache %1, 0xc80(%0) - cache %1, 0xd00(%0); cache %1, 0xd80(%0) - cache %1, 0xe00(%0); cache %1, 0xe80(%0) - cache %1, 0xf00(%0); cache %1, 0xf80(%0) - .set mips0 - .set reorder" - : - : "r" (page), - "i" (Hit_Writeback_Inv_D)); + cache128_unroll32(page,Hit_Writeback_Inv_SD); } extern inline void blast_scache128_page_indexed(unsigned long page) { - __asm__ __volatile__(" - .set noreorder - .set mips3 - cache %1, 0x000(%0); cache %1, 0x080(%0) - cache %1, 0x100(%0); cache %1, 0x180(%0) - cache %1, 0x200(%0); cache %1, 0x280(%0) - cache %1, 0x300(%0); cache %1, 0x380(%0) - cache %1, 0x400(%0); cache %1, 0x480(%0) - cache %1, 0x500(%0); cache %1, 0x580(%0) - cache %1, 0x600(%0); cache %1, 0x680(%0) - cache %1, 0x700(%0); cache %1, 0x780(%0) - cache %1, 0x800(%0); cache %1, 0x880(%0) - cache %1, 0x900(%0); cache %1, 0x980(%0) - cache %1, 0xa00(%0); cache %1, 0xa80(%0) - cache %1, 0xb00(%0); cache %1, 0xb80(%0) - cache %1, 0xc00(%0); cache %1, 0xc80(%0) - cache %1, 0xd00(%0); cache %1, 0xd80(%0) - cache %1, 0xe00(%0); cache %1, 0xe80(%0) - cache %1, 0xf00(%0); cache %1, 0xf80(%0) - .set mips0 - .set reorder" - : - : "r" (page), - "i" (Index_Writeback_Inv_SD)); + cache128_unroll32(page,Index_Writeback_Inv_SD); } #endif /* !(_MIPS_R4KCACHE_H) */ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/semaphore.h linux/include/asm-mips/semaphore.h --- v2.1.100/linux/include/asm-mips/semaphore.h Thu Jun 26 12:33:40 1997 +++ linux/include/asm-mips/semaphore.h Fri May 8 00:13:26 1998 @@ -10,7 +10,9 @@ #ifndef __ASM_MIPS_SEMAPHORE_H #define __ASM_MIPS_SEMAPHORE_H +#include #include +#include struct semaphore { atomic_t count; @@ -24,6 +26,8 @@ extern void __down(struct semaphore * sem); extern int __down_interruptible(struct semaphore * sem); extern void __up(struct semaphore * sem); + +extern spinlock_t semaphore_wake_lock; #define sema_init(sem, val) atomic_set(&((sem)->count), val) diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/sgi.h linux/include/asm-mips/sgi.h --- v2.1.100/linux/include/asm-mips/sgi.h Wed Dec 10 10:31:11 1997 +++ linux/include/asm-mips/sgi.h Fri May 8 00:13:26 1998 @@ -1,4 +1,4 @@ -/* $Id: sgi.h,v 1.1.1.1 1997/06/01 03:17:12 ralf Exp $ +/* $Id: sgi.h,v 1.2 1998/05/01 01:36:05 ralf Exp $ * sgi.h: Definitions specific to SGI machines. * * Copyright (C) 1996 David S. Miller (dm@sgi.com) diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/sgialib.h linux/include/asm-mips/sgialib.h --- v2.1.100/linux/include/asm-mips/sgialib.h Wed Dec 10 10:31:11 1997 +++ linux/include/asm-mips/sgialib.h Fri May 8 00:13:26 1998 @@ -1,4 +1,4 @@ -/* $Id: sgialib.h,v 1.1.1.1 1997/06/01 03:17:13 ralf Exp $ +/* $Id: sgialib.h,v 1.2 1998/05/01 01:36:06 ralf Exp $ * sgialib.h: SGI ARCS firmware interface library for the Linux kernel. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/sgiarcs.h linux/include/asm-mips/sgiarcs.h --- v2.1.100/linux/include/asm-mips/sgiarcs.h Wed Dec 10 10:31:11 1997 +++ linux/include/asm-mips/sgiarcs.h Fri May 8 00:13:26 1998 @@ -1,4 +1,4 @@ -/* $Id: sgiarcs.h,v 1.1.1.1 1997/06/01 03:17:12 ralf Exp $ +/* $Id: sgiarcs.h,v 1.2 1998/05/01 01:36:07 ralf Exp $ * SGI ARCS firmware interface defines. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/sgihpc.h linux/include/asm-mips/sgihpc.h --- v2.1.100/linux/include/asm-mips/sgihpc.h Wed Dec 10 10:31:11 1997 +++ linux/include/asm-mips/sgihpc.h Fri May 8 00:13:26 1998 @@ -1,4 +1,4 @@ -/* $Id: sgihpc.h,v 1.1.1.1 1997/06/01 03:17:12 ralf Exp $ +/* $Id: sgihpc.h,v 1.2 1998/05/01 01:36:07 ralf Exp $ * sgihpc.h: Various HPC I/O controller defines. The HPC is basically * the approximate functional equivalent of the Sun SYSIO * on SGI INDY machines. diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/sgimc.h linux/include/asm-mips/sgimc.h --- v2.1.100/linux/include/asm-mips/sgimc.h Wed Dec 10 10:31:11 1997 +++ linux/include/asm-mips/sgimc.h Fri May 8 00:13:26 1998 @@ -1,4 +1,4 @@ -/* $Id: sgimc.h,v 1.1.1.1 1997/06/01 03:17:13 ralf Exp $ +/* $Id: sgimc.h,v 1.2 1998/05/01 01:36:08 ralf Exp $ * sgimc.h: Definitions for memory controller hardware found on * SGI IP20, IP22, IP26, and IP28 machines. * diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/sgint23.h linux/include/asm-mips/sgint23.h --- v2.1.100/linux/include/asm-mips/sgint23.h Wed Dec 10 10:31:11 1997 +++ linux/include/asm-mips/sgint23.h Fri May 8 00:13:26 1998 @@ -1,4 +1,4 @@ -/* $Id: sgint23.h,v 1.1.1.1 1997/06/01 03:17:12 ralf Exp $ +/* $Id: sgint23.h,v 1.2 1998/05/01 01:36:09 ralf Exp $ * sgint23.h: Defines for the SGI INT2 and INT3 chipsets. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -126,7 +126,7 @@ #define SGINT_TCWORD_CNT2 0x80 /* Select counter two */ #define SGINT_TCWORD_CRBCK 0xc0 /* Readback command */ -#define SGINT_TCSAMP_COUNTER 0x164 +#define SGINT_TCSAMP_COUNTER 10255 struct sgi_int2_regs { struct sgi_ioc_ints ints; diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/sigcontext.h linux/include/asm-mips/sigcontext.h --- v2.1.100/linux/include/asm-mips/sigcontext.h Tue Dec 16 12:46:14 1997 +++ linux/include/asm-mips/sigcontext.h Fri May 8 00:13:26 1998 @@ -7,7 +7,7 @@ * * Copyright (C) 1996, 1997 by Ralf Baechle * - * $Id: sigcontext.h,v 1.4 1997/12/01 16:46:19 ralf Exp $ + * $Id: sigcontext.h,v 1.6 1998/05/01 01:36:10 ralf Exp $ */ #ifndef __ASM_MIPS_SIGCONTEXT_H #define __ASM_MIPS_SIGCONTEXT_H @@ -32,8 +32,7 @@ unsigned int sc_cause; /* Unused */ unsigned int sc_badvaddr; /* Unused */ - unsigned long sc_sigset; /* kernel's sigset_t */ - unsigned long __pad0[3]; /* pad for constant size */ + unsigned long sc_sigset[4]; /* kernel's sigset_t */ }; #endif /* __ASM_MIPS_SIGCONTEXT_H */ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/signal.h linux/include/asm-mips/signal.h --- v2.1.100/linux/include/asm-mips/signal.h Tue Dec 16 12:46:14 1997 +++ linux/include/asm-mips/signal.h Fri May 8 00:13:26 1998 @@ -7,17 +7,22 @@ * * Copyright (C) 1995, 1996, 1997 by Ralf Baechle * - * $Id: signal.h,v 1.2 1997/09/07 05:27:50 ralf Exp $ + * $Id: signal.h,v 1.8 1998/05/01 01:36:11 ralf Exp $ */ #ifndef __ASM_MIPS_SIGNAL_H #define __ASM_MIPS_SIGNAL_H -#include +#include -typedef unsigned long sigset_t; +#define _NSIG 128 +#define _NSIG_BPW 32 +#define _NSIG_WORDS (_NSIG / _NSIG_BPW) -#define _NSIG 32 -#define NSIG _NSIG +typedef struct { + unsigned long sig[_NSIG_WORDS]; +} sigset_t; + +typedef unsigned long old_sigset_t; /* at least 32 bits */ #define SIGHUP 1 /* Hangup (POSIX). */ #define SIGINT 2 /* Interrupt (ANSI). */ @@ -54,34 +59,48 @@ #define SIGXCPU 30 /* CPU limit exceeded (4.2 BSD). */ #define SIGXFSZ 31 /* File size limit exceeded (4.2 BSD). */ +/* These should not be considered constants from userland. */ +#define SIGRTMIN 32 +#define SIGRTMAX (_NSIG-1) + /* - * sa_flags values: SA_STACK is not currently supported, but will allow the - * usage of signal stacks by using the (now obsolete) sa_restorer field in - * the sigaction structure as a stack pointer. This is now possible due to - * the changes in signal handling. LBT 010493. + * SA_FLAGS values: + * + * SA_ONSTACK is not currently supported, but will allow sigaltstack(2). * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) - * SA_SHIRQ flag is for shared interrupt support on PCI and EISA. + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. + * SA_RESETHAND clears the handler when the signal is delivered. + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. + * SA_NODEFER prevents the current signal from being masked in the handler. + * + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single + * Unix names RESETHAND and NODEFER respectively. */ -#define SA_STACK 0x1 -#define SA_ONSTACK SA_STACK -#define SA_RESTART 0x4 -#define SA_NOCLDSTOP 0x20000 -/* Non ABI signals */ -#define SA_INTERRUPT 0x01000000 -#define SA_NOMASK 0x02000000 -#define SA_ONESHOT 0x04000000 -#define SA_SHIRQ 0x08000000 +#define SA_STACK 0x00000001 +#define SA_RESETHAND 0x00000002 +#define SA_RESTART 0x00000004 +#define SA_SIGINFO 0x00000008 +#define SA_NODEFER 0x00000010 +#define SA_NOCLDWAIT 0x00010000 /* Not supported yet */ +#define SA_NOCLDSTOP 0x00020000 + +#define SA_NOMASK SA_NODEFER /* DANGER: was 0x02000000 */ +#define SA_ONESHOT SA_RESETHAND /* DANGER: was 0x04000000 */ #ifdef __KERNEL__ /* * These values of sa_flags are used only by the kernel as part of the * irq handling routines. * - * SA_INTERRUPT is also used by the irq handling routines. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the + * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_SHIRQ flag is for shared interrupt support on PCI and EISA. */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART +#define SA_INTERRUPT 0x01000000 /* interrupt handling */ +#define SA_SHIRQ 0x08000000 +#define SA_PROBE SA_ONESHOT +#define SA_SAMPLE_RANDOM SA_RESTART #endif /* __KERNEL__ */ #define SIG_BLOCK 1 /* for blocking signals */ @@ -102,17 +121,13 @@ unsigned int sa_flags; __sighandler_t sa_handler; sigset_t sa_mask; - unsigned int __pad0[3]; /* reserved, keep size constant */ + int sa_resv[2]; /* reserved */ +}; - /* Abi says here follows reserved int[2] */ - void (*sa_restorer)(void); -#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) - /* - * For 32 bit code we have to pad struct sigaction to get - * constant size for the ABI - */ - int __pad1[1]; /* reserved */ -#endif +/* XXX use sa_rev for storing ka_restorer */ +struct k_sigaction { + struct sigaction sa; + void (*ka_restorer)(void); }; #ifdef __KERNEL__ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/smp.h linux/include/asm-mips/smp.h --- v2.1.100/linux/include/asm-mips/smp.h Thu Jun 26 12:33:40 1997 +++ linux/include/asm-mips/smp.h Fri May 8 00:13:26 1998 @@ -1,6 +1,6 @@ #ifndef __ASM_MIPS_SMP_H #define __ASM_MIPS_SMP_H -/* We'll get here eventually.. */ +#define cpu_logical_map(cpu) (cpu) #endif /* __ASM_MIPS_SMP_H */ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/socket.h linux/include/asm-mips/socket.h --- v2.1.100/linux/include/asm-mips/socket.h Sun Dec 21 17:41:24 1997 +++ linux/include/asm-mips/socket.h Fri May 8 00:13:26 1998 @@ -1,8 +1,5 @@ /* - * $Id: socket.h,v 1.4 1997/12/06 20:32:40 ralf Exp $ - */ -/* - * $Id: socket.h,v 1.4 1997/12/06 23:55:49 ralf Exp $ + * $Id: socket.h,v 1.10 1998/05/01 01:36:12 ralf Exp $ */ #ifndef __ASM_MIPS_SOCKET_H #define __ASM_MIPS_SOCKET_H diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/softirq.h linux/include/asm-mips/softirq.h --- v2.1.100/linux/include/asm-mips/softirq.h Thu Jun 26 12:33:40 1997 +++ linux/include/asm-mips/softirq.h Fri May 8 00:13:26 1998 @@ -1,3 +1,14 @@ +/* + * include/asm-mips/softirq.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1997, 1998 by Ralf Baechle + * + * $Id: softirq.h,v 1.2 1998/05/01 01:36:13 ralf Exp $ + */ #ifndef __ASM_MIPS_SOFTIRQ_H #define __ASM_MIPS_SOFTIRQ_H @@ -7,6 +18,8 @@ */ extern atomic_t __mips_bh_counter; +extern unsigned int local_bh_count[NR_CPUS]; + #define get_active_bhs() (bh_mask & bh_active) static inline void clear_active_bhs(unsigned long x) @@ -20,7 +33,7 @@ "beqz\t%0,1b" :"=&r" (temp), "=m" (bh_active) - :"Ir" (x), + :"Ir" (~x), "m" (bh_active)); } @@ -58,36 +71,21 @@ bh_mask |= 1 << nr; } -/* - * start_bh_atomic/end_bh_atomic also nest - * naturally by using a counter - */ extern inline void start_bh_atomic(void) { -#ifdef __SMP__ - atomic_inc(&__mips_bh_counter); - synchronize_irq(); -#else - atomic_inc(&__mips_bh_counter); -#endif + local_bh_count[smp_processor_id()]++; + barrier(); } extern inline void end_bh_atomic(void) { - atomic_dec(&__mips_bh_counter); + barrier(); + local_bh_count[smp_processor_id()]--; } -#ifndef __SMP__ - /* These are for the irq's testing the lock */ -#define softirq_trylock() (atomic_read(&__mips_bh_counter) ? \ - 0 : \ - ((atomic_set(&__mips_bh_counter,1)),1)) -#define softirq_endlock() (atomic_set(&__mips_bh_counter, 0)) - -#else - -#error FIXME +#define softirq_trylock(cpu) (local_bh_count[cpu] ? 0 : (local_bh_count[cpu] = 1)) +#define softirq_endlock(cpu) (local_bh_count[cpu] = 0) +#define synchronize_bh() do { } while (0) -#endif /* __SMP__ */ #endif /* __ASM_MIPS_SOFTIRQ_H */ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/stackframe.h linux/include/asm-mips/stackframe.h --- v2.1.100/linux/include/asm-mips/stackframe.h Wed Dec 10 10:31:11 1997 +++ linux/include/asm-mips/stackframe.h Fri May 8 00:13:26 1998 @@ -2,6 +2,8 @@ * include/asm-mips/stackframe.h * * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Paul M. Antoine. + * + * $Id: stackframe.h,v 1.6 1998/05/04 09:19:00 ralf Exp $ */ #ifndef __ASM_MIPS_STACKFRAME_H #define __ASM_MIPS_STACKFRAME_H @@ -9,14 +11,61 @@ #include #include -#define SAVE_ALL \ +#define SAVE_AT \ + sw $1, PT_R1(sp) + +#define SAVE_TEMP \ + mfhi v1; \ + sw $8, PT_R8(sp); \ + sw $9, PT_R9(sp); \ + sw v1, PT_HI(sp); \ + mflo v1; \ + sw $10,PT_R10(sp); \ + sw $11, PT_R11(sp); \ + sw v1, PT_LO(sp); \ + sw $12, PT_R12(sp); \ + sw $13, PT_R13(sp); \ + sw $14, PT_R14(sp); \ + sw $15, PT_R15(sp); \ + sw $24, PT_R24(sp) + +#define SAVE_STATIC \ + sw $16, PT_R16(sp); \ + sw $17, PT_R17(sp); \ + sw $18, PT_R18(sp); \ + sw $19, PT_R19(sp); \ + sw $20, PT_R20(sp); \ + sw $21, PT_R21(sp); \ + sw $22, PT_R22(sp); \ + sw $23, PT_R23(sp); \ + sw $30, PT_R30(sp) + +#define __str2(x) #x +#define __str(x) __str2(x) + +#define save_static(frame) \ + __asm__ __volatile__( \ + "sw\t$16,"__str(PT_R16)"(%0)\n\t" \ + "sw\t$17,"__str(PT_R17)"(%0)\n\t" \ + "sw\t$18,"__str(PT_R18)"(%0)\n\t" \ + "sw\t$19,"__str(PT_R19)"(%0)\n\t" \ + "sw\t$20,"__str(PT_R20)"(%0)\n\t" \ + "sw\t$21,"__str(PT_R21)"(%0)\n\t" \ + "sw\t$22,"__str(PT_R22)"(%0)\n\t" \ + "sw\t$23,"__str(PT_R23)"(%0)\n\t" \ + "sw\t$30,"__str(PT_R30)"(%0)\n\t" \ + : /* No outputs */ \ + : "r" (frame)) + +#define SAVE_SOME \ .set push; \ .set reorder; \ mfc0 k0, CP0_STATUS; \ sll k0, 3; /* extract cu0 bit */ \ - .set pop; \ + .set noreorder; \ bltz k0, 8f; \ move k1, sp; \ + .set reorder; \ /* Called from user mode, new stack. */ \ lui k1, %hi(kernelsp); \ lw k1, %lo(kernelsp)(k1); \ @@ -24,53 +73,65 @@ move k0, sp; \ subu sp, k1, PT_SIZE; \ sw k0, PT_R29(sp); \ - sw $2, PT_R2(sp); \ - sw $1, PT_R1(sp); \ - sw $2, PT_OR2(sp); \ - sw $0, PT_R0(sp); \ - mfc0 v0, CP0_STATUS; \ sw $3, PT_R3(sp); \ - sw v0, PT_STATUS(sp); \ + sw $0, PT_R0(sp); \ + mfc0 v1, CP0_STATUS; \ + sw $2, PT_R2(sp); \ + sw v1, PT_STATUS(sp); \ sw $4, PT_R4(sp); \ - mfc0 v0, CP0_CAUSE; \ + mfc0 v1, CP0_CAUSE; \ sw $5, PT_R5(sp); \ - sw v0, PT_CAUSE(sp); \ + sw v1, PT_CAUSE(sp); \ sw $6, PT_R6(sp); \ - mfc0 v0, CP0_EPC; \ + mfc0 v1, CP0_EPC; \ sw $7, PT_R7(sp); \ - sw v0, PT_EPC(sp); \ - sw $7, PT_OR7(sp); \ - sw $8, PT_R8(sp); \ - mfhi v0; \ - sw $9, PT_R9(sp); \ - sw v0, PT_HI(sp); \ - sw $10,PT_R10(sp); \ - mflo v0; \ - sw $11, PT_R11(sp); \ - sw v0, PT_LO(sp); \ - sw $12, PT_R12(sp); \ - sw $13, PT_R13(sp); \ - sw $14, PT_R14(sp); \ - sw $15, PT_R15(sp); \ - sw $16, PT_R16(sp); \ - sw $17, PT_R17(sp); \ - sw $18, PT_R18(sp); \ - sw $19, PT_R19(sp); \ - sw $20, PT_R20(sp); \ - sw $21, PT_R21(sp); \ - sw $22, PT_R22(sp); \ - sw $23, PT_R23(sp); \ - sw $24, PT_R24(sp); \ + sw v1, PT_EPC(sp); \ sw $25, PT_R25(sp); \ sw $28, PT_R28(sp); \ - sw $30, PT_R30(sp); \ - sw $31, PT_R31(sp); + sw $31, PT_R31(sp); \ + ori $28, sp, 0x1fff; \ + xori $28, 0x1fff; \ + .set pop -/* - * Note that we restore the IE flags from stack. This means - * that a modified IE mask will be nullified. - */ -#define RESTORE_ALL \ +#define SAVE_ALL \ + SAVE_SOME; \ + SAVE_AT; \ + SAVE_TEMP; \ + SAVE_STATIC + +#define RESTORE_AT \ + lw $1, PT_R1(sp); \ + +#define RESTORE_SP \ + lw sp, PT_R29(sp) + +#define RESTORE_TEMP \ + lw $24, PT_LO(sp); \ + lw $8, PT_R8(sp); \ + lw $9, PT_R9(sp); \ + mtlo $24; \ + lw $24, PT_HI(sp); \ + lw $10,PT_R10(sp); \ + lw $11, PT_R11(sp); \ + mthi $24; \ + lw $12, PT_R12(sp); \ + lw $13, PT_R13(sp); \ + lw $14, PT_R14(sp); \ + lw $15, PT_R15(sp); \ + lw $24, PT_R24(sp) + +#define RESTORE_STATIC \ + lw $16, PT_R16(sp); \ + lw $17, PT_R17(sp); \ + lw $18, PT_R18(sp); \ + lw $19, PT_R19(sp); \ + lw $20, PT_R20(sp); \ + lw $21, PT_R21(sp); \ + lw $22, PT_R22(sp); \ + lw $23, PT_R23(sp); \ + lw $30, PT_R30(sp) + +#define RESTORE_SOME \ .set push; \ .set reorder; \ mfc0 t0, CP0_STATUS; \ @@ -79,42 +140,25 @@ xori t0, 0x1f; \ mtc0 t0, CP0_STATUS; \ lw v0, PT_STATUS(sp); \ - lw v1, PT_LO(sp); \ mtc0 v0, CP0_STATUS; \ - mtlo v1; \ - lw v0, PT_HI(sp); \ lw v1, PT_EPC(sp); \ - mthi v0; \ mtc0 v1, CP0_EPC; \ lw $31, PT_R31(sp); \ - lw $30, PT_R30(sp); \ lw $28, PT_R28(sp); \ lw $25, PT_R25(sp); \ - lw $24, PT_R24(sp); \ - lw $23, PT_R23(sp); \ - lw $22, PT_R22(sp); \ - lw $21, PT_R21(sp); \ - lw $20, PT_R20(sp); \ - lw $19, PT_R19(sp); \ - lw $18, PT_R18(sp); \ - lw $17, PT_R17(sp); \ - lw $16, PT_R16(sp); \ - lw $15, PT_R15(sp); \ - lw $14, PT_R14(sp); \ - lw $13, PT_R13(sp); \ - lw $12, PT_R12(sp); \ - lw $11, PT_R11(sp); \ - lw $10, PT_R10(sp); \ - lw $9, PT_R9(sp); \ - lw $8, PT_R8(sp); \ lw $7, PT_R7(sp); \ lw $6, PT_R6(sp); \ lw $5, PT_R5(sp); \ lw $4, PT_R4(sp); \ lw $3, PT_R3(sp); \ - lw $2, PT_R2(sp); \ - lw $1, PT_R1(sp); \ - lw sp, PT_R29(sp); + lw $2, PT_R2(sp) + +#define RESTORE_ALL \ + RESTORE_SOME; \ + RESTORE_AT; \ + RESTORE_TEMP; \ + RESTORE_STATIC; \ + RESTORE_SP /* * Move to kernel mode and disable interrupts. @@ -130,14 +174,21 @@ /* * Move to kernel mode and enable interrupts. * Set cp0 enable bit as sign that we're running on the kernel stack - * - * Note that the mtc0 will be effective on R4000 pipeline stage 7. This - * means that another three instructions will be executed with interrupts - * disabled. Arch/mips/mips3/r4xx0.S makes use of this fact. */ #define STI \ mfc0 t0,CP0_STATUS; \ li t1,ST0_CU0|0x1f; \ + or t0,t1; \ + xori t0,0x1e; \ + mtc0 t0,CP0_STATUS + +/* + * Just move to kernel mode and leave interrupts as they are. + * Set cp0 enable bit as sign that we're running on the kernel stack + */ +#define KMODE \ + mfc0 t0,CP0_STATUS; \ + li t1,ST0_CU0|0x1e; \ or t0,t1; \ xori t0,0x1e; \ mtc0 t0,CP0_STATUS diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/string.h linux/include/asm-mips/string.h --- v2.1.100/linux/include/asm-mips/string.h Wed Dec 10 10:31:11 1997 +++ linux/include/asm-mips/string.h Fri May 8 00:13:26 1998 @@ -7,7 +7,7 @@ * * Copyright (c) 1994, 1995, 1996, 1997 by Ralf Baechle * - * $Id: string.h,v 1.3 1997/08/11 04:11:53 ralf Exp $ + * $Id: string.h,v 1.7 1998/05/04 09:19:02 ralf Exp $ */ #ifndef __ASM_MIPS_STRING_H #define __ASM_MIPS_STRING_H @@ -128,29 +128,23 @@ extern void *memmove(void *__dest, __const__ void *__src, size_t __n); #define __HAVE_ARCH_BCOPY -extern char * bcopy(const char * src, char * dest, int count); +extern __inline__ char * bcopy(const char * src, char * dest, int count) +{ + memmove(dest, src, count); +} #define __HAVE_ARCH_MEMSCAN extern __inline__ void *memscan(void *__addr, int __c, size_t __size) { char *__end = (char *)__addr + __size; - if (!__size) - return __addr; - __asm__(".set\tnoreorder\n\t" - ".set\tnoat\n" - "1:\tlbu\t$1,(%0)\n\t" -#if _MIPS_ISA == _MIPS_ISA_MIPS1 - "nop\n\t" -#endif - "beq\t$1,%3,2f\n\t" + __asm__(".set\tnoat\n" + "1:\tbeq\t%0,%1,2f\n\t" "addiu\t%0,1\n\t" - "bne\t%0,%2,1b\n\t" - "nop\n\t" - ".set\tat\n\t" - ".set\treorder\n" - "2:" - : "=r" (__addr) + "lb\t$1,-1(%0)\n\t" + "bne\t$1,%4,1b\n" + "2:\t.set\tat" + : "=r" (__addr), "=r" (__end) : "0" (__addr), "1" (__end), "r" (__c) : "$1"); diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/system.h linux/include/asm-mips/system.h --- v2.1.100/linux/include/asm-mips/system.h Wed Dec 10 10:31:11 1997 +++ linux/include/asm-mips/system.h Fri May 8 00:13:26 1998 @@ -7,6 +7,8 @@ * * Copyright (C) 1994, 1995 by Ralf Baechle * Modified further for R[236]000 by Paul M. Antoine, 1996 + * + * $Id: system.h,v 1.7 1998/05/04 09:19:03 ralf Exp $ */ #ifndef __ASM_MIPS_SYSTEM_H #define __ASM_MIPS_SYSTEM_H @@ -17,18 +19,18 @@ extern __inline__ void __sti(void) { - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "mfc0\t$1,$12\n\t" - "ori\t$1,0x1f\n\t" - "xori\t$1,0x1e\n\t" - "mtc0\t$1,$12\n\t" - ".set\tat\n\t" - ".set\treorder" - : /* no outputs */ - : /* no inputs */ - : "$1", "memory"); + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "mfc0\t$1,$12\n\t" + "ori\t$1,0x1f\n\t" + "xori\t$1,0x1e\n\t" + "mtc0\t$1,$12\n\t" + ".set\tat\n\t" + ".set\treorder" + : /* no outputs */ + : /* no inputs */ + : "$1", "memory"); } /* @@ -41,21 +43,21 @@ extern __inline__ void __cli(void) { - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "mfc0\t$1,$12\n\t" - "ori\t$1,1\n\t" - "xori\t$1,1\n\t" - "mtc0\t$1,$12\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - ".set\tat\n\t" - ".set\treorder" - : /* no outputs */ - : /* no inputs */ - : "$1", "memory"); + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "mfc0\t$1,$12\n\t" + "ori\t$1,1\n\t" + "xori\t$1,1\n\t" + "mtc0\t$1,$12\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + ".set\tat\n\t" + ".set\treorder" + : /* no outputs */ + : /* no inputs */ + : "$1", "memory"); } #define __save_flags(x) \ @@ -87,16 +89,16 @@ extern void __inline__ __restore_flags(int flags) { - __asm__ __volatile__( - ".set\tnoreorder\n\t" - "mtc0\t%0,$12\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - ".set\treorder" - : /* no output */ - : "r" (flags) - : "memory"); + __asm__ __volatile__( + ".set\tnoreorder\n\t" + "mtc0\t%0,$12\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + ".set\treorder" + : /* no output */ + : "r" (flags) + : "memory"); } /* @@ -113,7 +115,7 @@ "# prevent instructions being moved around\n\t" \ ".set\tnoreorder\n\t" \ ".set\treorder" \ - : /* no output */ \ + : /* no output */ \ : /* no input */ \ : "memory") @@ -125,47 +127,12 @@ extern asmlinkage void (*resume)(void *tsk); #endif /* !defined (__LANGUAGE_ASSEMBLY__) */ -/* - * FIXME: resume() assumes current == prev - */ #define switch_to(prev,next) \ do { \ - prev->tss.current_ds = active_ds; \ - active_ds = next->tss.current_ds; \ - resume(next); \ + resume(next); \ } while(0) /* - * The 8 and 16 bit variants have to disable interrupts temporarily. - * Both are currently unused. - */ -extern __inline__ unsigned long xchg_u8(volatile char * m, unsigned long val) -{ - unsigned long flags, retval; - - save_flags(flags); - cli(); - retval = *m; - *m = val; - restore_flags(flags); - - return retval; -} - -extern __inline__ unsigned long xchg_u16(volatile short * m, unsigned long val) -{ - unsigned long flags, retval; - - save_flags(flags); - cli(); - retval = *m; - *m = val; - restore_flags(flags); - - return retval; -} - -/* * For 32 and 64 bit operands we can take advantage of ll and sc. * FIXME: This doesn't work for R3000 machines. */ @@ -186,8 +153,9 @@ ".set\tat\n\t" ".set\treorder" : "=r" (val), "=r" (m), "=r" (dummy) - : "1" (m), "2" (val)); -#else /* FIXME: Brain-dead approach, but then again, I AM hacking - PMA */ + : "1" (m), "2" (val) + : "memory"); +#else unsigned long flags, retval; save_flags(flags); @@ -218,7 +186,8 @@ ".set\tat\n\t" ".set\treorder" : "=r" (val), "=r" (m), "=r" (dummy) - : "1" (m), "2" (val)); + : "1" (m), "2" (val) + : "memory"); return val; } @@ -239,14 +208,12 @@ static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int size) { switch (size) { - case 1: - return xchg_u8(ptr, x); - case 2: - return xchg_u16(ptr, x); case 4: return xchg_u32(ptr, x); +#if defined(__mips64) case 8: return xchg_u64(ptr, x); +#endif } __xchg_called_with_bad_pointer(); return x; diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/termios.h linux/include/asm-mips/termios.h --- v2.1.100/linux/include/asm-mips/termios.h Wed Apr 8 19:36:29 1998 +++ linux/include/asm-mips/termios.h Fri May 8 00:13:26 1998 @@ -92,7 +92,6 @@ #define N_STRIP 4 #define N_AX25 5 #define N_X25 6 /* X.25 async */ -#define N_6PACK 7 #ifdef __KERNEL__ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/timex.h linux/include/asm-mips/timex.h --- v2.1.100/linux/include/asm-mips/timex.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/timex.h Thu May 7 23:53:35 1998 @@ -0,0 +1,15 @@ +/* + * linux/include/asm-mips/timex.h + * + * mips architecture timex specifications + */ +#ifndef _ASMmips_TIMEX_H +#define _ASMmips_TIMEX_H + +#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ +#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */ +#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \ + (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \ + << (SHIFT_SCALE-SHIFT_HZ)) / HZ) + +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/types.h linux/include/asm-mips/types.h --- v2.1.100/linux/include/asm-mips/types.h Fri Jan 30 11:28:09 1998 +++ linux/include/asm-mips/types.h Fri May 8 00:13:26 1998 @@ -60,15 +60,14 @@ typedef __signed__ long long s64; typedef unsigned long long u64; #endif -#define BITS_PER_LONG 32 #else typedef __signed__ long s64; typedef unsigned long u64; -#define BITS_PER_LONG 64 #endif +#define BITS_PER_LONG _MIPS_SZLONG #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/uaccess.h linux/include/asm-mips/uaccess.h --- v2.1.100/linux/include/asm-mips/uaccess.h Wed Dec 10 10:31:11 1997 +++ linux/include/asm-mips/uaccess.h Fri May 8 00:13:26 1998 @@ -7,7 +7,7 @@ * * Copyright (C) 1996, 1997 by Ralf Baechle * - * $Id: uaccess.h,v 1.5 1997/12/01 16:44:08 ralf Exp $ + * $Id: uaccess.h,v 1.9 1998/05/04 09:19:05 ralf Exp $ */ #ifndef __ASM_MIPS_UACCESS_H #define __ASM_MIPS_UACCESS_H @@ -26,21 +26,18 @@ * * For historical reasons, these macros are grossly misnamed. */ -#define KERNEL_DS 0 -#define USER_DS 1 +#define KERNEL_DS ((mm_segment_t) { 0UL }) +#define USER_DS ((mm_segment_t) { 1UL }) #define VERIFY_READ 0 #define VERIFY_WRITE 1 -extern int active_ds; +#define get_fs() (current->tss.current_ds) +#define get_ds() (KERNEL_DS) +#define set_fs(x) (current->tss.current_ds=(x)) -#define get_fs() active_ds -#define set_fs(x) (active_ds=(x)) +#define segment_eq(a,b) ((a).seg == (b).seg) -static inline unsigned long get_ds(void) -{ - return KERNEL_DS; -} /* * Is a address valid? This does a straighforward calculation rather @@ -53,8 +50,8 @@ * - OR we are in kernel mode. */ #define __access_ok(addr,size,mask) \ - (((__signed__ long)((mask)&(addr | size | (addr+size)))) >= 0) -#define __access_mask (-(long)get_fs()) + (((__signed__ long)((mask)&(addr | size | (addr+size)))) >= 0) +#define __access_mask (-(long)(get_fs().seg)) #define access_ok(type,addr,size) \ __access_ok(((unsigned long)(addr)),(size),__access_mask) @@ -108,24 +105,6 @@ struct __large_struct { unsigned long buf[100]; }; #define __m(x) (*(struct __large_struct *)(x)) -#define copy_to_user(to,from,n) __copy_tofrom_user((to),(from),(n),__cu_to) -#define copy_from_user(to,from,n) __copy_tofrom_user((to),(from),(n),__cu_from) - -extern size_t __copy_user(void *__to, const void *__from, size_t __n); - -#define __copy_tofrom_user(to,from,n,v) ({ \ - void * __cu_to; \ - const void * __cu_from; \ - long __cu_len; \ - \ - __cu_to = (to); \ - __cu_from = (from); \ - __cu_len = (n); \ - if (__access_ok(((unsigned long)(v)),__cu_len,__access_mask)) \ - __cu_len = __copy_user(__cu_to, __cu_from, __cu_len); \ - __cu_len; \ -}) - /* * Yuck. We need two variants, one for 64bit operation and one * for 32 bit mode and old iron. @@ -174,18 +153,15 @@ "move\t%0,$0\n" \ "2:\n\t" \ ".section\t.fixup,\"ax\"\n" \ - "3:\t.set\tnoat\n\t" \ - "la\t$1,2b\n\t" \ - "li\t%0,%3\n\t" \ - "jr\t$1\n\t" \ - ".set\tat\n\t" \ + "3:\tli\t%0,%3\n\t" \ + "move\t%1,$0\n\t" \ + "j\t2b\n\t" \ ".previous\n\t" \ ".section\t__ex_table,\"a\"\n\t" \ - STR(PTR)"\t1b,3b\n\t" \ + ".word\t1b,3b\n\t" \ ".previous" \ :"=r" (__gu_err), "=r" (__gu_val) \ - :"o" (__m(__gu_addr)), "i" (-EFAULT) \ - :"$1"); }) + :"o" (__m(__gu_addr)), "i" (-EFAULT)); }) /* * Get a long long 64 using 32 bit registers. @@ -197,20 +173,18 @@ "2:\tlw\t%D1,%3\n\t" \ "move\t%0,$0\n" \ "3:\t.section\t.fixup,\"ax\"\n" \ - "4:\t.set\tnoat\n\t" \ - "la\t$1,3b\n\t" \ - "li\t%0,%4\n\t" \ - "jr\t$1\n\t" \ - ".set\tat\n\t" \ + "4:\tli\t%0,%4\n\t" \ + "move\t%1,$0\n\t" \ + "move\t%D1,$0\n\t" \ + "j\t3b\n\t" \ ".previous\n\t" \ ".section\t__ex_table,\"a\"\n\t" \ - STR(PTR)"\t1b,4b\n\t" \ - STR(PTR)"\t2b,4b\n\t" \ + ".word\t1b,4b\n\t" \ + ".word\t2b,4b\n\t" \ ".previous" \ :"=r" (__gu_err), "=&r" (__gu_val) \ :"o" (__m(__gu_addr)), "o" (__m(__gu_addr + 4)), \ - "i" (-EFAULT) \ - :"$1"); }) + "i" (-EFAULT)); }) extern void __get_user_unknown(void); @@ -262,18 +236,14 @@ "move\t%0,$0\n" \ "2:\n\t" \ ".section\t.fixup,\"ax\"\n" \ - "3:\t.set\tnoat\n\t" \ - "la\t$1,2b\n\t" \ - "li\t%0,%3\n\t" \ - "jr\t$1\n\t" \ - ".set\tat\n\t" \ + "3:\tli\t%0,%3\n\t" \ + "j\t2b\n\t" \ ".previous\n\t" \ ".section\t__ex_table,\"a\"\n\t" \ - STR(PTR)"\t1b,3b\n\t" \ + ".word\t1b,3b\n\t" \ ".previous" \ :"=r" (__pu_err) \ - :"r" (__pu_val), "o" (__m(__pu_addr)), "i" (-EFAULT) \ - :"$1"); }) + :"r" (__pu_val), "o" (__m(__pu_addr)), "i" (-EFAULT)); }) #define __put_user_asm_ll32 \ ({ \ @@ -283,20 +253,16 @@ "move\t%0,$0\n" \ "3:\n\t" \ ".section\t.fixup,\"ax\"\n" \ - "4:\t.set\tnoat\n\t" \ - "la\t$1,3b\n\t" \ - "li\t%0,%4\n\t" \ - "jr\t$1\n\t" \ - ".set\tat\n\t" \ + "4:\tli\t%0,%4\n\t" \ + "j\t3b\n\t" \ ".previous\n\t" \ ".section\t__ex_table,\"a\"\n\t" \ - STR(PTR)"\t1b,4b\n\t" \ - STR(PTR)"\t2b,4b\n\t" \ + ".word\t1b,4b\n\t" \ + ".word\t2b,4b\n\t" \ ".previous" \ :"=r" (__pu_err) \ :"r" (__pu_val), "o" (__m(__pu_addr)), "o" (__m(__pu_addr + 4)), \ - "i" (-EFAULT) \ - :"$1"); }) + "i" (-EFAULT)); }) extern void __put_user_unknown(void); @@ -310,62 +276,195 @@ return retval; \ }) -#define __copy_to_user(to,from,n) \ - __copy_user((to),(from),(n)) +extern size_t __copy_user(void *__to, const void *__from, size_t __n); -#define __copy_from_user(to,from,n) \ - __copy_user((to),(from),(n)) +#define __copy_to_user(to,from,n) ({ \ + void *__cu_to; \ + const void *__cu_from; \ + long __cu_len; \ + \ + __cu_to = (to); \ + __cu_from = (from); \ + __cu_len = (n); \ + __asm__ __volatile__( \ + "move\t$4, %1\n\t" \ + "move\t$5, %2\n\t" \ + "move\t$6, %3\n\t" \ + "jal\t__copy_user\n\t" \ + "move\t%0, $6" \ + : "=r" (__cu_len) \ + : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \ + : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", "$15", \ + "$24", "$31","memory"); \ + __cu_len; \ +}) -#define __clear_user(addr,size) \ -({ \ - void *__cu_end; \ +#define __copy_from_user(to,from,n) ({ \ + void *__cu_to; \ + const void *__cu_from; \ + long __cu_len; \ + \ + __cu_to = (to); \ + __cu_from = (from); \ + __cu_len = (n); \ __asm__ __volatile__( \ - ".set\tnoreorder\n\t" \ - "1:\taddiu\t%0,1\n" \ - "bne\t%0,%1,1b\n\t" \ - "sb\t$0,-1(%0)\n\t" \ - "2:\t.set\treorder\n\t" \ - ".section\t.fixup,\"ax\"\n" \ - "3:\t.set\tnoat\n\t" \ - "subu\t%0,1\n\t" \ - "j\t2b\n\t" \ + "move\t$4, %1\n\t" \ + "move\t$5, %2\n\t" \ + "move\t$6, %3\n\t" \ + ".set\tnoat\n\t" \ + "addu\t$1, %2, %3\n\t" \ ".set\tat\n\t" \ - ".previous\n\t" \ - ".section\t__ex_table,\"a\"\n\t" \ - STR(PTR)"\t1b,3b\n\t" \ - ".previous" \ - :"=r" (addr), "=r" (__cu_end) \ - :"0" (addr), "1" (addr + size), "i" (-EFAULT) \ - :"$1","memory"); \ - size = __cu_end - (addr); \ + "jal\t__copy_user\n\t" \ + "move\t%0, $6" \ + : "=r" (__cu_len) \ + : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \ + : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", "$15", \ + "$24", "$31","memory"); \ + __cu_len; \ }) +#define copy_to_user(to,from,n) ({ \ + void *__cu_to; \ + const void *__cu_from; \ + long __cu_len; \ + \ + __cu_to = (to); \ + __cu_from = (from); \ + __cu_len = (n); \ + if (access_ok(VERIFY_WRITE, __cu_to, __cu_len)) \ + __asm__ __volatile__( \ + "move\t$4, %1\n\t" \ + "move\t$5, %2\n\t" \ + "move\t$6, %3\n\t" \ + "jal\t__copy_user\n\t" \ + "move\t%0, $6" \ + : "=r" (__cu_len) \ + : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \ + : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", \ + "$15", "$24", "$31","memory"); \ + __cu_len; \ +}) + +#define copy_from_user(to,from,n) ({ \ + void *__cu_to; \ + const void *__cu_from; \ + long __cu_len; \ + \ + __cu_to = (to); \ + __cu_from = (from); \ + __cu_len = (n); \ + if (access_ok(VERIFY_READ, __cu_from, __cu_len)) \ + __asm__ __volatile__( \ + "move\t$4, %1\n\t" \ + "move\t$5, %2\n\t" \ + "move\t$6, %3\n\t" \ + ".set\tnoat\n\t" \ + "addu\t$1, %2, %3\n\t" \ + ".set\tat\n\t" \ + "jal\t__copy_user\n\t" \ + "move\t%0, $6" \ + : "=r" (__cu_len) \ + : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \ + : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", \ + "$15", "$24", "$31","memory"); \ + __cu_len; \ +}) + +extern inline __kernel_size_t +__clear_user(void *addr, __kernel_size_t size) +{ + __kernel_size_t res; + + __asm__ __volatile__( + "move\t$4, %1\n\t" + "move\t$5, $0\n\t" + "move\t$6, %2\n\t" + "jal\t__bzero\n\t" + "move\t%0, $6" + : "=r" (res) + : "r" (addr), "r" (size) + : "$4", "$5", "$6", "$8", "$9", "$31"); + + return res; +} + #define clear_user(addr,n) ({ \ void * __cl_addr = (addr); \ unsigned long __cl_size = (n); \ if (__cl_size && __access_ok(VERIFY_WRITE, ((unsigned long)(__cl_addr)), __cl_size)) \ -__clear_user(__cl_addr, __cl_size); \ +__cl_size = __clear_user(__cl_addr, __cl_size); \ __cl_size; }) /* * Returns: -EFAULT if exception before terminator, N if the entire * buffer filled, else strlen. */ -extern long __strncpy_from_user(char *__to, const char *__from, long __to_len); +extern inline long +__strncpy_from_user(char *__to, const char *__from, long __len) +{ + long res; + + __asm__ __volatile__( + "move\t$4, %1\n\t" + "move\t$5, %2\n\t" + "move\t$6, %3\n\t" + "jal\t__strncpy_from_user_nocheck_asm\n\t" + "move\t%0, $2" + : "=r" (res) + : "r" (__to), "r" (__from), "r" (__len) + : "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory"); + + return res; +} + +extern inline long +strncpy_from_user(char *__to, const char *__from, long __len) +{ + long res; + + __asm__ __volatile__( + "move\t$4, %1\n\t" + "move\t$5, %2\n\t" + "move\t$6, %3\n\t" + "jal\t__strncpy_from_user_asm\n\t" + "move\t%0, $2" + : "=r" (res) + : "r" (__to), "r" (__from), "r" (__len) + : "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory"); + + return res; +} -#define strncpy_from_user(dest,src,count) ({ \ - const void * __sc_src = (src); \ - long __sc_res = -EFAULT; \ - if (access_ok(VERIFY_READ, __sc_src, 0)) { \ - __sc_res = __strncpy_from_user(dest, __sc_src, count); \ -} __sc_res; }) /* Returns: 0 if bad, string length+1 (memory size) of string if ok */ -extern long __strlen_user(const char *); +extern inline long __strlen_user(const char *s) +{ + long res; + + __asm__ __volatile__( + "move\t$4, %1\n\t" + "jal\t__strlen_user_nocheck_asm\n\t" + "move\t%0, $2" + : "=r" (res) + : "r" (s) + : "$2", "$4", "$8", "$31"); -extern inline long strlen_user(const char *str) + return res; +} + +extern inline long strlen_user(const char *s) { - return access_ok(VERIFY_READ,str,0) ? __strlen_user(str) : 0; + long res; + + __asm__ __volatile__( + "move\t$4, %1\n\t" + "jal\t__strlen_user_asm\n\t" + "move\t%0, $2" + : "=r" (res) + : "r" (s) + : "$2", "$4", "$8", "$31"); + + return res; } struct exception_table_entry diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/ucontext.h linux/include/asm-mips/ucontext.h --- v2.1.100/linux/include/asm-mips/ucontext.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/ucontext.h Fri May 8 00:13:26 1998 @@ -0,0 +1,12 @@ +#ifndef __ASM_MIPS_UCONTEXT_H +#define __ASM_MIPS_UCONTEXT_H + +struct ucontext { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + sigset_t uc_sigmask; /* mask last for extensibility */ +}; + +#endif /* __ASM_MIPS_UCONTEXT_H */ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/unistd.h linux/include/asm-mips/unistd.h --- v2.1.100/linux/include/asm-mips/unistd.h Wed Apr 8 19:36:29 1998 +++ linux/include/asm-mips/unistd.h Fri May 8 00:13:26 1998 @@ -1003,7 +1003,7 @@ #define __NR_time (__NR_Linux + 13) #define __NR_mknod (__NR_Linux + 14) #define __NR_chmod (__NR_Linux + 15) -#define __NR_chown (__NR_Linux + 16) +#define __NR_lchown (__NR_Linux + 16) #define __NR_break (__NR_Linux + 17) #define __NR_oldstat (__NR_Linux + 18) #define __NR_lseek (__NR_Linux + 19) @@ -1180,11 +1180,21 @@ #define __NR_setresgid (__NR_Linux + 190) #define __NR_getresgid (__NR_Linux + 191) #define __NR_prctl (__NR_Linux + 192) +#define __NR_rt_sigreturn (__NR_Linux + 193) +#define __NR_rt_sigaction (__NR_Linux + 194) +#define __NR_rt_sigprocmask (__NR_Linux + 195) +#define __NR_rt_sigpending (__NR_Linux + 196) +#define __NR_rt_sigtimedwait (__NR_Linux + 197) +#define __NR_rt_sigqueueinfo (__NR_Linux + 198) +#define __NR_rt_sigsuspend (__NR_Linux + 199) +#define __NR_pread (__NR_Linux + 200) +#define __NR_pwrite (__NR_Linux + 201) +#define __NR_chown (__NR_Linux + 202) /* * Offset of the last Linux flavoured syscall */ -#define __NR_Linux_syscalls 192 +#define __NR_Linux_syscalls 202 #ifndef __LANGUAGE_ASSEMBLY__ @@ -1197,7 +1207,8 @@ __asm__ volatile ("li\t$2,%2\n\t" \ "syscall" \ : "=r" (__res), "=r" (__err) \ - : "i" (__NR_##name)); \ + : "i" (__NR_##name) \ + : "$8","$9","$10","$11","$12","$13","$14","$15","$24"); \ if (__err == 0) \ return (type) __res; \ errno = __res; \ @@ -1218,7 +1229,7 @@ "syscall" \ : "=r" (__res), "=r" (__err) \ : "i" (__NR_##name),"r" ((long)(a)) \ - : "$4"); \ + : "$4","$8","$9","$10","$11","$12","$13","$14","$15","$24"); \ if (__err == 0) \ return (type) __res; \ errno = __res; \ @@ -1237,7 +1248,8 @@ : "=r" (__res), "=r" (__err) \ : "i" (__NR_##name),"r" ((long)(a)), \ "r" ((long)(b)) \ - : "$4","$5"); \ + : "$4","$5","$8","$9","$10","$11","$12","$13","$14","$15", \ + "$24"); \ if (__err == 0) \ return (type) __res; \ errno = __res; \ @@ -1258,7 +1270,8 @@ : "i" (__NR_##name),"r" ((long)(a)), \ "r" ((long)(b)), \ "r" ((long)(c)) \ - : "$4","$5","$6"); \ + : "$4","$5","$6","$8","$9","$10","$11","$12","$13","$14", \ + "$15","$24"); \ if (__err == 0) \ return (type) __res; \ errno = __res; \ @@ -1281,7 +1294,8 @@ "r" ((long)(b)), \ "r" ((long)(c)), \ "r" ((long)(d)) \ - : "$4","$5","$6"); \ + : "$4","$5","$6""$8","$9","$10","$11","$12","$13","$14", \ + "$15","$24"); \ if (__err == 0) \ return (type) __res; \ errno = __res; \ @@ -1309,7 +1323,8 @@ "r" ((long)(c)), \ "r" ((long)(d)), \ "m" ((long)(e)) \ - : "$2","$4","$5","$6","$7"); \ + : "$2","$4","$5","$6","$7","$8","$9","$10","$11","$12", \ + "$13","$14","$15","$24"); \ if (__err == 0) \ return (type) __res; \ errno = __res; \ @@ -1340,7 +1355,8 @@ "r" ((long)(d)), \ "m" ((long)(e)), \ "m" ((long)(f)) \ - : "$2","$3","$4","$5","$6","$7"); \ + : "$2","$3","$4","$5","$6","$7","$8","$9","$10","$11", \ + "$12","$13","$14","$15","$24"); \ if (__err == 0) \ return (type) __res; \ errno = __res; \ @@ -1374,7 +1390,8 @@ "m" ((long)(e)), \ "m" ((long)(f)), \ "m" ((long)(g)) \ - : "$2","$3","$4","$5","$6","$7"); \ + : "$2","$3","$4","$5","$6","$7","$8","$9","$10","$11", \ + "$12","$13","$14","$15","$24"); \ if (__err == 0) \ return (type) __res; \ errno = __res; \ @@ -1397,6 +1414,8 @@ */ #define __NR__exit __NR_exit static inline _syscall0(int,idle) +static inline _syscall0(int,fork) +static inline _syscall2(int,clone,unsigned long,flags,char *,esp) static inline _syscall0(int,pause) static inline _syscall1(int,setup,int,magic) static inline _syscall0(int,sync) @@ -1429,11 +1448,11 @@ __asm__ __volatile__( ".set\tnoreorder\n\t" - "move\t$8,$sp\n\t" + "move\t$6,$sp\n\t" "move\t$4,%5\n\t" "li\t$2,%1\n\t" "syscall\n\t" - "beq\t$8,$sp,1f\n\t" + "beq\t$6,$sp,1f\n\t" "subu\t$sp,32\n\t" /* delay slot */ "jalr\t%4\n\t" "move\t$4,%3\n\t" /* delay slot */ diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/watch.h linux/include/asm-mips/watch.h --- v2.1.100/linux/include/asm-mips/watch.h Wed Dec 10 10:31:11 1997 +++ linux/include/asm-mips/watch.h Fri May 8 00:13:26 1998 @@ -7,7 +7,7 @@ * * Copyright (C) 1996, 1997 by Ralf Baechle * - * $Id: watch.h,v 1.2 1997/09/19 08:37:44 ralf Exp $ + * $Id: watch.h,v 1.3 1998/05/01 01:36:18 ralf Exp $ */ #ifndef __ASM_WATCH_H #define __ASM_WATCH_H diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/xstat.h linux/include/asm-mips/xstat.h --- v2.1.100/linux/include/asm-mips/xstat.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/xstat.h Fri May 8 00:13:26 1998 @@ -0,0 +1,35 @@ +/* $Id: xstat.h,v 1.1 1998/02/06 12:51:41 jj Exp $ + * xstat.h: sys_xstat/xmknod architecture dependent stuff. + * + * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + */ + +extern __inline__ int cp_xstat(struct inode *inode, struct stat64 *s, unsigned long blocks, int blksize) +{ + struct stat64 tmp; + memset (&tmp, 0, sizeof(tmp)); + tmp.st_dev = (((__u64)MAJOR(inode->i_dev)) << 32) | MINOR(inode->i_dev); + tmp.st_ino = inode->i_ino; + tmp.st_mode = inode->i_mode; + tmp.st_nlink = inode->i_nlink; + tmp.st_uid = inode->i_uid; + tmp.st_gid = inode->i_gid; + tmp.st_rdev = (((__u64)MAJOR(inode->i_rdev)) << 32) | MINOR(inode->i_rdev); + tmp.st_size = inode->i_size; + tmp.st_atim.tv_sec = inode->i_atime; + tmp.st_mtim.tv_sec = inode->i_mtime; + tmp.st_ctim.tv_sec = inode->i_ctime; + tmp.st_blksize = blksize; + tmp.st_blocks = blocks; + /* Should I check if all fs names are < 16? All in the kernel tree are */ + if (inode->i_sb) + strcpy(tmp.st_fstype, inode->i_sb->s_type->name); + return copy_to_user(s,&tmp,sizeof(tmp)); +} + +extern __inline__ int get_user_new_dev_t(kdev_t *kdev, __new_dev_t *udev) { + __new_dev_t ndev; + if (copy_from_user (&ndev, udev, sizeof(__new_dev_t))) return -EFAULT; + *kdev = MKDEV((ndev >> 32), (__u32)ndev); + return 0; +} diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/byteorder.h linux/include/asm-ppc/byteorder.h --- v2.1.100/linux/include/asm-ppc/byteorder.h Fri Dec 5 12:47:08 1997 +++ linux/include/asm-ppc/byteorder.h Fri May 8 00:18:23 1998 @@ -31,6 +31,10 @@ asm volatile("stwbrx %0,0,%1" : : "r" (val), "r" (addr) : "memory"); } +/* alas, egcs sounds like it has a bug in this code that doesn't use the + inline asm correctly, and can cause file corruption. Until I hear that + it's fixed, I can live without the extra speed. I hope. */ +#if !(__GNUC__ >= 2 && __GNUC_MINOR__ >= 90) #if 0 # define __arch_swab16(x) ld_le16(&x) # define __arch_swab32(x) ld_le32(&x) @@ -59,6 +63,8 @@ #define __arch__swab32(x) ___arch__swab32(x) #define __arch__swab16(x) ___arch__swab16(x) #endif /* 0 */ + +#endif /* The same, but returns converted value from the location pointer by addr. */ #define __arch__swab16p(addr) ld_le16(addr) diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/cuda.h linux/include/asm-ppc/cuda.h --- v2.1.100/linux/include/asm-ppc/cuda.h Thu Apr 23 20:21:37 1998 +++ linux/include/asm-ppc/cuda.h Fri May 8 00:18:23 1998 @@ -37,6 +37,7 @@ #ifdef __KERNEL__ +void find_via_cuda(void); void via_cuda_init(void); int cuda_request(struct adb_request *req, void (*done)(struct adb_request *), int nbytes, ...); diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/init.h linux/include/asm-ppc/init.h --- v2.1.100/linux/include/asm-ppc/init.h Thu Jul 31 13:09:18 1997 +++ linux/include/asm-ppc/init.h Fri May 8 00:18:23 1998 @@ -1,23 +1,56 @@ #ifndef _PPC_INIT_H #define _PPC_INIT_H -#define __init -#define __initdata -#define __initfunc(x) x -/* +#if __GNUC__ > 2 || __GNUC_MINOR__ >= 90 /* egcs */ #define __init __attribute__ ((__section__ (".text.init"))) #define __initdata __attribute__ ((__section__ (".data.init"))) #define __initfunc(__arginit) \ __arginit __init; \ __arginit -*/ - /* For assembly routines */ -#define __INIT -#define __FINIT -#define __INITDATA -/* + +#define __pmac __attribute__ ((__section__ (".text.pmac"))) +#define __pmacdata __attribute__ ((__section__ (".data.pmac"))) +#define __pmacfunc(__argpmac) \ + __argpmac __pmac; \ + __argpmac + +#define __prep __attribute__ ((__section__ (".text.prep"))) +#define __prepdata __attribute__ ((__section__ (".data.prep"))) +#define __prepfunc(__argprep) \ + __argprep __prep; \ + __argprep + +/* this is actually just common chrp/pmac code, not OF code -- Cort */ +#define __openfirmware __attribute__ ((__section__ (".text.openfirmware"))) +#define __openfirmwaredata __attribute__ ((__section__ (".data.openfirmware"))) +#define __openfirmwarefunc(__argopenfirmware) \ + __argopenfirmware __openfirmware; \ + __argopenfirmware + #define __INIT .section ".text.init",#alloc,#execinstr #define __FINIT .previous #define __INITDATA .section ".data.init",#alloc,#write -*/ + +#else /* not egcs */ + +#define __init +#define __initdata +#define __initfunc(x) x + +#define __INIT +#define __FINIT +#define __INITDATA + +#define __pmac +#define __pmacdata +#define __pmacfunc(x) x + +#define __prep +#define __prepdata +#define __prepfunc(x) x + +#define __openfirmware +#define __openfirmwaredata +#define __openfirmwarefunc(x) x +#endif /* egcs */ #endif diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/irq.h linux/include/asm-ppc/irq.h --- v2.1.100/linux/include/asm-ppc/irq.h Sat Apr 25 18:13:12 1998 +++ linux/include/asm-ppc/irq.h Fri May 8 00:18:23 1998 @@ -3,6 +3,8 @@ #ifndef _ASM_IRQ_H #define _ASM_IRQ_H +#include /* for is_prep() */ + #ifndef CONFIG_8xx /* * this is the # irq's for all ppc arch's (pmac/chrp/prep) @@ -18,13 +20,19 @@ #define irq_to_openpic(n) ((n)-NUM_8259_INTERRUPTS) #define IRQ_8259_CASCADE NUM_8259_INTERRUPTS +extern void disable_irq(unsigned int); +extern void enable_irq(unsigned int); + +/* + * This gets called from serial.c, which is now used on + * powermacs as well as prep/chrp boxes. + * Prep and chrp both have cascaded 8259 PICs. + */ static __inline__ int irq_cannonicalize(int irq) { - return irq; + return (((is_prep || is_chrp) && irq == 2) ? 9 : irq); } -extern void disable_irq(unsigned int); -extern void enable_irq(unsigned int); #else /* CONFIG_8xx */ @@ -79,6 +87,12 @@ #define COMM_L_INT SIU_IRQ6 /* MBX Comm expansion connector pin */ #define STOP_ABRT_INT SIU_IRQ7 /* Stop/Abort header pin */ #endif /* CONFIG_MBX */ + +/* always the same on MBX -- Cort */ +static __inline__ int irq_cannonicalize(int irq) +{ + return irq; +} #endif /* CONFIG_8xx */ diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/linux_logo.h linux/include/asm-ppc/linux_logo.h --- v2.1.100/linux/include/asm-ppc/linux_logo.h Mon Jan 12 15:18:13 1998 +++ linux/include/asm-ppc/linux_logo.h Fri May 8 00:18:24 1998 @@ -20,1422 +20,9 @@ #define LINUX_LOGO_COLORS 221 #ifdef INCLUDE_LINUX_LOGO_DATA -unsigned char linux_logo_red[] __initdata = { - 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3, - 0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xE5, - 0xF1, 0xED, 0xEE, 0xE6, 0xC6, 0xDA, 0xDD, 0xE5, - 0xD9, 0xC6, 0xE3, 0xD0, 0xC6, 0xBA, 0xB0, 0xB6, - 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xB0, 0xAD, - 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x9D, - 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99, - 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, - 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x0D, 0x03, - 0x66, 0x44, 0x24, 0x08, 0xD6, 0xE6, 0xE9, 0xE6, - 0xE7, 0xCA, 0xDC, 0xDB, 0xD5, 0xD0, 0xC9, 0xE2, - 0xD5, 0xC6, 0xC4, 0xB3, 0xB2, 0xB9, 0xA9, 0x9A, - 0xB2, 0x9D, 0xE8, 0xEC, 0xF5, 0xF5, 0xF4, 0xF4, - 0xEC, 0xEE, 0xF0, 0xF5, 0xE0, 0xD6, 0xC5, 0xC2, - 0xD9, 0xD5, 0xD8, 0xD6, 0xF6, 0xF4, 0xED, 0xEC, - 0xEB, 0xF1, 0xF6, 0xF5, 0xF5, 0xEE, 0xEF, 0xEC, - 0xE7, 0xE3, 0xE6, 0xD6, 0xDD, 0xC3, 0xD6, 0xD7, - 0xCD, 0xCA, 0xC3, 0xAC, 0x95, 0x99, 0xB7, 0xA3, - 0x8B, 0x88, 0x95, 0x8A, 0x94, 0xD2, 0xCC, 0xC4, - 0xA8, 0x8E, 0x8F, 0xAE, 0xB8, 0xAC, 0xB6, 0xB4, - 0xAD, 0xA5, 0xA0, 0x9B, 0x8B, 0xA3, 0x94, 0x87, - 0x85, 0x89, 0x53, 0x80, 0x7D, 0x7C, 0x7A, 0x78, - 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62, - 0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46, - 0x42, 0x0F, 0x75, 0x78, 0x7D, 0x72, 0x5F, 0x6E, - 0x7A, 0x75, 0x6A, 0x58, 0x48, 0x4F, 0x00, 0x2B, - 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x3B, 0x11, - 0x1D, 0x14, 0x06, 0x02, 0x00 -}; -unsigned char linux_logo_green[] __initdata = { - 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3, - 0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xD3, - 0xDA, 0xD4, 0xD7, 0xCC, 0xC1, 0xCC, 0xCB, 0xC9, - 0xC5, 0xBC, 0xBC, 0xBB, 0xB7, 0xA5, 0xB0, 0xB6, - 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xAD, 0xAD, - 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x95, - 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99, - 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, - 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x08, 0x02, - 0x53, 0x2E, 0x19, 0x06, 0xC6, 0xC8, 0xCF, 0xBD, - 0xB3, 0xB6, 0xB4, 0xAB, 0xA5, 0xA3, 0x9B, 0xB6, - 0xA7, 0x99, 0x92, 0xA4, 0x9E, 0x9D, 0x98, 0x8C, - 0x8A, 0x86, 0xCD, 0xCC, 0xC9, 0xD7, 0xCA, 0xC4, - 0xCA, 0xC3, 0xC7, 0xC3, 0xC8, 0xB4, 0x91, 0x8E, - 0x8A, 0x82, 0x87, 0x85, 0xBD, 0xBF, 0xB6, 0xBC, - 0xAE, 0xB7, 0xBC, 0xB8, 0xBF, 0xB6, 0xBC, 0xB5, - 0xAB, 0xA6, 0xAD, 0xB2, 0xA5, 0x87, 0x9C, 0x96, - 0x95, 0x8E, 0x87, 0x8F, 0x86, 0x86, 0x8E, 0x80, - 0x7A, 0x70, 0x7B, 0x78, 0x78, 0x7F, 0x77, 0x6F, - 0x70, 0x76, 0x59, 0x77, 0x68, 0x64, 0x7B, 0x7C, - 0x75, 0x6D, 0x77, 0x69, 0x65, 0x5F, 0x5B, 0x54, - 0x4F, 0x5B, 0x39, 0x80, 0x7D, 0x7C, 0x7A, 0x78, - 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62, - 0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46, - 0x42, 0x0B, 0x69, 0x66, 0x64, 0x57, 0x4A, 0x4E, - 0x55, 0x4B, 0x46, 0x3B, 0x30, 0x33, 0x00, 0x2B, - 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x29, 0x0D, - 0x1D, 0x14, 0x06, 0x02, 0x00 -}; - -unsigned char linux_logo_blue[] __initdata = { - 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xEE, 0xE5, 0xDE, - 0xD7, 0xD3, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xB5, - 0xB0, 0xA6, 0xAC, 0x9B, 0xB5, 0xB5, 0xAE, 0x84, - 0x90, 0xA9, 0x81, 0x8D, 0x96, 0x86, 0xB0, 0xB6, - 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xA7, 0xAD, - 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA5, 0x87, - 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x9A, 0x9A, 0x99, - 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, - 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0xC8, 0xD7, - 0x9B, 0x8E, 0x8C, 0xB2, 0x77, 0x77, 0x4E, 0x77, - 0x69, 0x71, 0x78, 0x6B, 0x65, 0x66, 0x64, 0x59, - 0x5C, 0x5A, 0x48, 0x72, 0x7B, 0x6B, 0x67, 0x6E, - 0x42, 0x5B, 0x29, 0x36, 0x25, 0x10, 0x17, 0x14, - 0x19, 0x16, 0x13, 0x0E, 0x08, 0x2E, 0x2E, 0x3D, - 0x24, 0x24, 0x24, 0x24, 0x13, 0x12, 0x14, 0x14, - 0x0E, 0x08, 0x0D, 0x0F, 0x08, 0x0D, 0x0E, 0x08, - 0x08, 0x0C, 0x06, 0x06, 0x07, 0x16, 0x07, 0x0E, - 0x08, 0x0A, 0x07, 0x0D, 0x2D, 0x3E, 0x09, 0x4E, - 0x68, 0x52, 0x56, 0x58, 0x4B, 0x22, 0x20, 0x20, - 0x27, 0x39, 0x28, 0x19, 0x1E, 0x1E, 0x08, 0x06, - 0x07, 0x09, 0x08, 0x08, 0x05, 0x1D, 0x1F, 0x17, - 0x18, 0x06, 0x79, 0x80, 0x7D, 0x7C, 0x7A, 0x78, - 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x68, 0x65, 0x62, - 0x4B, 0x5B, 0x5F, 0x55, 0x56, 0x52, 0x4F, 0x46, - 0x42, 0x5A, 0x14, 0x23, 0x3D, 0x2B, 0x21, 0x14, - 0x06, 0x04, 0x03, 0x07, 0x09, 0x13, 0x2A, 0x3A, - 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x07, 0x09, - 0x1D, 0x14, 0x06, 0x02, 0x00 -}; - -unsigned char linux_logo[] __initdata = { - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57, - 0x58, 0x58, 0x59, 0x5C, 0x5D, 0x5F, 0x60, 0x61, - 0x62, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, - 0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5E, 0x5E, - 0x5E, 0x5D, 0x5D, 0x5C, 0x5D, 0x5B, 0x58, 0x58, - 0x58, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57, - 0x54, 0x56, 0x57, 0x67, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x67, 0x4C, - 0x4A, 0x49, 0x4A, 0x49, 0x4A, 0x49, 0x49, 0x4A, - 0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x50, 0x51, 0x52, - 0x54, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, 0x58, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x58, 0x56, 0x56, 0x53, - 0x52, 0x53, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, - 0x4B, 0x4B, 0x4B, 0x4A, 0x49, 0x4A, 0x4A, 0x49, - 0x49, 0x49, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4B, - 0x4C, 0x4D, 0x52, 0x54, 0x56, 0x55, 0x57, 0x58, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, - 0x50, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF4, 0xFB, - 0xFC, 0x67, 0x53, 0x50, 0x4D, 0x4C, 0x4C, 0x4C, - 0x4B, 0x4A, 0x4A, 0x48, 0x49, 0x48, 0x48, 0x49, - 0x49, 0x49, 0x4B, 0x4C, 0x50, 0x52, 0x53, 0x56, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x55, 0x54, 0x53, 0x51, 0x51, 0x50, 0x4C, 0x4D, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xD2, 0xD7, 0xF5, - 0xFC, 0xFC, 0x5D, 0x5D, 0x5C, 0x5C, 0x59, 0x58, - 0x58, 0x56, 0x52, 0x4C, 0x4B, 0x4A, 0x4A, 0x48, - 0x48, 0x48, 0x48, 0x48, 0x49, 0x4B, 0x4D, 0x51, - 0x54, 0x56, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x55, 0x54, - 0x53, 0x52, 0x51, 0x4D, 0x4D, 0x4D, 0x50, 0x50, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0x64, 0xD9, 0xF5, - 0xF9, 0xFC, 0xFC, 0x64, 0x63, 0x62, 0x61, 0x61, - 0x61, 0x60, 0x5E, 0x5B, 0x5A, 0x54, 0x52, 0x4C, - 0x4B, 0x49, 0x49, 0x47, 0x47, 0x48, 0x49, 0x4B, - 0x4C, 0x51, 0x53, 0x56, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x55, 0x53, 0x53, - 0x51, 0x50, 0x50, 0x50, 0x50, 0x50, 0x53, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xF5, 0xF9, 0xFC, - 0xFC, 0xFC, 0xFC, 0x64, 0x64, 0x64, 0x64, 0x64, - 0x64, 0x64, 0x64, 0x63, 0x61, 0x61, 0x5E, 0x59, - 0x55, 0x52, 0x4C, 0x4A, 0x49, 0x47, 0x48, 0x48, - 0x49, 0x4B, 0x4D, 0x51, 0x54, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x55, 0x54, 0x54, 0x52, 0x51, - 0x51, 0x51, 0x51, 0x51, 0x53, 0x54, 0x59, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF7, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0x60, 0x60, 0x60, 0x61, - 0x62, 0x63, 0x64, 0x64, 0x65, 0x65, 0x64, 0x63, - 0x61, 0x5E, 0x59, 0x56, 0x4D, 0x4B, 0x48, 0x48, - 0x48, 0x48, 0x49, 0x4B, 0x50, 0x53, 0x56, 0x56, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x56, 0x54, 0x53, 0x52, 0x51, 0x51, - 0x51, 0x52, 0x53, 0x55, 0x59, 0x5D, 0x5E, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0x4C, 0x4E, 0x51, 0x52, - 0x57, 0x5A, 0x5E, 0x60, 0x61, 0x63, 0x65, 0xCB, - 0x64, 0x64, 0x63, 0x60, 0x5C, 0x57, 0x50, 0x4B, - 0x48, 0x47, 0x47, 0x47, 0x4A, 0x4C, 0x52, 0x53, - 0x54, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x55, 0x54, 0x53, 0x53, 0x51, 0x52, 0x52, 0x53, - 0x53, 0x57, 0x5A, 0x5D, 0x5E, 0x5E, 0x60, 0xFC, - 0xFC, 0xFC, 0xFB, 0xF9, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFA, 0xF9, 0xF5, 0xFB, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x45, 0x3F, 0x3F, - 0x45, 0x48, 0x4B, 0x4D, 0x54, 0x5A, 0x5E, 0x61, - 0x63, 0xCB, 0xCB, 0x65, 0x64, 0x62, 0x5E, 0x57, - 0x50, 0x4B, 0x48, 0x47, 0x47, 0x48, 0x4B, 0x4D, - 0x51, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, - 0x54, 0x54, 0x53, 0x53, 0x52, 0x53, 0x54, 0x57, - 0x59, 0x5C, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0xFC, - 0xFC, 0xFA, 0xFC, 0xFA, 0xE0, 0xFC, 0xFC, 0xFC, - 0xFB, 0xFB, 0xFB, 0xDF, 0xD8, 0xF9, 0xE0, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x4C, 0x4A, 0x48, - 0x48, 0x3E, 0x44, 0x43, 0x3F, 0x47, 0x4B, 0x52, - 0x5A, 0x5E, 0x62, 0x64, 0xCB, 0xCB, 0x64, 0x61, - 0x5E, 0x57, 0x4D, 0x49, 0x47, 0x47, 0x48, 0x4A, - 0x4C, 0x52, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, - 0x54, 0x53, 0x53, 0x54, 0x54, 0x55, 0x58, 0x5B, - 0x5C, 0x5D, 0x5E, 0x5D, 0x5D, 0x5B, 0x58, 0xFC, - 0xFC, 0xD8, 0x4C, 0x60, 0xFC, 0xF5, 0xFC, 0xFC, - 0xFC, 0xF7, 0x5F, 0x48, 0x48, 0x2C, 0xF8, 0xF9, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x4A, 0x49, - 0x49, 0x49, 0x49, 0x47, 0x3E, 0x44, 0x42, 0x3F, - 0x3E, 0x4B, 0x54, 0x5C, 0x61, 0x64, 0xCB, 0xCB, - 0x64, 0x61, 0x5D, 0x53, 0x4B, 0x49, 0x47, 0x47, - 0x49, 0x4B, 0x50, 0x53, 0x56, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x55, 0x54, - 0x53, 0x53, 0x54, 0x56, 0x58, 0x5A, 0x5B, 0x5D, - 0x5D, 0x5D, 0x5C, 0x5A, 0x54, 0x52, 0x4C, 0xFC, - 0xF7, 0x4E, 0x2D, 0x29, 0x4E, 0xFC, 0xFC, 0xFC, - 0xFB, 0x5F, 0x26, 0x24, 0x20, 0x2E, 0x65, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x45, 0x3F, 0x45, - 0x3E, 0x47, 0x47, 0x47, 0x47, 0x47, 0x3E, 0x44, - 0x43, 0x40, 0x44, 0x49, 0x51, 0x5C, 0x62, 0x64, - 0xCB, 0xCB, 0x63, 0x60, 0x58, 0x50, 0x49, 0x48, - 0x48, 0x48, 0x4A, 0x4D, 0x53, 0x54, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54, - 0x54, 0x54, 0x55, 0x57, 0x59, 0x5B, 0x5C, 0x5D, - 0x5C, 0x5A, 0x54, 0x51, 0x4C, 0x4C, 0x54, 0xFC, - 0xF9, 0x23, 0xDB, 0x2D, 0x23, 0xFA, 0xFB, 0xFA, - 0xF5, 0x27, 0x21, 0xD9, 0xF8, 0x20, 0x21, 0xFB, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x5D, 0x58, 0x55, - 0x50, 0x48, 0x45, 0x43, 0x44, 0x44, 0x45, 0x45, - 0x3E, 0x3F, 0x43, 0x41, 0x3F, 0x48, 0x52, 0x5D, - 0x63, 0x65, 0xCB, 0x65, 0x61, 0x5D, 0x52, 0x4B, - 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54, - 0x54, 0x58, 0x5A, 0x59, 0x5B, 0x5B, 0x5B, 0x5A, - 0x55, 0x52, 0x4D, 0x4D, 0x55, 0x5B, 0x5D, 0xFC, - 0xF1, 0xF9, 0xFC, 0xD4, 0x21, 0xCC, 0xF7, 0xF8, - 0xF2, 0x21, 0xD9, 0xFC, 0xF2, 0xFB, 0x21, 0x45, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xD1, 0xD0, 0xCD, - 0xCC, 0x63, 0x5E, 0x58, 0x50, 0x47, 0x43, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x41, 0x3F, 0x4A, - 0x56, 0x5E, 0x64, 0xCB, 0x65, 0x63, 0x5E, 0x56, - 0x4C, 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, - 0x58, 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, - 0x57, 0x5A, 0x5A, 0x5C, 0x5B, 0x5A, 0x58, 0x54, - 0x51, 0x4C, 0x55, 0x5D, 0x5D, 0x5B, 0x54, 0xFC, - 0xF0, 0xF9, 0xFC, 0x65, 0x45, 0xCD, 0xFB, 0xFB, - 0xF8, 0x26, 0xFB, 0xFC, 0xFC, 0xFC, 0x21, 0x27, - 0xFB, 0xFC, 0xFC, 0xFC, 0xFB, 0xD7, 0x35, 0x34, - 0x2F, 0x35, 0x36, 0x2F, 0x2F, 0x36, 0x2F, 0x2F, - 0x36, 0x36, 0x35, 0x35, 0x43, 0x42, 0x41, 0x2E, - 0x45, 0x4C, 0x5B, 0x62, 0x65, 0xCC, 0x64, 0x60, - 0x58, 0x4D, 0x49, 0x47, 0x47, 0x49, 0x4C, 0x51, - 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x57, - 0x58, 0x5A, 0x5A, 0x5B, 0x5A, 0x55, 0x54, 0x51, - 0x53, 0x5C, 0x5D, 0x5D, 0x54, 0x4B, 0x4D, 0xFC, - 0xFC, 0x44, 0xFC, 0xFB, 0x7B, 0xAB, 0xA8, 0xAE, - 0xAB, 0x7F, 0xFC, 0xFC, 0xFB, 0xFB, 0x22, 0x2A, - 0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x2F, 0x30, 0x30, - 0x32, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x40, 0x41, - 0x2E, 0x40, 0x48, 0x56, 0x5F, 0x64, 0xCC, 0x65, - 0x61, 0x59, 0x50, 0x49, 0x47, 0x47, 0x49, 0x4C, - 0x5A, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, - 0x5A, 0x5A, 0x5A, 0x58, 0x55, 0x52, 0x51, 0x5A, - 0x5D, 0x5D, 0x57, 0x4C, 0x51, 0x54, 0x5D, 0xFC, - 0xFC, 0x2A, 0xFC, 0xC9, 0xAA, 0x8B, 0x8A, 0x8C, - 0xAB, 0x8C, 0x8C, 0xFB, 0xFB, 0x23, 0x20, 0xF1, - 0xFC, 0xFC, 0xFC, 0x3B, 0x33, 0x33, 0x32, 0x32, - 0x31, 0x32, 0x30, 0x32, 0x32, 0x32, 0x32, 0x30, - 0x31, 0x31, 0x31, 0x32, 0x33, 0x33, 0x3C, 0x41, - 0x41, 0x2E, 0x2D, 0x45, 0x4D, 0x5D, 0x63, 0xCC, - 0x65, 0x62, 0x5D, 0x51, 0x49, 0x47, 0x47, 0x4A, - 0x59, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, - 0x5A, 0x5A, 0x58, 0x55, 0x53, 0x53, 0x5C, 0x5E, - 0x59, 0x51, 0x4E, 0x54, 0x59, 0x5E, 0x62, 0xFC, - 0xFC, 0xDB, 0xAA, 0xA1, 0x95, 0x9C, 0x8C, 0x88, - 0x82, 0x83, 0x83, 0x8C, 0x88, 0xAE, 0xB9, 0xFB, - 0xFC, 0xFC, 0xFC, 0x3C, 0x3B, 0x72, 0x38, 0x33, - 0x33, 0x33, 0x31, 0x33, 0x31, 0x31, 0x31, 0x31, - 0x33, 0x33, 0x38, 0x33, 0x72, 0x3B, 0x44, 0x2E, - 0x41, 0x2E, 0x2E, 0x2D, 0x43, 0x4B, 0x5B, 0x63, - 0xCB, 0xCC, 0x63, 0x5D, 0x51, 0x49, 0x47, 0x49, - 0x5C, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, - 0x58, 0x58, 0x57, 0x53, 0x58, 0x5D, 0x5E, 0x55, - 0x51, 0x53, 0x58, 0x5E, 0x60, 0x63, 0x64, 0xFC, - 0xFC, 0xC0, 0xA6, 0x9D, 0x8B, 0x9C, 0x8C, 0x8C, - 0x6E, 0x83, 0x88, 0x8C, 0x8C, 0x8C, 0x83, 0xE8, - 0xFB, 0xFC, 0xFC, 0xFC, 0x33, 0x70, 0x70, 0x6F, - 0x6F, 0x6F, 0x6F, 0x3A, 0x6F, 0x6D, 0x6F, 0x6F, - 0x70, 0x6F, 0x6F, 0x70, 0x6F, 0x32, 0x5A, 0x48, - 0x41, 0x2D, 0x2D, 0x2D, 0x2C, 0x41, 0x49, 0x5A, - 0x62, 0xCB, 0xCB, 0x63, 0x5D, 0x50, 0x49, 0x4A, - 0x5C, 0x58, 0x58, 0x57, 0x55, 0x57, 0x57, 0x57, - 0x57, 0x55, 0x56, 0x59, 0x5E, 0x5C, 0x52, 0x53, - 0x55, 0x5B, 0x5E, 0x61, 0x63, 0x64, 0x63, 0xFC, - 0xE8, 0xBF, 0xA4, 0x99, 0x9C, 0x8C, 0x88, 0x88, - 0x6E, 0x88, 0x8C, 0x8C, 0x8C, 0xC2, 0xA6, 0xC4, - 0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x3A, 0x6F, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x37, 0x32, 0xCD, 0x5E, - 0x4C, 0x43, 0x2C, 0x2D, 0x2D, 0x2C, 0x2E, 0x47, - 0x57, 0x61, 0x65, 0xCC, 0x63, 0x5C, 0x50, 0x4D, - 0x5C, 0x5A, 0x57, 0x55, 0x55, 0x55, 0x58, 0x58, - 0x55, 0x54, 0x5B, 0x5E, 0x5D, 0x53, 0x53, 0x55, - 0x5D, 0x5E, 0x61, 0x61, 0x61, 0x61, 0x5E, 0xFC, - 0xEA, 0xBE, 0xA4, 0x9B, 0x8B, 0x85, 0x8C, 0x6E, - 0x8C, 0x8C, 0x8C, 0xA3, 0xAA, 0xA4, 0xA4, 0xE9, - 0xFB, 0xFC, 0xFC, 0xFC, 0x36, 0x6D, 0x70, 0x73, - 0x70, 0x70, 0x70, 0x73, 0x73, 0x73, 0x73, 0x70, - 0x70, 0x70, 0x73, 0x70, 0x37, 0x38, 0xD1, 0xCF, - 0x61, 0x4D, 0x44, 0x2C, 0x2D, 0x2E, 0x2C, 0x2E, - 0x3E, 0x56, 0x61, 0xCB, 0xCC, 0x62, 0x5B, 0x57, - 0x59, 0x58, 0x55, 0x54, 0x54, 0x55, 0x58, 0x58, - 0x58, 0x5B, 0x5E, 0x5B, 0x53, 0x55, 0x55, 0x5C, - 0x5E, 0x61, 0x61, 0x60, 0x5D, 0x5A, 0x4E, 0xFC, - 0xFC, 0xEA, 0xAA, 0x9C, 0x8A, 0x85, 0x82, 0x8C, - 0x8C, 0xA8, 0xEB, 0xA8, 0xA4, 0xA4, 0xAA, 0xFC, - 0xFC, 0xFC, 0x64, 0xFB, 0x39, 0x31, 0x72, 0x78, - 0x73, 0x78, 0x73, 0x74, 0x74, 0x74, 0x74, 0x73, - 0x78, 0x70, 0x73, 0x73, 0x33, 0xCC, 0xD2, 0xD1, - 0xCE, 0x62, 0x53, 0x3F, 0x2D, 0x2D, 0x41, 0x2C, - 0x2E, 0x3E, 0x56, 0x62, 0xCB, 0xCB, 0x61, 0x5D, - 0x54, 0x54, 0x54, 0x54, 0x56, 0x58, 0x58, 0x58, - 0x5C, 0x5E, 0x5A, 0x55, 0x58, 0x58, 0x5B, 0x5E, - 0x61, 0x5E, 0x5D, 0x5A, 0x52, 0x55, 0xCD, 0xFC, - 0xFC, 0x34, 0xC9, 0xE8, 0xA8, 0xAE, 0xC2, 0xE8, - 0xC3, 0xA6, 0xA7, 0xA6, 0xAA, 0x78, 0x2E, 0x42, - 0xFC, 0xFC, 0xD2, 0x64, 0xF8, 0x31, 0x72, 0x73, - 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x74, 0x73, - 0x73, 0x73, 0x73, 0x72, 0x33, 0x5C, 0x64, 0xD2, - 0xD1, 0xCF, 0x63, 0x54, 0x3F, 0x2C, 0x41, 0x41, - 0x2C, 0x2E, 0x47, 0x58, 0x63, 0xCB, 0xCB, 0x62, - 0x52, 0x53, 0x53, 0x56, 0x58, 0x58, 0x5A, 0x5B, - 0x5E, 0x5A, 0x57, 0x58, 0x58, 0x58, 0x60, 0x60, - 0x5D, 0x5A, 0x55, 0x4E, 0x64, 0xD2, 0xD1, 0xFC, - 0xFC, 0x41, 0x3E, 0xC1, 0xC0, 0xA3, 0xA6, 0xA7, - 0xA7, 0xA9, 0xAA, 0xB8, 0x2E, 0x3F, 0x2C, 0x41, - 0xFC, 0xFC, 0xF7, 0xCE, 0xCD, 0x36, 0x72, 0x73, - 0x74, 0x75, 0x78, 0x75, 0x75, 0x75, 0x74, 0x74, - 0x74, 0x74, 0x78, 0x72, 0x6D, 0x49, 0x59, 0xCB, - 0xD1, 0xD1, 0xD2, 0xCB, 0x56, 0x3F, 0x2C, 0x41, - 0x40, 0x2D, 0x2E, 0x49, 0x5B, 0x64, 0xCC, 0x64, - 0x51, 0x53, 0x53, 0x55, 0x58, 0x59, 0x5B, 0x5E, - 0x59, 0x58, 0x58, 0x58, 0x55, 0x60, 0x60, 0x5C, - 0x5A, 0x53, 0x5B, 0xD0, 0xD3, 0xD3, 0xD3, 0xFB, - 0xFC, 0x40, 0x41, 0x45, 0xC4, 0xC0, 0xBE, 0xBE, - 0xC1, 0xC0, 0x3C, 0x47, 0x2E, 0x21, 0x22, 0x20, - 0x65, 0xFC, 0xFC, 0xFC, 0xFC, 0x6D, 0x72, 0x75, - 0x78, 0x76, 0x75, 0x79, 0x76, 0x76, 0x76, 0x76, - 0x75, 0x75, 0x75, 0x72, 0x6D, 0x2E, 0x48, 0x5D, - 0xCE, 0xD1, 0xD4, 0xD3, 0xCB, 0x56, 0x43, 0x2C, - 0x42, 0x43, 0x2E, 0x2E, 0x4A, 0x5D, 0x64, 0x64, - 0x50, 0x52, 0x56, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, - 0x5A, 0x58, 0x58, 0x55, 0x61, 0x60, 0x58, 0x58, - 0x4E, 0x61, 0xD1, 0xD4, 0xD4, 0xD1, 0xEE, 0xFC, - 0xFC, 0x2B, 0x29, 0x2E, 0x3F, 0xB0, 0xAD, 0x81, - 0x46, 0x2D, 0x46, 0x2C, 0x24, 0x22, 0x22, 0x23, - 0x25, 0xFC, 0xFC, 0xFC, 0xFC, 0x6E, 0x73, 0x76, - 0x76, 0x79, 0x79, 0x79, 0x76, 0x76, 0x79, 0x76, - 0x79, 0x79, 0x79, 0x74, 0x3F, 0x41, 0x2C, 0x48, - 0x5F, 0xCF, 0xD5, 0xD7, 0xD6, 0xCD, 0x57, 0x40, - 0x2E, 0x3F, 0x44, 0x2E, 0x41, 0x4C, 0x60, 0x61, - 0x51, 0x53, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, 0x5C, - 0x58, 0x57, 0x54, 0x5F, 0x5E, 0x55, 0x55, 0x52, - 0x64, 0xD4, 0xD5, 0xD4, 0xD1, 0x5D, 0xFA, 0xFB, - 0xF4, 0x21, 0x24, 0x41, 0x40, 0x44, 0x2E, 0x2E, - 0x42, 0x41, 0x2A, 0x24, 0x22, 0x22, 0x22, 0x22, - 0x23, 0xD9, 0xFC, 0xFC, 0xFC, 0xFC, 0xE5, 0xB8, - 0x8F, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, - 0x8F, 0x8F, 0xB8, 0xE5, 0x3F, 0x3E, 0x43, 0x2C, - 0x48, 0x61, 0xD1, 0xD7, 0xD9, 0xD7, 0xD0, 0x57, - 0x41, 0x2E, 0x3E, 0x44, 0x2D, 0x40, 0x52, 0x5D, - 0x53, 0x55, 0x59, 0x5D, 0x5E, 0x5E, 0x5D, 0x5A, - 0x57, 0x53, 0x5E, 0x5E, 0x54, 0x53, 0x54, 0x65, - 0xD5, 0xD6, 0xD4, 0xCE, 0x53, 0xFB, 0xF9, 0xFC, - 0x24, 0x22, 0x23, 0x23, 0x41, 0x42, 0x2E, 0x40, - 0x2B, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x23, 0x23, 0xFC, 0xFC, 0xFC, 0xFC, 0xE7, 0xBD, - 0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0xB5, 0xC6, 0xEB, 0x2D, 0x47, 0x4A, 0x47, - 0x2C, 0x3E, 0x61, 0xD4, 0xDC, 0xDC, 0xDA, 0xCF, - 0x54, 0x41, 0x41, 0x3E, 0x45, 0x2C, 0x3F, 0x4A, - 0x58, 0x5A, 0x5C, 0x5F, 0x60, 0x5E, 0x5D, 0x57, - 0x51, 0x5D, 0x5D, 0x51, 0x53, 0x53, 0xCB, 0xD5, - 0xD6, 0xD5, 0x63, 0x55, 0xFC, 0xFC, 0xFC, 0x2C, - 0x23, 0x22, 0x23, 0x22, 0x20, 0x2D, 0x2C, 0x26, - 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x21, 0xF0, 0xFC, 0xFC, 0xFC, 0xE2, 0xC6, - 0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0xC7, 0xE3, 0x3E, 0x2E, 0x49, 0x52, - 0x4C, 0x41, 0x44, 0x62, 0xD6, 0xDE, 0xDE, 0xD9, - 0xD0, 0x51, 0x2E, 0x40, 0x47, 0x44, 0x2C, 0x42, - 0x5D, 0x5D, 0x5F, 0x60, 0x60, 0x5D, 0x57, 0x51, - 0x58, 0x5D, 0x4E, 0x52, 0x55, 0x64, 0xD5, 0xD6, - 0xD4, 0x61, 0x59, 0x6B, 0xFC, 0xFC, 0xFC, 0x21, - 0x23, 0x22, 0x23, 0x22, 0x23, 0x21, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x21, 0x24, 0xFC, 0xFC, 0xFC, 0xE2, 0xC7, - 0xB5, 0x90, 0x93, 0x93, 0x93, 0x90, 0x93, 0x93, - 0x90, 0xB5, 0xC8, 0xE4, 0x5F, 0x45, 0x2E, 0x4D, - 0x57, 0x57, 0x44, 0x43, 0x63, 0xDA, 0xDF, 0xDF, - 0xD9, 0xCE, 0x4C, 0x2C, 0x3F, 0x3E, 0x40, 0x40, - 0x60, 0x5E, 0x61, 0x61, 0x5E, 0x5B, 0x53, 0x52, - 0x5C, 0x52, 0x52, 0x55, 0x61, 0xD4, 0xD5, 0xD1, - 0x5E, 0x5B, 0x5C, 0xFB, 0xFC, 0xFC, 0x2A, 0x21, - 0x23, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0xFB, 0xFC, 0xFC, 0xB3, 0xC8, - 0xB5, 0x90, 0x92, 0xB5, 0x93, 0x93, 0xB5, 0x93, - 0x92, 0xB5, 0xC8, 0xB9, 0xD0, 0x5E, 0x44, 0x40, - 0x52, 0x58, 0x57, 0x48, 0x40, 0x63, 0xD9, 0xE0, - 0xE0, 0xD9, 0xCB, 0x49, 0x2D, 0x3F, 0x45, 0x3F, - 0x63, 0x61, 0x62, 0x60, 0x5E, 0x55, 0x4D, 0x59, - 0x53, 0x4E, 0x54, 0x5D, 0xD2, 0xD4, 0xD2, 0x5E, - 0x5C, 0x5D, 0xFC, 0xFC, 0xFC, 0xF8, 0x29, 0x23, - 0x23, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x23, 0x22, 0x22, 0x23, 0x23, 0x23, 0x22, 0x22, - 0x22, 0x22, 0x22, 0xF0, 0xFC, 0xFC, 0xB3, 0xC7, - 0xB5, 0x93, 0xB5, 0x93, 0x93, 0x91, 0x93, 0x93, - 0x91, 0xB5, 0xC7, 0xAD, 0xD6, 0xD2, 0x5E, 0x3F, - 0x3F, 0x57, 0x57, 0x58, 0x4A, 0x41, 0x64, 0xDC, - 0xF1, 0xDF, 0xDA, 0x61, 0x45, 0x2E, 0x43, 0x47, - 0xCB, 0x63, 0x62, 0x5F, 0x58, 0x51, 0x53, 0x54, - 0x4C, 0x52, 0x5C, 0xCD, 0xD3, 0xD2, 0x60, 0x5D, - 0x5D, 0xFB, 0xFC, 0xFC, 0xFC, 0xDB, 0x49, 0x24, - 0x21, 0x23, 0x23, 0x22, 0x26, 0x26, 0x2A, 0x24, - 0x22, 0x23, 0x22, 0x21, 0x24, 0x26, 0x26, 0x2A, - 0x29, 0x2B, 0x24, 0x25, 0xFC, 0xFC, 0xB3, 0xC5, - 0x91, 0x91, 0x92, 0x91, 0x92, 0x92, 0x93, 0x93, - 0x91, 0x93, 0xC6, 0xAD, 0xDC, 0xD9, 0xD4, 0x60, - 0x43, 0x45, 0x58, 0x58, 0x57, 0x4B, 0x43, 0xCC, - 0xDD, 0xF1, 0xD8, 0xD5, 0x5D, 0x43, 0x41, 0x47, - 0xCD, 0x63, 0x62, 0x5D, 0x54, 0x4C, 0x55, 0x4B, - 0x51, 0x58, 0x62, 0xD0, 0xD0, 0x62, 0x5D, 0x5D, - 0x67, 0xFC, 0xFC, 0xFC, 0xFC, 0x58, 0x4E, 0x28, - 0x2A, 0x20, 0x23, 0x22, 0x23, 0x2A, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x23, 0x25, 0x2A, 0x2E, 0x2D, - 0x2E, 0x2E, 0x2E, 0x23, 0xFA, 0xFC, 0xB2, 0xBD, - 0xB5, 0x90, 0x91, 0x93, 0x92, 0x90, 0x91, 0x93, - 0x92, 0x91, 0xBD, 0xAD, 0xDE, 0xE0, 0xD8, 0xD7, - 0x61, 0x40, 0x48, 0x58, 0x58, 0x58, 0x48, 0x44, - 0xCF, 0xDE, 0xE0, 0xDD, 0xD0, 0x52, 0x41, 0x45, - 0xCD, 0x63, 0x61, 0x58, 0x4D, 0x51, 0x4C, 0x4B, - 0x54, 0x5D, 0xCC, 0xCE, 0x63, 0x61, 0x5D, 0x5D, - 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x27, 0x21, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x24, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x20, - 0x27, 0x2B, 0x41, 0x2B, 0x23, 0xFC, 0xB2, 0xB6, - 0x93, 0x90, 0x92, 0xB5, 0x92, 0x90, 0xB5, 0x90, - 0x92, 0x93, 0xBC, 0xAD, 0xDC, 0xF1, 0xF3, 0xF0, - 0xD9, 0x61, 0x41, 0x4A, 0x58, 0x57, 0x57, 0x44, - 0x49, 0xD2, 0xDD, 0xD8, 0xDA, 0x63, 0x4A, 0x45, - 0xCC, 0x63, 0x5E, 0x52, 0x4B, 0x4C, 0x49, 0x51, - 0x5C, 0x61, 0xCD, 0x65, 0x63, 0x5E, 0x4E, 0xCF, - 0xFB, 0xFB, 0xF0, 0xFC, 0xD2, 0x2A, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x26, 0x41, 0x27, 0xF9, 0x81, 0xB7, - 0xB5, 0x91, 0x92, 0xB5, 0x91, 0xB5, 0x93, 0xB5, - 0x93, 0xB6, 0xB7, 0xB9, 0xCB, 0xD8, 0xF3, 0xF2, - 0xF2, 0xDB, 0x61, 0x2D, 0x51, 0x58, 0x57, 0x58, - 0x41, 0x51, 0xD4, 0xDB, 0xDC, 0xD1, 0x5B, 0x4C, - 0xCB, 0x62, 0x59, 0x4C, 0x4A, 0x49, 0x4B, 0x55, - 0x60, 0x64, 0xCC, 0x64, 0x5E, 0x55, 0x60, 0xE1, - 0xFB, 0xF8, 0xFC, 0xFC, 0x21, 0x22, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x21, 0x24, 0x2D, 0x21, 0xB4, 0xBB, - 0xB6, 0xB5, 0xB6, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6, - 0xB6, 0xB6, 0xBB, 0xB9, 0x45, 0xCB, 0xDF, 0xF3, - 0xF3, 0xF3, 0xDB, 0x5E, 0x2C, 0x51, 0x58, 0x58, - 0x52, 0x2D, 0x5C, 0xD4, 0xD9, 0xD5, 0x63, 0x58, - 0x64, 0x60, 0x53, 0x49, 0x4A, 0x49, 0x52, 0x5C, - 0x63, 0xCD, 0xCD, 0x63, 0x5C, 0x4E, 0x65, 0xFC, - 0xFC, 0xF5, 0xFC, 0xD2, 0x23, 0x22, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x21, 0x22, 0x25, 0x29, 0xB3, 0xC7, - 0xB5, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, - 0xB6, 0xB5, 0xC7, 0xAD, 0x57, 0x3F, 0xCB, 0xF0, - 0xF3, 0xF3, 0xF2, 0xD9, 0x58, 0x41, 0x4C, 0x58, - 0x57, 0x47, 0x42, 0x62, 0xD4, 0xD4, 0xCC, 0x60, - 0x63, 0x5D, 0x50, 0x47, 0x48, 0x4B, 0x58, 0x60, - 0xCC, 0xCE, 0xCD, 0x60, 0x53, 0x5C, 0x62, 0xFB, - 0xF9, 0xFC, 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x23, 0x23, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0x81, 0xC7, - 0xB7, 0xB7, 0xBC, 0xB7, 0xBC, 0xBC, 0xBC, 0xB7, - 0xB7, 0xB7, 0xC8, 0x80, 0x58, 0x57, 0x40, 0xCE, - 0xF3, 0xF2, 0xF2, 0xF0, 0xD5, 0x4C, 0x3F, 0x4B, - 0x52, 0x50, 0x2D, 0x4B, 0x64, 0xD2, 0xCC, 0x61, - 0x60, 0x58, 0x4A, 0x47, 0x47, 0x4C, 0x59, 0x64, - 0xD0, 0xD0, 0x64, 0x59, 0x49, 0x5D, 0xFB, 0xFC, - 0xD9, 0xFC, 0xD6, 0x23, 0x22, 0x22, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x23, 0x21, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0xB4, 0xC8, - 0xBD, 0xB7, 0xBD, 0xBC, 0xBD, 0xC5, 0xBC, 0xC5, - 0xBC, 0xBD, 0xC7, 0xAC, 0x58, 0x57, 0x58, 0x2C, - 0xD1, 0xF0, 0xF3, 0xF3, 0xE0, 0xCD, 0x45, 0x3E, - 0x48, 0x4B, 0x3F, 0x41, 0x56, 0x64, 0x65, 0x62, - 0x5D, 0x52, 0x47, 0x48, 0x48, 0x53, 0x60, 0xCC, - 0xD2, 0xD0, 0x63, 0x52, 0x4E, 0x53, 0xFB, 0xFB, - 0xFC, 0xFC, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x23, 0x20, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0xB4, 0xC7, - 0xC5, 0xBC, 0xC5, 0xBD, 0xC5, 0xC5, 0xBD, 0xC5, - 0xBC, 0xC6, 0xC7, 0xB9, 0x58, 0x57, 0x58, 0x57, - 0x2D, 0xD4, 0xF1, 0xF2, 0xF0, 0xD9, 0x5D, 0x47, - 0x48, 0x3F, 0x42, 0x2C, 0x48, 0x5C, 0x5F, 0x60, - 0x58, 0x50, 0x47, 0x4A, 0x49, 0x55, 0x63, 0xD0, - 0xD2, 0xCD, 0x5D, 0x49, 0x4E, 0xE1, 0xFC, 0xF0, - 0xFC, 0xF8, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x20, 0x21, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, - 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, 0xC4, 0xC8, - 0xBD, 0xBD, 0xC6, 0xBD, 0xC6, 0xC6, 0xC5, 0xC6, - 0xBD, 0xC6, 0xC7, 0xE4, 0x54, 0x57, 0x58, 0x57, - 0x57, 0x43, 0xD7, 0xE0, 0xF1, 0xD8, 0xCD, 0x4B, - 0x4A, 0x47, 0x42, 0x2C, 0x3F, 0x4D, 0x58, 0x5C, - 0x52, 0x4B, 0x48, 0x4B, 0x4A, 0x58, 0xCB, 0xD3, - 0xD2, 0xCD, 0x58, 0x47, 0x4A, 0xFC, 0xFC, 0xFB, - 0xFC, 0x2B, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x26, 0x21, 0x21, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0xE5, 0xC8, - 0xBA, 0xC5, 0xC6, 0xC6, 0xC6, 0xC7, 0xC6, 0xC7, - 0xC5, 0xC6, 0xC8, 0xE5, 0x2E, 0x54, 0x58, 0x57, - 0x57, 0x4C, 0x4D, 0xDA, 0xD8, 0xD8, 0xD4, 0x5C, - 0x4B, 0x4B, 0x3F, 0x42, 0x44, 0x4A, 0x51, 0x58, - 0x4B, 0x48, 0x4B, 0x51, 0x4D, 0x5F, 0xD0, 0xD1, - 0xD0, 0x64, 0x51, 0x44, 0x6B, 0xFC, 0xFB, 0xFC, - 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x26, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0xE5, 0xED, - 0xE7, 0xBA, 0xC8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7, - 0xC7, 0xE5, 0xED, 0xE6, 0x61, 0x41, 0x52, 0x58, - 0x58, 0x57, 0x45, 0x5E, 0xD7, 0xDD, 0xD5, 0x60, - 0x4B, 0x4C, 0x48, 0x4D, 0x4D, 0x50, 0x4D, 0x56, - 0x4A, 0x3E, 0x53, 0x53, 0x52, 0x63, 0xD3, 0xD0, - 0xCE, 0x60, 0x4A, 0x45, 0xFC, 0xFC, 0xF7, 0xFC, - 0xFC, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x21, 0x2A, 0x20, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x21, 0x23, 0xEB, 0xF6, - 0xF6, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, - 0xF6, 0xF6, 0xF6, 0xE6, 0xDB, 0x58, 0x45, 0x4B, - 0x58, 0x57, 0x4D, 0x4B, 0x64, 0xD4, 0xD0, 0x5C, - 0x48, 0x51, 0x4C, 0x5D, 0x5E, 0x5C, 0x56, 0x59, - 0x3E, 0x4A, 0x58, 0x54, 0x52, 0x65, 0xD3, 0xD0, - 0xCF, 0x5D, 0x48, 0xFC, 0xFC, 0xFC, 0xFA, 0xFC, - 0xFC, 0x21, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x21, 0x2A, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x21, 0x4F, 0xE6, 0xC6, - 0xC6, 0xBD, 0xC6, 0xBD, 0xBD, 0xBD, 0xBD, 0xC6, - 0xC5, 0xBA, 0xC7, 0xE6, 0xF2, 0xD4, 0x49, 0x4B, - 0x3E, 0x4D, 0x52, 0x3E, 0x52, 0x63, 0x64, 0x56, - 0x48, 0x54, 0x4D, 0x61, 0xCC, 0xCC, 0x60, 0x60, - 0x47, 0x4D, 0x5C, 0x53, 0x58, 0xCF, 0xD1, 0xCF, - 0xD0, 0x59, 0x45, 0xFC, 0xFC, 0xFC, 0xEF, 0xF9, - 0xFC, 0x21, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x23, 0x4F, 0xE4, 0xB9, - 0xAF, 0x80, 0x80, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F, - 0x80, 0xB4, 0xB9, 0xE4, 0x7F, 0xDE, 0x61, 0x52, - 0x54, 0x48, 0x3F, 0x43, 0x4D, 0x56, 0x59, 0x4B, - 0x3E, 0x58, 0x53, 0x61, 0xD3, 0xD4, 0xCF, 0xCD, - 0x4C, 0x58, 0x5F, 0x53, 0x5E, 0xD3, 0xD0, 0xCE, - 0xCE, 0x52, 0x3F, 0xFC, 0xFC, 0xFC, 0xF7, 0x65, - 0xFA, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x21, 0x2A, 0x23, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x21, 0xB1, 0xE4, 0xE6, - 0x7C, 0xB1, 0x7C, 0xB1, 0xB2, 0xB2, 0xB3, 0x3D, - 0xB3, 0x3C, 0xE5, 0xB3, 0xB0, 0xF1, 0xD0, 0x58, - 0x5D, 0x4D, 0x40, 0x41, 0x48, 0x51, 0x4C, 0x3F, - 0x3F, 0x4D, 0x5A, 0x5A, 0xD5, 0xD9, 0xD7, 0xD4, - 0x57, 0x5E, 0x61, 0x4C, 0x63, 0xD4, 0xCF, 0xCE, - 0xCB, 0x4D, 0x4A, 0xFC, 0xFC, 0xFC, 0xFC, 0xF0, - 0xFB, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x22, 0x23, 0x22, 0x23, 0x23, 0xB1, 0x81, 0x7D, - 0x39, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x7C, 0xB2, 0xB0, 0xDF, 0xD2, 0x57, - 0x60, 0x59, 0x5B, 0x59, 0x52, 0x4C, 0x4A, 0x40, - 0x42, 0x4A, 0x53, 0x4D, 0xD2, 0xDE, 0xDE, 0xD9, - 0x5E, 0x5E, 0x60, 0x4A, 0xCD, 0xD1, 0xCF, 0xCE, - 0x63, 0x49, 0x5C, 0xFB, 0xE8, 0x89, 0x9F, 0xFC, - 0xD6, 0x21, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x21, 0x2A, 0x22, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x7F, 0xB9, - 0x71, 0x6C, 0x38, 0x38, 0x33, 0x33, 0x33, 0x38, - 0x38, 0x71, 0xAD, 0xE4, 0xD3, 0xDA, 0xCC, 0x52, - 0x63, 0x60, 0xCE, 0xD4, 0xCF, 0x60, 0x4C, 0x40, - 0x3F, 0x45, 0x4B, 0x5A, 0xCB, 0xD8, 0xDE, 0xDC, - 0x5E, 0x5E, 0x5F, 0x4C, 0xD2, 0xD2, 0xCF, 0xCF, - 0x61, 0x45, 0x5E, 0xA7, 0x9D, 0x95, 0x8B, 0x99, - 0xFC, 0x41, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x23, 0x2A, 0x23, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x77, 0x77, 0xF6, - 0xFC, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, - 0x7D, 0xFC, 0x47, 0x64, 0xD0, 0xD0, 0x5D, 0x4B, - 0x62, 0xCC, 0xD1, 0xDE, 0xDE, 0xD4, 0x5E, 0x43, - 0x3F, 0x3E, 0x48, 0x53, 0x58, 0xDB, 0xD8, 0xDC, - 0x5E, 0x5E, 0x5E, 0x53, 0xD4, 0xD2, 0xD0, 0xD0, - 0x5E, 0x49, 0xA7, 0xA6, 0x89, 0x95, 0x8B, 0x9C, - 0x9C, 0xFB, 0xD4, 0x22, 0x22, 0x22, 0x22, 0x23, - 0x22, 0x23, 0x23, 0x2A, 0x22, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x23, 0x22, 0x23, 0x23, 0x98, 0x8C, 0x8C, 0x88, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, - 0xE9, 0x9C, 0x48, 0x5C, 0xD0, 0xCB, 0x48, 0x49, - 0x5B, 0xCB, 0xCD, 0xE0, 0xF1, 0xDD, 0xD0, 0x4A, - 0x41, 0x47, 0x45, 0x4C, 0x48, 0xD7, 0xDE, 0xDC, - 0x5E, 0x5E, 0x5A, 0x58, 0xD1, 0xD0, 0xD0, 0xD2, - 0x5C, 0x55, 0xA7, 0xA6, 0x87, 0x86, 0x89, 0x94, - 0x9C, 0xA9, 0xFC, 0xF4, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x22, 0x2A, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x22, 0x23, 0xA4, 0x89, 0x8C, 0xAA, - 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF7, - 0x85, 0x88, 0x8D, 0x59, 0x64, 0x63, 0x47, 0x3E, - 0x4C, 0x60, 0x61, 0xE0, 0xF0, 0xDF, 0xD9, 0x5D, - 0x2E, 0x3E, 0x3E, 0x47, 0x4D, 0xCD, 0xDE, 0xDC, - 0x5D, 0x5C, 0x51, 0x5D, 0xD1, 0xD2, 0xD2, 0xD4, - 0x5A, 0xBE, 0xA7, 0x98, 0x8A, 0x8A, 0xA0, 0x8B, - 0x86, 0x86, 0xF7, 0xFC, 0xF7, 0x26, 0x23, 0x23, - 0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x21, 0x21, 0x21, 0xA1, 0x98, 0x9F, 0xBF, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xA7, - 0x8C, 0x86, 0x8D, 0x59, 0x5E, 0x5D, 0x3F, 0x3E, - 0x47, 0x53, 0x63, 0xD9, 0xF0, 0xF1, 0xDE, 0xD0, - 0x43, 0x3E, 0x47, 0x45, 0x4A, 0x5B, 0xDC, 0xDA, - 0x5D, 0x59, 0x49, 0x5F, 0xD1, 0xD2, 0xD3, 0xB9, - 0xA5, 0xA7, 0x98, 0x9B, 0x96, 0x9D, 0x89, 0x89, - 0x8B, 0x9C, 0x9D, 0xFC, 0xFC, 0xFC, 0x26, 0x22, - 0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x29, 0x2D, 0x99, 0x99, 0xA2, 0xAA, - 0xC4, 0xFB, 0xFC, 0xFC, 0xFC, 0xF6, 0xBF, 0xA2, - 0x9C, 0x9C, 0x8E, 0xDC, 0xCD, 0x51, 0x41, 0x3E, - 0x45, 0x49, 0x58, 0xCD, 0xE0, 0xE0, 0xD8, 0xDA, - 0x4C, 0x4A, 0x45, 0x45, 0x48, 0x47, 0xDA, 0xDA, - 0x5C, 0x58, 0x44, 0x69, 0xA9, 0x98, 0xA4, 0xA6, - 0xA1, 0xA4, 0x99, 0x9E, 0x9D, 0x8B, 0x8A, 0x97, - 0x87, 0x9A, 0x8A, 0xC2, 0xFC, 0xFC, 0xFC, 0x4D, - 0x21, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, - 0x21, 0x22, 0x2D, 0x34, 0xA4, 0xA2, 0xA2, 0xA9, - 0xBF, 0xC0, 0xC3, 0xC1, 0xC0, 0xBE, 0xA6, 0x9D, - 0x99, 0x87, 0xA2, 0xF1, 0xDC, 0x64, 0x42, 0x45, - 0x47, 0x3E, 0x49, 0x4C, 0xDD, 0xDF, 0xD8, 0xDB, - 0x5E, 0x4C, 0x48, 0x45, 0x45, 0x41, 0xD1, 0xD6, - 0x5A, 0x55, 0x3F, 0xA7, 0xA1, 0x98, 0x9F, 0x99, - 0x9F, 0x9D, 0x9A, 0x95, 0x8B, 0x97, 0x89, 0x8A, - 0x88, 0x94, 0x9C, 0x8C, 0xFC, 0xFC, 0xFC, 0xFC, - 0xF4, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x23, 0x23, 0x2C, 0x2C, 0xA8, 0xA2, 0xA4, 0xA4, - 0xA9, 0xAA, 0xAA, 0xAA, 0xA9, 0xA6, 0x98, 0x9C, - 0x8B, 0x88, 0x98, 0x8D, 0xD8, 0xD6, 0x4E, 0x47, - 0x47, 0x49, 0x47, 0x3F, 0xDA, 0xDD, 0xDE, 0xDD, - 0xCC, 0x4A, 0x4B, 0x3E, 0x45, 0x43, 0x61, 0xD4, - 0x56, 0x51, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0x9A, - 0xA0, 0xA2, 0x98, 0x98, 0x8B, 0x8B, 0x98, 0x98, - 0x84, 0x8B, 0x94, 0x8A, 0xA4, 0xFC, 0xFC, 0xFC, - 0xFC, 0xF2, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x22, 0x2C, 0x2D, 0xC0, 0xA4, 0xA2, 0xA4, - 0xA4, 0xA6, 0xA6, 0xA6, 0xA4, 0xA2, 0x9F, 0x89, - 0x8B, 0x9C, 0x9C, 0x8B, 0x68, 0xDB, 0x5F, 0x4B, - 0x3E, 0x49, 0x4B, 0x3E, 0xCC, 0xDA, 0xDC, 0xDD, - 0xD3, 0x49, 0x52, 0x48, 0x45, 0x45, 0x53, 0xD0, - 0x51, 0x4A, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0xA0, - 0x9B, 0x86, 0x89, 0x98, 0x89, 0x8A, 0x96, 0x8A, - 0x9C, 0x89, 0x89, 0x9C, 0x8C, 0xF6, 0xFC, 0xFC, - 0xFC, 0xFC, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23, - 0x22, 0x21, 0x2B, 0x34, 0xC0, 0xA8, 0xA4, 0xA2, - 0xA2, 0x98, 0xA1, 0xA0, 0x98, 0x9F, 0x95, 0x8A, - 0x94, 0xA1, 0x8A, 0x84, 0x9B, 0x68, 0xCC, 0x49, - 0x4A, 0x47, 0x4C, 0x4B, 0x51, 0xD3, 0xDA, 0xDC, - 0xD5, 0x56, 0x56, 0x4A, 0x3E, 0x45, 0x48, 0x63, - 0x4A, 0x47, 0x3E, 0xA7, 0x98, 0x9D, 0x9E, 0x8B, - 0x95, 0x9B, 0x89, 0x86, 0x9B, 0x8B, 0x89, 0x84, - 0x9A, 0xA1, 0x95, 0x9A, 0x8C, 0xA4, 0xFC, 0xFC, - 0xFC, 0xFA, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23, - 0x21, 0x23, 0x2C, 0xF6, 0xBF, 0xA9, 0xA2, 0x99, - 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9B, 0x87, 0x8B, - 0x9C, 0x86, 0x9C, 0x8A, 0x87, 0x87, 0x89, 0x51, - 0x54, 0x47, 0x4B, 0x50, 0x4B, 0xCF, 0xD6, 0xDC, - 0xD5, 0x60, 0x54, 0x52, 0x48, 0x45, 0x40, 0x5A, - 0x45, 0x43, 0x47, 0xA7, 0x98, 0x9B, 0x95, 0x95, - 0x9A, 0x87, 0x98, 0x98, 0x8A, 0x86, 0x87, 0x9E, - 0x9B, 0x95, 0x9D, 0x9D, 0x99, 0x85, 0xA6, 0xFA, - 0xF2, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x22, - 0x21, 0x24, 0xFB, 0xF7, 0xBF, 0xA6, 0xA2, 0x99, - 0x97, 0x89, 0x86, 0x89, 0x9C, 0x96, 0x9E, 0x94, - 0x89, 0x99, 0x98, 0x89, 0x9E, 0x9B, 0x89, 0x8B, - 0x58, 0x4B, 0x4A, 0x52, 0x48, 0xCC, 0xD3, 0xDA, - 0xD3, 0x65, 0x4C, 0x58, 0x49, 0x3E, 0x2E, 0x4D, - 0x40, 0x41, 0x45, 0xA9, 0xA1, 0x9B, 0x9E, 0x9C, - 0x95, 0x8A, 0x94, 0x89, 0x96, 0x87, 0x9C, 0x9A, - 0x84, 0x9D, 0x9C, 0x9E, 0x9A, 0x9C, 0x9D, 0xBB, - 0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x23, 0x23, - 0x24, 0xFC, 0xFC, 0xF6, 0xBF, 0xA6, 0x9F, 0x99, - 0x89, 0x95, 0x87, 0x94, 0x9D, 0x9E, 0x97, 0x9E, - 0x95, 0x9B, 0x89, 0x95, 0x95, 0x9B, 0x89, 0x87, - 0x5D, 0x56, 0x3E, 0x51, 0x3E, 0x60, 0xCF, 0xD3, - 0xD2, 0xCD, 0x5C, 0x49, 0x4B, 0x3E, 0x2C, 0x48, - 0x3E, 0x43, 0x3E, 0xA9, 0xA1, 0x9B, 0x97, 0x94, - 0x95, 0x9A, 0x9C, 0x87, 0x87, 0x9B, 0x9C, 0x95, - 0x9D, 0x89, 0x9A, 0x89, 0x9E, 0x9E, 0x8C, 0xA6, - 0x20, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x20, 0x40, - 0xFC, 0xFC, 0xFC, 0xEC, 0xBE, 0xA4, 0x9F, 0x99, - 0x95, 0x9F, 0xA0, 0x88, 0x9D, 0x8B, 0x97, 0x95, - 0x87, 0x95, 0x96, 0x95, 0x97, 0x94, 0x94, 0x98, - 0xD3, 0x4C, 0x47, 0x4D, 0x42, 0x4C, 0x60, 0xCC, - 0xCE, 0xD0, 0x65, 0x4B, 0x47, 0x44, 0x2B, 0x45, - 0x4B, 0x47, 0x49, 0xA7, 0xA1, 0x9A, 0x97, 0x89, - 0x95, 0x97, 0x97, 0x9E, 0x89, 0x95, 0x89, 0x9C, - 0x87, 0x95, 0x97, 0x99, 0x95, 0x99, 0x9F, 0xA4, - 0xC4, 0x21, 0x21, 0x23, 0x21, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x21, 0x20, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xEA, 0xAA, 0xA6, 0xA2, 0x99, - 0x8B, 0x9A, 0x95, 0x9E, 0x9E, 0x9A, 0x94, 0x87, - 0x94, 0x94, 0x89, 0x94, 0x9B, 0x9B, 0xA7, 0xDC, - 0xDB, 0x65, 0x2E, 0x3E, 0x43, 0x44, 0x49, 0x58, - 0x63, 0xD3, 0xD3, 0x5E, 0x42, 0x42, 0x2D, 0x40, - 0x54, 0x4C, 0x4A, 0xA7, 0xA0, 0x99, 0x9B, 0x94, - 0xA0, 0x8A, 0x9B, 0x9D, 0x87, 0x95, 0x94, 0x8B, - 0x8A, 0x98, 0x9C, 0x8A, 0x9B, 0x99, 0xA2, 0xA6, - 0xBF, 0xEC, 0x2A, 0x20, 0x21, 0x23, 0x21, 0x20, - 0x20, 0x20, 0x20, 0x4C, 0xF9, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xEB, 0xAA, 0xA4, 0x9F, 0x9C, - 0x8B, 0x9B, 0x88, 0x84, 0x9E, 0x9D, 0x96, 0x94, - 0x94, 0x9A, 0x9B, 0x9B, 0xA4, 0xD5, 0xCD, 0xDE, - 0xF1, 0xDA, 0x4C, 0x2D, 0x41, 0x2B, 0x42, 0x4C, - 0x5E, 0xD4, 0xD7, 0xCD, 0x49, 0x2E, 0x2E, 0x41, - 0x5E, 0x57, 0xA7, 0xA6, 0xA7, 0xA4, 0xA2, 0x98, - 0x9D, 0x9C, 0xA1, 0x99, 0x9D, 0x88, 0x8B, 0x9C, - 0x8A, 0x9C, 0x9C, 0x94, 0x9C, 0x89, 0xA0, 0xA6, - 0xAA, 0xEB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFB, 0xE9, 0xAA, 0xA6, 0xA2, 0x8B, - 0x8B, 0x8A, 0x86, 0x9B, 0x9C, 0x98, 0xA0, 0x9B, - 0x9B, 0x84, 0xA7, 0xB4, 0x61, 0xD1, 0xD2, 0xE0, - 0xF1, 0xDC, 0x61, 0x2D, 0x2E, 0x3F, 0x56, 0x62, - 0x5D, 0xD4, 0xD9, 0xD3, 0x54, 0x41, 0x41, 0x44, - 0xCB, 0x60, 0x52, 0xA9, 0xA9, 0xA9, 0xA7, 0xA6, - 0xA6, 0xA4, 0xA4, 0xA2, 0xA2, 0x9D, 0x95, 0x89, - 0x9C, 0x8A, 0x9E, 0x9C, 0x8A, 0x9E, 0xA0, 0xA8, - 0xC0, 0xE9, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xE9, 0xAA, 0xA6, 0xA0, 0x99, - 0x9C, 0x8B, 0x9A, 0x84, 0x9B, 0x9B, 0x98, 0x98, - 0xA9, 0xB9, 0x49, 0x57, 0xCB, 0xD4, 0xD3, 0xF1, - 0xD8, 0xDA, 0xCE, 0x3F, 0x41, 0x4B, 0x5D, 0xCB, - 0x5E, 0xD6, 0xDB, 0xD6, 0x5D, 0x43, 0x3F, 0x49, - 0xD1, 0xCC, 0x4F, 0xDD, 0xC3, 0xBB, 0xBF, 0xAA, - 0xAA, 0xA9, 0xAA, 0xA8, 0xA8, 0xA6, 0xA6, 0xA2, - 0x9C, 0x9F, 0x9B, 0x9A, 0x9D, 0xA2, 0xA8, 0xAA, - 0xC1, 0xEA, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xEA, 0xC0, 0xAA, 0xA6, 0xA2, - 0xA2, 0x99, 0xA0, 0xA0, 0xA4, 0xA7, 0xA9, 0xC0, - 0x67, 0x49, 0x54, 0x60, 0xD0, 0xD4, 0xCC, 0xDF, - 0xD9, 0xD5, 0xD2, 0x3E, 0x47, 0x56, 0x60, 0xCD, - 0x5D, 0xD9, 0xD9, 0xD6, 0x61, 0x3F, 0x47, 0x52, - 0xD6, 0xD3, 0x62, 0x4D, 0x40, 0x4A, 0x57, 0xCA, - 0xC3, 0xC1, 0xC1, 0xC0, 0xBF, 0xBF, 0xAA, 0xAA, - 0xA6, 0xA4, 0xA4, 0xA4, 0xA6, 0xA8, 0xBE, 0xC1, - 0xC9, 0xEB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xEB, 0xC3, 0xC0, 0xAA, 0xA8, - 0xA6, 0xA6, 0xA6, 0xA9, 0xAA, 0xC0, 0xE8, 0xD0, - 0xD2, 0x4C, 0x5E, 0x64, 0xD0, 0xD1, 0x5F, 0xD9, - 0xD5, 0xD1, 0xD0, 0x48, 0x52, 0x5C, 0x64, 0xCD, - 0x5C, 0xDC, 0xD7, 0xD5, 0x62, 0x3F, 0x4C, 0x53, - 0xDA, 0xD7, 0xCE, 0x56, 0x40, 0x4B, 0x52, 0x56, - 0xCE, 0xDF, 0x6A, 0xEB, 0xE9, 0xC9, 0xC3, 0xC0, - 0xC0, 0xBF, 0xBE, 0xAA, 0xBF, 0xC0, 0xC3, 0xC9, - 0xEA, 0xF6, 0xEE, 0x58, 0x57, 0x5E, 0xD6, 0xD0, - 0xD2, 0x61, 0xCB, 0xD6, 0xD6, 0xD4, 0xDF, 0xF3, - 0xF2, 0xDD, 0xD7, 0xEB, 0xC9, 0xC1, 0xC0, 0xBF, - 0xAA, 0xAA, 0xAA, 0xBE, 0xC3, 0xF0, 0xD2, 0xD2, - 0xD2, 0x51, 0x62, 0xCC, 0xD0, 0xCC, 0x61, 0xD3, - 0xCF, 0xCE, 0xD2, 0x48, 0x5A, 0x61, 0xCC, 0xCE, - 0x5F, 0xD9, 0xD5, 0xD1, 0x63, 0x44, 0x56, 0x56, - 0xDC, 0xD9, 0xD4, 0x5E, 0x42, 0x4A, 0x4C, 0x57, - 0x5D, 0xD8, 0xE0, 0xD8, 0xDC, 0xCB, 0x66, 0xEC, - 0xE8, 0xC3, 0xC3, 0xC3, 0xC3, 0xC9, 0xE8, 0xEA, - 0xF6, 0x50, 0x3E, 0x58, 0x57, 0x5A, 0xD6, 0xD4, - 0xCC, 0x4B, 0x53, 0x5C, 0x64, 0xD1, 0xDF, 0xF3, - 0xF1, 0xDE, 0xD9, 0xF6, 0xEB, 0xC9, 0xC1, 0xC1, - 0xC0, 0xC0, 0xC1, 0xC9, 0xF0, 0xD6, 0xCD, 0xD6, - 0xD3, 0x53, 0xCB, 0xCF, 0xCD, 0x5F, 0x5F, 0xCE, - 0xCF, 0xCD, 0xD0, 0x47, 0x5F, 0xCB, 0xCE, 0xCD, - 0x63, 0xD6, 0xD3, 0xD1, 0x63, 0x3F, 0x58, 0x58, - 0xDB, 0xDC, 0xDA, 0x65, 0x3E, 0x49, 0x49, 0x4D, - 0x49, 0xDC, 0xDF, 0xE0, 0xDE, 0xD5, 0x47, 0x47, - 0x46, 0x6B, 0xEB, 0xEA, 0xE9, 0xEA, 0xEB, 0xF6, - 0xD0, 0x57, 0x57, 0x47, 0x47, 0x5B, 0xD4, 0xD4, - 0xCD, 0x44, 0x3E, 0x4B, 0x50, 0x4B, 0x51, 0xD5, - 0xDB, 0xD8, 0xDE, 0x4B, 0xF6, 0xF6, 0xEA, 0xE9, - 0xE8, 0xEA, 0xEB, 0x67, 0x5E, 0xCC, 0xD6, 0xDC, - 0xD5, 0x58, 0xCE, 0xCE, 0x62, 0x50, 0xCC, 0xD3, - 0xD2, 0xCD, 0xCD, 0x4B, 0x64, 0xCE, 0xCE, 0x64, - 0xCC, 0xD3, 0xD2, 0xD2, 0x61, 0x47, 0x5D, 0x5C, - 0xDD, 0xDD, 0xD9, 0xD1, 0x4C, 0x47, 0x49, 0x4A, - 0x4B, 0xD1, 0xD8, 0xE0, 0xDF, 0xDD, 0x5D, 0x4A, - 0x48, 0x52, 0x51, 0x3F, 0xF6, 0xEC, 0xE0, 0xE0, - 0xD3, 0x5E, 0x5F, 0x50, 0x4B, 0x50, 0xCB, 0xCE, - 0x64, 0x45, 0x4C, 0x57, 0x57, 0x58, 0x52, 0xD6, - 0xD3, 0xDE, 0xDF, 0xD1, 0x3E, 0x4B, 0xF6, 0xF6, - 0xEC, 0x66, 0x53, 0x43, 0x56, 0xD1, 0xD9, 0xDE, - 0xD4, 0x5E, 0xCE, 0xCC, 0x5B, 0x2C, 0xD4, 0xD5, - 0xD2, 0xD0, 0x63, 0x5D, 0xCD, 0xD0, 0xCD, 0x5E, - 0xD0, 0xCF, 0xCE, 0xD2, 0x5E, 0x50, 0x60, 0x5D, - 0xDE, 0xDD, 0xDC, 0xD7, 0x5D, 0x45, 0x47, 0x3E, - 0x4B, 0x5E, 0xDE, 0xDF, 0xE0, 0xD8, 0xCF, 0x3E, - 0x45, 0x51, 0x58, 0x42, 0xCB, 0xDA, 0xDE, 0xD8, - 0xD2, 0x61, 0xCC, 0xCF, 0xD6, 0xDA, 0xDA, 0xD5, - 0xD0, 0x50, 0x44, 0x57, 0x57, 0x58, 0x45, 0xD1, - 0xD1, 0xD7, 0xDF, 0xDF, 0xD7, 0xCF, 0x64, 0x60, - 0xCE, 0xCE, 0xCE, 0x63, 0xCF, 0xDA, 0xDE, 0xD9, - 0xCF, 0x63, 0xCD, 0x63, 0x4D, 0x4B, 0xD6, 0xD5, - 0xCE, 0xD3, 0x60, 0xCB, 0xD0, 0xD0, 0x65, 0x47, - 0xD0, 0xCC, 0xCC, 0xD1, 0x59, 0x5D, 0x63, 0x5E, - 0xDD, 0xDD, 0xDE, 0xDC, 0xCB, 0x40, 0x48, 0x45, - 0x3E, 0x3E, 0xD9, 0xDF, 0xE0, 0xDF, 0xDA, 0x51, - 0x4C, 0x48, 0x56, 0x4C, 0x5B, 0xD2, 0xDA, 0xDB, - 0xCB, 0x5F, 0xD0, 0xCC, 0xDC, 0xF0, 0xF3, 0xE0, - 0xDD, 0xCC, 0x41, 0x50, 0x57, 0x57, 0x4B, 0x5D, - 0xD3, 0xD1, 0xDE, 0xDF, 0xDE, 0xD7, 0xD0, 0xD0, - 0xD5, 0xD6, 0xD6, 0xCE, 0xD7, 0xDC, 0xDA, 0xD5, - 0x60, 0x63, 0x64, 0x5E, 0x47, 0x61, 0xD5, 0xD2, - 0xCF, 0xD0, 0x59, 0xCD, 0xD1, 0xCF, 0x61, 0x4D, - 0xCC, 0xCE, 0xCD, 0xD0, 0x52, 0x61, 0x64, 0x60, - 0xDA, 0xDE, 0xDE, 0xDD, 0xD1, 0x4B, 0x4A, 0x45, - 0x3E, 0x41, 0xCD, 0xDE, 0xE0, 0xF1, 0xDE, 0x63, - 0x4A, 0x4A, 0x4A, 0x4B, 0x50, 0xCB, 0xD4, 0xD7, - 0x5E, 0x54, 0x62, 0xD3, 0xD4, 0xF0, 0xF3, 0xF3, - 0xF2, 0xDE, 0x61, 0x40, 0x49, 0x56, 0x4D, 0x3E, - 0x4B, 0xCE, 0xD9, 0xD8, 0xD9, 0xD5, 0xCF, 0xD2, - 0xD6, 0xD6, 0xD1, 0xD1, 0xD7, 0xD5, 0xCF, 0xD0, - 0x54, 0x64, 0x63, 0x56, 0x2C, 0xCB, 0xD1, 0xCC, - 0xD3, 0xCD, 0x54, 0xCF, 0xD1, 0xCE, 0x5E, 0x5C, - 0xCE, 0xCE, 0xCE, 0xCB, 0x4B, 0x63, 0xCC, 0x61, - 0xD4, 0xDC, 0xDE, 0xDE, 0xDA, 0x5D, 0x45, 0x45, - 0x48, 0x3F, 0x52, 0xD9, 0xD8, 0xDF, 0xDF, 0xD2, - 0x52, 0x4B, 0x3E, 0x2E, 0x47, 0x60, 0xCF, 0xD3, - 0x59, 0x48, 0x50, 0x5E, 0xCC, 0xDE, 0xF2, 0xF2, - 0xF3, 0xF3, 0xDD, 0x5D, 0x3E, 0x48, 0x47, 0x47, - 0x58, 0xD1, 0xDA, 0xDA, 0xD5, 0xD1, 0xCD, 0xD2, - 0xD3, 0xCF, 0xD3, 0xD1, 0xCD, 0xD3, 0xD2, 0x5E, - 0x52, 0x64, 0x60, 0x4B, 0x45, 0x61, 0xCD, 0xD3, - 0xD3, 0x64, 0x61, 0xD0, 0xD0, 0x64, 0x45, 0x63, - 0xD0, 0xCE, 0xD0, 0x60, 0x56, 0xCB, 0xCC, 0x62, - 0xCE, 0xDA, 0xDE, 0xD8, 0xDD, 0xCC, 0x45, 0x49, - 0x3E, 0x47, 0x42, 0xD1, 0xDC, 0xD8, 0xD8, 0xD3, - 0x5D, 0x4C, 0x49, 0x3F, 0x47, 0x59, 0xCD, 0xCF, - 0x59, 0x2E, 0x48, 0x47, 0x52, 0x63, 0xF0, 0xF2, - 0xF3, 0xF3, 0xF2, 0xDA, 0x52, 0x4B, 0x52, 0x58, - 0x5E, 0x63, 0xD0, 0xD0, 0xD0, 0xCF, 0xCE, 0xCE, - 0xCF, 0x65, 0x61, 0xD6, 0xD6, 0xD6, 0xCB, 0x4B, - 0x61, 0x62, 0x5D, 0x43, 0x4B, 0x61, 0xD0, 0xD4, - 0xD1, 0x61, 0xCE, 0xD2, 0xCD, 0x5E, 0x4A, 0xCE, - 0xD0, 0xCC, 0xD0, 0x59, 0x61, 0xCC, 0xCC, 0x62, - 0xD1, 0xD5, 0xDE, 0xD8, 0xDD, 0xCF, 0x4B, 0x4A, - 0x45, 0x3E, 0x2D, 0xCB, 0xDC, 0xDE, 0xD8, 0xD5, - 0x60, 0x54, 0x51, 0x4C, 0x4D, 0x5C, 0xCC, 0xCE, - 0x5A, 0x2C, 0x50, 0x53, 0x3E, 0x59, 0xD8, 0xF3, - 0xF2, 0xF3, 0xF3, 0xE0, 0x5E, 0x4A, 0x4C, 0x53, - 0x5E, 0x63, 0xCC, 0xCC, 0xCC, 0xCD, 0xCF, 0xD3, - 0x62, 0x53, 0xD6, 0xD6, 0xD6, 0xD6, 0x5B, 0x48, - 0x64, 0x63, 0x59, 0x44, 0x57, 0x63, 0xD2, 0xD3, - 0xD0, 0x5E, 0xD0, 0xD1, 0xCB, 0x58, 0x4C, 0xCF, - 0xCF, 0xCE, 0xCE, 0x57, 0x63, 0xCC, 0xCD, 0x57, -}; - -unsigned char linux_logo_bw[] __initdata = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, - 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, - 0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, - 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7, - 0x99, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xF3, 0xBC, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, - 0x19, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xC0, 0x03, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, - 0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xC0, 0x21, 0xD8, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0xC0, 0x1F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C, - 0xC0, 0x7C, 0x04, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, - 0xE3, 0x80, 0x00, 0x7C, 0x40, 0x11, 0xFF, 0xFF, - 0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0xD2, 0x29, - 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F, - 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00, - 0x00, 0x3F, 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, - 0x1E, 0x00, 0x00, 0x1F, 0x80, 0x19, 0xFF, 0xFF, - 0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1E, 0x80, 0x19, - 0xFF, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1E, - 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C, 0x00, - 0x00, 0x0F, 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, - 0xF8, 0x00, 0x00, 0x0E, 0x80, 0x11, 0xFF, 0xFF, - 0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x06, 0x00, 0x11, - 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x06, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00, - 0x00, 0x02, 0x00, 0x09, 0xFF, 0xFF, 0xFF, 0xF1, - 0xF0, 0x00, 0x00, 0x02, 0x80, 0x10, 0xFF, 0xFF, - 0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x97, 0x10, - 0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00, - 0xDF, 0xF0, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00, - 0x00, 0x00, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xC7, - 0xC0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, - 0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, - 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01, - 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, - 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x9F, - 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, - 0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0x18, - 0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03, - 0xA8, 0x11, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00, - 0x00, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x99, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFF, 0xFF, - 0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x01, - 0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00, - 0xFF, 0xC3, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00, - 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0xFF, 0xC0, 0x40, - 0x38, 0x00, 0x00, 0x00, 0xFE, 0x47, 0xFF, 0xFF, - 0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x23, - 0xFF, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x78, 0x11, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80, - 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, - 0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF, - 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04, - 0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10, - 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80, - 0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF, - 0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0, - 0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40, - 0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00, - 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF, - 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40, - 0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0, - 0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF, - 0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F, - 0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF, - 0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F, - 0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F, - 0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07, - 0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -}; - -unsigned char linux_logo16_red[] __initdata = { - 0x00, 0x90, 0xb0, 0x9c, 0xf7, 0x35, 0x83, 0xa5, - 0x65, 0x8f, 0x98, 0xc9, 0xdb, 0xe1, 0xe7, 0xf8 -}; - -unsigned char linux_logo16_green[] __initdata = { - 0x00, 0x90, 0xb0, 0x9c, 0xf7, 0x2e, 0x83, 0xa5, - 0x65, 0x6e, 0x98, 0x89, 0xbf, 0xac, 0xda, 0xf8 -}; - -unsigned char linux_logo16_blue[] __initdata = { - 0x00, 0x90, 0xaf, 0x9c, 0xf7, 0x2b, 0x82, 0xa5, - 0x65, 0x41, 0x97, 0x1e, 0x60, 0x29, 0xa5, 0xf8 -}; - -unsigned char linux_logo16[] __initdata = { - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa1, 0x11, 0x11, - 0x61, 0x16, 0x66, 0x66, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0xa8, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x87, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x73, 0x33, 0x33, 0x3a, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x27, 0x77, 0x77, 0x77, 0x33, 0x3a, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xa3, 0x33, 0x33, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x55, 0x50, 0x08, 0x33, 0x77, 0x77, - 0x77, 0x72, 0x72, 0x27, 0x77, 0x77, 0x33, 0x33, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xa3, 0x33, 0x33, 0x77, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x58, 0x85, 0x00, 0x11, 0x11, 0xaa, - 0xa3, 0x37, 0x77, 0x72, 0x22, 0x22, 0x77, 0x73, - 0x33, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, - 0x33, 0x37, 0x77, 0x33, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x56, 0x85, 0x00, 0x06, 0x66, 0x11, - 0x11, 0x1a, 0xa3, 0x37, 0x77, 0x72, 0x22, 0x77, - 0x73, 0x33, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, - 0x33, 0x33, 0x33, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x55, 0x00, 0x00, 0x06, 0x66, 0x66, - 0x66, 0x66, 0x11, 0x1a, 0xa3, 0x77, 0x72, 0x22, - 0x77, 0x73, 0x3a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, - 0x33, 0x33, 0x33, 0xa0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x66, 0x66, 0x66, 0x66, 0x11, 0xa3, 0x77, 0x22, - 0x22, 0x77, 0x33, 0x33, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x33, - 0x33, 0x3a, 0xa1, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x33, - 0xaa, 0x11, 0x16, 0x66, 0x66, 0x61, 0x1a, 0x37, - 0x22, 0x22, 0x77, 0x33, 0x3a, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0x33, - 0x3a, 0xa1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x22, - 0x22, 0x77, 0x3a, 0x11, 0x66, 0x66, 0x66, 0x1a, - 0x37, 0x22, 0x22, 0x77, 0x33, 0x3a, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x33, 0x3a, - 0xa1, 0x11, 0x11, 0x10, 0x00, 0x00, 0x50, 0x00, - 0x00, 0x05, 0x80, 0x50, 0x00, 0x00, 0x07, 0x72, - 0x22, 0x22, 0x22, 0x73, 0xa1, 0x66, 0x66, 0x61, - 0x1a, 0x77, 0x22, 0x27, 0x73, 0x33, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x3a, 0xaa, - 0x11, 0x11, 0x1a, 0xa0, 0x08, 0x71, 0x05, 0x00, - 0x00, 0x12, 0x22, 0x50, 0x00, 0x00, 0x07, 0x77, - 0x77, 0x72, 0x22, 0x22, 0x27, 0x31, 0x16, 0x66, - 0x61, 0x13, 0x77, 0x22, 0x77, 0x33, 0x3a, 0xaa, - 0xaa, 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0xaa, 0xa1, - 0x11, 0x1a, 0x33, 0x70, 0x07, 0x2e, 0x70, 0x00, - 0x01, 0x44, 0x42, 0x60, 0x00, 0x00, 0x02, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x27, 0x31, 0x66, - 0x66, 0x61, 0xa3, 0x72, 0x22, 0x77, 0x33, 0xaa, - 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0xaa, 0xaa, 0x11, - 0x1a, 0x33, 0x77, 0x30, 0x04, 0x82, 0x40, 0x00, - 0x54, 0x48, 0x54, 0x40, 0x00, 0x00, 0x01, 0xaa, - 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x31, - 0x66, 0x66, 0x11, 0x37, 0x22, 0x27, 0x73, 0x3a, - 0xaa, 0xaa, 0xa3, 0x33, 0x3a, 0xaa, 0xaa, 0xaa, - 0xa3, 0x77, 0xaa, 0x10, 0x50, 0x08, 0x46, 0x05, - 0x54, 0x80, 0x50, 0x42, 0x00, 0x00, 0x08, 0x66, - 0x66, 0x1a, 0x32, 0x22, 0x22, 0x22, 0x22, 0x27, - 0x31, 0x66, 0x66, 0x13, 0x72, 0x22, 0x77, 0x33, - 0xaa, 0xaa, 0xaa, 0x33, 0xaa, 0xa1, 0xaa, 0xa3, - 0x37, 0xa1, 0x1a, 0x30, 0x50, 0x06, 0x26, 0x00, - 0x54, 0x00, 0x00, 0x44, 0x00, 0x00, 0x08, 0xe2, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22, 0x22, - 0x27, 0xa6, 0x66, 0x61, 0xa7, 0x72, 0x27, 0x73, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, - 0x31, 0x11, 0x37, 0x70, 0x02, 0x00, 0xab, 0xbb, - 0xb6, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22, - 0x22, 0x23, 0x16, 0x66, 0x1a, 0x37, 0x22, 0x77, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0x3a, - 0x11, 0xa7, 0x33, 0x10, 0x04, 0x09, 0xbd, 0xdd, - 0xbd, 0xd0, 0x04, 0x45, 0x00, 0x0e, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22, - 0x22, 0x22, 0x71, 0x66, 0x66, 0x13, 0x72, 0x27, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x11, - 0xa3, 0x73, 0xa1, 0x60, 0x08, 0xbd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdb, 0x90, 0x00, 0x02, 0xec, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xce, 0x22, - 0x22, 0x22, 0x27, 0xa6, 0x66, 0x61, 0x37, 0x27, - 0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0xa1, 0x1a, - 0x33, 0xa1, 0x16, 0x60, 0x0b, 0xbd, 0xdd, 0xdd, - 0xcd, 0xdd, 0xdd, 0xd9, 0x00, 0x00, 0xec, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0xa2, - 0x22, 0x22, 0x22, 0x7a, 0x66, 0x66, 0x13, 0x77, - 0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0x3a, 0x11, 0x33, - 0xaa, 0x11, 0x66, 0x60, 0x9b, 0xdd, 0xdd, 0xdd, - 0xcd, 0xdd, 0xdb, 0xb9, 0x00, 0x00, 0xec, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xee, 0x61, - 0x72, 0x22, 0x22, 0x22, 0xa1, 0x66, 0x61, 0x37, - 0x1a, 0xaa, 0xaa, 0xaa, 0xa3, 0xa1, 0x13, 0x3a, - 0x11, 0x11, 0x11, 0x10, 0x5b, 0xdd, 0xdd, 0xdc, - 0xdd, 0xdd, 0xbd, 0xd9, 0x00, 0x00, 0xec, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xee, 0x86, - 0x17, 0x22, 0x22, 0x22, 0x23, 0x16, 0x66, 0xaa, - 0xaa, 0xa3, 0x3a, 0xaa, 0xaa, 0x1a, 0x3a, 0xa1, - 0x11, 0x11, 0x1a, 0x70, 0x05, 0xbd, 0xdd, 0xdd, - 0xdb, 0x5b, 0xdd, 0xb0, 0x00, 0x60, 0x2e, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xe6, 0x88, - 0x66, 0x32, 0x22, 0x22, 0x22, 0x36, 0x66, 0x11, - 0x33, 0x33, 0x3a, 0xaa, 0x11, 0xaa, 0xaa, 0xa1, - 0x11, 0x1a, 0x3a, 0x60, 0x02, 0x99, 0xbb, 0xb9, - 0x9b, 0xbb, 0xbc, 0x22, 0x00, 0x86, 0x5e, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xe1, 0x68, - 0x86, 0x63, 0x22, 0x22, 0x22, 0x2a, 0x66, 0x66, - 0x33, 0x33, 0xaa, 0xaa, 0x1a, 0xaa, 0xaa, 0x11, - 0x1a, 0xa7, 0x68, 0x80, 0x02, 0x2b, 0xbd, 0xbb, - 0xbb, 0xb9, 0x22, 0x22, 0x00, 0x06, 0x6e, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xc7, 0xa6, - 0x88, 0x86, 0x32, 0x22, 0x22, 0x27, 0xa6, 0x66, - 0x33, 0x3a, 0xaa, 0xa1, 0xaa, 0xaa, 0xa1, 0x11, - 0xa3, 0xa6, 0x88, 0x80, 0x02, 0x22, 0x9b, 0xbb, - 0xbb, 0x22, 0x24, 0xf4, 0x60, 0x00, 0x0c, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xc2, 0x21, - 0x68, 0x88, 0x63, 0x22, 0x22, 0x22, 0x71, 0x66, - 0x33, 0x3a, 0x11, 0x11, 0xaa, 0xaa, 0x11, 0xaa, - 0x71, 0x88, 0x88, 0x00, 0x02, 0xe2, 0x26, 0x99, - 0x22, 0x22, 0x4f, 0xf4, 0x40, 0x00, 0x0c, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x22, 0x22, - 0x16, 0x88, 0x86, 0xa2, 0x22, 0x22, 0x27, 0x11, - 0x33, 0xa1, 0x11, 0x11, 0xaa, 0x31, 0x1a, 0xa3, - 0x68, 0x88, 0x81, 0x00, 0x54, 0x42, 0x22, 0x22, - 0x22, 0x44, 0xff, 0xff, 0x48, 0x00, 0x00, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x22, 0x22, - 0x21, 0x88, 0x88, 0x6a, 0x22, 0x22, 0x22, 0x31, - 0x3a, 0xa1, 0x11, 0x1a, 0xa3, 0x11, 0x33, 0x36, - 0x88, 0x86, 0x30, 0x00, 0x4f, 0x44, 0x22, 0x22, - 0x24, 0xff, 0xff, 0xff, 0x44, 0x00, 0x00, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x95, 0x22, 0x72, - 0x22, 0x18, 0x88, 0x86, 0x32, 0x22, 0x22, 0x27, - 0xaa, 0x11, 0x11, 0x1a, 0x31, 0x13, 0x33, 0x68, - 0x88, 0x6a, 0x00, 0x02, 0x4f, 0x4f, 0x42, 0x24, - 0x4f, 0xff, 0xff, 0xff, 0xf4, 0x50, 0x00, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x22, 0x73, - 0x72, 0x26, 0x88, 0x88, 0x63, 0x22, 0x22, 0x22, - 0x11, 0x11, 0x11, 0xa3, 0xa1, 0x73, 0xa6, 0x88, - 0x81, 0xa5, 0x00, 0x04, 0x4f, 0x4f, 0x44, 0x4f, - 0xff, 0xff, 0xff, 0xff, 0xf4, 0x40, 0x00, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x12, 0x27, - 0xaa, 0x22, 0x68, 0x55, 0x86, 0x72, 0x22, 0x22, - 0x11, 0x11, 0x1a, 0x33, 0x13, 0x3a, 0x18, 0x88, - 0x1a, 0x10, 0x00, 0x44, 0x4f, 0x4f, 0xff, 0x4f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x61, 0x22, - 0x3a, 0xa2, 0x26, 0x85, 0x58, 0x67, 0x22, 0x22, - 0x61, 0x61, 0x1a, 0x7a, 0x37, 0x31, 0x88, 0x81, - 0x11, 0x00, 0x05, 0xe4, 0x44, 0xff, 0xff, 0xff, - 0x4f, 0xf4, 0x44, 0xff, 0xff, 0xf5, 0x00, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x88, 0x12, - 0x2a, 0xaa, 0x72, 0x68, 0x55, 0x81, 0x22, 0x22, - 0x66, 0x61, 0xa3, 0x33, 0x73, 0x16, 0x88, 0x11, - 0x10, 0x00, 0x08, 0x74, 0x44, 0x4f, 0x44, 0x44, - 0xf4, 0xf4, 0x44, 0x44, 0xe2, 0x44, 0x00, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x88, 0x81, - 0x22, 0xaa, 0xa7, 0x26, 0x85, 0x88, 0x12, 0x22, - 0x66, 0x61, 0x37, 0xa7, 0x3a, 0x66, 0x66, 0x11, - 0x80, 0x00, 0x0a, 0x72, 0x44, 0x4f, 0x44, 0x4f, - 0xff, 0x44, 0x44, 0x22, 0x22, 0x24, 0x00, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x85, 0x88, - 0x12, 0x2a, 0xaa, 0x22, 0x68, 0x58, 0x63, 0x22, - 0x66, 0x1a, 0x73, 0x77, 0x31, 0x66, 0x61, 0x11, - 0x00, 0x00, 0x07, 0x44, 0xff, 0x4f, 0xf4, 0x4f, - 0xff, 0x4f, 0x44, 0xf4, 0x42, 0x22, 0x40, 0x9b, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x85, 0x55, - 0x81, 0x27, 0xaa, 0xa2, 0x78, 0x88, 0x86, 0x72, - 0x66, 0x13, 0x77, 0x73, 0x11, 0x66, 0x61, 0x76, - 0x00, 0x50, 0x84, 0xf4, 0xff, 0x4f, 0xf4, 0xff, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x42, 0x40, 0x9b, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x68, 0x55, - 0x58, 0x12, 0x3a, 0xaa, 0x23, 0x88, 0x88, 0xa7, - 0x66, 0xa7, 0x77, 0x7a, 0x16, 0x66, 0x1a, 0x15, - 0x05, 0x00, 0x4f, 0xf4, 0xff, 0x4f, 0xf4, 0xff, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0x24, 0x9b, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x26, 0x55, - 0x55, 0x81, 0x23, 0xaa, 0x32, 0x18, 0x88, 0x6a, - 0x61, 0x37, 0x77, 0x31, 0x66, 0x66, 0x17, 0x60, - 0x05, 0x08, 0x4f, 0xf4, 0xff, 0x4f, 0xf4, 0xff, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x4e, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0xa2, 0x65, - 0x55, 0x58, 0xa2, 0x7a, 0xa2, 0x26, 0x88, 0x61, - 0x61, 0x32, 0x27, 0xa1, 0x66, 0x61, 0x31, 0x60, - 0x00, 0x04, 0x4f, 0xf4, 0xff, 0x44, 0x44, 0xff, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0xf4, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x9b, 0xaa, 0x26, - 0x55, 0x55, 0x87, 0x27, 0x33, 0x27, 0x68, 0x61, - 0x1a, 0x72, 0x27, 0xa6, 0x66, 0x6a, 0x71, 0x00, - 0x80, 0x84, 0xff, 0xf4, 0xff, 0x44, 0x44, 0xff, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0xf4, 0x99, - 0x9b, 0x9b, 0x99, 0xb9, 0xb9, 0x99, 0xaa, 0xa2, - 0x85, 0x55, 0x56, 0x22, 0x27, 0x22, 0x36, 0x66, - 0x13, 0x22, 0x23, 0x16, 0x86, 0x63, 0x73, 0x00, - 0x00, 0x44, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0xff, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x4f, 0x99, - 0x9b, 0x99, 0x99, 0x99, 0xb9, 0x99, 0xaa, 0xaa, - 0x28, 0x55, 0x58, 0x12, 0x22, 0x22, 0x21, 0x11, - 0xa3, 0x27, 0x7a, 0x66, 0x86, 0x17, 0x75, 0x05, - 0x05, 0xff, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0xff, - 0xff, 0x4f, 0x44, 0x4f, 0x4f, 0x44, 0x4f, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x3a, 0xaa, - 0xa2, 0x85, 0x58, 0x67, 0x72, 0x22, 0x27, 0xa1, - 0x37, 0x27, 0x7a, 0x68, 0x86, 0xa2, 0x70, 0x00, - 0x02, 0xff, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0xf4, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x23, 0xaa, - 0xa7, 0x78, 0x88, 0x81, 0x77, 0x22, 0x27, 0x3a, - 0x72, 0x73, 0x71, 0x68, 0x66, 0x32, 0x50, 0x00, - 0x04, 0x4f, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0x44, 0x95, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x55, 0x12, 0x3a, - 0xaa, 0x21, 0x88, 0x81, 0x77, 0x27, 0x73, 0x73, - 0x72, 0x33, 0x36, 0x86, 0x61, 0x72, 0x00, 0x00, - 0x04, 0x44, 0xf4, 0xf4, 0xf4, 0x44, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x44, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x8a, 0x27, - 0xaa, 0x77, 0x68, 0x61, 0x23, 0x71, 0x11, 0x3a, - 0x27, 0xa3, 0x36, 0x86, 0x61, 0x20, 0x00, 0x00, - 0x04, 0xf4, 0xf4, 0xf4, 0xf4, 0x44, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x41, 0x59, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x95, 0x58, 0x77, - 0x27, 0x32, 0x36, 0x63, 0x23, 0x71, 0x66, 0x11, - 0x27, 0x13, 0xa6, 0x86, 0x6a, 0x20, 0x00, 0x50, - 0x04, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x41, 0x99, - 0x9b, 0xbb, 0xbb, 0xbb, 0xb9, 0x99, 0x68, 0x13, - 0x32, 0x22, 0x73, 0xa7, 0x2a, 0x31, 0x88, 0x66, - 0x7a, 0x13, 0x18, 0x66, 0x63, 0x20, 0x00, 0x06, - 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x49, 0x95, - 0xa9, 0xa9, 0x99, 0x97, 0x92, 0x99, 0x65, 0x6a, - 0x17, 0x22, 0x23, 0x72, 0x27, 0xaa, 0x88, 0x88, - 0xa1, 0x17, 0x68, 0x66, 0x67, 0x70, 0x00, 0x05, - 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xff, 0xf4, 0xf4, 0x49, 0x9c, - 0x2e, 0xee, 0xee, 0xee, 0xee, 0xa9, 0x65, 0x8a, - 0x1a, 0xaa, 0x37, 0x72, 0x27, 0x37, 0x88, 0x88, - 0x11, 0x17, 0x68, 0x66, 0x67, 0x10, 0x9d, 0xd0, - 0x84, 0x44, 0xff, 0x4f, 0x4f, 0x44, 0xf4, 0x4f, - 0xff, 0x4f, 0x44, 0xff, 0xf4, 0xf4, 0x4f, 0x69, - 0xcc, 0xee, 0xee, 0xee, 0xec, 0x99, 0x88, 0x63, - 0x61, 0x68, 0x61, 0x72, 0x22, 0x7a, 0x68, 0x88, - 0x11, 0x17, 0x88, 0x66, 0x12, 0x1b, 0xdd, 0xdd, - 0x02, 0x44, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xff, 0xff, 0x4f, 0x4c, 0xc5, - 0x0c, 0xc1, 0x11, 0x1c, 0xc0, 0x26, 0x66, 0x17, - 0x66, 0x88, 0x88, 0x12, 0x22, 0x23, 0xa8, 0x88, - 0x11, 0x13, 0x88, 0x66, 0x17, 0xbb, 0xdd, 0xdd, - 0xd0, 0x8f, 0xff, 0xf4, 0xf4, 0x44, 0xf4, 0x4f, - 0xff, 0x4f, 0x44, 0xf4, 0x4f, 0x44, 0xdd, 0xdd, - 0x00, 0x00, 0x00, 0x05, 0x9d, 0x21, 0x66, 0x27, - 0xa6, 0x65, 0x58, 0x67, 0x22, 0x27, 0x28, 0x88, - 0x11, 0xaa, 0x86, 0x68, 0x1a, 0xbb, 0xdd, 0xdd, - 0xdb, 0x05, 0xf4, 0xf4, 0xf4, 0xf4, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0xdd, 0xdb, - 0x00, 0x00, 0x00, 0x00, 0xdd, 0xda, 0x66, 0x22, - 0x71, 0x15, 0x55, 0x81, 0x22, 0x22, 0x76, 0x88, - 0x11, 0x31, 0x88, 0x88, 0xab, 0xbd, 0xdd, 0xdd, - 0xdd, 0x00, 0x04, 0x44, 0xff, 0xff, 0x4f, 0x4f, - 0xff, 0x4f, 0x44, 0xf4, 0xf4, 0x44, 0xdd, 0xdb, - 0x00, 0x00, 0x00, 0x0b, 0xdd, 0xda, 0x11, 0x22, - 0x23, 0x68, 0x55, 0x86, 0x22, 0x22, 0x7a, 0x88, - 0x1a, 0x71, 0x88, 0x89, 0xbb, 0xdd, 0xdd, 0xdd, - 0xdd, 0xd0, 0x00, 0x4f, 0x44, 0xff, 0x4f, 0x4f, - 0xff, 0x4f, 0x44, 0xf4, 0xff, 0xe2, 0xdd, 0xdb, - 0x90, 0x00, 0x05, 0xbd, 0xdd, 0xb8, 0x63, 0x22, - 0x27, 0xa6, 0x55, 0x88, 0x77, 0x22, 0x22, 0x88, - 0x1a, 0x28, 0xbd, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdb, 0x00, 0x07, 0x44, 0x4f, 0x4f, 0x4f, - 0xff, 0x4f, 0x44, 0x4f, 0x4f, 0x22, 0xdd, 0xdb, - 0xbb, 0x9b, 0xbb, 0xbd, 0xdd, 0xd5, 0x86, 0x22, - 0x22, 0x77, 0x85, 0x88, 0x17, 0x22, 0x22, 0x88, - 0xaa, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0x00, 0x00, 0x54, 0x4f, 0x4f, 0x4f, - 0xff, 0x4f, 0x44, 0xf4, 0x44, 0x22, 0xbd, 0xdd, - 0xbb, 0xbb, 0xbb, 0xdd, 0xdd, 0xdd, 0x88, 0x72, - 0x27, 0x22, 0x88, 0x88, 0x67, 0x72, 0x22, 0x18, - 0x33, 0x2d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xd0, 0x00, 0x05, 0x4f, 0x4f, 0x4f, - 0xff, 0x4f, 0x44, 0x44, 0x4f, 0x22, 0xbd, 0xdd, - 0xdb, 0xbb, 0xdd, 0xdd, 0xdd, 0xdd, 0x88, 0x17, - 0x27, 0x72, 0x68, 0x88, 0x87, 0x32, 0x22, 0x36, - 0x37, 0x2d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xd5, 0x00, 0x00, 0x4f, 0x4f, 0x4f, - 0xff, 0xf4, 0xf4, 0xf4, 0xf4, 0x22, 0xbb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd8, 0x67, - 0x72, 0x77, 0x38, 0x88, 0x83, 0x37, 0x22, 0x26, - 0x72, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0x00, 0x00, 0x4f, 0x4f, 0x4f, - 0xff, 0xf4, 0xf4, 0xf4, 0x44, 0x25, 0xbb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd3, - 0x32, 0x73, 0x76, 0x88, 0x81, 0x33, 0x22, 0x2a, - 0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xb0, 0x54, 0x4f, 0x4f, 0x4f, - 0xff, 0xf4, 0xf4, 0xff, 0x44, 0x00, 0xbb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xa7, 0x73, 0x26, 0x88, 0x86, 0x7a, 0x72, 0x27, - 0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdb, 0x44, 0xff, 0x4f, 0x4f, - 0xff, 0xf4, 0xf4, 0x44, 0x40, 0x05, 0xbb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0x13, 0x23, 0x21, 0x68, 0x86, 0x17, 0x72, 0x22, - 0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdb, 0x44, 0x4f, 0x4f, 0x4f, - 0xff, 0xff, 0x44, 0x42, 0x00, 0x05, 0xbd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0x87, 0x27, 0x27, 0x16, 0x66, 0x67, 0x22, 0x22, - 0x72, 0x7b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0x94, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x00, 0x00, 0x05, 0xbb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xb8, - 0x86, 0x22, 0x22, 0x7a, 0x68, 0x81, 0x22, 0x22, - 0x37, 0x7b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdb, 0xb5, 0x44, 0x44, 0x44, - 0x44, 0x47, 0x00, 0x00, 0x00, 0x05, 0xbd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd8, 0x68, - 0x58, 0x72, 0x22, 0x27, 0x18, 0x86, 0x72, 0x22, - 0x1a, 0xbb, 0xbd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdb, 0xb5, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xbb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xb9, 0x18, 0x85, - 0x58, 0x12, 0x22, 0x36, 0x18, 0x88, 0x32, 0x22, - 0x61, 0x3b, 0xbb, 0xbb, 0xbd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdb, 0xb9, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xbb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xb9, 0x7a, 0x68, 0x85, - 0x88, 0x62, 0x27, 0x16, 0x18, 0x88, 0x12, 0x27, - 0x86, 0x18, 0x9b, 0xbb, 0xbb, 0xbb, 0xbb, 0xbd, - 0xdd, 0xdd, 0xdd, 0xbb, 0xb5, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xbb, 0xbd, - 0xdd, 0xdd, 0xdb, 0xbb, 0x87, 0x31, 0x68, 0x65, - 0x88, 0x82, 0x23, 0x16, 0x18, 0x88, 0x12, 0x23, - 0x88, 0x67, 0x27, 0xa8, 0x9b, 0xbb, 0xbb, 0xbb, - 0xbd, 0xdd, 0xbb, 0xbb, 0x95, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x9b, 0xbb, - 0xbb, 0xbb, 0xbb, 0x96, 0x87, 0x16, 0x68, 0x18, - 0x88, 0x62, 0x31, 0x66, 0x18, 0x88, 0x62, 0x73, - 0x88, 0x63, 0x27, 0x33, 0x65, 0x55, 0x99, 0x9b, - 0xbb, 0xbb, 0xbb, 0x99, 0x55, 0x0a, 0xa1, 0x86, - 0x81, 0x68, 0x88, 0x55, 0x58, 0x85, 0x9b, 0xbb, - 0xbb, 0xbb, 0x95, 0x88, 0x83, 0x66, 0x66, 0x18, - 0x66, 0x82, 0xa1, 0x66, 0x18, 0x88, 0x62, 0x33, - 0x88, 0x81, 0x27, 0x7a, 0x18, 0x58, 0x86, 0x85, - 0x99, 0x99, 0x99, 0x95, 0x53, 0x2a, 0xaa, 0x88, - 0x67, 0x31, 0x68, 0x55, 0x58, 0x85, 0x59, 0xbb, - 0xbb, 0xb9, 0x58, 0x68, 0x83, 0x66, 0x61, 0x16, - 0x66, 0x62, 0x16, 0x66, 0x68, 0x88, 0x62, 0xaa, - 0x88, 0x86, 0x27, 0x77, 0x78, 0x55, 0x88, 0x22, - 0x25, 0x55, 0x95, 0x55, 0x6a, 0xa2, 0x2a, 0x88, - 0x62, 0x27, 0x37, 0x38, 0x88, 0x87, 0x55, 0x59, - 0x95, 0x58, 0x16, 0x88, 0x8a, 0x66, 0x63, 0x68, - 0x86, 0x67, 0x66, 0x66, 0x68, 0x88, 0x12, 0x11, - 0x88, 0x88, 0x72, 0x77, 0x78, 0x85, 0x58, 0x17, - 0x23, 0x32, 0x55, 0x55, 0x81, 0x13, 0x73, 0x66, - 0x62, 0x7a, 0xaa, 0x38, 0x88, 0x58, 0x27, 0x55, - 0x58, 0x32, 0x38, 0x88, 0x81, 0x66, 0xa2, 0x88, - 0x86, 0x61, 0x66, 0x61, 0x66, 0x68, 0x13, 0x11, - 0x88, 0x88, 0x12, 0x22, 0x71, 0x85, 0x58, 0x62, - 0x23, 0xa2, 0x68, 0x88, 0x81, 0x66, 0x88, 0x88, - 0x63, 0x2a, 0xaa, 0x28, 0x88, 0x55, 0x86, 0x61, - 0x66, 0x66, 0x68, 0x88, 0x66, 0x66, 0x77, 0x88, - 0x68, 0x16, 0x66, 0x62, 0x66, 0x68, 0xa1, 0x61, - 0x88, 0x88, 0x62, 0x22, 0x22, 0x85, 0x55, 0x83, - 0x72, 0x37, 0xa8, 0x88, 0x61, 0x66, 0x85, 0x55, - 0x86, 0x23, 0xaa, 0x71, 0x88, 0x85, 0x88, 0x66, - 0x88, 0x86, 0x88, 0x88, 0x16, 0x61, 0x21, 0x88, - 0x66, 0xa6, 0x86, 0x17, 0x66, 0x66, 0x31, 0x61, - 0x88, 0x88, 0x87, 0x72, 0x22, 0x68, 0x55, 0x86, - 0x77, 0x77, 0x36, 0x88, 0x13, 0x68, 0x85, 0x55, - 0x58, 0x12, 0x73, 0x72, 0x76, 0x88, 0x88, 0x68, - 0x88, 0x88, 0x88, 0x66, 0x36, 0x63, 0x26, 0x86, - 0x86, 0x36, 0x86, 0x11, 0x66, 0x66, 0x76, 0x61, - 0x88, 0x88, 0x81, 0x22, 0x22, 0x38, 0x85, 0x58, - 0x37, 0x22, 0x21, 0x68, 0xa2, 0x31, 0x68, 0x55, - 0x55, 0x81, 0x22, 0x22, 0xa8, 0x88, 0x88, 0x68, - 0x86, 0x88, 0x68, 0x81, 0x36, 0x17, 0x21, 0x68, - 0x86, 0x16, 0x66, 0x26, 0x66, 0x61, 0x36, 0x66, - 0x68, 0x88, 0x86, 0x27, 0x22, 0x28, 0x88, 0x88, - 0x17, 0x72, 0x2a, 0x66, 0xa2, 0x22, 0x36, 0x55, - 0x55, 0x58, 0x37, 0x3a, 0x16, 0x66, 0x66, 0x66, - 0x66, 0x18, 0x88, 0x67, 0x16, 0x12, 0x71, 0x68, - 0x81, 0x68, 0x61, 0x76, 0x66, 0x6a, 0x16, 0x66, - 0x88, 0x88, 0x86, 0x77, 0x22, 0x26, 0x88, 0x88, - 0x13, 0x37, 0x71, 0x66, 0xa2, 0x33, 0x2a, 0x85, - 0x55, 0x55, 0x17, 0x73, 0x16, 0x66, 0x66, 0x68, - 0x63, 0x88, 0x88, 0xa2, 0x66, 0xa2, 0xa6, 0x88, - 0x61, 0x68, 0x6a, 0x76, 0x66, 0x6a, 0x66, 0x6a -}; +#define INCLUDE_LINUX_LOGO16 +#include /* Painted by Johnny Stenback */ diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/page.h linux/include/asm-ppc/page.h --- v2.1.100/linux/include/asm-ppc/page.h Sat Apr 25 18:13:12 1998 +++ linux/include/asm-ppc/page.h Fri May 8 00:18:24 1998 @@ -64,6 +64,8 @@ #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) +#define get_user_page(vaddr) __get_free_page(GFP_KERNEL) +#define free_user_page(page, addr) free_page(addr) #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) #define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE) /* map phys->virtual and virtual->phys for RAM pages */ diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/pmu.h linux/include/asm-ppc/pmu.h --- v2.1.100/linux/include/asm-ppc/pmu.h Thu Apr 23 20:21:37 1998 +++ linux/include/asm-ppc/pmu.h Fri May 8 00:18:24 1998 @@ -16,12 +16,18 @@ #define PMU_READ_NVRAM 0x3b /* read non-volatile RAM */ #define PMU_SET_RTC 0x30 /* set real-time clock */ #define PMU_READ_RTC 0x38 /* read real-time clock */ +#define PMU_SET_VOLBUTTON 0x40 /* set volume up/down position */ #define PMU_BACKLIGHT_BRIGHT 0x41 /* set backlight brightness */ +#define PMU_GET_VOLBUTTON 0x48 /* get volume up/down position */ +#define PMU_PCEJECT 0x4c /* eject PC-card from slot */ +#define PMU_BATTERY_STATE 0x6b /* report battery state etc. */ #define PMU_SET_INTR_MASK 0x70 /* set PMU interrupt mask */ #define PMU_INT_ACK 0x78 /* read interrupt bits */ #define PMU_SHUTDOWN 0x7e /* turn power off */ #define PMU_SLEEP 0x7f /* put CPU to sleep */ #define PMU_RESET 0xd0 /* reset CPU */ +#define PMU_GET_BRIGHTBUTTON 0xd9 /* report brightness up/down pos */ +#define PMU_GET_COVER 0xdc /* report cover open/closed */ /* Bits in PMU interrupt and interrupt mask bytes */ #define PMU_INT_ADB_AUTO 0x04 /* ADB autopoll, when PMU_INT_ADB */ @@ -31,6 +37,7 @@ #define PMU_INT_TICK 0x80 /* 1-second tick interrupt */ #ifdef __KERNEL__ +void find_via_pmu(void); void via_pmu_init(void); int pmu_request(struct adb_request *req, void (*done)(struct adb_request *), int nbytes, ...); diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h --- v2.1.100/linux/include/asm-ppc/processor.h Thu Apr 23 20:21:37 1998 +++ linux/include/asm-ppc/processor.h Fri May 8 00:18:24 1998 @@ -234,7 +234,8 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 8 * 3) +#define TASK_UNMAPPED_BASE(off) (TASK_SIZE / 8 * 3) +#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) #define COPY_TASK_STRUCT(dst, src) \ do { \ @@ -284,6 +285,9 @@ { return (t->regs) ? t->regs->nip : 0; } + +#define copy_segments(nr, tsk, mm) do { } while (0) +#define release_segments(mm) do { } while (0) /* * NOTE! The task struct and the stack go together diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/serial.h linux/include/asm-ppc/serial.h --- v2.1.100/linux/include/asm-ppc/serial.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-ppc/serial.h Fri May 8 00:18:24 1998 @@ -0,0 +1,116 @@ +/* + * include/asm-ppc/serial.h + */ + +/* + * This assumes you have a 1.8432 MHz clock for your UART. + * + * It'd be nice if someone built a serial card with a 24.576 MHz + * clock, since the 16550A is capable of handling a top speed of 1.5 + * megabits/second; but this requires the faster clock. + */ +#define BASE_BAUD ( 1843200 / 16 ) + +/* Standard COM flags (except for COM4, because of the 8514 problem) */ +#ifdef CONFIG_SERIAL_DETECT_IRQ +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ) +#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ) +#else +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) +#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF +#endif + +#ifdef CONFIG_SERIAL_MANY_PORTS +#define FOURPORT_FLAGS ASYNC_FOURPORT +#define ACCENT_FLAGS 0 +#define BOCA_FLAGS 0 +#define HUB6_FLAGS 0 +#endif + +/* + * The following define the access methods for the HUB6 card. All + * access is through two ports for all 24 possible chips. The card is + * selected through the high 2 bits, the port on that card with the + * "middle" 3 bits, and the register on that port with the bottom + * 3 bits. + * + * While the access port and interrupt is configurable, the default + * port locations are 0x302 for the port control register, and 0x303 + * for the data read/write register. Normally, the interrupt is at irq3 + * but can be anything from 3 to 7 inclusive. Note that using 3 will + * require disabling com2. + */ + +#define C_P(card,port) (((card)<<6|(port)<<3) + 1) + +#define STD_SERIAL_PORT_DEFNS \ + /* UART CLK PORT IRQ FLAGS */ \ + { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \ + { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \ + { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \ + { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */ + + +#ifdef CONFIG_SERIAL_MANY_PORTS +#define EXTRA_SERIAL_PORT_DEFNS \ + { 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, /* ttyS4 */ \ + { 0, BASE_BAUD, 0x1A8, 9, FOURPORT_FLAGS }, /* ttyS5 */ \ + { 0, BASE_BAUD, 0x1B0, 9, FOURPORT_FLAGS }, /* ttyS6 */ \ + { 0, BASE_BAUD, 0x1B8, 9, FOURPORT_FLAGS }, /* ttyS7 */ \ + { 0, BASE_BAUD, 0x2A0, 5, FOURPORT_FLAGS }, /* ttyS8 */ \ + { 0, BASE_BAUD, 0x2A8, 5, FOURPORT_FLAGS }, /* ttyS9 */ \ + { 0, BASE_BAUD, 0x2B0, 5, FOURPORT_FLAGS }, /* ttyS10 */ \ + { 0, BASE_BAUD, 0x2B8, 5, FOURPORT_FLAGS }, /* ttyS11 */ \ + { 0, BASE_BAUD, 0x330, 4, ACCENT_FLAGS }, /* ttyS12 */ \ + { 0, BASE_BAUD, 0x338, 4, ACCENT_FLAGS }, /* ttyS13 */ \ + { 0, BASE_BAUD, 0x000, 0, 0 }, /* ttyS14 (spare) */ \ + { 0, BASE_BAUD, 0x000, 0, 0 }, /* ttyS15 (spare) */ \ + { 0, BASE_BAUD, 0x100, 12, BOCA_FLAGS }, /* ttyS16 */ \ + { 0, BASE_BAUD, 0x108, 12, BOCA_FLAGS }, /* ttyS17 */ \ + { 0, BASE_BAUD, 0x110, 12, BOCA_FLAGS }, /* ttyS18 */ \ + { 0, BASE_BAUD, 0x118, 12, BOCA_FLAGS }, /* ttyS19 */ \ + { 0, BASE_BAUD, 0x120, 12, BOCA_FLAGS }, /* ttyS20 */ \ + { 0, BASE_BAUD, 0x128, 12, BOCA_FLAGS }, /* ttyS21 */ \ + { 0, BASE_BAUD, 0x130, 12, BOCA_FLAGS }, /* ttyS22 */ \ + { 0, BASE_BAUD, 0x138, 12, BOCA_FLAGS }, /* ttyS23 */ \ + { 0, BASE_BAUD, 0x140, 12, BOCA_FLAGS }, /* ttyS24 */ \ + { 0, BASE_BAUD, 0x148, 12, BOCA_FLAGS }, /* ttyS25 */ \ + { 0, BASE_BAUD, 0x150, 12, BOCA_FLAGS }, /* ttyS26 */ \ + { 0, BASE_BAUD, 0x158, 12, BOCA_FLAGS }, /* ttyS27 */ \ + { 0, BASE_BAUD, 0x160, 12, BOCA_FLAGS }, /* ttyS28 */ \ + { 0, BASE_BAUD, 0x168, 12, BOCA_FLAGS }, /* ttyS29 */ \ + { 0, BASE_BAUD, 0x170, 12, BOCA_FLAGS }, /* ttyS30 */ \ + { 0, BASE_BAUD, 0x178, 12, BOCA_FLAGS }, /* ttyS31 */ +#else +#define EXTRA_SERIAL_PORT_DEFNS +#endif + +/* You can have up to four HUB6's in the system, but I've only + * included two cards here for a total of twelve ports. + */ +#if (defined(CONFIG_HUB6) && defined(CONFIG_SERIAL_MANY_PORTS)) +#define HUB6_SERIAL_PORT_DFNS \ + { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,0) }, /* ttyS32 */ \ + { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,1) }, /* ttyS33 */ \ + { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,2) }, /* ttyS34 */ \ + { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,3) }, /* ttyS35 */ \ + { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,4) }, /* ttyS36 */ \ + { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,5) }, /* ttyS37 */ \ + { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,0) }, /* ttyS38 */ \ + { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,1) }, /* ttyS39 */ \ + { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,2) }, /* ttyS40 */ \ + { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,3) }, /* ttyS41 */ \ + { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,4) }, /* ttyS42 */ \ + { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,5) }, /* ttyS43 */ +#else +#define HUB6_SERIAL_PORT_DFNS +#endif + +#define MCA_SERIAL_PORT_DFNS + +#define SERIAL_PORT_DFNS \ + STD_SERIAL_PORT_DEFNS \ + EXTRA_SERIAL_PORT_DEFNS \ + HUB6_SERIAL_PORT_DFNS \ + MCA_SERIAL_PORT_DFNS + diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/spinlock.h linux/include/asm-ppc/spinlock.h --- v2.1.100/linux/include/asm-ppc/spinlock.h Thu Apr 23 20:21:37 1998 +++ linux/include/asm-ppc/spinlock.h Fri May 8 00:18:24 1998 @@ -64,8 +64,7 @@ } spinlock_t; #define SPIN_LOCK_UNLOCKED { 0, 0, 0 } -#define spin_lock_init(lp) \ -do { spinlock_t *p = (lp); p->owner_pc = p->owner_cpu = p->lock = 0; } while(0) +#define spin_lock_init(lp) do { (lp)->lock = 0; } while(0) #define spin_unlock_wait(lp) do { barrier(); } while((lp)->lock) extern void _spin_lock(spinlock_t *lock); diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/timex.h linux/include/asm-ppc/timex.h --- v2.1.100/linux/include/asm-ppc/timex.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-ppc/timex.h Thu May 7 23:53:35 1998 @@ -0,0 +1,15 @@ +/* + * linux/include/asm-ppc/timex.h + * + * ppc architecture timex specifications + */ +#ifndef _ASMppc_TIMEX_H +#define _ASMppc_TIMEX_H + +#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ +#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */ +#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \ + (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \ + << (SHIFT_SCALE-SHIFT_HZ)) / HZ) + +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/unistd.h linux/include/asm-ppc/unistd.h --- v2.1.100/linux/include/asm-ppc/unistd.h Thu Apr 23 20:21:37 1998 +++ linux/include/asm-ppc/unistd.h Fri May 8 00:18:24 1998 @@ -21,7 +21,7 @@ #define __NR_time 13 #define __NR_mknod 14 #define __NR_chmod 15 -#define __NR_chown 16 +#define __NR_lchown 16 #define __NR_break 17 #define __NR_oldstat 18 #define __NR_lseek 19 @@ -177,8 +177,19 @@ #define __NR_setresgid 169 #define __NR_getresgid 170 #define __NR_prctl 171 -#define __NR_xstat 172 -#define __NR_xmknod 173 +#define __NR_rt_sigreturn 172 +#define __NR_rt_sigaction 173 +#define __NR_rt_sigprocmask 174 +#define __NR_rt_sigpending 175 +#define __NR_rt_sigtimedwait 177 +#define __NR_rt_sigqueueinfo 178 +#define __NR_rt_sigsuspend 179 +#define __NR_pread 180 +#define __NR_pwrite 181 +#define __NR_chown 182 +#define __NR_getcwd 183 +#define __NR_xstat 184 +#define __NR_xmknod 185 #define __NR(n) #n #define __do_syscall(n) \ diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/asm_offsets.h linux/include/asm-sparc/asm_offsets.h --- v2.1.100/linux/include/asm-sparc/asm_offsets.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc/asm_offsets.h Fri May 8 00:11:29 1998 @@ -48,108 +48,110 @@ #define ASIZ_task_session 0x00000004 #define AOFF_task_leader 0x00000074 #define ASIZ_task_leader 0x00000004 -#define AOFF_task_ngroups 0x00000078 -#define ASIZ_task_ngroups 0x00000004 -#define AOFF_task_groups 0x0000007c -#define ASIZ_task_groups 0x00000040 -#define AOFF_task_p_opptr 0x000000bc +#define AOFF_task_p_opptr 0x00000078 #define ASIZ_task_p_opptr 0x00000004 -#define AOFF_task_p_pptr 0x000000c0 +#define AOFF_task_p_pptr 0x0000007c #define ASIZ_task_p_pptr 0x00000004 -#define AOFF_task_p_cptr 0x000000c4 +#define AOFF_task_p_cptr 0x00000080 #define ASIZ_task_p_cptr 0x00000004 -#define AOFF_task_p_ysptr 0x000000c8 +#define AOFF_task_p_ysptr 0x00000084 #define ASIZ_task_p_ysptr 0x00000004 -#define AOFF_task_p_osptr 0x000000cc +#define AOFF_task_p_osptr 0x00000088 #define ASIZ_task_p_osptr 0x00000004 -#define AOFF_task_pidhash_next 0x000000d0 +#define AOFF_task_pidhash_next 0x0000008c #define ASIZ_task_pidhash_next 0x00000004 -#define AOFF_task_pidhash_pprev 0x000000d4 +#define AOFF_task_pidhash_pprev 0x00000090 #define ASIZ_task_pidhash_pprev 0x00000004 -#define AOFF_task_tarray_ptr 0x000000d8 +#define AOFF_task_tarray_ptr 0x00000094 #define ASIZ_task_tarray_ptr 0x00000004 -#define AOFF_task_wait_chldexit 0x000000dc +#define AOFF_task_wait_chldexit 0x00000098 #define ASIZ_task_wait_chldexit 0x00000004 -#define AOFF_task_uid 0x000000e0 -#define ASIZ_task_uid 0x00000002 -#define AOFF_task_euid 0x000000e2 -#define ASIZ_task_euid 0x00000002 -#define AOFF_task_suid 0x000000e4 -#define ASIZ_task_suid 0x00000002 -#define AOFF_task_fsuid 0x000000e6 -#define ASIZ_task_fsuid 0x00000002 -#define AOFF_task_gid 0x000000e8 -#define ASIZ_task_gid 0x00000002 -#define AOFF_task_egid 0x000000ea -#define ASIZ_task_egid 0x00000002 -#define AOFF_task_sgid 0x000000ec -#define ASIZ_task_sgid 0x00000002 -#define AOFF_task_fsgid 0x000000ee -#define ASIZ_task_fsgid 0x00000002 -#define AOFF_task_timeout 0x000000f0 +#define AOFF_task_timeout 0x0000009c #define ASIZ_task_timeout 0x00000004 -#define AOFF_task_policy 0x000000f4 +#define AOFF_task_policy 0x000000a0 #define ASIZ_task_policy 0x00000004 -#define AOFF_task_rt_priority 0x000000f8 +#define AOFF_task_rt_priority 0x000000a4 #define ASIZ_task_rt_priority 0x00000004 -#define AOFF_task_it_real_value 0x000000fc +#define AOFF_task_it_real_value 0x000000a8 #define ASIZ_task_it_real_value 0x00000004 -#define AOFF_task_it_prof_value 0x00000100 +#define AOFF_task_it_prof_value 0x000000ac #define ASIZ_task_it_prof_value 0x00000004 -#define AOFF_task_it_virt_value 0x00000104 +#define AOFF_task_it_virt_value 0x000000b0 #define ASIZ_task_it_virt_value 0x00000004 -#define AOFF_task_it_real_incr 0x00000108 +#define AOFF_task_it_real_incr 0x000000b4 #define ASIZ_task_it_real_incr 0x00000004 -#define AOFF_task_it_prof_incr 0x0000010c +#define AOFF_task_it_prof_incr 0x000000b8 #define ASIZ_task_it_prof_incr 0x00000004 -#define AOFF_task_it_virt_incr 0x00000110 +#define AOFF_task_it_virt_incr 0x000000bc #define ASIZ_task_it_virt_incr 0x00000004 -#define AOFF_task_real_timer 0x00000114 +#define AOFF_task_real_timer 0x000000c0 #define ASIZ_task_real_timer 0x00000014 -#define AOFF_task_times 0x00000128 +#define AOFF_task_times 0x000000d4 #define ASIZ_task_times 0x00000010 -#define AOFF_task_start_time 0x00000138 +#define AOFF_task_start_time 0x000000e4 #define ASIZ_task_start_time 0x00000004 -#define AOFF_task_per_cpu_utime 0x0000013c +#define AOFF_task_per_cpu_utime 0x000000e8 #define ASIZ_task_per_cpu_utime 0x00000004 -#define AOFF_task_min_flt 0x00000144 +#define AOFF_task_min_flt 0x000000f0 #define ASIZ_task_min_flt 0x00000004 -#define AOFF_task_maj_flt 0x00000148 +#define AOFF_task_maj_flt 0x000000f4 #define ASIZ_task_maj_flt 0x00000004 -#define AOFF_task_nswap 0x0000014c +#define AOFF_task_nswap 0x000000f8 #define ASIZ_task_nswap 0x00000004 -#define AOFF_task_cmin_flt 0x00000150 +#define AOFF_task_cmin_flt 0x000000fc #define ASIZ_task_cmin_flt 0x00000004 -#define AOFF_task_cmaj_flt 0x00000154 +#define AOFF_task_cmaj_flt 0x00000100 #define ASIZ_task_cmaj_flt 0x00000004 -#define AOFF_task_cnswap 0x00000158 +#define AOFF_task_cnswap 0x00000104 #define ASIZ_task_cnswap 0x00000004 -#define AOFF_task_swap_address 0x00000160 +#define AOFF_task_swap_address 0x0000010c #define ASIZ_task_swap_address 0x00000004 -#define AOFF_task_old_maj_flt 0x00000164 +#define AOFF_task_old_maj_flt 0x00000110 #define ASIZ_task_old_maj_flt 0x00000004 -#define AOFF_task_dec_flt 0x00000168 +#define AOFF_task_dec_flt 0x00000114 #define ASIZ_task_dec_flt 0x00000004 -#define AOFF_task_swap_cnt 0x0000016c +#define AOFF_task_swap_cnt 0x00000118 #define ASIZ_task_swap_cnt 0x00000004 -#define AOFF_task_rlim 0x00000170 +#define AOFF_task_uid 0x0000011c +#define ASIZ_task_uid 0x00000002 +#define AOFF_task_euid 0x0000011e +#define ASIZ_task_euid 0x00000002 +#define AOFF_task_suid 0x00000120 +#define ASIZ_task_suid 0x00000002 +#define AOFF_task_fsuid 0x00000122 +#define ASIZ_task_fsuid 0x00000002 +#define AOFF_task_gid 0x00000124 +#define ASIZ_task_gid 0x00000002 +#define AOFF_task_egid 0x00000126 +#define ASIZ_task_egid 0x00000002 +#define AOFF_task_sgid 0x00000128 +#define ASIZ_task_sgid 0x00000002 +#define AOFF_task_fsgid 0x0000012a +#define ASIZ_task_fsgid 0x00000002 +#define AOFF_task_ngroups 0x0000012c +#define ASIZ_task_ngroups 0x00000004 +#define AOFF_task_groups 0x00000130 +#define ASIZ_task_groups 0x00000040 +#define AOFF_task_cap_effective 0x00000170 +#define ASIZ_task_cap_effective 0x00000004 +#define AOFF_task_cap_inheritable 0x00000174 +#define ASIZ_task_cap_inheritable 0x00000004 +#define AOFF_task_cap_permitted 0x00000178 +#define ASIZ_task_cap_permitted 0x00000004 +#define AOFF_task_rlim 0x0000017c #define ASIZ_task_rlim 0x00000050 -#define AOFF_task_used_math 0x000001c0 +#define AOFF_task_used_math 0x000001cc #define ASIZ_task_used_math 0x00000002 -#define AOFF_task_io_usage 0x000001c4 -#define ASIZ_task_io_usage 0x00000004 -#define AOFF_task_comm 0x000001c8 +#define AOFF_task_comm 0x000001ce #define ASIZ_task_comm 0x00000010 -#define AOFF_task_link_count 0x000001d8 +#define AOFF_task_link_count 0x000001e0 #define ASIZ_task_link_count 0x00000004 -#define AOFF_task_tty 0x000001dc +#define AOFF_task_tty 0x000001e4 #define ASIZ_task_tty 0x00000004 -#define AOFF_task_semundo 0x000001e0 +#define AOFF_task_semundo 0x000001e8 #define ASIZ_task_semundo 0x00000004 -#define AOFF_task_semsleeping 0x000001e4 +#define AOFF_task_semsleeping 0x000001ec #define ASIZ_task_semsleeping 0x00000004 -#define AOFF_task_ldt 0x000001e8 -#define ASIZ_task_ldt 0x00000004 #define AOFF_task_tss 0x000001f0 #define ASIZ_task_tss 0x00000390 #define AOFF_task_fs 0x00000580 @@ -224,6 +226,8 @@ #define ASIZ_mm_def_flags 0x00000004 #define AOFF_mm_cpu_vm_mask 0x00000060 #define ASIZ_mm_cpu_vm_mask 0x00000004 +#define AOFF_mm_segments 0x00000064 +#define ASIZ_mm_segments 0x00000004 #define AOFF_thread_uwinmask 0x00000000 #define ASIZ_thread_uwinmask 0x00000004 #define AOFF_thread_kregs 0x00000004 @@ -315,108 +319,110 @@ #define ASIZ_task_session 0x00000004 #define AOFF_task_leader 0x00000074 #define ASIZ_task_leader 0x00000004 -#define AOFF_task_ngroups 0x00000078 -#define ASIZ_task_ngroups 0x00000004 -#define AOFF_task_groups 0x0000007c -#define ASIZ_task_groups 0x00000040 -#define AOFF_task_p_opptr 0x000000bc +#define AOFF_task_p_opptr 0x00000078 #define ASIZ_task_p_opptr 0x00000004 -#define AOFF_task_p_pptr 0x000000c0 +#define AOFF_task_p_pptr 0x0000007c #define ASIZ_task_p_pptr 0x00000004 -#define AOFF_task_p_cptr 0x000000c4 +#define AOFF_task_p_cptr 0x00000080 #define ASIZ_task_p_cptr 0x00000004 -#define AOFF_task_p_ysptr 0x000000c8 +#define AOFF_task_p_ysptr 0x00000084 #define ASIZ_task_p_ysptr 0x00000004 -#define AOFF_task_p_osptr 0x000000cc +#define AOFF_task_p_osptr 0x00000088 #define ASIZ_task_p_osptr 0x00000004 -#define AOFF_task_pidhash_next 0x000000d0 +#define AOFF_task_pidhash_next 0x0000008c #define ASIZ_task_pidhash_next 0x00000004 -#define AOFF_task_pidhash_pprev 0x000000d4 +#define AOFF_task_pidhash_pprev 0x00000090 #define ASIZ_task_pidhash_pprev 0x00000004 -#define AOFF_task_tarray_ptr 0x000000d8 +#define AOFF_task_tarray_ptr 0x00000094 #define ASIZ_task_tarray_ptr 0x00000004 -#define AOFF_task_wait_chldexit 0x000000dc +#define AOFF_task_wait_chldexit 0x00000098 #define ASIZ_task_wait_chldexit 0x00000004 -#define AOFF_task_uid 0x000000e0 -#define ASIZ_task_uid 0x00000002 -#define AOFF_task_euid 0x000000e2 -#define ASIZ_task_euid 0x00000002 -#define AOFF_task_suid 0x000000e4 -#define ASIZ_task_suid 0x00000002 -#define AOFF_task_fsuid 0x000000e6 -#define ASIZ_task_fsuid 0x00000002 -#define AOFF_task_gid 0x000000e8 -#define ASIZ_task_gid 0x00000002 -#define AOFF_task_egid 0x000000ea -#define ASIZ_task_egid 0x00000002 -#define AOFF_task_sgid 0x000000ec -#define ASIZ_task_sgid 0x00000002 -#define AOFF_task_fsgid 0x000000ee -#define ASIZ_task_fsgid 0x00000002 -#define AOFF_task_timeout 0x000000f0 +#define AOFF_task_timeout 0x0000009c #define ASIZ_task_timeout 0x00000004 -#define AOFF_task_policy 0x000000f4 +#define AOFF_task_policy 0x000000a0 #define ASIZ_task_policy 0x00000004 -#define AOFF_task_rt_priority 0x000000f8 +#define AOFF_task_rt_priority 0x000000a4 #define ASIZ_task_rt_priority 0x00000004 -#define AOFF_task_it_real_value 0x000000fc +#define AOFF_task_it_real_value 0x000000a8 #define ASIZ_task_it_real_value 0x00000004 -#define AOFF_task_it_prof_value 0x00000100 +#define AOFF_task_it_prof_value 0x000000ac #define ASIZ_task_it_prof_value 0x00000004 -#define AOFF_task_it_virt_value 0x00000104 +#define AOFF_task_it_virt_value 0x000000b0 #define ASIZ_task_it_virt_value 0x00000004 -#define AOFF_task_it_real_incr 0x00000108 +#define AOFF_task_it_real_incr 0x000000b4 #define ASIZ_task_it_real_incr 0x00000004 -#define AOFF_task_it_prof_incr 0x0000010c +#define AOFF_task_it_prof_incr 0x000000b8 #define ASIZ_task_it_prof_incr 0x00000004 -#define AOFF_task_it_virt_incr 0x00000110 +#define AOFF_task_it_virt_incr 0x000000bc #define ASIZ_task_it_virt_incr 0x00000004 -#define AOFF_task_real_timer 0x00000114 +#define AOFF_task_real_timer 0x000000c0 #define ASIZ_task_real_timer 0x00000014 -#define AOFF_task_times 0x00000128 +#define AOFF_task_times 0x000000d4 #define ASIZ_task_times 0x00000010 -#define AOFF_task_start_time 0x00000138 +#define AOFF_task_start_time 0x000000e4 #define ASIZ_task_start_time 0x00000004 -#define AOFF_task_per_cpu_utime 0x0000013c +#define AOFF_task_per_cpu_utime 0x000000e8 #define ASIZ_task_per_cpu_utime 0x00000080 -#define AOFF_task_min_flt 0x0000023c +#define AOFF_task_min_flt 0x000001e8 #define ASIZ_task_min_flt 0x00000004 -#define AOFF_task_maj_flt 0x00000240 +#define AOFF_task_maj_flt 0x000001ec #define ASIZ_task_maj_flt 0x00000004 -#define AOFF_task_nswap 0x00000244 +#define AOFF_task_nswap 0x000001f0 #define ASIZ_task_nswap 0x00000004 -#define AOFF_task_cmin_flt 0x00000248 +#define AOFF_task_cmin_flt 0x000001f4 #define ASIZ_task_cmin_flt 0x00000004 -#define AOFF_task_cmaj_flt 0x0000024c +#define AOFF_task_cmaj_flt 0x000001f8 #define ASIZ_task_cmaj_flt 0x00000004 -#define AOFF_task_cnswap 0x00000250 +#define AOFF_task_cnswap 0x000001fc #define ASIZ_task_cnswap 0x00000004 -#define AOFF_task_swap_address 0x00000258 +#define AOFF_task_swap_address 0x00000204 #define ASIZ_task_swap_address 0x00000004 -#define AOFF_task_old_maj_flt 0x0000025c +#define AOFF_task_old_maj_flt 0x00000208 #define ASIZ_task_old_maj_flt 0x00000004 -#define AOFF_task_dec_flt 0x00000260 +#define AOFF_task_dec_flt 0x0000020c #define ASIZ_task_dec_flt 0x00000004 -#define AOFF_task_swap_cnt 0x00000264 +#define AOFF_task_swap_cnt 0x00000210 #define ASIZ_task_swap_cnt 0x00000004 -#define AOFF_task_rlim 0x00000268 +#define AOFF_task_uid 0x00000214 +#define ASIZ_task_uid 0x00000002 +#define AOFF_task_euid 0x00000216 +#define ASIZ_task_euid 0x00000002 +#define AOFF_task_suid 0x00000218 +#define ASIZ_task_suid 0x00000002 +#define AOFF_task_fsuid 0x0000021a +#define ASIZ_task_fsuid 0x00000002 +#define AOFF_task_gid 0x0000021c +#define ASIZ_task_gid 0x00000002 +#define AOFF_task_egid 0x0000021e +#define ASIZ_task_egid 0x00000002 +#define AOFF_task_sgid 0x00000220 +#define ASIZ_task_sgid 0x00000002 +#define AOFF_task_fsgid 0x00000222 +#define ASIZ_task_fsgid 0x00000002 +#define AOFF_task_ngroups 0x00000224 +#define ASIZ_task_ngroups 0x00000004 +#define AOFF_task_groups 0x00000228 +#define ASIZ_task_groups 0x00000040 +#define AOFF_task_cap_effective 0x00000268 +#define ASIZ_task_cap_effective 0x00000004 +#define AOFF_task_cap_inheritable 0x0000026c +#define ASIZ_task_cap_inheritable 0x00000004 +#define AOFF_task_cap_permitted 0x00000270 +#define ASIZ_task_cap_permitted 0x00000004 +#define AOFF_task_rlim 0x00000274 #define ASIZ_task_rlim 0x00000050 -#define AOFF_task_used_math 0x000002b8 +#define AOFF_task_used_math 0x000002c4 #define ASIZ_task_used_math 0x00000002 -#define AOFF_task_io_usage 0x000002bc -#define ASIZ_task_io_usage 0x00000004 -#define AOFF_task_comm 0x000002c0 +#define AOFF_task_comm 0x000002c6 #define ASIZ_task_comm 0x00000010 -#define AOFF_task_link_count 0x000002d0 +#define AOFF_task_link_count 0x000002d8 #define ASIZ_task_link_count 0x00000004 -#define AOFF_task_tty 0x000002d4 +#define AOFF_task_tty 0x000002dc #define ASIZ_task_tty 0x00000004 -#define AOFF_task_semundo 0x000002d8 +#define AOFF_task_semundo 0x000002e0 #define ASIZ_task_semundo 0x00000004 -#define AOFF_task_semsleeping 0x000002dc +#define AOFF_task_semsleeping 0x000002e4 #define ASIZ_task_semsleeping 0x00000004 -#define AOFF_task_ldt 0x000002e0 -#define ASIZ_task_ldt 0x00000004 #define AOFF_task_tss 0x000002e8 #define ASIZ_task_tss 0x00000390 #define AOFF_task_fs 0x00000678 @@ -491,6 +497,8 @@ #define ASIZ_mm_def_flags 0x00000004 #define AOFF_mm_cpu_vm_mask 0x00000060 #define ASIZ_mm_cpu_vm_mask 0x00000004 +#define AOFF_mm_segments 0x00000064 +#define ASIZ_mm_segments 0x00000004 #define AOFF_thread_uwinmask 0x00000000 #define ASIZ_thread_uwinmask 0x00000004 #define AOFF_thread_kregs 0x00000004 diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/audioio.h linux/include/asm-sparc/audioio.h --- v2.1.100/linux/include/asm-sparc/audioio.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc/audioio.h Fri May 8 00:11:29 1998 @@ -0,0 +1,409 @@ +/* + * include/asm-sparc/audioio.h + * + * Sparc Audio Midlayer + * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) + */ + +#ifndef _AUDIOIO_H_ +#define _AUDIOIO_H_ + +/* + * SunOS/Solaris /dev/audio interface + */ + +#include +#include +#include + +/* + * This structure contains state information for audio device IO streams. + */ +typedef struct audio_prinfo { + /* + * The following values describe the audio data encoding. + */ + unsigned int sample_rate; /* samples per second */ + unsigned int channels; /* number of interleaved channels */ + unsigned int precision; /* bit-width of each sample */ + unsigned int encoding; /* data encoding method */ + + /* + * The following values control audio device configuration + */ + unsigned int gain; /* gain level: 0 - 255 */ + unsigned int port; /* selected I/O port (see below) */ + unsigned int avail_ports; /* available I/O ports (see below) */ + unsigned int _xxx[2]; /* Reserved for future use */ + + unsigned int buffer_size; /* I/O buffer size */ + + /* + * The following values describe driver state + */ + unsigned int samples; /* number of samples converted */ + unsigned int eof; /* End Of File counter (play only) */ + + unsigned char pause; /* non-zero for pause, zero to resume */ + unsigned char error; /* non-zero if overflow/underflow */ + unsigned char waiting; /* non-zero if a process wants access */ + unsigned char balance; /* stereo channel balance */ + + unsigned short minordev; + + /* + * The following values are read-only state flags + */ + unsigned char open; /* non-zero if open access permitted */ + unsigned char active; /* non-zero if I/O is active */ +} audio_prinfo_t; + + +/* + * This structure describes the current state of the audio device. + */ +typedef struct audio_info { + /* + * Per-stream information + */ + audio_prinfo_t play; /* output status information */ + audio_prinfo_t record; /* input status information */ + + /* + * Per-unit/channel information + */ + unsigned int monitor_gain; /* input to output mix: 0 - 255 */ + unsigned char output_muted; /* non-zero if output is muted */ + unsigned char _xxx[3]; /* Reserved for future use */ + unsigned int _yyy[3]; /* Reserved for future use */ +} audio_info_t; + + +/* + * Audio encoding types + */ +#define AUDIO_ENCODING_NONE (0) /* no encoding assigned */ +#define AUDIO_ENCODING_ULAW (1) /* u-law encoding */ +#define AUDIO_ENCODING_ALAW (2) /* A-law encoding */ +#define AUDIO_ENCODING_LINEAR (3) /* Linear PCM encoding */ +#define AUDIO_ENCODING_DVI (104) /* DVI ADPCM */ +#define AUDIO_ENCODING_LINEAR8 (105) /* 8 bit UNSIGNED */ +#define AUDIO_ENCODING_LINEARLE (106) /* Linear PCM LE encoding */ + +/* + * These ranges apply to record, play, and monitor gain values + */ +#define AUDIO_MIN_GAIN (0) /* minimum gain value */ +#define AUDIO_MAX_GAIN (255) /* maximum gain value */ + +/* + * These values apply to the balance field to adjust channel gain values + */ +#define AUDIO_LEFT_BALANCE (0) /* left channel only */ +#define AUDIO_MID_BALANCE (32) /* equal left/right channel */ +#define AUDIO_RIGHT_BALANCE (64) /* right channel only */ +#define AUDIO_BALANCE_SHIFT (3) + +/* + * Generic minimum/maximum limits for number of channels, both modes + */ +#define AUDIO_MIN_PLAY_CHANNELS (1) +#define AUDIO_MAX_PLAY_CHANNELS (4) +#define AUDIO_MIN_REC_CHANNELS (1) +#define AUDIO_MAX_REC_CHANNELS (4) + +/* + * Generic minimum/maximum limits for sample precision + */ +#define AUDIO_MIN_PLAY_PRECISION (8) +#define AUDIO_MAX_PLAY_PRECISION (32) +#define AUDIO_MIN_REC_PRECISION (8) +#define AUDIO_MAX_REC_PRECISION (32) + +/* + * Define some convenient names for typical audio ports + */ +/* + * output ports (several may be enabled simultaneously) + */ +#define AUDIO_SPEAKER 0x01 /* output to built-in speaker */ +#define AUDIO_HEADPHONE 0x02 /* output to headphone jack */ +#define AUDIO_LINE_OUT 0x04 /* output to line out */ + +/* + * input ports (usually only one at a time) + */ +#define AUDIO_MICROPHONE 0x01 /* input from microphone */ +#define AUDIO_LINE_IN 0x02 /* input from line in */ +#define AUDIO_CD 0x04 /* input from on-board CD inputs */ +#define AUDIO_INTERNAL_CD_IN AUDIO_CD /* input from internal CDROM */ +/* Supposedly an undocumented feature of the 4231 */ +#define AUDIO_ANALOG_LOOPBACK 0x40 + + +/* + * This macro initializes an audio_info structure to 'harmless' values. + * Note that (~0) might not be a harmless value for a flag that was + * a signed int. + */ +#define AUDIO_INITINFO(i) { \ + unsigned int *__x__; \ + for (__x__ = (unsigned int *)(i); \ + (char *) __x__ < (((char *)(i)) + sizeof (audio_info_t)); \ + *__x__++ = ~0); \ +} + +/* + * These allow testing for what the user wants to set + */ +#define AUD_INITVALUE (~0) +#define Modify(X) ((unsigned int)(X) != AUD_INITVALUE) +#define Modifys(X) ((X) != (unsigned short)AUD_INITVALUE) +#define Modifyc(X) ((X) != (unsigned char)AUD_INITVALUE) + +/* + * Parameter for the AUDIO_GETDEV ioctl to determine current + * audio devices. + */ +#define MAX_AUDIO_DEV_LEN (16) +typedef struct audio_device { + char name[MAX_AUDIO_DEV_LEN]; + char version[MAX_AUDIO_DEV_LEN]; + char config[MAX_AUDIO_DEV_LEN]; +} audio_device_t; + + +/* + * Ioctl calls for the audio device. + */ + +/* + * AUDIO_GETINFO retrieves the current state of the audio device. + * + * AUDIO_SETINFO copies all fields of the audio_info structure whose + * values are not set to the initialized value (-1) to the device state. + * It performs an implicit AUDIO_GETINFO to return the new state of the + * device. Note that the record.samples and play.samples fields are set + * to the last value before the AUDIO_SETINFO took effect. This allows + * an application to reset the counters while atomically retrieving the + * last value. + * + * AUDIO_DRAIN suspends the calling process until the write buffers are + * empty. + * + * AUDIO_GETDEV returns a structure of type audio_device_t which contains + * three strings. The string "name" is a short identifying string (for + * example, the SBus Fcode name string), the string "version" identifies + * the current version of the device, and the "config" string identifies + * the specific configuration of the audio stream. All fields are + * device-dependent -- see the device specific manual pages for details. + * + * AUDIO_GETDEV_SUNOS returns a number which is an audio device defined + * herein (making it not too portable) + * + * AUDIO_FLUSH stops all playback and recording, clears all queued buffers, + * resets error counters, and restarts recording and playback as appropriate + * for the current sampling mode. + */ +#define AUDIO_GETINFO _IOR('A', 1, audio_info_t) +#define AUDIO_SETINFO _IOWR('A', 2, audio_info_t) +#define AUDIO_DRAIN _IO('A', 3) +#define AUDIO_GETDEV _IOR('A', 4, audio_device_t) +#define AUDIO_GETDEV_SUNOS _IOR('A', 4, int) +#define AUDIO_FLUSH _IO('A', 5) + +/* Define possible audio hardware configurations for + * old SunOS-style AUDIO_GETDEV ioctl */ +#define AUDIO_DEV_UNKNOWN (0) /* not defined */ +#define AUDIO_DEV_AMD (1) /* audioamd device */ +#define AUDIO_DEV_SPEAKERBOX (2) /* dbri device with speakerbox */ +#define AUDIO_DEV_CODEC (3) /* dbri device (internal speaker) */ +#define AUDIO_DEV_CS4231 (5) /* cs4231 device */ + +/* + * The following ioctl sets the audio device into an internal loopback mode, + * if the hardware supports this. The argument is TRUE to set loopback, + * FALSE to reset to normal operation. If the hardware does not support + * internal loopback, the ioctl should fail with EINVAL. + */ +#define AUDIO_DIAG_LOOPBACK _IOW('A', 101, int) + +#ifdef notneeded +/* + * Structure sent up as a M_PROTO message on trace streams + */ +typedef struct audtrace_hdr audtrace_hdr_t; +struct audtrace_hdr { + unsigned int seq; /* Sequence number (per-aud_stream) */ + int type; /* device-dependent */ + struct timeval timestamp; + char _f[8]; /* filler */ +}; +#endif + +/* + * Linux kernel internal implementation. + */ + +#ifdef __KERNEL__ + +#include +#include +#include +#include + +#define SDF_OPEN_WRITE 0x00000001 +#define SDF_OPEN_READ 0x00000002 + +struct sparcaudio_driver +{ + const char * name; + struct sparcaudio_operations *ops; + void *private; + unsigned long flags; + + /* Processes blocked on open() sit here. */ + struct wait_queue *open_wait; + + /* Task queue for this driver's bottom half. */ + struct tq_struct tqueue; + + /* Support for a circular queue of output buffers. */ + __u8 **output_buffers; + size_t *output_sizes, output_size; + int num_output_buffers, output_front, output_rear; + int output_count, output_active, playing_count; + struct wait_queue *output_write_wait, *output_drain_wait; + + /* Support for a circular queue of input buffers. */ + __u8 **input_buffers; + int input_offset; + int num_input_buffers, input_front, input_rear; + int input_count, input_active, recording_count; + struct wait_queue *input_read_wait; +}; + +struct sparcaudio_operations +{ + int (*open)(struct inode *, struct file *, struct sparcaudio_driver *); + void (*release)(struct inode *, struct file *, struct sparcaudio_driver *); + int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long, + struct sparcaudio_driver *); + + /* Ask driver to begin playing a buffer. */ + void (*start_output)(struct sparcaudio_driver *, __u8 *, unsigned long); + + /* Ask driver to stop playing a buffer. */ + void (*stop_output)(struct sparcaudio_driver *); + + /* Ask driver to begin recording into a buffer. */ + void (*start_input)(struct sparcaudio_driver *, __u8 *, unsigned long); + + /* Ask driver to stop recording. */ + void (*stop_input)(struct sparcaudio_driver *); + + /* Return driver name/version to caller. (/dev/audio specific) */ + void (*sunaudio_getdev)(struct sparcaudio_driver *, audio_device_t *); + + /* Get and set the output volume. (0-255) */ + int (*set_output_volume)(struct sparcaudio_driver *, int); + int (*get_output_volume)(struct sparcaudio_driver *); + + /* Get and set the input volume. (0-255) */ + int (*set_input_volume)(struct sparcaudio_driver *, int); + int (*get_input_volume)(struct sparcaudio_driver *); + + /* Get and set the monitor volume. (0-255) */ + int (*set_monitor_volume)(struct sparcaudio_driver *, int); + int (*get_monitor_volume)(struct sparcaudio_driver *); + + /* Get and set the output balance. (0-64) */ + int (*set_output_balance)(struct sparcaudio_driver *, int); + int (*get_output_balance)(struct sparcaudio_driver *); + + /* Get and set the input balance. (0-64) */ + int (*set_input_balance)(struct sparcaudio_driver *, int); + int (*get_input_balance)(struct sparcaudio_driver *); + + /* Get and set the output channels. (1-4) */ + int (*set_output_channels)(struct sparcaudio_driver *, int); + int (*get_output_channels)(struct sparcaudio_driver *); + + /* Get and set the input channels. (1-4) */ + int (*set_input_channels)(struct sparcaudio_driver *, int); + int (*get_input_channels)(struct sparcaudio_driver *); + + /* Get and set the output precision. (8-32) */ + int (*set_output_precision)(struct sparcaudio_driver *, int); + int (*get_output_precision)(struct sparcaudio_driver *); + + /* Get and set the input precision. (8-32) */ + int (*set_input_precision)(struct sparcaudio_driver *, int); + int (*get_input_precision)(struct sparcaudio_driver *); + + /* Get and set the output port. () */ + int (*set_output_port)(struct sparcaudio_driver *, int); + int (*get_output_port)(struct sparcaudio_driver *); + + /* Get and set the input port. () */ + int (*set_input_port)(struct sparcaudio_driver *, int); + int (*get_input_port)(struct sparcaudio_driver *); + + /* Get and set the output encoding. () */ + int (*set_output_encoding)(struct sparcaudio_driver *, int); + int (*get_output_encoding)(struct sparcaudio_driver *); + + /* Get and set the input encoding. () */ + int (*set_input_encoding)(struct sparcaudio_driver *, int); + int (*get_input_encoding)(struct sparcaudio_driver *); + + /* Get and set the output rate. () */ + int (*set_output_rate)(struct sparcaudio_driver *, int); + int (*get_output_rate)(struct sparcaudio_driver *); + + /* Get and set the input rate. () */ + int (*set_input_rate)(struct sparcaudio_driver *, int); + int (*get_input_rate)(struct sparcaudio_driver *); + + /* Return driver number to caller. (SunOS /dev/audio specific) */ + int (*sunaudio_getdev_sunos)(struct sparcaudio_driver *); + + /* Get available ports */ + int (*get_output_ports)(struct sparcaudio_driver *); + int (*get_input_ports)(struct sparcaudio_driver *); + + /* Get and set output mute */ + int (*set_output_muted)(struct sparcaudio_driver *, int); + int (*get_output_muted)(struct sparcaudio_driver *); +}; + +extern int register_sparcaudio_driver(struct sparcaudio_driver *); +extern int unregister_sparcaudio_driver(struct sparcaudio_driver *); +extern void sparcaudio_output_done(struct sparcaudio_driver *, int); +extern void sparcaudio_input_done(struct sparcaudio_driver *); +extern int sparcaudio_init(void); +extern int amd7930_init(void); +extern int cs4231_init(void); + +#endif + +/* Macros to convert between mixer stereo volumes and gain (mono) */ +#define s_to_m(a) (((((a) >> 8) & 0x7f) + ((a) & 0x7f)) / 2) +#define m_to_s(a) (((a) << 8) + (a)) + +/* convert mixer stereo volume to balance */ +#define s_to_b(a) (AUDIO_RIGHT_BALANCE * ((((a) >> 8) & 0xff) / (((((a) >> 8) & 0xff) + ((a) & 0xff)) / 2))) + +/* convert mixer stereo volume to audio gain */ +#define s_to_g(a) (((((a) >> 8) & 0xff) + ((a) & 0xff)) / 2) + +/* convert gain a and balance b to mixer volume */ +#define b_to_s(a,b) ((a * (b / AUDIO_RIGHT_BALANCE) << 8) + (a * (1 - (b / AUDIO_RIGHT_BALANCE)))) + +#define SPARCAUDIO_MIXER_MINOR 0 +#define SPARCAUDIO_DSP16_MINOR 1 +#define SPARCAUDIO_DSP_MINOR 3 +#define SPARCAUDIO_AUDIO_MINOR 4 +#define SPARCAUDIO_AUDIOCTL_MINOR 5 +#define SPARCAUDIO_STATUS_MINOR 6 +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/dma.h linux/include/asm-sparc/dma.h --- v2.1.100/linux/include/asm-sparc/dma.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc/dma.h Fri May 8 00:11:29 1998 @@ -1,4 +1,4 @@ -/* $Id: dma.h,v 1.25 1998/02/09 13:27:01 jj Exp $ +/* $Id: dma.h,v 1.26 1998/04/13 07:27:05 davem Exp $ * include/asm-sparc/dma.h * * Copyright 1995 (C) David S. Miller (davem@caip.rutgers.edu) @@ -82,7 +82,7 @@ #define DMA_ISESC1(dma) ((dma)->revision == dvmaesc1) /* Main routines in dma.c */ -extern unsigned long dvma_init(struct linux_sbus *, unsigned long); +extern void dvma_init(struct linux_sbus *); /* Fields in the cond_reg register */ /* First, the version identification bits */ diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/elf.h linux/include/asm-sparc/elf.h --- v2.1.100/linux/include/asm-sparc/elf.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc/elf.h Fri May 8 00:11:29 1998 @@ -1,4 +1,4 @@ -/* $Id: elf.h,v 1.15 1998/03/23 08:41:32 jj Exp $ */ +/* $Id: elf.h,v 1.16 1998/05/01 16:28:47 davem Exp $ */ #ifndef __ASMSPARC_ELF_H #define __ASMSPARC_ELF_H @@ -42,7 +42,7 @@ the loader. We need to make sure that it is out of the way of the program that it will "exec", and that there is sufficient room for the brk. */ -#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000) +#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE(0) + 0x1000000) /* This yields a mask that user programs can use to figure out what instruction set this cpu supports. This can NOT be done in userspace diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/irq.h linux/include/asm-sparc/irq.h --- v2.1.100/linux/include/asm-sparc/irq.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc/irq.h Fri May 8 00:11:29 1998 @@ -67,11 +67,6 @@ #define irq_exit(cpu, irq) (local_irq_count[cpu]--) #endif -static __inline__ int irq_cannonicalize(int irq) -{ - return irq; -} - /* Dave Redman (djhr@tadpole.co.uk) * changed these to function pointers.. it saves cycles and will allow * the irq dependencies to be split into different files at a later date diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/linux_logo.h linux/include/asm-sparc/linux_logo.h --- v2.1.100/linux/include/asm-sparc/linux_logo.h Tue May 13 22:41:18 1997 +++ linux/include/asm-sparc/linux_logo.h Fri May 8 00:11:29 1998 @@ -1,4 +1,4 @@ -/* $Id: linux_logo.h,v 1.1 1997/04/16 17:51:24 jj Exp $ +/* $Id: linux_logo.h,v 1.2 1998/05/04 14:20:59 jj Exp $ * include/asm-sparc/linux_logo.h: This is a linux logo * to be displayed on boot. * @@ -25,1004 +25,7 @@ #define LINUX_LOGO_COLORS 221 -unsigned char linux_logo_red[] __initdata = { - 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3, - 0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xE5, - 0xF1, 0xED, 0xEE, 0xE6, 0xC6, 0xDA, 0xDD, 0xE5, - 0xD9, 0xC6, 0xE3, 0xD0, 0xC6, 0xBA, 0xB0, 0xB6, - 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xB0, 0xAD, - 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x9D, - 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99, - 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, - 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x0D, 0x03, - 0x66, 0x44, 0x24, 0x08, 0xD6, 0xE6, 0xE9, 0xE6, - 0xE7, 0xCA, 0xDC, 0xDB, 0xD5, 0xD0, 0xC9, 0xE2, - 0xD5, 0xC6, 0xC4, 0xB3, 0xB2, 0xB9, 0xA9, 0x9A, - 0xB2, 0x9D, 0xE8, 0xEC, 0xF5, 0xF5, 0xF4, 0xF4, - 0xEC, 0xEE, 0xF0, 0xF5, 0xE0, 0xD6, 0xC5, 0xC2, - 0xD9, 0xD5, 0xD8, 0xD6, 0xF6, 0xF4, 0xED, 0xEC, - 0xEB, 0xF1, 0xF6, 0xF5, 0xF5, 0xEE, 0xEF, 0xEC, - 0xE7, 0xE3, 0xE6, 0xD6, 0xDD, 0xC3, 0xD6, 0xD7, - 0xCD, 0xCA, 0xC3, 0xAC, 0x95, 0x99, 0xB7, 0xA3, - 0x8B, 0x88, 0x95, 0x8A, 0x94, 0xD2, 0xCC, 0xC4, - 0xA8, 0x8E, 0x8F, 0xAE, 0xB8, 0xAC, 0xB6, 0xB4, - 0xAD, 0xA5, 0xA0, 0x9B, 0x8B, 0xA3, 0x94, 0x87, - 0x85, 0x89, 0x53, 0x80, 0x7D, 0x7C, 0x7A, 0x78, - 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62, - 0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46, - 0x42, 0x0F, 0x75, 0x78, 0x7D, 0x72, 0x5F, 0x6E, - 0x7A, 0x75, 0x6A, 0x58, 0x48, 0x4F, 0x00, 0x2B, - 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x3B, 0x11, - 0x1D, 0x14, 0x06, 0x02, 0x00 -}; - -unsigned char linux_logo_green[] __initdata = { - 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3, - 0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xD3, - 0xDA, 0xD4, 0xD7, 0xCC, 0xC1, 0xCC, 0xCB, 0xC9, - 0xC5, 0xBC, 0xBC, 0xBB, 0xB7, 0xA5, 0xB0, 0xB6, - 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xAD, 0xAD, - 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x95, - 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99, - 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, - 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x08, 0x02, - 0x53, 0x2E, 0x19, 0x06, 0xC6, 0xC8, 0xCF, 0xBD, - 0xB3, 0xB6, 0xB4, 0xAB, 0xA5, 0xA3, 0x9B, 0xB6, - 0xA7, 0x99, 0x92, 0xA4, 0x9E, 0x9D, 0x98, 0x8C, - 0x8A, 0x86, 0xCD, 0xCC, 0xC9, 0xD7, 0xCA, 0xC4, - 0xCA, 0xC3, 0xC7, 0xC3, 0xC8, 0xB4, 0x91, 0x8E, - 0x8A, 0x82, 0x87, 0x85, 0xBD, 0xBF, 0xB6, 0xBC, - 0xAE, 0xB7, 0xBC, 0xB8, 0xBF, 0xB6, 0xBC, 0xB5, - 0xAB, 0xA6, 0xAD, 0xB2, 0xA5, 0x87, 0x9C, 0x96, - 0x95, 0x8E, 0x87, 0x8F, 0x86, 0x86, 0x8E, 0x80, - 0x7A, 0x70, 0x7B, 0x78, 0x78, 0x7F, 0x77, 0x6F, - 0x70, 0x76, 0x59, 0x77, 0x68, 0x64, 0x7B, 0x7C, - 0x75, 0x6D, 0x77, 0x69, 0x65, 0x5F, 0x5B, 0x54, - 0x4F, 0x5B, 0x39, 0x80, 0x7D, 0x7C, 0x7A, 0x78, - 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62, - 0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46, - 0x42, 0x0B, 0x69, 0x66, 0x64, 0x57, 0x4A, 0x4E, - 0x55, 0x4B, 0x46, 0x3B, 0x30, 0x33, 0x00, 0x2B, - 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x29, 0x0D, - 0x1D, 0x14, 0x06, 0x02, 0x00 -}; - -unsigned char linux_logo_blue[] __initdata = { - 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xEE, 0xE5, 0xDE, - 0xD7, 0xD3, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xB5, - 0xB0, 0xA6, 0xAC, 0x9B, 0xB5, 0xB5, 0xAE, 0x84, - 0x90, 0xA9, 0x81, 0x8D, 0x96, 0x86, 0xB0, 0xB6, - 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xA7, 0xAD, - 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA5, 0x87, - 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x9A, 0x9A, 0x99, - 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, - 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0xC8, 0xD7, - 0x9B, 0x8E, 0x8C, 0xB2, 0x77, 0x77, 0x4E, 0x77, - 0x69, 0x71, 0x78, 0x6B, 0x65, 0x66, 0x64, 0x59, - 0x5C, 0x5A, 0x48, 0x72, 0x7B, 0x6B, 0x67, 0x6E, - 0x42, 0x5B, 0x29, 0x36, 0x25, 0x10, 0x17, 0x14, - 0x19, 0x16, 0x13, 0x0E, 0x08, 0x2E, 0x2E, 0x3D, - 0x24, 0x24, 0x24, 0x24, 0x13, 0x12, 0x14, 0x14, - 0x0E, 0x08, 0x0D, 0x0F, 0x08, 0x0D, 0x0E, 0x08, - 0x08, 0x0C, 0x06, 0x06, 0x07, 0x16, 0x07, 0x0E, - 0x08, 0x0A, 0x07, 0x0D, 0x2D, 0x3E, 0x09, 0x4E, - 0x68, 0x52, 0x56, 0x58, 0x4B, 0x22, 0x20, 0x20, - 0x27, 0x39, 0x28, 0x19, 0x1E, 0x1E, 0x08, 0x06, - 0x07, 0x09, 0x08, 0x08, 0x05, 0x1D, 0x1F, 0x17, - 0x18, 0x06, 0x79, 0x80, 0x7D, 0x7C, 0x7A, 0x78, - 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x68, 0x65, 0x62, - 0x4B, 0x5B, 0x5F, 0x55, 0x56, 0x52, 0x4F, 0x46, - 0x42, 0x5A, 0x14, 0x23, 0x3D, 0x2B, 0x21, 0x14, - 0x06, 0x04, 0x03, 0x07, 0x09, 0x13, 0x2A, 0x3A, - 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x07, 0x09, - 0x1D, 0x14, 0x06, 0x02, 0x00 -}; - -unsigned char linux_logo[] __initdata = { - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57, - 0x58, 0x58, 0x59, 0x5C, 0x5D, 0x5F, 0x60, 0x61, - 0x62, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, - 0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5E, 0x5E, - 0x5E, 0x5D, 0x5D, 0x5C, 0x5D, 0x5B, 0x58, 0x58, - 0x58, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57, - 0x54, 0x56, 0x57, 0x67, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x67, 0x4C, - 0x4A, 0x49, 0x4A, 0x49, 0x4A, 0x49, 0x49, 0x4A, - 0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x50, 0x51, 0x52, - 0x54, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, 0x58, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x58, 0x56, 0x56, 0x53, - 0x52, 0x53, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, - 0x4B, 0x4B, 0x4B, 0x4A, 0x49, 0x4A, 0x4A, 0x49, - 0x49, 0x49, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4B, - 0x4C, 0x4D, 0x52, 0x54, 0x56, 0x55, 0x57, 0x58, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, - 0x50, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF4, 0xFB, - 0xFC, 0x67, 0x53, 0x50, 0x4D, 0x4C, 0x4C, 0x4C, - 0x4B, 0x4A, 0x4A, 0x48, 0x49, 0x48, 0x48, 0x49, - 0x49, 0x49, 0x4B, 0x4C, 0x50, 0x52, 0x53, 0x56, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x55, 0x54, 0x53, 0x51, 0x51, 0x50, 0x4C, 0x4D, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xD2, 0xD7, 0xF5, - 0xFC, 0xFC, 0x5D, 0x5D, 0x5C, 0x5C, 0x59, 0x58, - 0x58, 0x56, 0x52, 0x4C, 0x4B, 0x4A, 0x4A, 0x48, - 0x48, 0x48, 0x48, 0x48, 0x49, 0x4B, 0x4D, 0x51, - 0x54, 0x56, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x55, 0x54, - 0x53, 0x52, 0x51, 0x4D, 0x4D, 0x4D, 0x50, 0x50, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0x64, 0xD9, 0xF5, - 0xF9, 0xFC, 0xFC, 0x64, 0x63, 0x62, 0x61, 0x61, - 0x61, 0x60, 0x5E, 0x5B, 0x5A, 0x54, 0x52, 0x4C, - 0x4B, 0x49, 0x49, 0x47, 0x47, 0x48, 0x49, 0x4B, - 0x4C, 0x51, 0x53, 0x56, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x55, 0x53, 0x53, - 0x51, 0x50, 0x50, 0x50, 0x50, 0x50, 0x53, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xF5, 0xF9, 0xFC, - 0xFC, 0xFC, 0xFC, 0x64, 0x64, 0x64, 0x64, 0x64, - 0x64, 0x64, 0x64, 0x63, 0x61, 0x61, 0x5E, 0x59, - 0x55, 0x52, 0x4C, 0x4A, 0x49, 0x47, 0x48, 0x48, - 0x49, 0x4B, 0x4D, 0x51, 0x54, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x55, 0x54, 0x54, 0x52, 0x51, - 0x51, 0x51, 0x51, 0x51, 0x53, 0x54, 0x59, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF7, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0x60, 0x60, 0x60, 0x61, - 0x62, 0x63, 0x64, 0x64, 0x65, 0x65, 0x64, 0x63, - 0x61, 0x5E, 0x59, 0x56, 0x4D, 0x4B, 0x48, 0x48, - 0x48, 0x48, 0x49, 0x4B, 0x50, 0x53, 0x56, 0x56, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x56, 0x54, 0x53, 0x52, 0x51, 0x51, - 0x51, 0x52, 0x53, 0x55, 0x59, 0x5D, 0x5E, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0x4C, 0x4E, 0x51, 0x52, - 0x57, 0x5A, 0x5E, 0x60, 0x61, 0x63, 0x65, 0xCB, - 0x64, 0x64, 0x63, 0x60, 0x5C, 0x57, 0x50, 0x4B, - 0x48, 0x47, 0x47, 0x47, 0x4A, 0x4C, 0x52, 0x53, - 0x54, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x55, 0x54, 0x53, 0x53, 0x51, 0x52, 0x52, 0x53, - 0x53, 0x57, 0x5A, 0x5D, 0x5E, 0x5E, 0x60, 0xFC, - 0xFC, 0xFC, 0xFB, 0xF9, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFA, 0xF9, 0xF5, 0xFB, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x45, 0x3F, 0x3F, - 0x45, 0x48, 0x4B, 0x4D, 0x54, 0x5A, 0x5E, 0x61, - 0x63, 0xCB, 0xCB, 0x65, 0x64, 0x62, 0x5E, 0x57, - 0x50, 0x4B, 0x48, 0x47, 0x47, 0x48, 0x4B, 0x4D, - 0x51, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, - 0x54, 0x54, 0x53, 0x53, 0x52, 0x53, 0x54, 0x57, - 0x59, 0x5C, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0xFC, - 0xFC, 0xFA, 0xFC, 0xFA, 0xE0, 0xFC, 0xFC, 0xFC, - 0xFB, 0xFB, 0xFB, 0xDF, 0xD8, 0xF9, 0xE0, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x4C, 0x4A, 0x48, - 0x48, 0x3E, 0x44, 0x43, 0x3F, 0x47, 0x4B, 0x52, - 0x5A, 0x5E, 0x62, 0x64, 0xCB, 0xCB, 0x64, 0x61, - 0x5E, 0x57, 0x4D, 0x49, 0x47, 0x47, 0x48, 0x4A, - 0x4C, 0x52, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, - 0x54, 0x53, 0x53, 0x54, 0x54, 0x55, 0x58, 0x5B, - 0x5C, 0x5D, 0x5E, 0x5D, 0x5D, 0x5B, 0x58, 0xFC, - 0xFC, 0xD8, 0x4C, 0x60, 0xFC, 0xF5, 0xFC, 0xFC, - 0xFC, 0xF7, 0x5F, 0x48, 0x48, 0x2C, 0xF8, 0xF9, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x4A, 0x49, - 0x49, 0x49, 0x49, 0x47, 0x3E, 0x44, 0x42, 0x3F, - 0x3E, 0x4B, 0x54, 0x5C, 0x61, 0x64, 0xCB, 0xCB, - 0x64, 0x61, 0x5D, 0x53, 0x4B, 0x49, 0x47, 0x47, - 0x49, 0x4B, 0x50, 0x53, 0x56, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x55, 0x54, - 0x53, 0x53, 0x54, 0x56, 0x58, 0x5A, 0x5B, 0x5D, - 0x5D, 0x5D, 0x5C, 0x5A, 0x54, 0x52, 0x4C, 0xFC, - 0xF7, 0x4E, 0x2D, 0x29, 0x4E, 0xFC, 0xFC, 0xFC, - 0xFB, 0x5F, 0x26, 0x24, 0x20, 0x2E, 0x65, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x45, 0x3F, 0x45, - 0x3E, 0x47, 0x47, 0x47, 0x47, 0x47, 0x3E, 0x44, - 0x43, 0x40, 0x44, 0x49, 0x51, 0x5C, 0x62, 0x64, - 0xCB, 0xCB, 0x63, 0x60, 0x58, 0x50, 0x49, 0x48, - 0x48, 0x48, 0x4A, 0x4D, 0x53, 0x54, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54, - 0x54, 0x54, 0x55, 0x57, 0x59, 0x5B, 0x5C, 0x5D, - 0x5C, 0x5A, 0x54, 0x51, 0x4C, 0x4C, 0x54, 0xFC, - 0xF9, 0x23, 0xDB, 0x2D, 0x23, 0xFA, 0xFB, 0xFA, - 0xF5, 0x27, 0x21, 0xD9, 0xF8, 0x20, 0x21, 0xFB, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x5D, 0x58, 0x55, - 0x50, 0x48, 0x45, 0x43, 0x44, 0x44, 0x45, 0x45, - 0x3E, 0x3F, 0x43, 0x41, 0x3F, 0x48, 0x52, 0x5D, - 0x63, 0x65, 0xCB, 0x65, 0x61, 0x5D, 0x52, 0x4B, - 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54, - 0x54, 0x58, 0x5A, 0x59, 0x5B, 0x5B, 0x5B, 0x5A, - 0x55, 0x52, 0x4D, 0x4D, 0x55, 0x5B, 0x5D, 0xFC, - 0xF1, 0xF9, 0xFC, 0xD4, 0x21, 0xCC, 0xF7, 0xF8, - 0xF2, 0x21, 0xD9, 0xFC, 0xF2, 0xFB, 0x21, 0x45, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xD1, 0xD0, 0xCD, - 0xCC, 0x63, 0x5E, 0x58, 0x50, 0x47, 0x43, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x41, 0x3F, 0x4A, - 0x56, 0x5E, 0x64, 0xCB, 0x65, 0x63, 0x5E, 0x56, - 0x4C, 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, - 0x58, 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, - 0x57, 0x5A, 0x5A, 0x5C, 0x5B, 0x5A, 0x58, 0x54, - 0x51, 0x4C, 0x55, 0x5D, 0x5D, 0x5B, 0x54, 0xFC, - 0xF0, 0xF9, 0xFC, 0x65, 0x45, 0xCD, 0xFB, 0xFB, - 0xF8, 0x26, 0xFB, 0xFC, 0xFC, 0xFC, 0x21, 0x27, - 0xFB, 0xFC, 0xFC, 0xFC, 0xFB, 0xD7, 0x35, 0x34, - 0x2F, 0x35, 0x36, 0x2F, 0x2F, 0x36, 0x2F, 0x2F, - 0x36, 0x36, 0x35, 0x35, 0x43, 0x42, 0x41, 0x2E, - 0x45, 0x4C, 0x5B, 0x62, 0x65, 0xCC, 0x64, 0x60, - 0x58, 0x4D, 0x49, 0x47, 0x47, 0x49, 0x4C, 0x51, - 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x57, - 0x58, 0x5A, 0x5A, 0x5B, 0x5A, 0x55, 0x54, 0x51, - 0x53, 0x5C, 0x5D, 0x5D, 0x54, 0x4B, 0x4D, 0xFC, - 0xFC, 0x44, 0xFC, 0xFB, 0x7B, 0xAB, 0xA8, 0xAE, - 0xAB, 0x7F, 0xFC, 0xFC, 0xFB, 0xFB, 0x22, 0x2A, - 0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x2F, 0x30, 0x30, - 0x32, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x40, 0x41, - 0x2E, 0x40, 0x48, 0x56, 0x5F, 0x64, 0xCC, 0x65, - 0x61, 0x59, 0x50, 0x49, 0x47, 0x47, 0x49, 0x4C, - 0x5A, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, - 0x5A, 0x5A, 0x5A, 0x58, 0x55, 0x52, 0x51, 0x5A, - 0x5D, 0x5D, 0x57, 0x4C, 0x51, 0x54, 0x5D, 0xFC, - 0xFC, 0x2A, 0xFC, 0xC9, 0xAA, 0x8B, 0x8A, 0x8C, - 0xAB, 0x8C, 0x8C, 0xFB, 0xFB, 0x23, 0x20, 0xF1, - 0xFC, 0xFC, 0xFC, 0x3B, 0x33, 0x33, 0x32, 0x32, - 0x31, 0x32, 0x30, 0x32, 0x32, 0x32, 0x32, 0x30, - 0x31, 0x31, 0x31, 0x32, 0x33, 0x33, 0x3C, 0x41, - 0x41, 0x2E, 0x2D, 0x45, 0x4D, 0x5D, 0x63, 0xCC, - 0x65, 0x62, 0x5D, 0x51, 0x49, 0x47, 0x47, 0x4A, - 0x59, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, - 0x5A, 0x5A, 0x58, 0x55, 0x53, 0x53, 0x5C, 0x5E, - 0x59, 0x51, 0x4E, 0x54, 0x59, 0x5E, 0x62, 0xFC, - 0xFC, 0xDB, 0xAA, 0xA1, 0x95, 0x9C, 0x8C, 0x88, - 0x82, 0x83, 0x83, 0x8C, 0x88, 0xAE, 0xB9, 0xFB, - 0xFC, 0xFC, 0xFC, 0x3C, 0x3B, 0x72, 0x38, 0x33, - 0x33, 0x33, 0x31, 0x33, 0x31, 0x31, 0x31, 0x31, - 0x33, 0x33, 0x38, 0x33, 0x72, 0x3B, 0x44, 0x2E, - 0x41, 0x2E, 0x2E, 0x2D, 0x43, 0x4B, 0x5B, 0x63, - 0xCB, 0xCC, 0x63, 0x5D, 0x51, 0x49, 0x47, 0x49, - 0x5C, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, - 0x58, 0x58, 0x57, 0x53, 0x58, 0x5D, 0x5E, 0x55, - 0x51, 0x53, 0x58, 0x5E, 0x60, 0x63, 0x64, 0xFC, - 0xFC, 0xC0, 0xA6, 0x9D, 0x8B, 0x9C, 0x8C, 0x8C, - 0x6E, 0x83, 0x88, 0x8C, 0x8C, 0x8C, 0x83, 0xE8, - 0xFB, 0xFC, 0xFC, 0xFC, 0x33, 0x70, 0x70, 0x6F, - 0x6F, 0x6F, 0x6F, 0x3A, 0x6F, 0x6D, 0x6F, 0x6F, - 0x70, 0x6F, 0x6F, 0x70, 0x6F, 0x32, 0x5A, 0x48, - 0x41, 0x2D, 0x2D, 0x2D, 0x2C, 0x41, 0x49, 0x5A, - 0x62, 0xCB, 0xCB, 0x63, 0x5D, 0x50, 0x49, 0x4A, - 0x5C, 0x58, 0x58, 0x57, 0x55, 0x57, 0x57, 0x57, - 0x57, 0x55, 0x56, 0x59, 0x5E, 0x5C, 0x52, 0x53, - 0x55, 0x5B, 0x5E, 0x61, 0x63, 0x64, 0x63, 0xFC, - 0xE8, 0xBF, 0xA4, 0x99, 0x9C, 0x8C, 0x88, 0x88, - 0x6E, 0x88, 0x8C, 0x8C, 0x8C, 0xC2, 0xA6, 0xC4, - 0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x3A, 0x6F, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x37, 0x32, 0xCD, 0x5E, - 0x4C, 0x43, 0x2C, 0x2D, 0x2D, 0x2C, 0x2E, 0x47, - 0x57, 0x61, 0x65, 0xCC, 0x63, 0x5C, 0x50, 0x4D, - 0x5C, 0x5A, 0x57, 0x55, 0x55, 0x55, 0x58, 0x58, - 0x55, 0x54, 0x5B, 0x5E, 0x5D, 0x53, 0x53, 0x55, - 0x5D, 0x5E, 0x61, 0x61, 0x61, 0x61, 0x5E, 0xFC, - 0xEA, 0xBE, 0xA4, 0x9B, 0x8B, 0x85, 0x8C, 0x6E, - 0x8C, 0x8C, 0x8C, 0xA3, 0xAA, 0xA4, 0xA4, 0xE9, - 0xFB, 0xFC, 0xFC, 0xFC, 0x36, 0x6D, 0x70, 0x73, - 0x70, 0x70, 0x70, 0x73, 0x73, 0x73, 0x73, 0x70, - 0x70, 0x70, 0x73, 0x70, 0x37, 0x38, 0xD1, 0xCF, - 0x61, 0x4D, 0x44, 0x2C, 0x2D, 0x2E, 0x2C, 0x2E, - 0x3E, 0x56, 0x61, 0xCB, 0xCC, 0x62, 0x5B, 0x57, - 0x59, 0x58, 0x55, 0x54, 0x54, 0x55, 0x58, 0x58, - 0x58, 0x5B, 0x5E, 0x5B, 0x53, 0x55, 0x55, 0x5C, - 0x5E, 0x61, 0x61, 0x60, 0x5D, 0x5A, 0x4E, 0xFC, - 0xFC, 0xEA, 0xAA, 0x9C, 0x8A, 0x85, 0x82, 0x8C, - 0x8C, 0xA8, 0xEB, 0xA8, 0xA4, 0xA4, 0xAA, 0xFC, - 0xFC, 0xFC, 0x64, 0xFB, 0x39, 0x31, 0x72, 0x78, - 0x73, 0x78, 0x73, 0x74, 0x74, 0x74, 0x74, 0x73, - 0x78, 0x70, 0x73, 0x73, 0x33, 0xCC, 0xD2, 0xD1, - 0xCE, 0x62, 0x53, 0x3F, 0x2D, 0x2D, 0x41, 0x2C, - 0x2E, 0x3E, 0x56, 0x62, 0xCB, 0xCB, 0x61, 0x5D, - 0x54, 0x54, 0x54, 0x54, 0x56, 0x58, 0x58, 0x58, - 0x5C, 0x5E, 0x5A, 0x55, 0x58, 0x58, 0x5B, 0x5E, - 0x61, 0x5E, 0x5D, 0x5A, 0x52, 0x55, 0xCD, 0xFC, - 0xFC, 0x34, 0xC9, 0xE8, 0xA8, 0xAE, 0xC2, 0xE8, - 0xC3, 0xA6, 0xA7, 0xA6, 0xAA, 0x78, 0x2E, 0x42, - 0xFC, 0xFC, 0xD2, 0x64, 0xF8, 0x31, 0x72, 0x73, - 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x74, 0x73, - 0x73, 0x73, 0x73, 0x72, 0x33, 0x5C, 0x64, 0xD2, - 0xD1, 0xCF, 0x63, 0x54, 0x3F, 0x2C, 0x41, 0x41, - 0x2C, 0x2E, 0x47, 0x58, 0x63, 0xCB, 0xCB, 0x62, - 0x52, 0x53, 0x53, 0x56, 0x58, 0x58, 0x5A, 0x5B, - 0x5E, 0x5A, 0x57, 0x58, 0x58, 0x58, 0x60, 0x60, - 0x5D, 0x5A, 0x55, 0x4E, 0x64, 0xD2, 0xD1, 0xFC, - 0xFC, 0x41, 0x3E, 0xC1, 0xC0, 0xA3, 0xA6, 0xA7, - 0xA7, 0xA9, 0xAA, 0xB8, 0x2E, 0x3F, 0x2C, 0x41, - 0xFC, 0xFC, 0xF7, 0xCE, 0xCD, 0x36, 0x72, 0x73, - 0x74, 0x75, 0x78, 0x75, 0x75, 0x75, 0x74, 0x74, - 0x74, 0x74, 0x78, 0x72, 0x6D, 0x49, 0x59, 0xCB, - 0xD1, 0xD1, 0xD2, 0xCB, 0x56, 0x3F, 0x2C, 0x41, - 0x40, 0x2D, 0x2E, 0x49, 0x5B, 0x64, 0xCC, 0x64, - 0x51, 0x53, 0x53, 0x55, 0x58, 0x59, 0x5B, 0x5E, - 0x59, 0x58, 0x58, 0x58, 0x55, 0x60, 0x60, 0x5C, - 0x5A, 0x53, 0x5B, 0xD0, 0xD3, 0xD3, 0xD3, 0xFB, - 0xFC, 0x40, 0x41, 0x45, 0xC4, 0xC0, 0xBE, 0xBE, - 0xC1, 0xC0, 0x3C, 0x47, 0x2E, 0x21, 0x22, 0x20, - 0x65, 0xFC, 0xFC, 0xFC, 0xFC, 0x6D, 0x72, 0x75, - 0x78, 0x76, 0x75, 0x79, 0x76, 0x76, 0x76, 0x76, - 0x75, 0x75, 0x75, 0x72, 0x6D, 0x2E, 0x48, 0x5D, - 0xCE, 0xD1, 0xD4, 0xD3, 0xCB, 0x56, 0x43, 0x2C, - 0x42, 0x43, 0x2E, 0x2E, 0x4A, 0x5D, 0x64, 0x64, - 0x50, 0x52, 0x56, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, - 0x5A, 0x58, 0x58, 0x55, 0x61, 0x60, 0x58, 0x58, - 0x4E, 0x61, 0xD1, 0xD4, 0xD4, 0xD1, 0xEE, 0xFC, - 0xFC, 0x2B, 0x29, 0x2E, 0x3F, 0xB0, 0xAD, 0x81, - 0x46, 0x2D, 0x46, 0x2C, 0x24, 0x22, 0x22, 0x23, - 0x25, 0xFC, 0xFC, 0xFC, 0xFC, 0x6E, 0x73, 0x76, - 0x76, 0x79, 0x79, 0x79, 0x76, 0x76, 0x79, 0x76, - 0x79, 0x79, 0x79, 0x74, 0x3F, 0x41, 0x2C, 0x48, - 0x5F, 0xCF, 0xD5, 0xD7, 0xD6, 0xCD, 0x57, 0x40, - 0x2E, 0x3F, 0x44, 0x2E, 0x41, 0x4C, 0x60, 0x61, - 0x51, 0x53, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, 0x5C, - 0x58, 0x57, 0x54, 0x5F, 0x5E, 0x55, 0x55, 0x52, - 0x64, 0xD4, 0xD5, 0xD4, 0xD1, 0x5D, 0xFA, 0xFB, - 0xF4, 0x21, 0x24, 0x41, 0x40, 0x44, 0x2E, 0x2E, - 0x42, 0x41, 0x2A, 0x24, 0x22, 0x22, 0x22, 0x22, - 0x23, 0xD9, 0xFC, 0xFC, 0xFC, 0xFC, 0xE5, 0xB8, - 0x8F, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, - 0x8F, 0x8F, 0xB8, 0xE5, 0x3F, 0x3E, 0x43, 0x2C, - 0x48, 0x61, 0xD1, 0xD7, 0xD9, 0xD7, 0xD0, 0x57, - 0x41, 0x2E, 0x3E, 0x44, 0x2D, 0x40, 0x52, 0x5D, - 0x53, 0x55, 0x59, 0x5D, 0x5E, 0x5E, 0x5D, 0x5A, - 0x57, 0x53, 0x5E, 0x5E, 0x54, 0x53, 0x54, 0x65, - 0xD5, 0xD6, 0xD4, 0xCE, 0x53, 0xFB, 0xF9, 0xFC, - 0x24, 0x22, 0x23, 0x23, 0x41, 0x42, 0x2E, 0x40, - 0x2B, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x23, 0x23, 0xFC, 0xFC, 0xFC, 0xFC, 0xE7, 0xBD, - 0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0xB5, 0xC6, 0xEB, 0x2D, 0x47, 0x4A, 0x47, - 0x2C, 0x3E, 0x61, 0xD4, 0xDC, 0xDC, 0xDA, 0xCF, - 0x54, 0x41, 0x41, 0x3E, 0x45, 0x2C, 0x3F, 0x4A, - 0x58, 0x5A, 0x5C, 0x5F, 0x60, 0x5E, 0x5D, 0x57, - 0x51, 0x5D, 0x5D, 0x51, 0x53, 0x53, 0xCB, 0xD5, - 0xD6, 0xD5, 0x63, 0x55, 0xFC, 0xFC, 0xFC, 0x2C, - 0x23, 0x22, 0x23, 0x22, 0x20, 0x2D, 0x2C, 0x26, - 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x21, 0xF0, 0xFC, 0xFC, 0xFC, 0xE2, 0xC6, - 0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0xC7, 0xE3, 0x3E, 0x2E, 0x49, 0x52, - 0x4C, 0x41, 0x44, 0x62, 0xD6, 0xDE, 0xDE, 0xD9, - 0xD0, 0x51, 0x2E, 0x40, 0x47, 0x44, 0x2C, 0x42, - 0x5D, 0x5D, 0x5F, 0x60, 0x60, 0x5D, 0x57, 0x51, - 0x58, 0x5D, 0x4E, 0x52, 0x55, 0x64, 0xD5, 0xD6, - 0xD4, 0x61, 0x59, 0x6B, 0xFC, 0xFC, 0xFC, 0x21, - 0x23, 0x22, 0x23, 0x22, 0x23, 0x21, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x21, 0x24, 0xFC, 0xFC, 0xFC, 0xE2, 0xC7, - 0xB5, 0x90, 0x93, 0x93, 0x93, 0x90, 0x93, 0x93, - 0x90, 0xB5, 0xC8, 0xE4, 0x5F, 0x45, 0x2E, 0x4D, - 0x57, 0x57, 0x44, 0x43, 0x63, 0xDA, 0xDF, 0xDF, - 0xD9, 0xCE, 0x4C, 0x2C, 0x3F, 0x3E, 0x40, 0x40, - 0x60, 0x5E, 0x61, 0x61, 0x5E, 0x5B, 0x53, 0x52, - 0x5C, 0x52, 0x52, 0x55, 0x61, 0xD4, 0xD5, 0xD1, - 0x5E, 0x5B, 0x5C, 0xFB, 0xFC, 0xFC, 0x2A, 0x21, - 0x23, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0xFB, 0xFC, 0xFC, 0xB3, 0xC8, - 0xB5, 0x90, 0x92, 0xB5, 0x93, 0x93, 0xB5, 0x93, - 0x92, 0xB5, 0xC8, 0xB9, 0xD0, 0x5E, 0x44, 0x40, - 0x52, 0x58, 0x57, 0x48, 0x40, 0x63, 0xD9, 0xE0, - 0xE0, 0xD9, 0xCB, 0x49, 0x2D, 0x3F, 0x45, 0x3F, - 0x63, 0x61, 0x62, 0x60, 0x5E, 0x55, 0x4D, 0x59, - 0x53, 0x4E, 0x54, 0x5D, 0xD2, 0xD4, 0xD2, 0x5E, - 0x5C, 0x5D, 0xFC, 0xFC, 0xFC, 0xF8, 0x29, 0x23, - 0x23, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x23, 0x22, 0x22, 0x23, 0x23, 0x23, 0x22, 0x22, - 0x22, 0x22, 0x22, 0xF0, 0xFC, 0xFC, 0xB3, 0xC7, - 0xB5, 0x93, 0xB5, 0x93, 0x93, 0x91, 0x93, 0x93, - 0x91, 0xB5, 0xC7, 0xAD, 0xD6, 0xD2, 0x5E, 0x3F, - 0x3F, 0x57, 0x57, 0x58, 0x4A, 0x41, 0x64, 0xDC, - 0xF1, 0xDF, 0xDA, 0x61, 0x45, 0x2E, 0x43, 0x47, - 0xCB, 0x63, 0x62, 0x5F, 0x58, 0x51, 0x53, 0x54, - 0x4C, 0x52, 0x5C, 0xCD, 0xD3, 0xD2, 0x60, 0x5D, - 0x5D, 0xFB, 0xFC, 0xFC, 0xFC, 0xDB, 0x49, 0x24, - 0x21, 0x23, 0x23, 0x22, 0x26, 0x26, 0x2A, 0x24, - 0x22, 0x23, 0x22, 0x21, 0x24, 0x26, 0x26, 0x2A, - 0x29, 0x2B, 0x24, 0x25, 0xFC, 0xFC, 0xB3, 0xC5, - 0x91, 0x91, 0x92, 0x91, 0x92, 0x92, 0x93, 0x93, - 0x91, 0x93, 0xC6, 0xAD, 0xDC, 0xD9, 0xD4, 0x60, - 0x43, 0x45, 0x58, 0x58, 0x57, 0x4B, 0x43, 0xCC, - 0xDD, 0xF1, 0xD8, 0xD5, 0x5D, 0x43, 0x41, 0x47, - 0xCD, 0x63, 0x62, 0x5D, 0x54, 0x4C, 0x55, 0x4B, - 0x51, 0x58, 0x62, 0xD0, 0xD0, 0x62, 0x5D, 0x5D, - 0x67, 0xFC, 0xFC, 0xFC, 0xFC, 0x58, 0x4E, 0x28, - 0x2A, 0x20, 0x23, 0x22, 0x23, 0x2A, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x23, 0x25, 0x2A, 0x2E, 0x2D, - 0x2E, 0x2E, 0x2E, 0x23, 0xFA, 0xFC, 0xB2, 0xBD, - 0xB5, 0x90, 0x91, 0x93, 0x92, 0x90, 0x91, 0x93, - 0x92, 0x91, 0xBD, 0xAD, 0xDE, 0xE0, 0xD8, 0xD7, - 0x61, 0x40, 0x48, 0x58, 0x58, 0x58, 0x48, 0x44, - 0xCF, 0xDE, 0xE0, 0xDD, 0xD0, 0x52, 0x41, 0x45, - 0xCD, 0x63, 0x61, 0x58, 0x4D, 0x51, 0x4C, 0x4B, - 0x54, 0x5D, 0xCC, 0xCE, 0x63, 0x61, 0x5D, 0x5D, - 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x27, 0x21, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x24, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x20, - 0x27, 0x2B, 0x41, 0x2B, 0x23, 0xFC, 0xB2, 0xB6, - 0x93, 0x90, 0x92, 0xB5, 0x92, 0x90, 0xB5, 0x90, - 0x92, 0x93, 0xBC, 0xAD, 0xDC, 0xF1, 0xF3, 0xF0, - 0xD9, 0x61, 0x41, 0x4A, 0x58, 0x57, 0x57, 0x44, - 0x49, 0xD2, 0xDD, 0xD8, 0xDA, 0x63, 0x4A, 0x45, - 0xCC, 0x63, 0x5E, 0x52, 0x4B, 0x4C, 0x49, 0x51, - 0x5C, 0x61, 0xCD, 0x65, 0x63, 0x5E, 0x4E, 0xCF, - 0xFB, 0xFB, 0xF0, 0xFC, 0xD2, 0x2A, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x26, 0x41, 0x27, 0xF9, 0x81, 0xB7, - 0xB5, 0x91, 0x92, 0xB5, 0x91, 0xB5, 0x93, 0xB5, - 0x93, 0xB6, 0xB7, 0xB9, 0xCB, 0xD8, 0xF3, 0xF2, - 0xF2, 0xDB, 0x61, 0x2D, 0x51, 0x58, 0x57, 0x58, - 0x41, 0x51, 0xD4, 0xDB, 0xDC, 0xD1, 0x5B, 0x4C, - 0xCB, 0x62, 0x59, 0x4C, 0x4A, 0x49, 0x4B, 0x55, - 0x60, 0x64, 0xCC, 0x64, 0x5E, 0x55, 0x60, 0xE1, - 0xFB, 0xF8, 0xFC, 0xFC, 0x21, 0x22, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x21, 0x24, 0x2D, 0x21, 0xB4, 0xBB, - 0xB6, 0xB5, 0xB6, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6, - 0xB6, 0xB6, 0xBB, 0xB9, 0x45, 0xCB, 0xDF, 0xF3, - 0xF3, 0xF3, 0xDB, 0x5E, 0x2C, 0x51, 0x58, 0x58, - 0x52, 0x2D, 0x5C, 0xD4, 0xD9, 0xD5, 0x63, 0x58, - 0x64, 0x60, 0x53, 0x49, 0x4A, 0x49, 0x52, 0x5C, - 0x63, 0xCD, 0xCD, 0x63, 0x5C, 0x4E, 0x65, 0xFC, - 0xFC, 0xF5, 0xFC, 0xD2, 0x23, 0x22, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x21, 0x22, 0x25, 0x29, 0xB3, 0xC7, - 0xB5, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, - 0xB6, 0xB5, 0xC7, 0xAD, 0x57, 0x3F, 0xCB, 0xF0, - 0xF3, 0xF3, 0xF2, 0xD9, 0x58, 0x41, 0x4C, 0x58, - 0x57, 0x47, 0x42, 0x62, 0xD4, 0xD4, 0xCC, 0x60, - 0x63, 0x5D, 0x50, 0x47, 0x48, 0x4B, 0x58, 0x60, - 0xCC, 0xCE, 0xCD, 0x60, 0x53, 0x5C, 0x62, 0xFB, - 0xF9, 0xFC, 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x23, 0x23, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0x81, 0xC7, - 0xB7, 0xB7, 0xBC, 0xB7, 0xBC, 0xBC, 0xBC, 0xB7, - 0xB7, 0xB7, 0xC8, 0x80, 0x58, 0x57, 0x40, 0xCE, - 0xF3, 0xF2, 0xF2, 0xF0, 0xD5, 0x4C, 0x3F, 0x4B, - 0x52, 0x50, 0x2D, 0x4B, 0x64, 0xD2, 0xCC, 0x61, - 0x60, 0x58, 0x4A, 0x47, 0x47, 0x4C, 0x59, 0x64, - 0xD0, 0xD0, 0x64, 0x59, 0x49, 0x5D, 0xFB, 0xFC, - 0xD9, 0xFC, 0xD6, 0x23, 0x22, 0x22, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x23, 0x21, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0xB4, 0xC8, - 0xBD, 0xB7, 0xBD, 0xBC, 0xBD, 0xC5, 0xBC, 0xC5, - 0xBC, 0xBD, 0xC7, 0xAC, 0x58, 0x57, 0x58, 0x2C, - 0xD1, 0xF0, 0xF3, 0xF3, 0xE0, 0xCD, 0x45, 0x3E, - 0x48, 0x4B, 0x3F, 0x41, 0x56, 0x64, 0x65, 0x62, - 0x5D, 0x52, 0x47, 0x48, 0x48, 0x53, 0x60, 0xCC, - 0xD2, 0xD0, 0x63, 0x52, 0x4E, 0x53, 0xFB, 0xFB, - 0xFC, 0xFC, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x23, 0x20, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0xB4, 0xC7, - 0xC5, 0xBC, 0xC5, 0xBD, 0xC5, 0xC5, 0xBD, 0xC5, - 0xBC, 0xC6, 0xC7, 0xB9, 0x58, 0x57, 0x58, 0x57, - 0x2D, 0xD4, 0xF1, 0xF2, 0xF0, 0xD9, 0x5D, 0x47, - 0x48, 0x3F, 0x42, 0x2C, 0x48, 0x5C, 0x5F, 0x60, - 0x58, 0x50, 0x47, 0x4A, 0x49, 0x55, 0x63, 0xD0, - 0xD2, 0xCD, 0x5D, 0x49, 0x4E, 0xE1, 0xFC, 0xF0, - 0xFC, 0xF8, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x20, 0x21, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, - 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, 0xC4, 0xC8, - 0xBD, 0xBD, 0xC6, 0xBD, 0xC6, 0xC6, 0xC5, 0xC6, - 0xBD, 0xC6, 0xC7, 0xE4, 0x54, 0x57, 0x58, 0x57, - 0x57, 0x43, 0xD7, 0xE0, 0xF1, 0xD8, 0xCD, 0x4B, - 0x4A, 0x47, 0x42, 0x2C, 0x3F, 0x4D, 0x58, 0x5C, - 0x52, 0x4B, 0x48, 0x4B, 0x4A, 0x58, 0xCB, 0xD3, - 0xD2, 0xCD, 0x58, 0x47, 0x4A, 0xFC, 0xFC, 0xFB, - 0xFC, 0x2B, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x26, 0x21, 0x21, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0xE5, 0xC8, - 0xBA, 0xC5, 0xC6, 0xC6, 0xC6, 0xC7, 0xC6, 0xC7, - 0xC5, 0xC6, 0xC8, 0xE5, 0x2E, 0x54, 0x58, 0x57, - 0x57, 0x4C, 0x4D, 0xDA, 0xD8, 0xD8, 0xD4, 0x5C, - 0x4B, 0x4B, 0x3F, 0x42, 0x44, 0x4A, 0x51, 0x58, - 0x4B, 0x48, 0x4B, 0x51, 0x4D, 0x5F, 0xD0, 0xD1, - 0xD0, 0x64, 0x51, 0x44, 0x6B, 0xFC, 0xFB, 0xFC, - 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x26, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0xE5, 0xED, - 0xE7, 0xBA, 0xC8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7, - 0xC7, 0xE5, 0xED, 0xE6, 0x61, 0x41, 0x52, 0x58, - 0x58, 0x57, 0x45, 0x5E, 0xD7, 0xDD, 0xD5, 0x60, - 0x4B, 0x4C, 0x48, 0x4D, 0x4D, 0x50, 0x4D, 0x56, - 0x4A, 0x3E, 0x53, 0x53, 0x52, 0x63, 0xD3, 0xD0, - 0xCE, 0x60, 0x4A, 0x45, 0xFC, 0xFC, 0xF7, 0xFC, - 0xFC, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x21, 0x2A, 0x20, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x21, 0x23, 0xEB, 0xF6, - 0xF6, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, - 0xF6, 0xF6, 0xF6, 0xE6, 0xDB, 0x58, 0x45, 0x4B, - 0x58, 0x57, 0x4D, 0x4B, 0x64, 0xD4, 0xD0, 0x5C, - 0x48, 0x51, 0x4C, 0x5D, 0x5E, 0x5C, 0x56, 0x59, - 0x3E, 0x4A, 0x58, 0x54, 0x52, 0x65, 0xD3, 0xD0, - 0xCF, 0x5D, 0x48, 0xFC, 0xFC, 0xFC, 0xFA, 0xFC, - 0xFC, 0x21, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x21, 0x2A, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x21, 0x4F, 0xE6, 0xC6, - 0xC6, 0xBD, 0xC6, 0xBD, 0xBD, 0xBD, 0xBD, 0xC6, - 0xC5, 0xBA, 0xC7, 0xE6, 0xF2, 0xD4, 0x49, 0x4B, - 0x3E, 0x4D, 0x52, 0x3E, 0x52, 0x63, 0x64, 0x56, - 0x48, 0x54, 0x4D, 0x61, 0xCC, 0xCC, 0x60, 0x60, - 0x47, 0x4D, 0x5C, 0x53, 0x58, 0xCF, 0xD1, 0xCF, - 0xD0, 0x59, 0x45, 0xFC, 0xFC, 0xFC, 0xEF, 0xF9, - 0xFC, 0x21, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x23, 0x4F, 0xE4, 0xB9, - 0xAF, 0x80, 0x80, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F, - 0x80, 0xB4, 0xB9, 0xE4, 0x7F, 0xDE, 0x61, 0x52, - 0x54, 0x48, 0x3F, 0x43, 0x4D, 0x56, 0x59, 0x4B, - 0x3E, 0x58, 0x53, 0x61, 0xD3, 0xD4, 0xCF, 0xCD, - 0x4C, 0x58, 0x5F, 0x53, 0x5E, 0xD3, 0xD0, 0xCE, - 0xCE, 0x52, 0x3F, 0xFC, 0xFC, 0xFC, 0xF7, 0x65, - 0xFA, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x21, 0x2A, 0x23, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x21, 0xB1, 0xE4, 0xE6, - 0x7C, 0xB1, 0x7C, 0xB1, 0xB2, 0xB2, 0xB3, 0x3D, - 0xB3, 0x3C, 0xE5, 0xB3, 0xB0, 0xF1, 0xD0, 0x58, - 0x5D, 0x4D, 0x40, 0x41, 0x48, 0x51, 0x4C, 0x3F, - 0x3F, 0x4D, 0x5A, 0x5A, 0xD5, 0xD9, 0xD7, 0xD4, - 0x57, 0x5E, 0x61, 0x4C, 0x63, 0xD4, 0xCF, 0xCE, - 0xCB, 0x4D, 0x4A, 0xFC, 0xFC, 0xFC, 0xFC, 0xF0, - 0xFB, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x22, 0x23, 0x22, 0x23, 0x23, 0xB1, 0x81, 0x7D, - 0x39, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x7C, 0xB2, 0xB0, 0xDF, 0xD2, 0x57, - 0x60, 0x59, 0x5B, 0x59, 0x52, 0x4C, 0x4A, 0x40, - 0x42, 0x4A, 0x53, 0x4D, 0xD2, 0xDE, 0xDE, 0xD9, - 0x5E, 0x5E, 0x60, 0x4A, 0xCD, 0xD1, 0xCF, 0xCE, - 0x63, 0x49, 0x5C, 0xFB, 0xE8, 0x89, 0x9F, 0xFC, - 0xD6, 0x21, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x21, 0x2A, 0x22, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x7F, 0xB9, - 0x71, 0x6C, 0x38, 0x38, 0x33, 0x33, 0x33, 0x38, - 0x38, 0x71, 0xAD, 0xE4, 0xD3, 0xDA, 0xCC, 0x52, - 0x63, 0x60, 0xCE, 0xD4, 0xCF, 0x60, 0x4C, 0x40, - 0x3F, 0x45, 0x4B, 0x5A, 0xCB, 0xD8, 0xDE, 0xDC, - 0x5E, 0x5E, 0x5F, 0x4C, 0xD2, 0xD2, 0xCF, 0xCF, - 0x61, 0x45, 0x5E, 0xA7, 0x9D, 0x95, 0x8B, 0x99, - 0xFC, 0x41, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x23, 0x2A, 0x23, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x77, 0x77, 0xF6, - 0xFC, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, - 0x7D, 0xFC, 0x47, 0x64, 0xD0, 0xD0, 0x5D, 0x4B, - 0x62, 0xCC, 0xD1, 0xDE, 0xDE, 0xD4, 0x5E, 0x43, - 0x3F, 0x3E, 0x48, 0x53, 0x58, 0xDB, 0xD8, 0xDC, - 0x5E, 0x5E, 0x5E, 0x53, 0xD4, 0xD2, 0xD0, 0xD0, - 0x5E, 0x49, 0xA7, 0xA6, 0x89, 0x95, 0x8B, 0x9C, - 0x9C, 0xFB, 0xD4, 0x22, 0x22, 0x22, 0x22, 0x23, - 0x22, 0x23, 0x23, 0x2A, 0x22, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x23, 0x22, 0x23, 0x23, 0x98, 0x8C, 0x8C, 0x88, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, - 0xE9, 0x9C, 0x48, 0x5C, 0xD0, 0xCB, 0x48, 0x49, - 0x5B, 0xCB, 0xCD, 0xE0, 0xF1, 0xDD, 0xD0, 0x4A, - 0x41, 0x47, 0x45, 0x4C, 0x48, 0xD7, 0xDE, 0xDC, - 0x5E, 0x5E, 0x5A, 0x58, 0xD1, 0xD0, 0xD0, 0xD2, - 0x5C, 0x55, 0xA7, 0xA6, 0x87, 0x86, 0x89, 0x94, - 0x9C, 0xA9, 0xFC, 0xF4, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x22, 0x2A, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x22, 0x23, 0xA4, 0x89, 0x8C, 0xAA, - 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF7, - 0x85, 0x88, 0x8D, 0x59, 0x64, 0x63, 0x47, 0x3E, - 0x4C, 0x60, 0x61, 0xE0, 0xF0, 0xDF, 0xD9, 0x5D, - 0x2E, 0x3E, 0x3E, 0x47, 0x4D, 0xCD, 0xDE, 0xDC, - 0x5D, 0x5C, 0x51, 0x5D, 0xD1, 0xD2, 0xD2, 0xD4, - 0x5A, 0xBE, 0xA7, 0x98, 0x8A, 0x8A, 0xA0, 0x8B, - 0x86, 0x86, 0xF7, 0xFC, 0xF7, 0x26, 0x23, 0x23, - 0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x21, 0x21, 0x21, 0xA1, 0x98, 0x9F, 0xBF, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xA7, - 0x8C, 0x86, 0x8D, 0x59, 0x5E, 0x5D, 0x3F, 0x3E, - 0x47, 0x53, 0x63, 0xD9, 0xF0, 0xF1, 0xDE, 0xD0, - 0x43, 0x3E, 0x47, 0x45, 0x4A, 0x5B, 0xDC, 0xDA, - 0x5D, 0x59, 0x49, 0x5F, 0xD1, 0xD2, 0xD3, 0xB9, - 0xA5, 0xA7, 0x98, 0x9B, 0x96, 0x9D, 0x89, 0x89, - 0x8B, 0x9C, 0x9D, 0xFC, 0xFC, 0xFC, 0x26, 0x22, - 0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x29, 0x2D, 0x99, 0x99, 0xA2, 0xAA, - 0xC4, 0xFB, 0xFC, 0xFC, 0xFC, 0xF6, 0xBF, 0xA2, - 0x9C, 0x9C, 0x8E, 0xDC, 0xCD, 0x51, 0x41, 0x3E, - 0x45, 0x49, 0x58, 0xCD, 0xE0, 0xE0, 0xD8, 0xDA, - 0x4C, 0x4A, 0x45, 0x45, 0x48, 0x47, 0xDA, 0xDA, - 0x5C, 0x58, 0x44, 0x69, 0xA9, 0x98, 0xA4, 0xA6, - 0xA1, 0xA4, 0x99, 0x9E, 0x9D, 0x8B, 0x8A, 0x97, - 0x87, 0x9A, 0x8A, 0xC2, 0xFC, 0xFC, 0xFC, 0x4D, - 0x21, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, - 0x21, 0x22, 0x2D, 0x34, 0xA4, 0xA2, 0xA2, 0xA9, - 0xBF, 0xC0, 0xC3, 0xC1, 0xC0, 0xBE, 0xA6, 0x9D, - 0x99, 0x87, 0xA2, 0xF1, 0xDC, 0x64, 0x42, 0x45, - 0x47, 0x3E, 0x49, 0x4C, 0xDD, 0xDF, 0xD8, 0xDB, - 0x5E, 0x4C, 0x48, 0x45, 0x45, 0x41, 0xD1, 0xD6, - 0x5A, 0x55, 0x3F, 0xA7, 0xA1, 0x98, 0x9F, 0x99, - 0x9F, 0x9D, 0x9A, 0x95, 0x8B, 0x97, 0x89, 0x8A, - 0x88, 0x94, 0x9C, 0x8C, 0xFC, 0xFC, 0xFC, 0xFC, - 0xF4, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x23, 0x23, 0x2C, 0x2C, 0xA8, 0xA2, 0xA4, 0xA4, - 0xA9, 0xAA, 0xAA, 0xAA, 0xA9, 0xA6, 0x98, 0x9C, - 0x8B, 0x88, 0x98, 0x8D, 0xD8, 0xD6, 0x4E, 0x47, - 0x47, 0x49, 0x47, 0x3F, 0xDA, 0xDD, 0xDE, 0xDD, - 0xCC, 0x4A, 0x4B, 0x3E, 0x45, 0x43, 0x61, 0xD4, - 0x56, 0x51, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0x9A, - 0xA0, 0xA2, 0x98, 0x98, 0x8B, 0x8B, 0x98, 0x98, - 0x84, 0x8B, 0x94, 0x8A, 0xA4, 0xFC, 0xFC, 0xFC, - 0xFC, 0xF2, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x22, 0x2C, 0x2D, 0xC0, 0xA4, 0xA2, 0xA4, - 0xA4, 0xA6, 0xA6, 0xA6, 0xA4, 0xA2, 0x9F, 0x89, - 0x8B, 0x9C, 0x9C, 0x8B, 0x68, 0xDB, 0x5F, 0x4B, - 0x3E, 0x49, 0x4B, 0x3E, 0xCC, 0xDA, 0xDC, 0xDD, - 0xD3, 0x49, 0x52, 0x48, 0x45, 0x45, 0x53, 0xD0, - 0x51, 0x4A, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0xA0, - 0x9B, 0x86, 0x89, 0x98, 0x89, 0x8A, 0x96, 0x8A, - 0x9C, 0x89, 0x89, 0x9C, 0x8C, 0xF6, 0xFC, 0xFC, - 0xFC, 0xFC, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23, - 0x22, 0x21, 0x2B, 0x34, 0xC0, 0xA8, 0xA4, 0xA2, - 0xA2, 0x98, 0xA1, 0xA0, 0x98, 0x9F, 0x95, 0x8A, - 0x94, 0xA1, 0x8A, 0x84, 0x9B, 0x68, 0xCC, 0x49, - 0x4A, 0x47, 0x4C, 0x4B, 0x51, 0xD3, 0xDA, 0xDC, - 0xD5, 0x56, 0x56, 0x4A, 0x3E, 0x45, 0x48, 0x63, - 0x4A, 0x47, 0x3E, 0xA7, 0x98, 0x9D, 0x9E, 0x8B, - 0x95, 0x9B, 0x89, 0x86, 0x9B, 0x8B, 0x89, 0x84, - 0x9A, 0xA1, 0x95, 0x9A, 0x8C, 0xA4, 0xFC, 0xFC, - 0xFC, 0xFA, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23, - 0x21, 0x23, 0x2C, 0xF6, 0xBF, 0xA9, 0xA2, 0x99, - 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9B, 0x87, 0x8B, - 0x9C, 0x86, 0x9C, 0x8A, 0x87, 0x87, 0x89, 0x51, - 0x54, 0x47, 0x4B, 0x50, 0x4B, 0xCF, 0xD6, 0xDC, - 0xD5, 0x60, 0x54, 0x52, 0x48, 0x45, 0x40, 0x5A, - 0x45, 0x43, 0x47, 0xA7, 0x98, 0x9B, 0x95, 0x95, - 0x9A, 0x87, 0x98, 0x98, 0x8A, 0x86, 0x87, 0x9E, - 0x9B, 0x95, 0x9D, 0x9D, 0x99, 0x85, 0xA6, 0xFA, - 0xF2, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x22, - 0x21, 0x24, 0xFB, 0xF7, 0xBF, 0xA6, 0xA2, 0x99, - 0x97, 0x89, 0x86, 0x89, 0x9C, 0x96, 0x9E, 0x94, - 0x89, 0x99, 0x98, 0x89, 0x9E, 0x9B, 0x89, 0x8B, - 0x58, 0x4B, 0x4A, 0x52, 0x48, 0xCC, 0xD3, 0xDA, - 0xD3, 0x65, 0x4C, 0x58, 0x49, 0x3E, 0x2E, 0x4D, - 0x40, 0x41, 0x45, 0xA9, 0xA1, 0x9B, 0x9E, 0x9C, - 0x95, 0x8A, 0x94, 0x89, 0x96, 0x87, 0x9C, 0x9A, - 0x84, 0x9D, 0x9C, 0x9E, 0x9A, 0x9C, 0x9D, 0xBB, - 0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x23, 0x23, - 0x24, 0xFC, 0xFC, 0xF6, 0xBF, 0xA6, 0x9F, 0x99, - 0x89, 0x95, 0x87, 0x94, 0x9D, 0x9E, 0x97, 0x9E, - 0x95, 0x9B, 0x89, 0x95, 0x95, 0x9B, 0x89, 0x87, - 0x5D, 0x56, 0x3E, 0x51, 0x3E, 0x60, 0xCF, 0xD3, - 0xD2, 0xCD, 0x5C, 0x49, 0x4B, 0x3E, 0x2C, 0x48, - 0x3E, 0x43, 0x3E, 0xA9, 0xA1, 0x9B, 0x97, 0x94, - 0x95, 0x9A, 0x9C, 0x87, 0x87, 0x9B, 0x9C, 0x95, - 0x9D, 0x89, 0x9A, 0x89, 0x9E, 0x9E, 0x8C, 0xA6, - 0x20, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x20, 0x40, - 0xFC, 0xFC, 0xFC, 0xEC, 0xBE, 0xA4, 0x9F, 0x99, - 0x95, 0x9F, 0xA0, 0x88, 0x9D, 0x8B, 0x97, 0x95, - 0x87, 0x95, 0x96, 0x95, 0x97, 0x94, 0x94, 0x98, - 0xD3, 0x4C, 0x47, 0x4D, 0x42, 0x4C, 0x60, 0xCC, - 0xCE, 0xD0, 0x65, 0x4B, 0x47, 0x44, 0x2B, 0x45, - 0x4B, 0x47, 0x49, 0xA7, 0xA1, 0x9A, 0x97, 0x89, - 0x95, 0x97, 0x97, 0x9E, 0x89, 0x95, 0x89, 0x9C, - 0x87, 0x95, 0x97, 0x99, 0x95, 0x99, 0x9F, 0xA4, - 0xC4, 0x21, 0x21, 0x23, 0x21, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x21, 0x20, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xEA, 0xAA, 0xA6, 0xA2, 0x99, - 0x8B, 0x9A, 0x95, 0x9E, 0x9E, 0x9A, 0x94, 0x87, - 0x94, 0x94, 0x89, 0x94, 0x9B, 0x9B, 0xA7, 0xDC, - 0xDB, 0x65, 0x2E, 0x3E, 0x43, 0x44, 0x49, 0x58, - 0x63, 0xD3, 0xD3, 0x5E, 0x42, 0x42, 0x2D, 0x40, - 0x54, 0x4C, 0x4A, 0xA7, 0xA0, 0x99, 0x9B, 0x94, - 0xA0, 0x8A, 0x9B, 0x9D, 0x87, 0x95, 0x94, 0x8B, - 0x8A, 0x98, 0x9C, 0x8A, 0x9B, 0x99, 0xA2, 0xA6, - 0xBF, 0xEC, 0x2A, 0x20, 0x21, 0x23, 0x21, 0x20, - 0x20, 0x20, 0x20, 0x4C, 0xF9, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xEB, 0xAA, 0xA4, 0x9F, 0x9C, - 0x8B, 0x9B, 0x88, 0x84, 0x9E, 0x9D, 0x96, 0x94, - 0x94, 0x9A, 0x9B, 0x9B, 0xA4, 0xD5, 0xCD, 0xDE, - 0xF1, 0xDA, 0x4C, 0x2D, 0x41, 0x2B, 0x42, 0x4C, - 0x5E, 0xD4, 0xD7, 0xCD, 0x49, 0x2E, 0x2E, 0x41, - 0x5E, 0x57, 0xA7, 0xA6, 0xA7, 0xA4, 0xA2, 0x98, - 0x9D, 0x9C, 0xA1, 0x99, 0x9D, 0x88, 0x8B, 0x9C, - 0x8A, 0x9C, 0x9C, 0x94, 0x9C, 0x89, 0xA0, 0xA6, - 0xAA, 0xEB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFB, 0xE9, 0xAA, 0xA6, 0xA2, 0x8B, - 0x8B, 0x8A, 0x86, 0x9B, 0x9C, 0x98, 0xA0, 0x9B, - 0x9B, 0x84, 0xA7, 0xB4, 0x61, 0xD1, 0xD2, 0xE0, - 0xF1, 0xDC, 0x61, 0x2D, 0x2E, 0x3F, 0x56, 0x62, - 0x5D, 0xD4, 0xD9, 0xD3, 0x54, 0x41, 0x41, 0x44, - 0xCB, 0x60, 0x52, 0xA9, 0xA9, 0xA9, 0xA7, 0xA6, - 0xA6, 0xA4, 0xA4, 0xA2, 0xA2, 0x9D, 0x95, 0x89, - 0x9C, 0x8A, 0x9E, 0x9C, 0x8A, 0x9E, 0xA0, 0xA8, - 0xC0, 0xE9, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xE9, 0xAA, 0xA6, 0xA0, 0x99, - 0x9C, 0x8B, 0x9A, 0x84, 0x9B, 0x9B, 0x98, 0x98, - 0xA9, 0xB9, 0x49, 0x57, 0xCB, 0xD4, 0xD3, 0xF1, - 0xD8, 0xDA, 0xCE, 0x3F, 0x41, 0x4B, 0x5D, 0xCB, - 0x5E, 0xD6, 0xDB, 0xD6, 0x5D, 0x43, 0x3F, 0x49, - 0xD1, 0xCC, 0x4F, 0xDD, 0xC3, 0xBB, 0xBF, 0xAA, - 0xAA, 0xA9, 0xAA, 0xA8, 0xA8, 0xA6, 0xA6, 0xA2, - 0x9C, 0x9F, 0x9B, 0x9A, 0x9D, 0xA2, 0xA8, 0xAA, - 0xC1, 0xEA, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xEA, 0xC0, 0xAA, 0xA6, 0xA2, - 0xA2, 0x99, 0xA0, 0xA0, 0xA4, 0xA7, 0xA9, 0xC0, - 0x67, 0x49, 0x54, 0x60, 0xD0, 0xD4, 0xCC, 0xDF, - 0xD9, 0xD5, 0xD2, 0x3E, 0x47, 0x56, 0x60, 0xCD, - 0x5D, 0xD9, 0xD9, 0xD6, 0x61, 0x3F, 0x47, 0x52, - 0xD6, 0xD3, 0x62, 0x4D, 0x40, 0x4A, 0x57, 0xCA, - 0xC3, 0xC1, 0xC1, 0xC0, 0xBF, 0xBF, 0xAA, 0xAA, - 0xA6, 0xA4, 0xA4, 0xA4, 0xA6, 0xA8, 0xBE, 0xC1, - 0xC9, 0xEB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xEB, 0xC3, 0xC0, 0xAA, 0xA8, - 0xA6, 0xA6, 0xA6, 0xA9, 0xAA, 0xC0, 0xE8, 0xD0, - 0xD2, 0x4C, 0x5E, 0x64, 0xD0, 0xD1, 0x5F, 0xD9, - 0xD5, 0xD1, 0xD0, 0x48, 0x52, 0x5C, 0x64, 0xCD, - 0x5C, 0xDC, 0xD7, 0xD5, 0x62, 0x3F, 0x4C, 0x53, - 0xDA, 0xD7, 0xCE, 0x56, 0x40, 0x4B, 0x52, 0x56, - 0xCE, 0xDF, 0x6A, 0xEB, 0xE9, 0xC9, 0xC3, 0xC0, - 0xC0, 0xBF, 0xBE, 0xAA, 0xBF, 0xC0, 0xC3, 0xC9, - 0xEA, 0xF6, 0xEE, 0x58, 0x57, 0x5E, 0xD6, 0xD0, - 0xD2, 0x61, 0xCB, 0xD6, 0xD6, 0xD4, 0xDF, 0xF3, - 0xF2, 0xDD, 0xD7, 0xEB, 0xC9, 0xC1, 0xC0, 0xBF, - 0xAA, 0xAA, 0xAA, 0xBE, 0xC3, 0xF0, 0xD2, 0xD2, - 0xD2, 0x51, 0x62, 0xCC, 0xD0, 0xCC, 0x61, 0xD3, - 0xCF, 0xCE, 0xD2, 0x48, 0x5A, 0x61, 0xCC, 0xCE, - 0x5F, 0xD9, 0xD5, 0xD1, 0x63, 0x44, 0x56, 0x56, - 0xDC, 0xD9, 0xD4, 0x5E, 0x42, 0x4A, 0x4C, 0x57, - 0x5D, 0xD8, 0xE0, 0xD8, 0xDC, 0xCB, 0x66, 0xEC, - 0xE8, 0xC3, 0xC3, 0xC3, 0xC3, 0xC9, 0xE8, 0xEA, - 0xF6, 0x50, 0x3E, 0x58, 0x57, 0x5A, 0xD6, 0xD4, - 0xCC, 0x4B, 0x53, 0x5C, 0x64, 0xD1, 0xDF, 0xF3, - 0xF1, 0xDE, 0xD9, 0xF6, 0xEB, 0xC9, 0xC1, 0xC1, - 0xC0, 0xC0, 0xC1, 0xC9, 0xF0, 0xD6, 0xCD, 0xD6, - 0xD3, 0x53, 0xCB, 0xCF, 0xCD, 0x5F, 0x5F, 0xCE, - 0xCF, 0xCD, 0xD0, 0x47, 0x5F, 0xCB, 0xCE, 0xCD, - 0x63, 0xD6, 0xD3, 0xD1, 0x63, 0x3F, 0x58, 0x58, - 0xDB, 0xDC, 0xDA, 0x65, 0x3E, 0x49, 0x49, 0x4D, - 0x49, 0xDC, 0xDF, 0xE0, 0xDE, 0xD5, 0x47, 0x47, - 0x46, 0x6B, 0xEB, 0xEA, 0xE9, 0xEA, 0xEB, 0xF6, - 0xD0, 0x57, 0x57, 0x47, 0x47, 0x5B, 0xD4, 0xD4, - 0xCD, 0x44, 0x3E, 0x4B, 0x50, 0x4B, 0x51, 0xD5, - 0xDB, 0xD8, 0xDE, 0x4B, 0xF6, 0xF6, 0xEA, 0xE9, - 0xE8, 0xEA, 0xEB, 0x67, 0x5E, 0xCC, 0xD6, 0xDC, - 0xD5, 0x58, 0xCE, 0xCE, 0x62, 0x50, 0xCC, 0xD3, - 0xD2, 0xCD, 0xCD, 0x4B, 0x64, 0xCE, 0xCE, 0x64, - 0xCC, 0xD3, 0xD2, 0xD2, 0x61, 0x47, 0x5D, 0x5C, - 0xDD, 0xDD, 0xD9, 0xD1, 0x4C, 0x47, 0x49, 0x4A, - 0x4B, 0xD1, 0xD8, 0xE0, 0xDF, 0xDD, 0x5D, 0x4A, - 0x48, 0x52, 0x51, 0x3F, 0xF6, 0xEC, 0xE0, 0xE0, - 0xD3, 0x5E, 0x5F, 0x50, 0x4B, 0x50, 0xCB, 0xCE, - 0x64, 0x45, 0x4C, 0x57, 0x57, 0x58, 0x52, 0xD6, - 0xD3, 0xDE, 0xDF, 0xD1, 0x3E, 0x4B, 0xF6, 0xF6, - 0xEC, 0x66, 0x53, 0x43, 0x56, 0xD1, 0xD9, 0xDE, - 0xD4, 0x5E, 0xCE, 0xCC, 0x5B, 0x2C, 0xD4, 0xD5, - 0xD2, 0xD0, 0x63, 0x5D, 0xCD, 0xD0, 0xCD, 0x5E, - 0xD0, 0xCF, 0xCE, 0xD2, 0x5E, 0x50, 0x60, 0x5D, - 0xDE, 0xDD, 0xDC, 0xD7, 0x5D, 0x45, 0x47, 0x3E, - 0x4B, 0x5E, 0xDE, 0xDF, 0xE0, 0xD8, 0xCF, 0x3E, - 0x45, 0x51, 0x58, 0x42, 0xCB, 0xDA, 0xDE, 0xD8, - 0xD2, 0x61, 0xCC, 0xCF, 0xD6, 0xDA, 0xDA, 0xD5, - 0xD0, 0x50, 0x44, 0x57, 0x57, 0x58, 0x45, 0xD1, - 0xD1, 0xD7, 0xDF, 0xDF, 0xD7, 0xCF, 0x64, 0x60, - 0xCE, 0xCE, 0xCE, 0x63, 0xCF, 0xDA, 0xDE, 0xD9, - 0xCF, 0x63, 0xCD, 0x63, 0x4D, 0x4B, 0xD6, 0xD5, - 0xCE, 0xD3, 0x60, 0xCB, 0xD0, 0xD0, 0x65, 0x47, - 0xD0, 0xCC, 0xCC, 0xD1, 0x59, 0x5D, 0x63, 0x5E, - 0xDD, 0xDD, 0xDE, 0xDC, 0xCB, 0x40, 0x48, 0x45, - 0x3E, 0x3E, 0xD9, 0xDF, 0xE0, 0xDF, 0xDA, 0x51, - 0x4C, 0x48, 0x56, 0x4C, 0x5B, 0xD2, 0xDA, 0xDB, - 0xCB, 0x5F, 0xD0, 0xCC, 0xDC, 0xF0, 0xF3, 0xE0, - 0xDD, 0xCC, 0x41, 0x50, 0x57, 0x57, 0x4B, 0x5D, - 0xD3, 0xD1, 0xDE, 0xDF, 0xDE, 0xD7, 0xD0, 0xD0, - 0xD5, 0xD6, 0xD6, 0xCE, 0xD7, 0xDC, 0xDA, 0xD5, - 0x60, 0x63, 0x64, 0x5E, 0x47, 0x61, 0xD5, 0xD2, - 0xCF, 0xD0, 0x59, 0xCD, 0xD1, 0xCF, 0x61, 0x4D, - 0xCC, 0xCE, 0xCD, 0xD0, 0x52, 0x61, 0x64, 0x60, - 0xDA, 0xDE, 0xDE, 0xDD, 0xD1, 0x4B, 0x4A, 0x45, - 0x3E, 0x41, 0xCD, 0xDE, 0xE0, 0xF1, 0xDE, 0x63, - 0x4A, 0x4A, 0x4A, 0x4B, 0x50, 0xCB, 0xD4, 0xD7, - 0x5E, 0x54, 0x62, 0xD3, 0xD4, 0xF0, 0xF3, 0xF3, - 0xF2, 0xDE, 0x61, 0x40, 0x49, 0x56, 0x4D, 0x3E, - 0x4B, 0xCE, 0xD9, 0xD8, 0xD9, 0xD5, 0xCF, 0xD2, - 0xD6, 0xD6, 0xD1, 0xD1, 0xD7, 0xD5, 0xCF, 0xD0, - 0x54, 0x64, 0x63, 0x56, 0x2C, 0xCB, 0xD1, 0xCC, - 0xD3, 0xCD, 0x54, 0xCF, 0xD1, 0xCE, 0x5E, 0x5C, - 0xCE, 0xCE, 0xCE, 0xCB, 0x4B, 0x63, 0xCC, 0x61, - 0xD4, 0xDC, 0xDE, 0xDE, 0xDA, 0x5D, 0x45, 0x45, - 0x48, 0x3F, 0x52, 0xD9, 0xD8, 0xDF, 0xDF, 0xD2, - 0x52, 0x4B, 0x3E, 0x2E, 0x47, 0x60, 0xCF, 0xD3, - 0x59, 0x48, 0x50, 0x5E, 0xCC, 0xDE, 0xF2, 0xF2, - 0xF3, 0xF3, 0xDD, 0x5D, 0x3E, 0x48, 0x47, 0x47, - 0x58, 0xD1, 0xDA, 0xDA, 0xD5, 0xD1, 0xCD, 0xD2, - 0xD3, 0xCF, 0xD3, 0xD1, 0xCD, 0xD3, 0xD2, 0x5E, - 0x52, 0x64, 0x60, 0x4B, 0x45, 0x61, 0xCD, 0xD3, - 0xD3, 0x64, 0x61, 0xD0, 0xD0, 0x64, 0x45, 0x63, - 0xD0, 0xCE, 0xD0, 0x60, 0x56, 0xCB, 0xCC, 0x62, - 0xCE, 0xDA, 0xDE, 0xD8, 0xDD, 0xCC, 0x45, 0x49, - 0x3E, 0x47, 0x42, 0xD1, 0xDC, 0xD8, 0xD8, 0xD3, - 0x5D, 0x4C, 0x49, 0x3F, 0x47, 0x59, 0xCD, 0xCF, - 0x59, 0x2E, 0x48, 0x47, 0x52, 0x63, 0xF0, 0xF2, - 0xF3, 0xF3, 0xF2, 0xDA, 0x52, 0x4B, 0x52, 0x58, - 0x5E, 0x63, 0xD0, 0xD0, 0xD0, 0xCF, 0xCE, 0xCE, - 0xCF, 0x65, 0x61, 0xD6, 0xD6, 0xD6, 0xCB, 0x4B, - 0x61, 0x62, 0x5D, 0x43, 0x4B, 0x61, 0xD0, 0xD4, - 0xD1, 0x61, 0xCE, 0xD2, 0xCD, 0x5E, 0x4A, 0xCE, - 0xD0, 0xCC, 0xD0, 0x59, 0x61, 0xCC, 0xCC, 0x62, - 0xD1, 0xD5, 0xDE, 0xD8, 0xDD, 0xCF, 0x4B, 0x4A, - 0x45, 0x3E, 0x2D, 0xCB, 0xDC, 0xDE, 0xD8, 0xD5, - 0x60, 0x54, 0x51, 0x4C, 0x4D, 0x5C, 0xCC, 0xCE, - 0x5A, 0x2C, 0x50, 0x53, 0x3E, 0x59, 0xD8, 0xF3, - 0xF2, 0xF3, 0xF3, 0xE0, 0x5E, 0x4A, 0x4C, 0x53, - 0x5E, 0x63, 0xCC, 0xCC, 0xCC, 0xCD, 0xCF, 0xD3, - 0x62, 0x53, 0xD6, 0xD6, 0xD6, 0xD6, 0x5B, 0x48, - 0x64, 0x63, 0x59, 0x44, 0x57, 0x63, 0xD2, 0xD3, - 0xD0, 0x5E, 0xD0, 0xD1, 0xCB, 0x58, 0x4C, 0xCF, - 0xCF, 0xCE, 0xCE, 0x57, 0x63, 0xCC, 0xCD, 0x57, -}; - -unsigned char linux_logo_bw[] __initdata = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, - 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, - 0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, - 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7, - 0x99, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xF3, 0xBC, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, - 0x19, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xC0, 0x03, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, - 0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xC0, 0x21, 0xD8, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0xC0, 0x1F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C, - 0xC0, 0x7C, 0x04, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, - 0xE3, 0x80, 0x00, 0x7C, 0x40, 0x11, 0xFF, 0xFF, - 0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0xD2, 0x29, - 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F, - 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00, - 0x00, 0x3F, 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, - 0x1E, 0x00, 0x00, 0x1F, 0x80, 0x19, 0xFF, 0xFF, - 0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1E, 0x80, 0x19, - 0xFF, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1E, - 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C, 0x00, - 0x00, 0x0F, 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, - 0xF8, 0x00, 0x00, 0x0E, 0x80, 0x11, 0xFF, 0xFF, - 0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x06, 0x00, 0x11, - 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x06, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00, - 0x00, 0x02, 0x00, 0x09, 0xFF, 0xFF, 0xFF, 0xF1, - 0xF0, 0x00, 0x00, 0x02, 0x80, 0x10, 0xFF, 0xFF, - 0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x97, 0x10, - 0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00, - 0xDF, 0xF0, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00, - 0x00, 0x00, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xC7, - 0xC0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, - 0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, - 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01, - 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, - 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x9F, - 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, - 0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0x18, - 0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03, - 0xA8, 0x11, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00, - 0x00, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x99, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFF, 0xFF, - 0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x01, - 0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00, - 0xFF, 0xC3, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00, - 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0xFF, 0xC0, 0x40, - 0x38, 0x00, 0x00, 0x00, 0xFE, 0x47, 0xFF, 0xFF, - 0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x23, - 0xFF, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x78, 0x11, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80, - 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, - 0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF, - 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04, - 0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10, - 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80, - 0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF, - 0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0, - 0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40, - 0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00, - 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF, - 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40, - 0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0, - 0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF, - 0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F, - 0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF, - 0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F, - 0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F, - 0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07, - 0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -}; +#include /* Painted by Johnny Stenback */ diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/page.h linux/include/asm-sparc/page.h --- v2.1.100/linux/include/asm-sparc/page.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc/page.h Fri May 8 00:11:35 1998 @@ -1,4 +1,4 @@ -/* $Id: page.h,v 1.40 1998/02/06 14:14:46 jj Exp $ +/* $Id: page.h,v 1.42 1998/05/01 13:55:21 mj Exp $ * page.h: Various defines and such for MMU operations on the Sparc for * the Linux kernel. * @@ -28,6 +28,8 @@ #ifndef __ASSEMBLY__ +#define get_user_page(vaddr) __get_free_page(GFP_KERNEL) +#define free_user_page(page, addr) free_page(addr) #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) #define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE) @@ -268,7 +270,8 @@ BTFIXUPDEF_SETHI(sparc_unmapped_base) -#define TASK_UNMAPPED_BASE BTFIXUP_SETHI(sparc_unmapped_base) +#define TASK_UNMAPPED_BASE(off) BTFIXUP_SETHI(sparc_unmapped_base) +#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) /* to align the pointer to the (next) page boundary */ #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h --- v2.1.100/linux/include/asm-sparc/processor.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc/processor.h Fri May 8 00:11:35 1998 @@ -1,4 +1,4 @@ -/* $Id: processor.h,v 1.62 1998/02/05 14:20:02 jj Exp $ +/* $Id: processor.h,v 1.63 1998/04/23 08:26:22 davem Exp $ * include/asm-sparc/processor.h * * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) @@ -153,6 +153,9 @@ /* Free all resources held by a thread. */ #define release_thread(tsk) do { } while(0) + +#define copy_segments(nr, tsk, mm) do { } while (0) +#define release_segments(mm) do { } while (0) #ifdef __KERNEL__ diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/system.h linux/include/asm-sparc/system.h --- v2.1.100/linux/include/asm-sparc/system.h Sat Apr 25 18:13:12 1998 +++ linux/include/asm-sparc/system.h Fri May 8 00:11:35 1998 @@ -1,4 +1,4 @@ -/* $Id: system.h,v 1.68 1998/03/09 14:04:51 jj Exp $ */ +/* $Id: system.h,v 1.69 1998/04/24 12:30:19 davem Exp $ */ #include #ifndef __SPARC_SYSTEM_H diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/termios.h linux/include/asm-sparc/termios.h --- v2.1.100/linux/include/asm-sparc/termios.h Wed Apr 8 19:36:29 1998 +++ linux/include/asm-sparc/termios.h Fri May 8 00:11:35 1998 @@ -1,4 +1,4 @@ -/* $Id: termios.h,v 1.25 1997/03/04 19:36:18 davem Exp $ */ +/* $Id: termios.h,v 1.26 1998/04/12 06:27:19 davem Exp $ */ #ifndef _SPARC_TERMIOS_H #define _SPARC_TERMIOS_H diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/timer.h linux/include/asm-sparc/timer.h --- v2.1.100/linux/include/asm-sparc/timer.h Sat Apr 25 18:13:12 1998 +++ linux/include/asm-sparc/timer.h Fri May 8 00:11:35 1998 @@ -1,4 +1,4 @@ -/* $Id: timer.h,v 1.16 1998/01/30 10:59:59 jj Exp $ +/* $Id: timer.h,v 1.17 1998/04/24 12:30:19 davem Exp $ * timer.h: Definitions for the timer chips on the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/timex.h linux/include/asm-sparc/timex.h --- v2.1.100/linux/include/asm-sparc/timex.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc/timex.h Thu May 7 23:53:35 1998 @@ -0,0 +1,15 @@ +/* + * linux/include/asm-sparc/timex.h + * + * sparc architecture timex specifications + */ +#ifndef _ASMsparc_TIMEX_H +#define _ASMsparc_TIMEX_H + +#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ +#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */ +#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \ + (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \ + << (SHIFT_SCALE-SHIFT_HZ)) / HZ) + +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/unistd.h linux/include/asm-sparc/unistd.h --- v2.1.100/linux/include/asm-sparc/unistd.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc/unistd.h Fri May 8 00:11:35 1998 @@ -1,4 +1,4 @@ -/* $Id: unistd.h,v 1.38 1998/03/27 07:01:56 davem Exp $ */ +/* $Id: unistd.h,v 1.40 1998/04/14 13:49:55 jj Exp $ */ #ifndef _SPARC_UNISTD_H #define _SPARC_UNISTD_H @@ -135,7 +135,7 @@ #define __NR_gettimeofday 116 /* Common */ #define __NR_getrusage 117 /* Common */ #define __NR_getsockopt 118 /* Common */ -/* #define __NR_ni_syscall 119 ENOSYS under SunOS */ +#define __NR_getcwd 119 /* Linux Specific */ #define __NR_readv 120 /* Common */ #define __NR_writev 121 /* Common */ #define __NR_settimeofday 122 /* Common */ diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/asm_offsets.h linux/include/asm-sparc64/asm_offsets.h --- v2.1.100/linux/include/asm-sparc64/asm_offsets.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc64/asm_offsets.h Fri May 8 00:11:36 1998 @@ -48,135 +48,137 @@ #define ASIZ_task_session 0x00000004 #define AOFF_task_leader 0x000000cc #define ASIZ_task_leader 0x00000004 -#define AOFF_task_ngroups 0x000000d0 -#define ASIZ_task_ngroups 0x00000004 -#define AOFF_task_groups 0x000000d4 -#define ASIZ_task_groups 0x00000080 -#define AOFF_task_p_opptr 0x00000158 +#define AOFF_task_p_opptr 0x000000d0 #define ASIZ_task_p_opptr 0x00000008 -#define AOFF_task_p_pptr 0x00000160 +#define AOFF_task_p_pptr 0x000000d8 #define ASIZ_task_p_pptr 0x00000008 -#define AOFF_task_p_cptr 0x00000168 +#define AOFF_task_p_cptr 0x000000e0 #define ASIZ_task_p_cptr 0x00000008 -#define AOFF_task_p_ysptr 0x00000170 +#define AOFF_task_p_ysptr 0x000000e8 #define ASIZ_task_p_ysptr 0x00000008 -#define AOFF_task_p_osptr 0x00000178 +#define AOFF_task_p_osptr 0x000000f0 #define ASIZ_task_p_osptr 0x00000008 -#define AOFF_task_pidhash_next 0x00000180 +#define AOFF_task_pidhash_next 0x000000f8 #define ASIZ_task_pidhash_next 0x00000008 -#define AOFF_task_pidhash_pprev 0x00000188 +#define AOFF_task_pidhash_pprev 0x00000100 #define ASIZ_task_pidhash_pprev 0x00000008 -#define AOFF_task_tarray_ptr 0x00000190 +#define AOFF_task_tarray_ptr 0x00000108 #define ASIZ_task_tarray_ptr 0x00000008 -#define AOFF_task_wait_chldexit 0x00000198 +#define AOFF_task_wait_chldexit 0x00000110 #define ASIZ_task_wait_chldexit 0x00000008 -#define AOFF_task_uid 0x000001a0 -#define ASIZ_task_uid 0x00000004 -#define AOFF_task_euid 0x000001a4 -#define ASIZ_task_euid 0x00000004 -#define AOFF_task_suid 0x000001a8 -#define ASIZ_task_suid 0x00000004 -#define AOFF_task_fsuid 0x000001ac -#define ASIZ_task_fsuid 0x00000004 -#define AOFF_task_gid 0x000001b0 -#define ASIZ_task_gid 0x00000004 -#define AOFF_task_egid 0x000001b4 -#define ASIZ_task_egid 0x00000004 -#define AOFF_task_sgid 0x000001b8 -#define ASIZ_task_sgid 0x00000004 -#define AOFF_task_fsgid 0x000001bc -#define ASIZ_task_fsgid 0x00000004 -#define AOFF_task_timeout 0x000001c0 +#define AOFF_task_timeout 0x00000118 #define ASIZ_task_timeout 0x00000008 -#define AOFF_task_policy 0x000001c8 +#define AOFF_task_policy 0x00000120 #define ASIZ_task_policy 0x00000008 -#define AOFF_task_rt_priority 0x000001d0 +#define AOFF_task_rt_priority 0x00000128 #define ASIZ_task_rt_priority 0x00000008 -#define AOFF_task_it_real_value 0x000001d8 +#define AOFF_task_it_real_value 0x00000130 #define ASIZ_task_it_real_value 0x00000008 -#define AOFF_task_it_prof_value 0x000001e0 +#define AOFF_task_it_prof_value 0x00000138 #define ASIZ_task_it_prof_value 0x00000008 -#define AOFF_task_it_virt_value 0x000001e8 +#define AOFF_task_it_virt_value 0x00000140 #define ASIZ_task_it_virt_value 0x00000008 -#define AOFF_task_it_real_incr 0x000001f0 +#define AOFF_task_it_real_incr 0x00000148 #define ASIZ_task_it_real_incr 0x00000008 -#define AOFF_task_it_prof_incr 0x000001f8 +#define AOFF_task_it_prof_incr 0x00000150 #define ASIZ_task_it_prof_incr 0x00000008 -#define AOFF_task_it_virt_incr 0x00000200 +#define AOFF_task_it_virt_incr 0x00000158 #define ASIZ_task_it_virt_incr 0x00000008 -#define AOFF_task_real_timer 0x00000208 +#define AOFF_task_real_timer 0x00000160 #define ASIZ_task_real_timer 0x00000028 -#define AOFF_task_times 0x00000230 +#define AOFF_task_times 0x00000188 #define ASIZ_task_times 0x00000020 -#define AOFF_task_start_time 0x00000250 +#define AOFF_task_start_time 0x000001a8 #define ASIZ_task_start_time 0x00000008 -#define AOFF_task_per_cpu_utime 0x00000258 +#define AOFF_task_per_cpu_utime 0x000001b0 #define ASIZ_task_per_cpu_utime 0x00000008 -#define AOFF_task_min_flt 0x00000268 +#define AOFF_task_min_flt 0x000001c0 #define ASIZ_task_min_flt 0x00000008 -#define AOFF_task_maj_flt 0x00000270 +#define AOFF_task_maj_flt 0x000001c8 #define ASIZ_task_maj_flt 0x00000008 -#define AOFF_task_nswap 0x00000278 +#define AOFF_task_nswap 0x000001d0 #define ASIZ_task_nswap 0x00000008 -#define AOFF_task_cmin_flt 0x00000280 +#define AOFF_task_cmin_flt 0x000001d8 #define ASIZ_task_cmin_flt 0x00000008 -#define AOFF_task_cmaj_flt 0x00000288 +#define AOFF_task_cmaj_flt 0x000001e0 #define ASIZ_task_cmaj_flt 0x00000008 -#define AOFF_task_cnswap 0x00000290 +#define AOFF_task_cnswap 0x000001e8 #define ASIZ_task_cnswap 0x00000008 -#define AOFF_task_swap_address 0x000002a0 +#define AOFF_task_swap_address 0x000001f8 #define ASIZ_task_swap_address 0x00000008 -#define AOFF_task_old_maj_flt 0x000002a8 +#define AOFF_task_old_maj_flt 0x00000200 #define ASIZ_task_old_maj_flt 0x00000008 -#define AOFF_task_dec_flt 0x000002b0 +#define AOFF_task_dec_flt 0x00000208 #define ASIZ_task_dec_flt 0x00000008 -#define AOFF_task_swap_cnt 0x000002b8 +#define AOFF_task_swap_cnt 0x00000210 #define ASIZ_task_swap_cnt 0x00000008 -#define AOFF_task_rlim 0x000002c0 +#define AOFF_task_uid 0x00000218 +#define ASIZ_task_uid 0x00000004 +#define AOFF_task_euid 0x0000021c +#define ASIZ_task_euid 0x00000004 +#define AOFF_task_suid 0x00000220 +#define ASIZ_task_suid 0x00000004 +#define AOFF_task_fsuid 0x00000224 +#define ASIZ_task_fsuid 0x00000004 +#define AOFF_task_gid 0x00000228 +#define ASIZ_task_gid 0x00000004 +#define AOFF_task_egid 0x0000022c +#define ASIZ_task_egid 0x00000004 +#define AOFF_task_sgid 0x00000230 +#define ASIZ_task_sgid 0x00000004 +#define AOFF_task_fsgid 0x00000234 +#define ASIZ_task_fsgid 0x00000004 +#define AOFF_task_ngroups 0x00000238 +#define ASIZ_task_ngroups 0x00000004 +#define AOFF_task_groups 0x0000023c +#define ASIZ_task_groups 0x00000080 +#define AOFF_task_cap_effective 0x000002bc +#define ASIZ_task_cap_effective 0x00000004 +#define AOFF_task_cap_inheritable 0x000002c0 +#define ASIZ_task_cap_inheritable 0x00000004 +#define AOFF_task_cap_permitted 0x000002c4 +#define ASIZ_task_cap_permitted 0x00000004 +#define AOFF_task_rlim 0x000002c8 #define ASIZ_task_rlim 0x000000a0 -#define AOFF_task_used_math 0x00000360 +#define AOFF_task_used_math 0x00000368 #define ASIZ_task_used_math 0x00000002 -#define AOFF_task_io_usage 0x00000368 -#define ASIZ_task_io_usage 0x00000008 -#define AOFF_task_comm 0x00000370 +#define AOFF_task_comm 0x0000036a #define ASIZ_task_comm 0x00000010 -#define AOFF_task_link_count 0x00000380 +#define AOFF_task_link_count 0x0000037c #define ASIZ_task_link_count 0x00000004 -#define AOFF_task_tty 0x00000388 +#define AOFF_task_tty 0x00000380 #define ASIZ_task_tty 0x00000008 -#define AOFF_task_semundo 0x00000390 +#define AOFF_task_semundo 0x00000388 #define ASIZ_task_semundo 0x00000008 -#define AOFF_task_semsleeping 0x00000398 +#define AOFF_task_semsleeping 0x00000390 #define ASIZ_task_semsleeping 0x00000008 -#define AOFF_task_ldt 0x000003a0 -#define ASIZ_task_ldt 0x00000008 -#define AOFF_task_tss 0x000003b0 +#define AOFF_task_tss 0x000003a0 #define ASIZ_task_tss 0x00000490 -#define AOFF_task_fs 0x00000840 +#define AOFF_task_fs 0x00000830 #define ASIZ_task_fs 0x00000008 -#define AOFF_task_files 0x00000848 +#define AOFF_task_files 0x00000838 #define ASIZ_task_files 0x00000008 -#define AOFF_task_mm 0x00000850 +#define AOFF_task_mm 0x00000840 #define ASIZ_task_mm 0x00000008 -#define AOFF_task_sig 0x00000858 +#define AOFF_task_sig 0x00000848 #define ASIZ_task_sig 0x00000008 -#define AOFF_task_signal 0x00000860 +#define AOFF_task_signal 0x00000850 #define ASIZ_task_signal 0x00000008 -#define AOFF_task_blocked 0x00000868 +#define AOFF_task_blocked 0x00000858 #define ASIZ_task_blocked 0x00000008 -#define AOFF_task_sigqueue 0x00000870 +#define AOFF_task_sigqueue 0x00000860 #define ASIZ_task_sigqueue 0x00000008 -#define AOFF_task_sigqueue_tail 0x00000878 +#define AOFF_task_sigqueue_tail 0x00000868 #define ASIZ_task_sigqueue_tail 0x00000008 -#define AOFF_task_has_cpu 0x00000880 +#define AOFF_task_has_cpu 0x00000870 #define ASIZ_task_has_cpu 0x00000004 -#define AOFF_task_processor 0x00000884 +#define AOFF_task_processor 0x00000874 #define ASIZ_task_processor 0x00000004 -#define AOFF_task_last_processor 0x00000888 +#define AOFF_task_last_processor 0x00000878 #define ASIZ_task_last_processor 0x00000004 -#define AOFF_task_lock_depth 0x0000088c +#define AOFF_task_lock_depth 0x0000087c #define ASIZ_task_lock_depth 0x00000004 -#define AOFF_task_sigmask_lock 0x00000890 +#define AOFF_task_sigmask_lock 0x00000880 #define ASIZ_task_sigmask_lock 0x00000000 #define AOFF_mm_mmap 0x00000000 #define ASIZ_mm_mmap 0x00000008 @@ -224,6 +226,8 @@ #define ASIZ_mm_def_flags 0x00000008 #define AOFF_mm_cpu_vm_mask 0x000000b0 #define ASIZ_mm_cpu_vm_mask 0x00000008 +#define AOFF_mm_segments 0x000000b8 +#define ASIZ_mm_segments 0x00000008 #define AOFF_thread_ksp 0x00000000 #define ASIZ_thread_ksp 0x00000008 #define AOFF_thread_kpc 0x00000008 @@ -303,135 +307,137 @@ #define ASIZ_task_session 0x00000004 #define AOFF_task_leader 0x000000cc #define ASIZ_task_leader 0x00000004 -#define AOFF_task_ngroups 0x000000d0 -#define ASIZ_task_ngroups 0x00000004 -#define AOFF_task_groups 0x000000d4 -#define ASIZ_task_groups 0x00000080 -#define AOFF_task_p_opptr 0x00000158 +#define AOFF_task_p_opptr 0x000000d0 #define ASIZ_task_p_opptr 0x00000008 -#define AOFF_task_p_pptr 0x00000160 +#define AOFF_task_p_pptr 0x000000d8 #define ASIZ_task_p_pptr 0x00000008 -#define AOFF_task_p_cptr 0x00000168 +#define AOFF_task_p_cptr 0x000000e0 #define ASIZ_task_p_cptr 0x00000008 -#define AOFF_task_p_ysptr 0x00000170 +#define AOFF_task_p_ysptr 0x000000e8 #define ASIZ_task_p_ysptr 0x00000008 -#define AOFF_task_p_osptr 0x00000178 +#define AOFF_task_p_osptr 0x000000f0 #define ASIZ_task_p_osptr 0x00000008 -#define AOFF_task_pidhash_next 0x00000180 +#define AOFF_task_pidhash_next 0x000000f8 #define ASIZ_task_pidhash_next 0x00000008 -#define AOFF_task_pidhash_pprev 0x00000188 +#define AOFF_task_pidhash_pprev 0x00000100 #define ASIZ_task_pidhash_pprev 0x00000008 -#define AOFF_task_tarray_ptr 0x00000190 +#define AOFF_task_tarray_ptr 0x00000108 #define ASIZ_task_tarray_ptr 0x00000008 -#define AOFF_task_wait_chldexit 0x00000198 +#define AOFF_task_wait_chldexit 0x00000110 #define ASIZ_task_wait_chldexit 0x00000008 -#define AOFF_task_uid 0x000001a0 -#define ASIZ_task_uid 0x00000004 -#define AOFF_task_euid 0x000001a4 -#define ASIZ_task_euid 0x00000004 -#define AOFF_task_suid 0x000001a8 -#define ASIZ_task_suid 0x00000004 -#define AOFF_task_fsuid 0x000001ac -#define ASIZ_task_fsuid 0x00000004 -#define AOFF_task_gid 0x000001b0 -#define ASIZ_task_gid 0x00000004 -#define AOFF_task_egid 0x000001b4 -#define ASIZ_task_egid 0x00000004 -#define AOFF_task_sgid 0x000001b8 -#define ASIZ_task_sgid 0x00000004 -#define AOFF_task_fsgid 0x000001bc -#define ASIZ_task_fsgid 0x00000004 -#define AOFF_task_timeout 0x000001c0 +#define AOFF_task_timeout 0x00000118 #define ASIZ_task_timeout 0x00000008 -#define AOFF_task_policy 0x000001c8 +#define AOFF_task_policy 0x00000120 #define ASIZ_task_policy 0x00000008 -#define AOFF_task_rt_priority 0x000001d0 +#define AOFF_task_rt_priority 0x00000128 #define ASIZ_task_rt_priority 0x00000008 -#define AOFF_task_it_real_value 0x000001d8 +#define AOFF_task_it_real_value 0x00000130 #define ASIZ_task_it_real_value 0x00000008 -#define AOFF_task_it_prof_value 0x000001e0 +#define AOFF_task_it_prof_value 0x00000138 #define ASIZ_task_it_prof_value 0x00000008 -#define AOFF_task_it_virt_value 0x000001e8 +#define AOFF_task_it_virt_value 0x00000140 #define ASIZ_task_it_virt_value 0x00000008 -#define AOFF_task_it_real_incr 0x000001f0 +#define AOFF_task_it_real_incr 0x00000148 #define ASIZ_task_it_real_incr 0x00000008 -#define AOFF_task_it_prof_incr 0x000001f8 +#define AOFF_task_it_prof_incr 0x00000150 #define ASIZ_task_it_prof_incr 0x00000008 -#define AOFF_task_it_virt_incr 0x00000200 +#define AOFF_task_it_virt_incr 0x00000158 #define ASIZ_task_it_virt_incr 0x00000008 -#define AOFF_task_real_timer 0x00000208 +#define AOFF_task_real_timer 0x00000160 #define ASIZ_task_real_timer 0x00000028 -#define AOFF_task_times 0x00000230 +#define AOFF_task_times 0x00000188 #define ASIZ_task_times 0x00000020 -#define AOFF_task_start_time 0x00000250 +#define AOFF_task_start_time 0x000001a8 #define ASIZ_task_start_time 0x00000008 -#define AOFF_task_per_cpu_utime 0x00000258 +#define AOFF_task_per_cpu_utime 0x000001b0 #define ASIZ_task_per_cpu_utime 0x00000100 -#define AOFF_task_min_flt 0x00000458 +#define AOFF_task_min_flt 0x000003b0 #define ASIZ_task_min_flt 0x00000008 -#define AOFF_task_maj_flt 0x00000460 +#define AOFF_task_maj_flt 0x000003b8 #define ASIZ_task_maj_flt 0x00000008 -#define AOFF_task_nswap 0x00000468 +#define AOFF_task_nswap 0x000003c0 #define ASIZ_task_nswap 0x00000008 -#define AOFF_task_cmin_flt 0x00000470 +#define AOFF_task_cmin_flt 0x000003c8 #define ASIZ_task_cmin_flt 0x00000008 -#define AOFF_task_cmaj_flt 0x00000478 +#define AOFF_task_cmaj_flt 0x000003d0 #define ASIZ_task_cmaj_flt 0x00000008 -#define AOFF_task_cnswap 0x00000480 +#define AOFF_task_cnswap 0x000003d8 #define ASIZ_task_cnswap 0x00000008 -#define AOFF_task_swap_address 0x00000490 +#define AOFF_task_swap_address 0x000003e8 #define ASIZ_task_swap_address 0x00000008 -#define AOFF_task_old_maj_flt 0x00000498 +#define AOFF_task_old_maj_flt 0x000003f0 #define ASIZ_task_old_maj_flt 0x00000008 -#define AOFF_task_dec_flt 0x000004a0 +#define AOFF_task_dec_flt 0x000003f8 #define ASIZ_task_dec_flt 0x00000008 -#define AOFF_task_swap_cnt 0x000004a8 +#define AOFF_task_swap_cnt 0x00000400 #define ASIZ_task_swap_cnt 0x00000008 -#define AOFF_task_rlim 0x000004b0 +#define AOFF_task_uid 0x00000408 +#define ASIZ_task_uid 0x00000004 +#define AOFF_task_euid 0x0000040c +#define ASIZ_task_euid 0x00000004 +#define AOFF_task_suid 0x00000410 +#define ASIZ_task_suid 0x00000004 +#define AOFF_task_fsuid 0x00000414 +#define ASIZ_task_fsuid 0x00000004 +#define AOFF_task_gid 0x00000418 +#define ASIZ_task_gid 0x00000004 +#define AOFF_task_egid 0x0000041c +#define ASIZ_task_egid 0x00000004 +#define AOFF_task_sgid 0x00000420 +#define ASIZ_task_sgid 0x00000004 +#define AOFF_task_fsgid 0x00000424 +#define ASIZ_task_fsgid 0x00000004 +#define AOFF_task_ngroups 0x00000428 +#define ASIZ_task_ngroups 0x00000004 +#define AOFF_task_groups 0x0000042c +#define ASIZ_task_groups 0x00000080 +#define AOFF_task_cap_effective 0x000004ac +#define ASIZ_task_cap_effective 0x00000004 +#define AOFF_task_cap_inheritable 0x000004b0 +#define ASIZ_task_cap_inheritable 0x00000004 +#define AOFF_task_cap_permitted 0x000004b4 +#define ASIZ_task_cap_permitted 0x00000004 +#define AOFF_task_rlim 0x000004b8 #define ASIZ_task_rlim 0x000000a0 -#define AOFF_task_used_math 0x00000550 +#define AOFF_task_used_math 0x00000558 #define ASIZ_task_used_math 0x00000002 -#define AOFF_task_io_usage 0x00000558 -#define ASIZ_task_io_usage 0x00000008 -#define AOFF_task_comm 0x00000560 +#define AOFF_task_comm 0x0000055a #define ASIZ_task_comm 0x00000010 -#define AOFF_task_link_count 0x00000570 +#define AOFF_task_link_count 0x0000056c #define ASIZ_task_link_count 0x00000004 -#define AOFF_task_tty 0x00000578 +#define AOFF_task_tty 0x00000570 #define ASIZ_task_tty 0x00000008 -#define AOFF_task_semundo 0x00000580 +#define AOFF_task_semundo 0x00000578 #define ASIZ_task_semundo 0x00000008 -#define AOFF_task_semsleeping 0x00000588 +#define AOFF_task_semsleeping 0x00000580 #define ASIZ_task_semsleeping 0x00000008 -#define AOFF_task_ldt 0x00000590 -#define ASIZ_task_ldt 0x00000008 -#define AOFF_task_tss 0x000005a0 +#define AOFF_task_tss 0x00000590 #define ASIZ_task_tss 0x00000490 -#define AOFF_task_fs 0x00000a30 +#define AOFF_task_fs 0x00000a20 #define ASIZ_task_fs 0x00000008 -#define AOFF_task_files 0x00000a38 +#define AOFF_task_files 0x00000a28 #define ASIZ_task_files 0x00000008 -#define AOFF_task_mm 0x00000a40 +#define AOFF_task_mm 0x00000a30 #define ASIZ_task_mm 0x00000008 -#define AOFF_task_sig 0x00000a48 +#define AOFF_task_sig 0x00000a38 #define ASIZ_task_sig 0x00000008 -#define AOFF_task_signal 0x00000a50 +#define AOFF_task_signal 0x00000a40 #define ASIZ_task_signal 0x00000008 -#define AOFF_task_blocked 0x00000a58 +#define AOFF_task_blocked 0x00000a48 #define ASIZ_task_blocked 0x00000008 -#define AOFF_task_sigqueue 0x00000a60 +#define AOFF_task_sigqueue 0x00000a50 #define ASIZ_task_sigqueue 0x00000008 -#define AOFF_task_sigqueue_tail 0x00000a68 +#define AOFF_task_sigqueue_tail 0x00000a58 #define ASIZ_task_sigqueue_tail 0x00000008 -#define AOFF_task_has_cpu 0x00000a70 +#define AOFF_task_has_cpu 0x00000a60 #define ASIZ_task_has_cpu 0x00000004 -#define AOFF_task_processor 0x00000a74 +#define AOFF_task_processor 0x00000a64 #define ASIZ_task_processor 0x00000004 -#define AOFF_task_last_processor 0x00000a78 +#define AOFF_task_last_processor 0x00000a68 #define ASIZ_task_last_processor 0x00000004 -#define AOFF_task_lock_depth 0x00000a7c +#define AOFF_task_lock_depth 0x00000a6c #define ASIZ_task_lock_depth 0x00000004 -#define AOFF_task_sigmask_lock 0x00000a80 +#define AOFF_task_sigmask_lock 0x00000a70 #define ASIZ_task_sigmask_lock 0x00000001 #define AOFF_mm_mmap 0x00000000 #define ASIZ_mm_mmap 0x00000008 @@ -479,6 +485,8 @@ #define ASIZ_mm_def_flags 0x00000008 #define AOFF_mm_cpu_vm_mask 0x000000b0 #define ASIZ_mm_cpu_vm_mask 0x00000008 +#define AOFF_mm_segments 0x000000b8 +#define ASIZ_mm_segments 0x00000008 #define AOFF_thread_ksp 0x00000000 #define ASIZ_thread_ksp 0x00000008 #define AOFF_thread_kpc 0x00000008 diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/audioio.h linux/include/asm-sparc64/audioio.h --- v2.1.100/linux/include/asm-sparc64/audioio.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc64/audioio.h Fri May 8 00:11:36 1998 @@ -0,0 +1,409 @@ +/* + * include/asm-sparc/audioio.h + * + * Sparc Audio Midlayer + * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) + */ + +#ifndef _AUDIOIO_H_ +#define _AUDIOIO_H_ + +/* + * SunOS/Solaris /dev/audio interface + */ + +#include +#include +#include + +/* + * This structure contains state information for audio device IO streams. + */ +typedef struct audio_prinfo { + /* + * The following values describe the audio data encoding. + */ + unsigned int sample_rate; /* samples per second */ + unsigned int channels; /* number of interleaved channels */ + unsigned int precision; /* bit-width of each sample */ + unsigned int encoding; /* data encoding method */ + + /* + * The following values control audio device configuration + */ + unsigned int gain; /* gain level: 0 - 255 */ + unsigned int port; /* selected I/O port (see below) */ + unsigned int avail_ports; /* available I/O ports (see below) */ + unsigned int _xxx[2]; /* Reserved for future use */ + + unsigned int buffer_size; /* I/O buffer size */ + + /* + * The following values describe driver state + */ + unsigned int samples; /* number of samples converted */ + unsigned int eof; /* End Of File counter (play only) */ + + unsigned char pause; /* non-zero for pause, zero to resume */ + unsigned char error; /* non-zero if overflow/underflow */ + unsigned char waiting; /* non-zero if a process wants access */ + unsigned char balance; /* stereo channel balance */ + + unsigned short minordev; + + /* + * The following values are read-only state flags + */ + unsigned char open; /* non-zero if open access permitted */ + unsigned char active; /* non-zero if I/O is active */ +} audio_prinfo_t; + + +/* + * This structure describes the current state of the audio device. + */ +typedef struct audio_info { + /* + * Per-stream information + */ + audio_prinfo_t play; /* output status information */ + audio_prinfo_t record; /* input status information */ + + /* + * Per-unit/channel information + */ + unsigned int monitor_gain; /* input to output mix: 0 - 255 */ + unsigned char output_muted; /* non-zero if output is muted */ + unsigned char _xxx[3]; /* Reserved for future use */ + unsigned int _yyy[3]; /* Reserved for future use */ +} audio_info_t; + + +/* + * Audio encoding types + */ +#define AUDIO_ENCODING_NONE (0) /* no encoding assigned */ +#define AUDIO_ENCODING_ULAW (1) /* u-law encoding */ +#define AUDIO_ENCODING_ALAW (2) /* A-law encoding */ +#define AUDIO_ENCODING_LINEAR (3) /* Linear PCM encoding */ +#define AUDIO_ENCODING_DVI (104) /* DVI ADPCM */ +#define AUDIO_ENCODING_LINEAR8 (105) /* 8 bit UNSIGNED */ +#define AUDIO_ENCODING_LINEARLE (106) /* Linear PCM LE encoding */ + +/* + * These ranges apply to record, play, and monitor gain values + */ +#define AUDIO_MIN_GAIN (0) /* minimum gain value */ +#define AUDIO_MAX_GAIN (255) /* maximum gain value */ + +/* + * These values apply to the balance field to adjust channel gain values + */ +#define AUDIO_LEFT_BALANCE (0) /* left channel only */ +#define AUDIO_MID_BALANCE (32) /* equal left/right channel */ +#define AUDIO_RIGHT_BALANCE (64) /* right channel only */ +#define AUDIO_BALANCE_SHIFT (3) + +/* + * Generic minimum/maximum limits for number of channels, both modes + */ +#define AUDIO_MIN_PLAY_CHANNELS (1) +#define AUDIO_MAX_PLAY_CHANNELS (4) +#define AUDIO_MIN_REC_CHANNELS (1) +#define AUDIO_MAX_REC_CHANNELS (4) + +/* + * Generic minimum/maximum limits for sample precision + */ +#define AUDIO_MIN_PLAY_PRECISION (8) +#define AUDIO_MAX_PLAY_PRECISION (32) +#define AUDIO_MIN_REC_PRECISION (8) +#define AUDIO_MAX_REC_PRECISION (32) + +/* + * Define some convenient names for typical audio ports + */ +/* + * output ports (several may be enabled simultaneously) + */ +#define AUDIO_SPEAKER 0x01 /* output to built-in speaker */ +#define AUDIO_HEADPHONE 0x02 /* output to headphone jack */ +#define AUDIO_LINE_OUT 0x04 /* output to line out */ + +/* + * input ports (usually only one at a time) + */ +#define AUDIO_MICROPHONE 0x01 /* input from microphone */ +#define AUDIO_LINE_IN 0x02 /* input from line in */ +#define AUDIO_CD 0x04 /* input from on-board CD inputs */ +#define AUDIO_INTERNAL_CD_IN AUDIO_CD /* input from internal CDROM */ +/* Supposedly an undocumented feature of the 4231 */ +#define AUDIO_ANALOG_LOOPBACK 0x40 + + +/* + * This macro initializes an audio_info structure to 'harmless' values. + * Note that (~0) might not be a harmless value for a flag that was + * a signed int. + */ +#define AUDIO_INITINFO(i) { \ + unsigned int *__x__; \ + for (__x__ = (unsigned int *)(i); \ + (char *) __x__ < (((char *)(i)) + sizeof (audio_info_t)); \ + *__x__++ = ~0); \ +} + +/* + * These allow testing for what the user wants to set + */ +#define AUD_INITVALUE (~0) +#define Modify(X) ((unsigned int)(X) != AUD_INITVALUE) +#define Modifys(X) ((X) != (unsigned short)AUD_INITVALUE) +#define Modifyc(X) ((X) != (unsigned char)AUD_INITVALUE) + +/* + * Parameter for the AUDIO_GETDEV ioctl to determine current + * audio devices. + */ +#define MAX_AUDIO_DEV_LEN (16) +typedef struct audio_device { + char name[MAX_AUDIO_DEV_LEN]; + char version[MAX_AUDIO_DEV_LEN]; + char config[MAX_AUDIO_DEV_LEN]; +} audio_device_t; + + +/* + * Ioctl calls for the audio device. + */ + +/* + * AUDIO_GETINFO retrieves the current state of the audio device. + * + * AUDIO_SETINFO copies all fields of the audio_info structure whose + * values are not set to the initialized value (-1) to the device state. + * It performs an implicit AUDIO_GETINFO to return the new state of the + * device. Note that the record.samples and play.samples fields are set + * to the last value before the AUDIO_SETINFO took effect. This allows + * an application to reset the counters while atomically retrieving the + * last value. + * + * AUDIO_DRAIN suspends the calling process until the write buffers are + * empty. + * + * AUDIO_GETDEV returns a structure of type audio_device_t which contains + * three strings. The string "name" is a short identifying string (for + * example, the SBus Fcode name string), the string "version" identifies + * the current version of the device, and the "config" string identifies + * the specific configuration of the audio stream. All fields are + * device-dependent -- see the device specific manual pages for details. + * + * AUDIO_GETDEV_SUNOS returns a number which is an audio device defined + * herein (making it not too portable) + * + * AUDIO_FLUSH stops all playback and recording, clears all queued buffers, + * resets error counters, and restarts recording and playback as appropriate + * for the current sampling mode. + */ +#define AUDIO_GETINFO _IOR('A', 1, audio_info_t) +#define AUDIO_SETINFO _IOWR('A', 2, audio_info_t) +#define AUDIO_DRAIN _IO('A', 3) +#define AUDIO_GETDEV _IOR('A', 4, audio_device_t) +#define AUDIO_GETDEV_SUNOS _IOR('A', 4, int) +#define AUDIO_FLUSH _IO('A', 5) + +/* Define possible audio hardware configurations for + * old SunOS-style AUDIO_GETDEV ioctl */ +#define AUDIO_DEV_UNKNOWN (0) /* not defined */ +#define AUDIO_DEV_AMD (1) /* audioamd device */ +#define AUDIO_DEV_SPEAKERBOX (2) /* dbri device with speakerbox */ +#define AUDIO_DEV_CODEC (3) /* dbri device (internal speaker) */ +#define AUDIO_DEV_CS4231 (5) /* cs4231 device */ + +/* + * The following ioctl sets the audio device into an internal loopback mode, + * if the hardware supports this. The argument is TRUE to set loopback, + * FALSE to reset to normal operation. If the hardware does not support + * internal loopback, the ioctl should fail with EINVAL. + */ +#define AUDIO_DIAG_LOOPBACK _IOW('A', 101, int) + +#ifdef notneeded +/* + * Structure sent up as a M_PROTO message on trace streams + */ +typedef struct audtrace_hdr audtrace_hdr_t; +struct audtrace_hdr { + unsigned int seq; /* Sequence number (per-aud_stream) */ + int type; /* device-dependent */ + struct timeval timestamp; + char _f[8]; /* filler */ +}; +#endif + +/* + * Linux kernel internal implementation. + */ + +#ifdef __KERNEL__ + +#include +#include +#include +#include + +#define SDF_OPEN_WRITE 0x00000001 +#define SDF_OPEN_READ 0x00000002 + +struct sparcaudio_driver +{ + const char * name; + struct sparcaudio_operations *ops; + void *private; + unsigned long flags; + + /* Processes blocked on open() sit here. */ + struct wait_queue *open_wait; + + /* Task queue for this driver's bottom half. */ + struct tq_struct tqueue; + + /* Support for a circular queue of output buffers. */ + __u8 **output_buffers; + size_t *output_sizes, output_size; + int num_output_buffers, output_front, output_rear; + int output_count, output_active, playing_count; + struct wait_queue *output_write_wait, *output_drain_wait; + + /* Support for a circular queue of input buffers. */ + __u8 **input_buffers; + int input_offset; + int num_input_buffers, input_front, input_rear; + int input_count, input_active, recording_count; + struct wait_queue *input_read_wait; +}; + +struct sparcaudio_operations +{ + int (*open)(struct inode *, struct file *, struct sparcaudio_driver *); + void (*release)(struct inode *, struct file *, struct sparcaudio_driver *); + int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long, + struct sparcaudio_driver *); + + /* Ask driver to begin playing a buffer. */ + void (*start_output)(struct sparcaudio_driver *, __u8 *, unsigned long); + + /* Ask driver to stop playing a buffer. */ + void (*stop_output)(struct sparcaudio_driver *); + + /* Ask driver to begin recording into a buffer. */ + void (*start_input)(struct sparcaudio_driver *, __u8 *, unsigned long); + + /* Ask driver to stop recording. */ + void (*stop_input)(struct sparcaudio_driver *); + + /* Return driver name/version to caller. (/dev/audio specific) */ + void (*sunaudio_getdev)(struct sparcaudio_driver *, audio_device_t *); + + /* Get and set the output volume. (0-255) */ + int (*set_output_volume)(struct sparcaudio_driver *, int); + int (*get_output_volume)(struct sparcaudio_driver *); + + /* Get and set the input volume. (0-255) */ + int (*set_input_volume)(struct sparcaudio_driver *, int); + int (*get_input_volume)(struct sparcaudio_driver *); + + /* Get and set the monitor volume. (0-255) */ + int (*set_monitor_volume)(struct sparcaudio_driver *, int); + int (*get_monitor_volume)(struct sparcaudio_driver *); + + /* Get and set the output balance. (0-64) */ + int (*set_output_balance)(struct sparcaudio_driver *, int); + int (*get_output_balance)(struct sparcaudio_driver *); + + /* Get and set the input balance. (0-64) */ + int (*set_input_balance)(struct sparcaudio_driver *, int); + int (*get_input_balance)(struct sparcaudio_driver *); + + /* Get and set the output channels. (1-4) */ + int (*set_output_channels)(struct sparcaudio_driver *, int); + int (*get_output_channels)(struct sparcaudio_driver *); + + /* Get and set the input channels. (1-4) */ + int (*set_input_channels)(struct sparcaudio_driver *, int); + int (*get_input_channels)(struct sparcaudio_driver *); + + /* Get and set the output precision. (8-32) */ + int (*set_output_precision)(struct sparcaudio_driver *, int); + int (*get_output_precision)(struct sparcaudio_driver *); + + /* Get and set the input precision. (8-32) */ + int (*set_input_precision)(struct sparcaudio_driver *, int); + int (*get_input_precision)(struct sparcaudio_driver *); + + /* Get and set the output port. () */ + int (*set_output_port)(struct sparcaudio_driver *, int); + int (*get_output_port)(struct sparcaudio_driver *); + + /* Get and set the input port. () */ + int (*set_input_port)(struct sparcaudio_driver *, int); + int (*get_input_port)(struct sparcaudio_driver *); + + /* Get and set the output encoding. () */ + int (*set_output_encoding)(struct sparcaudio_driver *, int); + int (*get_output_encoding)(struct sparcaudio_driver *); + + /* Get and set the input encoding. () */ + int (*set_input_encoding)(struct sparcaudio_driver *, int); + int (*get_input_encoding)(struct sparcaudio_driver *); + + /* Get and set the output rate. () */ + int (*set_output_rate)(struct sparcaudio_driver *, int); + int (*get_output_rate)(struct sparcaudio_driver *); + + /* Get and set the input rate. () */ + int (*set_input_rate)(struct sparcaudio_driver *, int); + int (*get_input_rate)(struct sparcaudio_driver *); + + /* Return driver number to caller. (SunOS /dev/audio specific) */ + int (*sunaudio_getdev_sunos)(struct sparcaudio_driver *); + + /* Get available ports */ + int (*get_output_ports)(struct sparcaudio_driver *); + int (*get_input_ports)(struct sparcaudio_driver *); + + /* Get and set output mute */ + int (*set_output_muted)(struct sparcaudio_driver *, int); + int (*get_output_muted)(struct sparcaudio_driver *); +}; + +extern int register_sparcaudio_driver(struct sparcaudio_driver *); +extern int unregister_sparcaudio_driver(struct sparcaudio_driver *); +extern void sparcaudio_output_done(struct sparcaudio_driver *, int); +extern void sparcaudio_input_done(struct sparcaudio_driver *); +extern int sparcaudio_init(void); +extern int amd7930_init(void); +extern int cs4231_init(void); + +#endif + +/* Macros to convert between mixer stereo volumes and gain (mono) */ +#define s_to_m(a) (((((a) >> 8) & 0x7f) + ((a) & 0x7f)) / 2) +#define m_to_s(a) (((a) << 8) + (a)) + +/* convert mixer stereo volume to balance */ +#define s_to_b(a) (AUDIO_RIGHT_BALANCE * ((((a) >> 8) & 0xff) / (((((a) >> 8) & 0xff) + ((a) & 0xff)) / 2))) + +/* convert mixer stereo volume to audio gain */ +#define s_to_g(a) (((((a) >> 8) & 0xff) + ((a) & 0xff)) / 2) + +/* convert gain a and balance b to mixer volume */ +#define b_to_s(a,b) ((a * (b / AUDIO_RIGHT_BALANCE) << 8) + (a * (1 - (b / AUDIO_RIGHT_BALANCE)))) + +#define SPARCAUDIO_MIXER_MINOR 0 +#define SPARCAUDIO_DSP16_MINOR 1 +#define SPARCAUDIO_DSP_MINOR 3 +#define SPARCAUDIO_AUDIO_MINOR 4 +#define SPARCAUDIO_AUDIOCTL_MINOR 5 +#define SPARCAUDIO_STATUS_MINOR 6 +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/dma.h linux/include/asm-sparc64/dma.h --- v2.1.100/linux/include/asm-sparc64/dma.h Mon Apr 14 16:28:22 1997 +++ linux/include/asm-sparc64/dma.h Fri May 8 00:11:36 1998 @@ -1,4 +1,4 @@ -/* $Id: dma.h,v 1.7 1997/04/10 05:13:28 davem Exp $ +/* $Id: dma.h,v 1.8 1998/04/13 07:27:06 davem Exp $ * include/asm-sparc64/dma.h * * Copyright 1996 (C) David S. Miller (davem@caip.rutgers.edu) @@ -74,7 +74,7 @@ #define DMA_ISESC1(dma) ((dma)->revision == dvmaesc1) /* Main routines in dma.c */ -extern unsigned long dvma_init(struct linux_sbus *, unsigned long); +extern void dvma_init(struct linux_sbus *); /* Fields in the cond_reg register */ /* First, the version identification bits */ diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/ebus.h linux/include/asm-sparc64/ebus.h --- v2.1.100/linux/include/asm-sparc64/ebus.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc64/ebus.h Fri May 8 00:11:36 1998 @@ -1,4 +1,4 @@ -/* $Id: ebus.h,v 1.5 1998/03/15 10:14:46 ecd Exp $ +/* $Id: ebus.h,v 1.6 1998/04/13 07:27:07 davem Exp $ * ebus.h: PCI to Ebus pseudo driver software state. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -82,7 +82,7 @@ extern struct linux_ebus *ebus_chain; -extern unsigned long ebus_init(unsigned long, unsigned long); +extern void ebus_init(void); #define for_each_ebus(bus) \ for((bus) = ebus_chain; (bus); (bus) = (bus)->next) diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/ide.h linux/include/asm-sparc64/ide.h --- v2.1.100/linux/include/asm-sparc64/ide.h Thu May 7 22:51:54 1998 +++ linux/include/asm-sparc64/ide.h Fri May 8 00:11:36 1998 @@ -1,4 +1,4 @@ -/* $Id: ide.h,v 1.6 1998/03/15 13:29:13 ecd Exp $ +/* $Id: ide.h,v 1.8 1998/04/23 05:04:14 davem Exp $ * ide.h: Ultra/PCI specific IDE glue. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -97,24 +97,43 @@ /* From m68k code... */ +#ifdef insl +#undef insl +#endif +#ifdef outsl +#undef outsl +#endif +#ifdef insw +#undef insw +#endif +#ifdef outsw +#undef outsw +#endif + #define insl(data_reg, buffer, wcount) insw(data_reg, buffer, (wcount)<<1) #define outsl(data_reg, buffer, wcount) outsw(data_reg, buffer, (wcount)<<1) #define insw(port, buf, nr) ide_insw((port), (buf), (nr)) #define outsw(port, buf, nr) ide_outsw((port), (buf), (nr)) +/* We need to use L1 cache bypassing to prevent dcache alias + * inconsistencies with user space. -DaveM + */ static __inline__ void ide_insw(unsigned long port, void *dst, unsigned long count) { volatile unsigned short *data_port; - u16 *ps = dst; + u16 *ps = (u16 *)__pa(dst); u32 *pi; data_port = (volatile unsigned short *)port; if(((u64)ps) & 0x2) { - *ps++ = *data_port; + __asm__ __volatile__("stha %0, [%1] %2" + : /* no outputs */ + : "r" (*data_port), "r" (ps++), + "i" (ASI_PHYS_USE_EC)); count--; } pi = (u32 *)ps; @@ -123,12 +142,18 @@ w = (*data_port) << 16; w |= (*data_port); - *pi++ = w; + __asm__ __volatile__("stwa %0, [%1] %2" + : /* no outputs */ + : "r" (w), "r" (pi++), + "i" (ASI_PHYS_USE_EC)); count -= 2; } ps = (u16 *)pi; if(count) - *ps = *data_port; + __asm__ __volatile__("stha %0, [%1] %2" + : /* no outputs */ + : "r" (*data_port), "r" (ps), + "i" (ASI_PHYS_USE_EC)); } static __inline__ void ide_outsw(unsigned long port, @@ -136,27 +161,37 @@ unsigned long count) { volatile unsigned short *data_port; - const u16 *ps = src; + const u16 *ps = (const u16 *)__pa(src); const u32 *pi; data_port = (volatile unsigned short *)port; if(((u64)src) & 0x2) { - *data_port = *ps++; + u16 w; + __asm__ __volatile__("lduha [%1] %2, %0" + : "=r" (w) + : "r" (ps++), "i" (ASI_PHYS_USE_EC)); + *data_port = w; count--; } pi = (const u32 *)ps; while(count >= 2) { u32 w; - - w = *pi++; + __asm__ __volatile__("lduwa [%1] %2, %0" + : "=r" (w) + : "r" (pi++), "i" (ASI_PHYS_USE_EC)); *data_port = (w >> 16); *data_port = w; count -= 2; } ps = (const u16 *)pi; - if(count) - *data_port = *ps; + if(count) { + u16 w; + __asm__ __volatile__("lduha [%1] %2, %0" + : "=r" (w) + : "r" (ps++), "i" (ASI_PHYS_USE_EC)); + *data_port = w; + } } #define T_CHAR (0x0000) /* char: don't touch */ diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/irq.h linux/include/asm-sparc64/irq.h --- v2.1.100/linux/include/asm-sparc64/irq.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc64/irq.h Fri May 8 00:11:36 1998 @@ -76,9 +76,4 @@ return retval; } -static __inline__ int irq_cannonicalize(int irq) -{ - return irq; -} - #endif diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/mmu_context.h linux/include/asm-sparc64/mmu_context.h --- v2.1.100/linux/include/asm-sparc64/mmu_context.h Thu May 7 22:51:54 1998 +++ linux/include/asm-sparc64/mmu_context.h Fri May 8 00:11:36 1998 @@ -1,4 +1,4 @@ -/* $Id: mmu_context.h,v 1.20 1997/09/18 10:42:08 rth Exp $ */ +/* $Id: mmu_context.h,v 1.24 1998/05/06 02:07:54 paulus Exp $ */ #ifndef __SPARC64_MMU_CONTEXT_H #define __SPARC64_MMU_CONTEXT_H @@ -6,38 +6,35 @@ #include #include +#include #define NO_CONTEXT 0 #ifndef __ASSEMBLY__ extern unsigned long tlb_context_cache; +extern spinlock_t scheduler_lock; +extern unsigned long mmu_context_bmap[]; -#define CTX_VERSION_SHIFT PAGE_SHIFT +#define CTX_VERSION_SHIFT (PAGE_SHIFT - 3) #define CTX_VERSION_MASK ((~0UL) << CTX_VERSION_SHIFT) #define CTX_FIRST_VERSION ((1UL << CTX_VERSION_SHIFT) + 1UL) -extern void get_new_mmu_context(struct mm_struct *mm, unsigned long *ctx); +extern void get_new_mmu_context(struct mm_struct *mm); /* Initialize/destroy the context related info for a new mm_struct * instance. */ #define init_new_context(mm) ((mm)->context = NO_CONTEXT) -#define destroy_context(mm) ((mm)->context = NO_CONTEXT) - -#ifdef __SMP__ -#define LOCAL_FLUSH_PENDING(cpu) \ - ((cpu_data[(cpu)].last_tlbversion_seen ^ tlb_context_cache) & CTX_VERSION_MASK) -#define DO_LOCAL_FLUSH(cpu) do { __flush_tlb_all(); \ - cpu_data[cpu].last_tlbversion_seen = \ - tlb_context_cache & CTX_VERSION_MASK; \ - } while(0) -#else -#define LOCAL_FLUSH_PENDING(cpu) 0 -#define DO_LOCAL_FLUSH(cpu) do { __flush_tlb_all(); } while(0) -#endif - -extern void __flush_tlb_all(void); +#define destroy_context(mm) do { \ + if ((mm)->context != NO_CONTEXT) { \ + spin_lock(&scheduler_lock); \ + if (!(((mm)->context ^ tlb_context_cache) & CTX_VERSION_MASK)) \ + clear_bit((mm)->context & ~(CTX_VERSION_MASK), mmu_context_bmap); \ + spin_unlock(&scheduler_lock); \ + (mm)->context = NO_CONTEXT; \ + } \ +} while (0) extern __inline__ void get_mmu_context(struct task_struct *tsk) { @@ -45,18 +42,22 @@ struct mm_struct *mm = tsk->mm; flushw_user(); - if(LOCAL_FLUSH_PENDING(current->processor)) - DO_LOCAL_FLUSH(current->processor); if(!(tsk->tss.flags & SPARC_FLAG_KTHREAD) && !(tsk->flags & PF_EXITING)) { unsigned long ctx = tlb_context_cache; if((mm->context ^ ctx) & CTX_VERSION_MASK) - get_new_mmu_context(mm, &tlb_context_cache); - + get_new_mmu_context(mm); + if(!(mm->cpu_vm_mask & (1UL<context & 0x3ff); + __asm__ __volatile__("flush %g6"); + spitfire_flush_dtlb_secondary_context(); + spitfire_flush_itlb_secondary_context(); + __asm__ __volatile__("flush %g6"); + } /* Don't worry, set_fs() will restore it... */ /* Sigh, damned include loops... just poke seg directly. */ tsk->tss.ctx = (tsk->tss.current_ds.seg ? - (mm->context & 0x1fff) : 0); + (mm->context & 0x3ff) : 0); } else tsk->tss.ctx = 0; spitfire_set_secondary_context(tsk->tss.ctx); diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/page.h linux/include/asm-sparc64/page.h --- v2.1.100/linux/include/asm-sparc64/page.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc64/page.h Fri May 8 00:11:36 1998 @@ -1,4 +1,4 @@ -/* $Id: page.h,v 1.17 1998/01/14 17:16:28 jj Exp $ */ +/* $Id: page.h,v 1.18 1998/05/01 09:33:50 davem Exp $ */ #ifndef _SPARC64_PAGE_H #define _SPARC64_PAGE_H @@ -13,10 +13,62 @@ #define PAGE_MASK (~(PAGE_SIZE-1)) + #ifdef __KERNEL__ #ifndef __ASSEMBLY__ +#define PAGE_ALIAS_BITS (PAGE_SIZE) /* 16K Dcache, 8K pages */ +#ifdef __SMP__ +#define ULOCK_DECLARE extern spinlock_t user_page_lock; +#else +#define ULOCK_DECLARE +#endif +struct upcache { + struct page *list; + unsigned long count; +}; +extern struct upcache user_page_cache[2]; +#define USER_PAGE_WATER 16 + +extern unsigned long get_user_page_slow(int which); +#define get_user_page(__vaddr) \ +({ \ + ULOCK_DECLARE \ + int which = ((__vaddr) & PAGE_ALIAS_BITS) ? 1 : 0; \ + struct upcache *up = &user_page_cache[which]; \ + struct page *p; \ + unsigned long ret; \ + spin_lock(&user_page_lock); \ + if((p = up->list) != NULL) { \ + up->list = p->next; \ + up->count--; \ + } \ + spin_unlock(&user_page_lock); \ + if(p != NULL) \ + ret = PAGE_OFFSET+PAGE_SIZE*p->map_nr; \ + else \ + ret = get_user_page_slow(which); \ + ret; \ +}) + +#define free_user_page(__page, __addr) \ +do { \ + ULOCK_DECLARE \ + int which = ((__addr) & PAGE_ALIAS_BITS) ? 1 : 0; \ + struct upcache *up = &user_page_cache[which]; \ + if(atomic_read(&(__page)->count) == 1 && \ + up->count < USER_PAGE_WATER) { \ + spin_lock(&user_page_lock); \ + (__page)->age = PAGE_INITIAL_AGE; \ + (__page)->next = up->list; \ + up->list = (__page); \ + up->count++; \ + spin_unlock(&user_page_lock); \ + } else \ + free_page(addr); \ +} while(0) + #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) extern void copy_page(unsigned long to, unsigned long from); @@ -81,9 +133,15 @@ #endif /* (STRICT_MM_TYPECHECKS) */ -#define TASK_UNMAPPED_BASE ((current->tss.flags & SPARC_FLAG_32BIT) ? \ - (0x0000000070000000UL) : \ - (0xfffff80000000000UL)) +#define TASK_UNMAPPED_BASE(__off) (((current->tss.flags & SPARC_FLAG_32BIT) ? \ + (0x0000000070000000UL) : \ + (0xfffff80000000000UL)) + \ + (__off & PAGE_SIZE)) + +/* On Ultra this aligns to the size of the L1 cache. */ +#define TASK_UNMAPPED_ALIGN(__addr, __off) \ + ((((__addr)+((PAGE_SIZE<<1UL)-1UL)) & ~((PAGE_SIZE << 1UL)-1UL)) + \ + (__off&PAGE_SIZE)) #endif /* !(__ASSEMBLY__) */ diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/pbm.h linux/include/asm-sparc64/pbm.h --- v2.1.100/linux/include/asm-sparc64/pbm.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc64/pbm.h Fri May 8 00:11:36 1998 @@ -1,4 +1,4 @@ -/* $Id: pbm.h,v 1.12 1998/04/10 12:29:55 ecd Exp $ +/* $Id: pbm.h,v 1.13 1998/04/20 07:15:11 ecd Exp $ * pbm.h: U2P PCI bus module pseudo driver software state. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -90,20 +90,21 @@ * irq registry layer, there is already enough crap in there due to sbus, * fhc, and dcookies. */ -#define PCI_IRQ_IDENT 0x80000000 /* This tells irq.c what we are */ -#define PCI_IRQ_IMAP_OFF 0x7ff00000 /* Offset from first PSYCHO imap */ +#define PCI_IRQ_IDENT 0x80000000 /* This tells irq.c what we are */ +#define PCI_IRQ_IMAP_OFF 0x7ff00000 /* Offset from first PSYCHO imap */ #define PCI_IRQ_IMAP_OFF_SHFT 20 -#define PCI_IRQ_BUSNO 0x000fc000 /* PSYCHO instance */ +#define PCI_IRQ_BUSNO 0x000fc000 /* PSYCHO instance */ #define PCI_IRQ_BUSNO_SHFT 14 -#define PCI_IRQ_IGN 0x000007c0 /* PSYCHO "Int Group Number" */ -#define PCI_IRQ_INO 0x0000003f /* PSYCHO INO */ +#define PCI_IRQ_DMA_SYNC 0x00001000 /* IRQ needs DMA sync for APB */ +#define PCI_IRQ_IGN 0x000007c0 /* PSYCHO "Int Group Number" */ +#define PCI_IRQ_INO 0x0000003f /* PSYCHO INO */ #define PCI_IRQ_P(__irq) (((__irq) & PCI_IRQ_IDENT) != 0) extern __inline__ unsigned int pci_irq_encode(unsigned long imap_off, unsigned long psycho_instance, unsigned long ign, - unsigned long ino) + unsigned long ino, int dma_sync) { unsigned int irq; @@ -112,8 +113,14 @@ irq |= ((psycho_instance << PCI_IRQ_BUSNO_SHFT) & PCI_IRQ_BUSNO); irq |= ((ign << 6) & PCI_IRQ_IGN); irq |= (ino & PCI_IRQ_INO); + irq |= dma_sync ? PCI_IRQ_DMA_SYNC : 0; return irq; } + +/* Used by EBus */ +extern unsigned int psycho_irq_build(struct linux_pbm_info *pbm, + struct pci_dev *pdev, + unsigned int full_ino); #endif /* !(__SPARC64_PBM_H) */ diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/pgtable.h linux/include/asm-sparc64/pgtable.h --- v2.1.100/linux/include/asm-sparc64/pgtable.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc64/pgtable.h Fri May 8 00:11:36 1998 @@ -1,4 +1,4 @@ -/* $Id: pgtable.h,v 1.64 1998/02/16 14:06:44 jj Exp $ +/* $Id: pgtable.h,v 1.67 1998/05/01 09:33:53 davem Exp $ * pgtable.h: SpitFire page table operations. * * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -186,14 +186,14 @@ extern __inline__ void flush_tlb_mm(struct mm_struct *mm) { if(mm->context != NO_CONTEXT) - __flush_tlb_mm(mm->context & 0x1fff); + __flush_tlb_mm(mm->context & 0x3ff); } extern __inline__ void flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { if(mm->context != NO_CONTEXT) - __flush_tlb_range(mm->context & 0x1fff, start, end); + __flush_tlb_range(mm->context & 0x3ff, start, end); } extern __inline__ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) @@ -201,7 +201,7 @@ struct mm_struct *mm = vma->vm_mm; if(mm->context != NO_CONTEXT) - __flush_tlb_page(mm->context & 0x1fff, page & PAGE_MASK); + __flush_tlb_page(mm->context & 0x3ff, page & PAGE_MASK); } #else /* __SMP__ */ @@ -355,28 +355,73 @@ unsigned long *pmd_cache; unsigned long *pte_cache; unsigned long pgcache_size; + unsigned long pgdcache_size; } pgt_quicklists; #endif #define pgd_quicklist (pgt_quicklists.pgd_cache) #define pmd_quicklist (pgt_quicklists.pmd_cache) #define pte_quicklist (pgt_quicklists.pte_cache) #define pgtable_cache_size (pgt_quicklists.pgcache_size) +#define pgd_cache_size (pgt_quicklists.pgdcache_size) -extern pgd_t *get_pgd_slow(void); +extern __inline__ void __init_pgd(pgd_t *pgdp) +{ + extern void __bfill64(void *, unsigned long *); + extern unsigned long two_null_pmd_table; + + __bfill64((void *)pgdp, &two_null_pmd_table); +} + +#ifndef __SMP__ + +extern __inline__ void free_pgd_fast(pgd_t *pgd) +{ + struct page *page = mem_map + MAP_NR(pgd); + + if (!page->pprev_hash) { + (unsigned long *)page->next_hash = pgd_quicklist; + pgd_quicklist = (unsigned long *)page; + } + (unsigned long)page->pprev_hash |= (((unsigned long)pgd & (PAGE_SIZE / 2)) ? 2 : 1); + pgd_cache_size++; +} extern __inline__ pgd_t *get_pgd_fast(void) { - unsigned long *ret; + struct page *ret; - if((ret = pgd_quicklist) != NULL) { - pgd_quicklist = (unsigned long *)(*ret); - ret[0] = ret[1]; - pgtable_cache_size--; - } else - ret = (unsigned long *)get_pgd_slow(); - return (pgd_t *)ret; + if ((ret = (struct page *)pgd_quicklist) != NULL) { + unsigned long mask = (unsigned long)ret->pprev_hash; + unsigned long off = 0; + + if (mask & 1) + mask &= ~1; + else { + off = PAGE_SIZE / 2; + mask &= ~2; + } + (unsigned long)ret->pprev_hash = mask; + if (!mask) + pgd_quicklist = (unsigned long *)ret->next_hash; + ret = (struct page *)(PAGE_OFFSET + (ret->map_nr << PAGE_SHIFT) + off); + pgd_cache_size--; + } else { + ret = (struct page *) __get_free_page(GFP_KERNEL); + if(ret) { + struct page *page = mem_map + MAP_NR(ret); + + __init_pgd((pgd_t *)ret); + (unsigned long)page->pprev_hash = 2; + (unsigned long *)page->next_hash = pgd_quicklist; + pgd_quicklist = (unsigned long *)page; + pgd_cache_size++; + } + } + return (pgd_t *)ret; } +#else /* __SMP__ */ + extern __inline__ void free_pgd_fast(pgd_t *pgd) { *(unsigned long *)pgd = (unsigned long) pgd_quicklist; @@ -384,6 +429,23 @@ pgtable_cache_size++; } +extern __inline__ pgd_t *get_pgd_fast(void) +{ + unsigned long *ret; + + if((ret = pgd_quicklist) != NULL) { + pgd_quicklist = (unsigned long *)(*ret); + ret[0] = ret[1]; + pgtable_cache_size--; + } else { + ret = (unsigned long *) __get_free_page(GFP_KERNEL); + if(ret) + __init_pgd((pgd_t *)ret); + } + return (pgd_t *)ret; +} +#endif /* __SMP__ */ + extern __inline__ void free_pgd_slow(pgd_t *pgd) { free_page((unsigned long)pgd); @@ -530,7 +592,7 @@ unsigned long address, pte_t pte) { struct mm_struct *mm = vma->vm_mm; - unsigned long ctx = mm->context & 0x1fff; + unsigned long ctx = mm->context & 0x3ff; unsigned long tag_access; tag_access = address | ctx; @@ -549,7 +611,7 @@ 2: wrpr %%g1, 0x0, %%pstate " : /* no outputs */ - : "i" (PSTATE_IE), "r" (vma->vm_flags & VM_EXEC), + : "i" (PSTATE_IE), "r" (vma->vm_flags & VM_EXECUTABLE), "i" (TLB_TAG_ACCESS), "r" (tag_access), "r" (pte_val(pte)), "i" (ASI_IMMU), "i" (ASI_ITLB_DATA_IN), "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_IN) diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/processor.h linux/include/asm-sparc64/processor.h --- v2.1.100/linux/include/asm-sparc64/processor.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc64/processor.h Fri May 8 00:11:36 1998 @@ -1,4 +1,4 @@ -/* $Id: processor.h,v 1.42 1998/01/28 10:00:04 ecd Exp $ +/* $Id: processor.h,v 1.43 1998/04/23 08:26:30 davem Exp $ * include/asm-sparc64/processor.h * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -205,6 +205,9 @@ /* Free all resources held by a thread. */ #define release_thread(tsk) do { } while(0) + +#define copy_segments(nr, tsk, mm) do { } while (0) +#define release_segments(mm) do { } while (0) #ifdef __KERNEL__ /* Allocation and freeing of task_struct and kernel stack. */ diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/smp.h linux/include/asm-sparc64/smp.h --- v2.1.100/linux/include/asm-sparc64/smp.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc64/smp.h Fri May 8 00:11:36 1998 @@ -36,8 +36,8 @@ unsigned long irq_count; unsigned int multiplier; unsigned int counter; - unsigned long last_tlbversion_seen; unsigned long pgcache_size; + unsigned long pgdcache_size; /* Dcache line 2 */ unsigned long *pgd_cache; diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/spitfire.h linux/include/asm-sparc64/spitfire.h --- v2.1.100/linux/include/asm-sparc64/spitfire.h Sat May 24 09:10:25 1997 +++ linux/include/asm-sparc64/spitfire.h Fri May 8 00:11:36 1998 @@ -1,4 +1,4 @@ -/* $Id: spitfire.h,v 1.8 1997/05/18 04:16:56 davem Exp $ +/* $Id: spitfire.h,v 1.9 1998/04/28 08:23:33 davem Exp $ * spitfire.h: SpitFire/BlackBird/Cheetah inline MMU operations. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -85,7 +85,7 @@ { __asm__ __volatile__("stxa %0, [%1] %2" : /* No outputs */ - : "r" (ctx & 0x1fff), + : "r" (ctx & 0x3ff), "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); membar("#Sync"); } @@ -104,7 +104,7 @@ { __asm__ __volatile__("stxa %0, [%1] %2" : /* No outputs */ - : "r" (ctx & 0x1fff), + : "r" (ctx & 0x3ff), "r" (SECONDARY_CONTEXT), "i" (ASI_DMMU)); membar("#Sync"); } diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/system.h linux/include/asm-sparc64/system.h --- v2.1.100/linux/include/asm-sparc64/system.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc64/system.h Fri May 8 00:11:36 1998 @@ -1,4 +1,4 @@ -/* $Id: system.h,v 1.38 1998/01/30 11:00:11 jj Exp $ */ +/* $Id: system.h,v 1.39 1998/05/01 09:33:55 davem Exp $ */ #ifndef __SPARC64_SYSTEM_H #define __SPARC64_SYSTEM_H @@ -43,10 +43,10 @@ __asm__ __volatile__("wrpr 0, %%pil" : : : "memory") #define getipl() \ -({ int retval; __asm__ __volatile__("rdpr %%pil, %0" : "=r" (retval)); retval; }) +({ unsigned long retval; __asm__ __volatile__("rdpr %%pil, %0" : "=r" (retval)); retval; }) #define swap_pil(__new_pil) \ -({ int retval; \ +({ unsigned long retval; \ __asm__ __volatile__("rdpr %%pil, %0\n\t" \ "wrpr %1, %%pil" \ : "=r" (retval) \ @@ -56,7 +56,7 @@ }) #define read_pil_and_cli() \ -({ int retval; \ +({ unsigned long retval; \ __asm__ __volatile__("rdpr %%pil, %0\n\t" \ "wrpr 15, %%pil" \ : "=r" (retval) \ diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/termios.h linux/include/asm-sparc64/termios.h --- v2.1.100/linux/include/asm-sparc64/termios.h Wed Apr 8 19:36:29 1998 +++ linux/include/asm-sparc64/termios.h Fri May 8 00:11:36 1998 @@ -1,4 +1,4 @@ -/* $Id: termios.h,v 1.4 1997/03/14 21:05:26 jj Exp $ */ +/* $Id: termios.h,v 1.5 1998/04/12 06:27:22 davem Exp $ */ #ifndef _SPARC64_TERMIOS_H #define _SPARC64_TERMIOS_H diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/timex.h linux/include/asm-sparc64/timex.h --- v2.1.100/linux/include/asm-sparc64/timex.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc64/timex.h Thu May 7 23:53:35 1998 @@ -0,0 +1,15 @@ +/* + * linux/include/asm-sparc64/timex.h + * + * sparc64 architecture timex specifications + */ +#ifndef _ASMsparc64_TIMEX_H +#define _ASMsparc64_TIMEX_H + +#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ +#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */ +#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \ + (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \ + << (SHIFT_SCALE-SHIFT_HZ)) / HZ) + +#endif diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/uaccess.h linux/include/asm-sparc64/uaccess.h --- v2.1.100/linux/include/asm-sparc64/uaccess.h Mon Jan 12 15:15:58 1998 +++ linux/include/asm-sparc64/uaccess.h Fri May 8 00:11:36 1998 @@ -1,4 +1,4 @@ -/* $Id: uaccess.h,v 1.24 1997/12/15 15:05:14 jj Exp $ */ +/* $Id: uaccess.h,v 1.25 1998/04/28 08:23:34 davem Exp $ */ #ifndef _ASM_UACCESS_H #define _ASM_UACCESS_H @@ -52,7 +52,7 @@ flushw_user (); \ current->tss.ctx = 0; \ } else { \ - current->tss.ctx = (current->mm->context & 0x1fff); \ + current->tss.ctx = (current->mm->context & 0x3ff); \ } \ spitfire_set_secondary_context(current->tss.ctx); \ __asm__ __volatile__("flush %g6"); \ diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/unistd.h linux/include/asm-sparc64/unistd.h --- v2.1.100/linux/include/asm-sparc64/unistd.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc64/unistd.h Fri May 8 00:11:36 1998 @@ -1,4 +1,4 @@ -/* $Id: unistd.h,v 1.17 1998/03/29 12:57:54 ecd Exp $ */ +/* $Id: unistd.h,v 1.18 1998/04/14 13:50:01 jj Exp $ */ #ifndef _SPARC64_UNISTD_H #define _SPARC64_UNISTD_H @@ -135,7 +135,7 @@ #define __NR_gettimeofday 116 /* Common */ #define __NR_getrusage 117 /* Common */ #define __NR_getsockopt 118 /* Common */ -/* #define __NR_ni_syscall 119 ENOSYS under SunOS */ +#define __NR_getcwd 119 /* Linux Specific */ #define __NR_readv 120 /* Common */ #define __NR_writev 121 /* Common */ #define __NR_settimeofday 122 /* Common */ diff -u --recursive --new-file v2.1.100/linux/include/linux/affs_fs.h linux/include/linux/affs_fs.h --- v2.1.100/linux/include/linux/affs_fs.h Fri Feb 6 15:34:49 1998 +++ linux/include/linux/affs_fs.h Thu May 7 22:58:04 1998 @@ -93,7 +93,8 @@ /* file.c */ -extern void affs_truncate(struct inode *); +void affs_free_prealloc(struct inode *inode); +extern void affs_truncate(struct inode *); /* dir.c */ diff -u --recursive --new-file v2.1.100/linux/include/linux/blk.h linux/include/linux/blk.h --- v2.1.100/linux/include/linux/blk.h Thu May 7 22:51:54 1998 +++ linux/include/linux/blk.h Fri May 8 18:21:47 1998 @@ -32,21 +32,6 @@ (s1)->sector < (s2)->sector))) /* - * These will have to be changed to be aware of different buffer - * sizes etc.. It actually needs a major cleanup. - */ -#if defined(IDE_DRIVER) || defined(MD_DRIVER) -#define SECTOR_MASK ((BLOCK_SIZE >> 9) - 1) -#else -#define SECTOR_MASK (blksize_size[MAJOR_NR] && \ - blksize_size[MAJOR_NR][MINOR(CURRENT->rq_dev)] ? \ - ((blksize_size[MAJOR_NR][MINOR(CURRENT->rq_dev)] >> 9) - 1) : \ - ((BLOCK_SIZE >> 9) - 1)) -#endif /* IDE_DRIVER */ - -#define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0) - -/* * Initialization functions. */ extern int isp16_init(void); @@ -65,12 +50,18 @@ extern int hd_init(void); extern int ide_init(void); extern int xd_init(void); +extern int mfm_init(void); extern int loop_init(void); extern int md_init(void); extern int ap_init(void); extern int ddv_init(void); extern int z2_init(void); extern int swim3_init(void); +extern int amiga_floppy_init(void); +extern int atari_floppy_init(void); +extern int nbd_init(void); +extern int ez_init(void); +extern int bpcd_init(void); extern int ps2esdi_init(void); extern void set_device_ro(kdev_t dev,int flag); @@ -112,6 +103,7 @@ #define DEVICE_NR(device) (MINOR(device) >> PARTN_BITS) #define DEVICE_ON(device) /* nothing */ #define DEVICE_OFF(device) /* nothing */ +#define DEVICE_NAME "ide" #elif (MAJOR_NR == RAMDISK_MAJOR) @@ -338,6 +330,23 @@ #define DEVICE_ON(device) #define DEVICE_OFF(device) +#elif (MAJOR_NR == MFM_ACORN_MAJOR) + +#define DEVICE_NAME "mfm disk" +#define DEVICE_INTR do_mfm +#define DEVICE_REQUEST do_mfm_request +#define DEVICE_NR(device) (MINOR(device) >> 6) +#define DEVICE_ON(device) +#define DEVICE_OFF(device) + +#elif (MAJOR_NR == NBD_MAJOR) + +#define DEVICE_NAME "nbd" +#define DEVICE_REQUEST do_nbd_request +#define DEVICE_NR(device) (MINOR(device)) +#define DEVICE_ON(device) +#define DEVICE_OFF(device) + #endif /* MAJOR_NR == whatever */ #if (MAJOR_NR != SCSI_TAPE_MAJOR) @@ -347,11 +356,16 @@ #define CURRENT (blk_dev[MAJOR_NR].current_request) #endif +#ifndef DEVICE_NAME +#define DEVICE_NAME "unknown" +#endif + #define CURRENT_DEV DEVICE_NR(CURRENT->rq_dev) #ifdef DEVICE_INTR static void (*DEVICE_INTR)(void) = NULL; #endif + #ifdef DEVICE_TIMEOUT #define SET_TIMER \ @@ -395,89 +409,40 @@ #endif /* !defined(IDE_DRIVER) */ -/* end_request() - SCSI devices have their own version */ -/* - IDE drivers have their own copy too */ - -#if ! SCSI_BLK_MAJOR(MAJOR_NR) - /* - * The [*_]end_request() handler has to be called with the request queue - * spinlock aquired. All functions called within end_request() _must be_ - * atomic. + * end_request() and friends. Must be called with the request queue spinlock + * acquired. All functions called within end_request() _must_be_ atomic. + * + * Several drivers define their own end_request and call end_that_request_first() + * and end_that_request_last() for parts of the original function. This prevents + * code duplication in drivers. */ -#if defined(IDE_DRIVER) && !defined(_IDE_C) /* shared copy for IDE modules */ -void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup); -#else -#ifdef IDE_DRIVER -void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup) { - int nsect; - struct buffer_head *bh; - struct request *req; - unsigned long flags; +int end_that_request_first(struct request *req, int uptodate, char *name); +void end_that_request_last(struct request *req); + +#ifndef LOCAL_END_REQUEST /* If we have our own end_request, we do not want to include this mess */ + +#if ! SCSI_BLK_MAJOR(MAJOR_NR) - spin_lock_irqsave(&io_request_lock,flags); - req = hwgroup->rq; -#else static void end_request(int uptodate) { - int nsect; - struct buffer_head *bh; struct request *req = CURRENT; -#endif /* IDE_DRIVER */ - req->errors = 0; - if (!uptodate) { - printk("end_request: I/O error, dev %s, sector %lu\n", - kdevname(req->rq_dev), req->sector); - if ((bh = req->bh) != NULL) { - nsect = bh->b_size >> 9; - req->nr_sectors--; - req->nr_sectors &= ~(nsect - 1); - req->sector += nsect; - req->sector &= ~(nsect - 1); - } - } + if (end_that_request_first(req, uptodate, DEVICE_NAME)) + return; - if ((bh = req->bh) != NULL) { - req->bh = bh->b_reqnext; - bh->b_reqnext = NULL; - bh->b_end_io(bh, uptodate); - if ((bh = req->bh) != NULL) { - req->current_nr_sectors = bh->b_size >> 9; - if (req->nr_sectors < req->current_nr_sectors) { - req->nr_sectors = req->current_nr_sectors; - printk("end_request: buffer-list destroyed\n"); - } - req->buffer = bh->b_data; -#ifdef IDE_DRIVER - spin_unlock_irqrestore(&io_request_lock,flags); -#endif /* IDE_DRIVER */ - return; - } - } #ifndef DEVICE_NO_RANDOM add_blkdev_randomness(MAJOR(req->rq_dev)); #endif -#ifdef IDE_DRIVER - hwgroup->drive->queue = req->next; - blk_dev[MAJOR(req->rq_dev)].current_request = NULL; - hwgroup->rq = NULL; -#else DEVICE_OFF(req->rq_dev); CURRENT = req->next; -#endif /* IDE_DRIVER */ - if (req->sem != NULL) - up(req->sem); - req->rq_status = RQ_INACTIVE; - wake_up(&wait_for_request); -#ifdef IDE_DRIVER - spin_unlock_irqrestore(&io_request_lock,flags); -#endif /* IDE_DRIVER */ + end_that_request_last(req); } -#endif /* defined(IDE_DRIVER) && !defined(_IDE_C) */ + #endif /* ! SCSI_BLK_MAJOR(MAJOR_NR) */ -#endif /* (MAJOR_NR != SCSI_TAPE_MAJOR) */ +#endif /* LOCAL_END_REQUEST */ +#endif /* (MAJOR_NR != SCSI_TAPE_MAJOR) */ #endif /* defined(MAJOR_NR) || defined(IDE_DRIVER) */ #endif /* _BLK_H */ diff -u --recursive --new-file v2.1.100/linux/include/linux/elf.h linux/include/linux/elf.h --- v2.1.100/linux/include/linux/elf.h Tue Mar 10 10:03:35 1998 +++ linux/include/linux/elf.h Fri May 8 00:13:22 1998 @@ -53,14 +53,14 @@ #define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */ -#define EM_SPARC64 11 /* SPARC v9 (not official) 64-bit */ - #define EM_PARISC 15 /* HPPA */ #define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ #define EM_PPC 20 /* PowerPC */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit */ + /* * This is an interim value that we will use until the committee comes * up with a final number. @@ -210,6 +210,7 @@ #define HWCAP_SPARC_STBAR 2 #define HWCAP_SPARC_SWAP 4 #define HWCAP_SPARC_MULDIV 8 +#define HWCAP_SPARC_V9 16 /* diff -u --recursive --new-file v2.1.100/linux/include/linux/fd.h linux/include/linux/fd.h --- v2.1.100/linux/include/linux/fd.h Tue Jan 20 16:44:58 1998 +++ linux/include/linux/fd.h Fri May 8 00:27:34 1998 @@ -189,7 +189,7 @@ * Current drive state (not directly modifiable by user, readonly) */ struct floppy_drive_struct { - signed char flags; + unsigned long flags; /* values for these flags */ #define FD_NEED_TWADDLE (1 << FD_NEED_TWADDLE_BIT) #define FD_VERIFY (1 << FD_VERIFY_BIT) diff -u --recursive --new-file v2.1.100/linux/include/linux/fs.h linux/include/linux/fs.h --- v2.1.100/linux/include/linux/fs.h Tue Mar 10 10:03:35 1998 +++ linux/include/linux/fs.h Fri May 8 18:21:34 1998 @@ -21,7 +21,9 @@ #include #include +#include +struct poll_table_struct; /* @@ -87,7 +89,7 @@ #define MS_SYNCHRONOUS 16 /* Writes are synced at once */ #define MS_REMOUNT 32 /* Alter flags of a mounted FS */ #define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ -#define S_WRITE 128 /* Write on file/directory/symlink */ +#define S_QUOTA 128 /* Quota initialized for file/directory/symlink */ #define S_APPEND 256 /* Append-only file */ #define S_IMMUTABLE 512 /* Immutable file */ #define MS_NOATIME 1024 /* Do not update access times. */ @@ -119,7 +121,7 @@ #define IS_SYNC(inode) ((inode)->i_flags & MS_SYNCHRONOUS) #define IS_MANDLOCK(inode) ((inode)->i_flags & MS_MANDLOCK) -#define IS_WRITABLE(inode) ((inode)->i_flags & S_WRITE) +#define IS_QUOTAINIT(inode) ((inode)->i_flags & S_QUOTA) #define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE) #define IS_NOATIME(inode) ((inode)->i_flags & MS_NOATIME) @@ -316,7 +318,11 @@ #define ATTR_FLAG_IMMUTABLE 8 /* Immutable file */ #define ATTR_FLAG_NODIRATIME 16 /* Don't update atime for directory */ +/* + * Includes for diskquotas and mount structures. + */ #include +#include struct inode { struct list_head i_hash; @@ -632,11 +638,11 @@ struct dquot_operations { void (*initialize) (struct inode *, short); void (*drop) (struct inode *); - int (*alloc_block) (const struct inode *, unsigned long); - int (*alloc_inode) (const struct inode *, unsigned long); + int (*alloc_block) (const struct inode *, unsigned long, uid_t, char); + int (*alloc_inode) (const struct inode *, unsigned long, uid_t); void (*free_block) (const struct inode *, unsigned long); void (*free_inode) (const struct inode *, unsigned long); - int (*transfer) (struct inode *, struct iattr *, char); + int (*transfer) (struct inode *, struct iattr *, char, uid_t); }; struct file_system_type { diff -u --recursive --new-file v2.1.100/linux/include/linux/hippidevice.h linux/include/linux/hippidevice.h --- v2.1.100/linux/include/linux/hippidevice.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/hippidevice.h Fri May 8 18:22:18 1998 @@ -0,0 +1,56 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Definitions for the HIPPI handlers. + * + * Version: @(#)hippidevice.h 1.0.0 05/26/97 + * + * Author: Jes Sorensen, + * + * hippidevice.h is based on previous fddidevice.h work by + * Ross Biro, + * Fred N. van Kempen, + * Alan Cox, + * Lawrence V. Stefani, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _LINUX_HIPPIDEVICE_H +#define _LINUX_HIPPIDEVICE_H + +#include + +#ifdef __KERNEL__ +extern int hippi_header(struct sk_buff *skb, + struct device *dev, + unsigned short type, + void *daddr, + void *saddr, + unsigned len); + +extern int hippi_rebuild_header(struct sk_buff *skb); + +extern unsigned short hippi_type_trans(struct sk_buff *skb, + struct device *dev); + +extern void hippi_header_cache_bind(struct hh_cache ** hhp, + struct device *dev, + unsigned short htype, + __u32 daddr); + +extern void hippi_header_cache_update(struct hh_cache *hh, + struct device *dev, + unsigned char * haddr); +extern int hippi_header_parse(struct sk_buff *skb, unsigned char *haddr); + +extern void hippi_net_init(void); + +extern struct device *init_hippi_dev(struct device *, int); +#endif + +#endif /* _LINUX_HIPPIDEVICE_H */ diff -u --recursive --new-file v2.1.100/linux/include/linux/if_fddi.h linux/include/linux/if_fddi.h --- v2.1.100/linux/include/linux/if_fddi.h Mon Nov 18 01:31:32 1996 +++ linux/include/linux/if_fddi.h Fri May 8 00:08:02 1998 @@ -107,6 +107,8 @@ { __u32 rx_packets; /* total packets received */ __u32 tx_packets; /* total packets transmitted */ + __u32 rx_bytes; /* total bytes received */ + __u32 tx_bytes; /* total bytes transmitted */ __u32 rx_errors; /* bad packets received */ __u32 tx_errors; /* packet transmit problems */ __u32 rx_dropped; /* no space in linux buffers */ @@ -114,6 +116,25 @@ __u32 multicast; /* multicast packets received */ __u32 transmit_collision; /* always 0 for FDDI */ + /* detailed rx_errors */ + __u32 rx_length_errors; + __u32 rx_over_errors; /* receiver ring buff overflow */ + __u32 rx_crc_errors; /* recved pkt with crc error */ + __u32 rx_frame_errors; /* recv'd frame alignment error */ + __u32 rx_fifo_errors; /* recv'r fifo overrun */ + __u32 rx_missed_errors; /* receiver missed packet */ + + /* detailed tx_errors */ + __u32 tx_aborted_errors; + __u32 tx_carrier_errors; + __u32 tx_fifo_errors; + __u32 tx_heartbeat_errors; + __u32 tx_window_errors; + + /* for cslip etc */ + __u32 rx_compressed; + __u32 tx_compressed; + /* Detailed FDDI statistics. Adopted from RFC 1512 */ __u8 smt_station_id[8]; diff -u --recursive --new-file v2.1.100/linux/include/linux/if_hippi.h linux/include/linux/if_hippi.h --- v2.1.100/linux/include/linux/if_hippi.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/if_hippi.h Fri May 8 18:22:17 1998 @@ -0,0 +1,157 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Global definitions for the HIPPI interface. + * + * Version: @(#)if_hippi.h 1.0.0 05/26/97 + * + * Author: Fred N. van Kempen, + * Donald Becker, + * Alan Cox, + * Steve Whitehouse, + * Jes Sorensen, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _LINUX_IF_HIPPI_H +#define _LINUX_IF_HIPPI_H + +#include + +/* + * HIPPI magic constants. + */ + +#define HIPPI_ALEN 6 /* Bytes in one HIPPI hw-addr */ +#define HIPPI_HLEN sizeof(struct hippi_hdr) +#define HIPPI_ZLEN 0 /* Min. bytes in frame without FCS */ +#define HIPPI_DATA_LEN 65280 /* Max. bytes in payload */ +#define HIPPI_FRAME_LEN (HIPPI_DATA_LEN + HIPPI_HLEN) + /* Max. bytes in frame without FCS */ + +/* + * Define LLC and SNAP constants. + */ +#define HIPPI_EXTENDED_SAP 0xAA +#define HIPPI_UI_CMD 0x03 + + +/* + * Do we need to list some sort of ID's here? + */ + +/* + * HIPPI statistics collection data. + */ + +struct hipnet_statistics +{ + int rx_packets; /* total packets received */ + int tx_packets; /* total packets transmitted */ + int rx_errors; /* bad packets received */ + int tx_errors; /* packet transmit problems */ + int rx_dropped; /* no space in linux buffers */ + int tx_dropped; /* no space available in linux */ + + /* detailed rx_errors: */ + int rx_length_errors; + int rx_over_errors; /* receiver ring buff overflow */ + int rx_crc_errors; /* recved pkt with crc error */ + int rx_frame_errors; /* recv'd frame alignment error */ + int rx_fifo_errors; /* recv'r fifo overrun */ + int rx_missed_errors; /* receiver missed packet */ + + /* detailed tx_errors */ + int tx_aborted_errors; + int tx_carrier_errors; + int tx_fifo_errors; + int tx_heartbeat_errors; + int tx_window_errors; +}; + + +struct hippi_fp_hdr +{ +#if 0 + __u8 ulp; /* must contain 4 */ +#if defined (__BIG_ENDIAN_BITFIELD) + __u8 d1_data_present:1; /* must be 1 */ + __u8 start_d2_burst_boundary:1; /* must be zero */ + __u8 reserved:6; /* must be zero */ +#if 0 + __u16 reserved1:5; + __u16 d1_area_size:8; /* must be 3 */ + __u16 d2_offset:3; /* must be zero */ +#endif +#elif defined(__LITTLE_ENDIAN_BITFIELD) + __u8 reserved:6; /* must be zero */ + __u8 start_d2_burst_boundary:1; /* must be zero */ + __u8 d1_data_present:1; /* must be 1 */ +#if 0 + __u16 d2_offset:3; /* must be zero */ + __u16 d1_area_size:8; /* must be 3 */ + __u16 reserved1:5; /* must be zero */ +#endif +#else +#error "Please fix " +#endif +#else + __u32 fixed; +#endif + __u32 d2_size; +} __attribute__ ((packed)); + +struct hippi_le_hdr +{ +#if defined (__BIG_ENDIAN_BITFIELD) + unsigned long fc:3; + unsigned long double_wide:1; + unsigned long message_type:4; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + unsigned long message_type:4; + unsigned long double_wide:1; + unsigned long fc:3; +#endif + __u8 dest_switch_addr[3]; +#if defined (__BIG_ENDIAN_BITFIELD) + __u8 dest_addr_type:4, + src_addr_type:4; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + __u8 src_addr_type:4, + dest_addr_type:4; +#endif + __u8 src_switch_addr[3]; + __u16 reserved; + __u8 daddr[HIPPI_ALEN]; + __u16 locally_administered; + __u8 saddr[HIPPI_ALEN]; +} __attribute__ ((packed)); + +#define HIPPI_OUI_LEN 3 +/* + * Looks like the dsap and ssap fields have been swapped by mistake in + * RFC 2067 "IP over HIPPI". + */ +struct hippi_snap_hdr +{ + __u8 dsap; /* always 0xAA */ + __u8 ssap; /* always 0xAA */ + __u8 ctrl; /* always 0x03 */ + __u8 oui[HIPPI_OUI_LEN]; /* organizational universal id (zero)*/ + __u16 ethertype; /* packet type ID field */ +} __attribute__ ((packed)); + +struct hippi_hdr +{ + struct hippi_fp_hdr fp; + struct hippi_le_hdr le; + struct hippi_snap_hdr snap; +} __attribute__ ((packed)); + +#endif /* _LINUX_IF_HIPPI_H */ diff -u --recursive --new-file v2.1.100/linux/include/linux/interrupt.h linux/include/linux/interrupt.h --- v2.1.100/linux/include/linux/interrupt.h Fri Jan 30 15:50:57 1998 +++ linux/include/linux/interrupt.h Fri May 8 18:21:34 1998 @@ -42,17 +42,12 @@ KEYBOARD_BH, CYCLADES_BH, CM206_BH, - JS_BH + JS_BH, + MACSERIAL_BH }; #include #include - -/* - * Are we in an interrupt context? Either doing bottom half - * or hardware interrupt processing? - */ -#define in_interrupt() (local_irq_count[smp_processor_id()] + local_bh_count[smp_processor_id()] != 0) /* * Autoprobing for irqs: diff -u --recursive --new-file v2.1.100/linux/include/linux/major.h linux/include/linux/major.h --- v2.1.100/linux/include/linux/major.h Wed Apr 1 20:11:54 1998 +++ linux/include/linux/major.h Fri May 8 00:42:39 1998 @@ -40,6 +40,7 @@ #define CYCLADES_MAJOR 19 #define CYCLADESAUX_MAJOR 20 #define MITSUMI_X_CDROM_MAJOR 20 +#define MFM_ACORN_MAJOR 21 /* ARM Linux /dev/mfm */ #define SCSI_GENERIC_MAJOR 21 #define Z8530_MAJOR 34 #define DIGI_MAJOR 23 diff -u --recursive --new-file v2.1.100/linux/include/linux/md.h linux/include/linux/md.h --- v2.1.100/linux/include/linux/md.h Sat Nov 8 11:39:13 1997 +++ linux/include/linux/md.h Fri May 8 00:17:13 1998 @@ -33,9 +33,10 @@ #define MD_DEFAULT_DISK_READAHEAD (256 * 1024) /* ioctls */ -#define REGISTER_DEV _IO (MD_MAJOR, 1) -#define START_MD _IO (MD_MAJOR, 2) -#define STOP_MD _IO (MD_MAJOR, 3) +#define REGISTER_DEV _IO (MD_MAJOR, 1) +#define START_MD _IO (MD_MAJOR, 2) +#define STOP_MD _IO (MD_MAJOR, 3) +#define REGISTER_DEV_NEW _IO (MD_MAJOR, 4) /* personalities : @@ -199,6 +200,7 @@ #include #include #include +#include /* * Kernel-based reconstruction is mostly working, but still requires @@ -209,12 +211,6 @@ #define MAX_REAL 8 /* Max number of physical dev per md dev */ #define MAX_MD_DEV 4 /* Max number of md dev */ -#if SUPPORT_RECONSTRUCTION -#define MAX_MD_THREADS (MAX_MD_DEV * 3) /* Max number of kernel threads */ -#else -#define MAX_MD_THREADS (MAX_MD_DEV) /* Max number of kernel threads */ -#endif /* SUPPORT_RECONSTRUCTION */ - #define FACTOR(a) ((a)->repartition & FACTOR_MASK) #define MAX_FAULT(a) (((a)->repartition & FAULT_MASK)>>8) #define PERSONALITY(a) ((a)->repartition & PERSONALITY_MASK) @@ -279,10 +275,12 @@ void (*run) (void *data); void *data; struct wait_queue *wqueue; - __u32 flags; + unsigned long flags; + struct semaphore *sem; + struct task_struct *tsk; }; -#define THREAD_WAKEUP 0 +#define THREAD_WAKEUP 0 extern struct md_dev md_dev[MAX_MD_DEV]; extern int md_size[MAX_MD_DEV]; diff -u --recursive --new-file v2.1.100/linux/include/linux/mount.h linux/include/linux/mount.h --- v2.1.100/linux/include/linux/mount.h Thu Dec 14 21:31:39 1995 +++ linux/include/linux/mount.h Fri May 8 17:54:39 1998 @@ -3,26 +3,36 @@ * Definitions for mount interface. This describes the in the kernel build * linkedlist with mounted filesystems. * - * Author: Marco van Wieringen + * Author: Marco van Wieringen * - * Version: $Id: mount.h,v 1.3 1994/07/20 22:01:00 mvw Exp mvw $ + * Version: $Id: mount.h,v 2.0 1996/11/17 16:48:14 mvw Exp mvw $ * */ #ifndef _LINUX_MOUNT_H #define _LINUX_MOUNT_H +#define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */ +#define DQUOT_GRP_ENABLED 0x02 /* Group diskquotas enabled */ + +struct quota_mount_options +{ + unsigned int flags; /* Flags for diskquotas on this device */ + struct semaphore semaphore; /* lock device while I/O in progress */ + struct file *files[MAXQUOTAS]; /* fp's to quotafiles */ + time_t inode_expire[MAXQUOTAS]; /* expiretime for inode-quota */ + time_t block_expire[MAXQUOTAS]; /* expiretime for block-quota */ + char rsquash[MAXQUOTAS]; /* for quotas threath root as any other user */ +}; + struct vfsmount { - kdev_t mnt_dev; /* Device this applies to */ - char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ - char *mnt_dirname; /* Name of directory mounted on */ - unsigned int mnt_flags; /* Flags of this device */ - struct semaphore mnt_sem; /* lock device while I/O in progress */ - struct super_block *mnt_sb; /* pointer to superblock */ - struct file *mnt_quotas[MAXQUOTAS]; /* fp's to quotafiles */ - time_t mnt_iexp[MAXQUOTAS]; /* expiretime for inodes */ - time_t mnt_bexp[MAXQUOTAS]; /* expiretime for blocks */ - struct vfsmount *mnt_next; /* pointer to next in linkedlist */ + kdev_t mnt_dev; /* Device this applies to */ + char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ + char *mnt_dirname; /* Name of directory mounted on */ + unsigned int mnt_flags; /* Flags of this device */ + struct super_block *mnt_sb; /* pointer to superblock */ + struct quota_mount_options mnt_dquot; /* Diskquota specific mount options */ + struct vfsmount *mnt_next; /* pointer to next in linkedlist */ }; struct vfsmount *lookup_vfsmnt(kdev_t dev); diff -u --recursive --new-file v2.1.100/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v2.1.100/linux/include/linux/proc_fs.h Thu May 7 22:51:55 1998 +++ linux/include/linux/proc_fs.h Fri May 8 18:21:39 1998 @@ -74,7 +74,7 @@ }; enum pid_subdirectory_inos { - PROC_PID_FD_DIR = 1 + PROC_PID_FD_DIR = 0x8000, /* 0x8000-0xffff */ }; enum net_directory_inos { diff -u --recursive --new-file v2.1.100/linux/include/linux/quota.h linux/include/linux/quota.h --- v2.1.100/linux/include/linux/quota.h Sat Nov 1 11:01:24 1997 +++ linux/include/linux/quota.h Fri May 8 17:54:39 1998 @@ -33,7 +33,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Version: $Id: quota.h,v 1.8 1995/03/11 11:43:07 mvw Exp mvw $ + * Version: $Id: quota.h,v 2.0 1996/11/17 16:48:14 mvw Exp mvw $ */ #ifndef _LINUX_QUOTA_ @@ -43,7 +43,6 @@ /* * Convert diskblocks to blocks and the other way around. - * currently only to fool the BSD source. :-) */ #define dbtob(num) (num << 10) #define btodb(num) (num >> 10) @@ -74,16 +73,20 @@ * Definitions for the default names of the quotas files. */ #define INITQFNAMES { \ - "user", /* USRQUOTA */ \ - "group", /* GRPQUOTA */ \ - "undefined", \ + "user", /* USRQUOTA */ \ + "group", /* GRPQUOTA */ \ + "undefined", \ }; #define QUOTAFILENAME "quota" #define QUOTAGROUP "staff" -#define NR_DQHASH 43 /* Just an arbitrary number any suggestions ? */ -#define NR_DQUOTS 256 /* Number of quotas active at one time */ +extern int nr_dquots, nr_free_dquots; +extern int max_dquots; +extern int dquot_root_squash; + +#define NR_DQHASH 43 /* Just an arbitrary number */ +#define NR_DQUOTS 256 /* Maximum number of quotas active at one time (Configurable from /proc/sys/fs) */ /* * Command definitions for the 'quotactl' system call. @@ -103,6 +106,7 @@ #define Q_SYNC 0x0600 /* sync disk copy of a filesystems quotas */ #define Q_SETQLIM 0x0700 /* set limits */ #define Q_GETSTATS 0x0800 /* get collected stats */ +#define Q_RSQUASH 0x1000 /* set root_squash option */ /* * The following structure defines the format of the disk quota file @@ -110,14 +114,14 @@ * indexed by user or group number. */ struct dqblk { - __u32 dqb_bhardlimit; /* absolute limit on disk blks alloc */ - __u32 dqb_bsoftlimit; /* preferred limit on disk blks */ - __u32 dqb_curblocks; /* current block count */ - __u32 dqb_ihardlimit; /* maximum # allocated inodes */ - __u32 dqb_isoftlimit; /* preferred inode limit */ - __u32 dqb_curinodes; /* current # allocated inodes */ - time_t dqb_btime; /* time limit for excessive disk use */ - time_t dqb_itime; /* time limit for excessive files */ + __u32 dqb_bhardlimit; /* absolute limit on disk blks alloc */ + __u32 dqb_bsoftlimit; /* preferred limit on disk blks */ + __u32 dqb_curblocks; /* current block count */ + __u32 dqb_ihardlimit; /* absolute limit on allocated inodes */ + __u32 dqb_isoftlimit; /* preferred inode limit */ + __u32 dqb_curinodes; /* current # allocated inodes */ + time_t dqb_btime; /* time limit for excessive disk use */ + time_t dqb_itime; /* time limit for excessive inode use */ }; /* @@ -135,21 +139,18 @@ #define dqoff(UID) ((loff_t)((UID) * sizeof (struct dqblk))) struct dqstats { - __u32 lookups; - __u32 drops; - __u32 reads; - __u32 writes; - __u32 cache_hits; - __u32 pages_allocated; - __u32 allocated_dquots; - __u32 free_dquots; - __u32 syncs; + __u32 lookups; + __u32 drops; + __u32 reads; + __u32 writes; + __u32 cache_hits; + __u32 allocated_dquots; + __u32 free_dquots; + __u32 syncs; }; #ifdef __KERNEL__ -#include - /* * Maximum length of a message generated in the quota system, * that needs to be kicked onto the tty. @@ -164,18 +165,19 @@ #define DQ_FAKE 0x40 /* no limits only usage */ struct dquot { - unsigned int dq_id; /* id this applies to (uid, gid) */ - short dq_type; /* type of quota */ - kdev_t dq_dev; /* Device this applies to */ - short dq_flags; /* see DQ_* */ - short dq_count; /* reference count */ - struct vfsmount *dq_mnt; /* vfsmountpoint this applies to */ - struct dqblk dq_dqb; /* diskquota usage */ - struct wait_queue *dq_wait; /* pointer to waitqueue */ - struct dquot *dq_prev; /* pointer to prev dquot */ - struct dquot *dq_next; /* pointer to next dquot */ - struct dquot *dq_hash_prev; /* pointer to prev dquot */ - struct dquot *dq_hash_next; /* pointer to next dquot */ + unsigned int dq_id; /* ID this applies to (uid, gid) */ + short dq_type; /* Type of quota */ + kdev_t dq_dev; /* Device this applies to */ + short dq_flags; /* See DQ_* */ + short dq_count; /* Reference count */ + unsigned long dq_referenced; /* Number of times this dquot was referenced during its lifetime */ + struct vfsmount *dq_mnt; /* VFS_mount_point this applies to */ + struct dqblk dq_dqb; /* Diskquota usage */ + struct wait_queue *dq_wait; /* Pointer to waitqueue */ + struct dquot *dq_next; /* Pointer to next dquot */ + struct dquot *dq_hash_next; /* Pointer to next in dquot_hash */ + struct dquot **dq_hash_pprev; /* Pointer to previous in dquot_hash */ + struct dquot **dq_pprev; }; #define NODQUOT (struct dquot *)NULL @@ -190,22 +192,6 @@ #define QUOTA_OK 0 #define NO_QUOTA 1 - -/* - * declaration of quota_function calls in kernel. - */ - -extern void dquot_initialize(struct inode *inode, short type); -extern void dquot_drop(struct inode *inode); -extern int dquot_alloc_block(const struct inode *inode, unsigned long number); -extern int dquot_alloc_inode(const struct inode *inode, unsigned long number); -extern void dquot_free_block(const struct inode *inode, unsigned long number); -extern void dquot_free_inode(const struct inode *inode, unsigned long number); -extern int dquot_transfer(struct inode *inode, struct iattr *iattr, char direction); - -extern void invalidate_dquots(kdev_t dev, short type); -extern int quota_off(kdev_t dev, short type); -extern int sync_dquots(kdev_t dev, short type); #else diff -u --recursive --new-file v2.1.100/linux/include/linux/quotaops.h linux/include/linux/quotaops.h --- v2.1.100/linux/include/linux/quotaops.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/quotaops.h Fri May 8 18:22:50 1998 @@ -0,0 +1,144 @@ +/* + * Definitions for diskquota-operations. When diskquota is configured these + * macros expand to the right source-code. + * + * Author: Marco van Wieringen + * + * Version: $Id: quotaops.h,v 1.2 1998/01/15 16:22:26 ecd Exp $ + * + */ +#ifndef _LINUX_QUOTAOPS_ +#define _LINUX_QUOTAOPS_ + +#include + +#if defined(CONFIG_QUOTA) + +/* + * declaration of quota_function calls in kernel. + */ +extern void dquot_initialize(struct inode *inode, short type); +extern void dquot_drop(struct inode *inode); +extern void invalidate_dquots(kdev_t dev, short type); +extern int quota_off(kdev_t dev, short type); +extern int sync_dquots(kdev_t dev, short type); + +extern int dquot_alloc_block(const struct inode *inode, unsigned long number, + uid_t initiator, char warn); +extern int dquot_alloc_inode(const struct inode *inode, unsigned long number, + uid_t initiator); + +extern void dquot_free_block(const struct inode *inode, unsigned long number); +extern void dquot_free_inode(const struct inode *inode, unsigned long number); + +extern int dquot_transfer(struct inode *inode, struct iattr *iattr, + char direction, uid_t initiator); + +/* + * Operations supported for diskquotas. + */ +#define DQUOT_INIT(inode) \ +if (inode->i_sb && inode->i_sb->dq_op) { \ + inode->i_sb->dq_op->initialize(inode, -1); \ +} + +#define DQUOT_DROP(inode) \ +if (IS_QUOTAINIT(inode)) { \ + if (inode->i_sb && inode->i_sb->dq_op) \ + inode->i_sb->dq_op->drop(inode); \ +} + +#define DQUOT_SAVE_DROP(inode) \ +if (IS_QUOTAINIT(inode)) { \ + inode->i_lock = 1; \ + if (inode->i_sb && inode->i_sb->dq_op) \ + inode->i_sb->dq_op->drop(inode); \ + unlock_inode(inode); \ + goto we_slept; \ +} + +#define DQUOT_PREALLOC_BLOCK(sb, inode, nr) \ +if (sb->dq_op) { \ + if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize), \ + current->euid, 0) == NO_QUOTA) \ + break; \ +} + +#define DQUOT_ALLOC_BLOCK(sb, inode, nr) \ +if (sb->dq_op) { \ + if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize), \ + current->euid, 1) == NO_QUOTA) { \ + unlock_super (sb); \ + *err = -EDQUOT; \ + return 0; \ + } \ +} + +#define DQUOT_ALLOC_INODE(sb, inode) \ +if (sb->dq_op) { \ + sb->dq_op->initialize (inode, -1); \ + if (sb->dq_op->alloc_inode (inode, 1, current->euid)) { \ + sb->dq_op->drop (inode); \ + inode->i_nlink = 0; \ + iput (inode); \ + *err = -EDQUOT; \ + return NULL; \ + } \ + inode->i_flags |= S_QUOTA; \ +} + +#define DQUOT_FREE_BLOCK(sb, inode, nr) \ +if (sb->dq_op) { \ + sb->dq_op->free_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize)); \ +} + +#define DQUOT_FREE_INODE(sb, inode) \ +if (sb->dq_op) { \ + sb->dq_op->free_inode(inode, 1); \ +} + +#define DQUOT_TRANSFER(dentry, iattr) \ +if (dentry->d_inode->i_sb->dq_op) { \ + if (IS_QUOTAINIT(dentry->d_inode) == 0) \ + dentry->d_inode->i_sb->dq_op->initialize(dentry->d_inode, -1); \ + if (dentry->d_inode->i_sb->dq_op->transfer(dentry->d_inode, &iattr, 0, current->euid)) { \ + error = -EDQUOT; \ + goto out; \ + } \ + error = notify_change(dentry, &iattr); \ + if (error) \ + inode->i_sb->dq_op->transfer(dentry->d_inode, &iattr, 1, current->euid); \ +} else { \ + error = notify_change(dentry, &iattr); \ +} + +#define DQUOT_SYNC(dev) \ +sync_dquots(dev, -1) + +#define DQUOT_OFF(dev) \ +quota_off(dev, -1) + +#else + +/* + * NO-OP when quota not configured. + */ +#define DQUOT_INIT(inode) +#define DQUOT_DROP(inode) +#define DQUOT_SAVE_DROP(inode) +#define DQUOT_PREALLOC_BLOCK(sb, inode, nr) +#define DQUOT_ALLOC_BLOCK(sb, inode, nr) +#define DQUOT_ALLOC_INODE(sb, inode) +#define DQUOT_FREE_BLOCK(sb, inode, nr) +#define DQUOT_FREE_INODE(sb, inode) +#define DQUOT_SYNC(dev) +#define DQUOT_OFF(dev) + +/* + * Special case expands to a simple notify_change. + */ +#define DQUOT_TRANSFER(dentry, iattr) \ +error = notify_change(dentry, &iattr) + +#endif /* CONFIG_QUOTA */ +#endif /* _LINUX_QUOTAOPS_ */ diff -u --recursive --new-file v2.1.100/linux/include/linux/raid1.h linux/include/linux/raid1.h --- v2.1.100/linux/include/linux/raid1.h Sat Nov 8 11:39:13 1997 +++ linux/include/linux/raid1.h Fri May 8 00:17:13 1998 @@ -37,8 +37,8 @@ struct raid1_bh { unsigned int remaining; - unsigned int state; int cmd; + unsigned long state; struct md_dev *mddev; struct buffer_head *master_bh; struct buffer_head *mirror_bh [MD_SB_DISKS]; diff -u --recursive --new-file v2.1.100/linux/include/linux/raid5.h linux/include/linux/raid5.h --- v2.1.100/linux/include/linux/raid5.h Sat Nov 8 11:39:13 1997 +++ linux/include/linux/raid5.h Fri May 8 00:17:13 1998 @@ -30,7 +30,7 @@ int size; /* buffers size */ int pd_idx; /* parity disk index */ int nr_pending; /* nr of pending cmds */ - __u32 state; /* state flags */ + unsigned long state; /* state flags */ int cmd; /* stripe cmd */ int count; /* nr of waiters */ int write_method; /* reconstruct-write / read-modify-write */ diff -u --recursive --new-file v2.1.100/linux/include/linux/smp.h linux/include/linux/smp.h --- v2.1.100/linux/include/linux/smp.h Sat May 2 14:19:54 1998 +++ linux/include/linux/smp.h Fri May 8 00:45:50 1998 @@ -10,9 +10,10 @@ #include /* - * main IPI interface, handles INIT, TLB flush, STOP, etc.: + * main IPI interface, handles INIT, TLB flush, STOP, etc. (defined in asm header): + * + * extern void smp_message_pass(int target, int msg, unsigned long data, int wait); */ -extern void smp_message_pass(int target, int msg, unsigned long data, int wait); /* * Boot processor call to load the other CPU's diff -u --recursive --new-file v2.1.100/linux/include/linux/sysctl.h linux/include/linux/sysctl.h --- v2.1.100/linux/include/linux/sysctl.h Thu May 7 22:51:55 1998 +++ linux/include/linux/sysctl.h Fri May 8 17:54:39 1998 @@ -27,7 +27,7 @@ /* For internal pattern-matching use only: */ #ifdef __KERNEL__ -#define CTL_ANY -1 /* Matches any name */ +#define CTL_ANY -1 /* Matches any name */ #define CTL_NONE 0 #endif @@ -54,24 +54,19 @@ KERN_PROF, /* table: profiling information */ KERN_NODENAME, KERN_DOMAINNAME, - KERN_NRINODE, - KERN_MAXINODE, - KERN_NRFILE, - KERN_MAXFILE, KERN_SECURELVL, /* int: system security level */ KERN_PANIC, /* int: panic timeout */ KERN_REALROOTDEV, /* real root device to mount after initrd */ - KERN_NFSRNAME, /* NFS root name */ - KERN_NFSRADDRS, /* NFS root addresses */ KERN_JAVA_INTERPRETER, /* path to Java(tm) interpreter */ KERN_JAVA_APPLETVIEWER, /* path to Java(tm) appletviewer */ KERN_SPARC_REBOOT, /* reboot command on Sparc */ KERN_CTLALTDEL, /* int: allow ctl-alt-del to reboot */ KERN_PRINTK, /* sturct: control printk logging parameters */ KERN_NAMETRANS, /* Name translation */ - KERN_STATINODE, - KERN_DENTRY, /* dentry statistics */ + KERN_PPC_HTABRECLAIM, /* turn htab reclaimation on/off on PPC */ + KERN_PPC_ZEROPAGED, /* turn idle page zeroing on/off on PPC */ KERN_MODPROBE, + KERN_SG_BIG_BUFF }; @@ -360,6 +355,17 @@ /* CTL_PROC names: */ /* CTL_FS names: */ +enum +{ + FS_NRINODE=1, /* int: current number of allocated inodes */ + FS_STATINODE, + FS_MAXINODE, /* int: maximum number of inodes that can be allocated */ + FS_NRDQUOT, /* int: current number of allocated dquots */ + FS_MAXDQUOT, /* int: maximum number of dquots that can be allocated */ + FS_NRFILE, /* int: current number of allocated filedescriptors */ + FS_MAXFILE, /* int: maximum number of filedescriptors that can be allocated */ + FS_DENTRY, +}; /* CTL_DEBUG names: */ diff -u --recursive --new-file v2.1.100/linux/include/linux/timex.h linux/include/linux/timex.h --- v2.1.100/linux/include/linux/timex.h Wed Apr 16 14:15:00 1997 +++ linux/include/linux/timex.h Thu May 7 23:53:35 1998 @@ -17,6 +17,10 @@ /* * Modification history timex.h * + * 29 Dec 97 Russell King + * Moved CLOCK_TICK_RATE, CLOCK_TICK_FACTOR and FINETUNE to asm/timex.h + * for ARM machines + * * 9 Jan 97 Adrian Sun * Shifted LATCH define to allow access to alpha machines. * @@ -125,20 +129,13 @@ #define PPS_VALID 120 /* pps signal watchdog max (s) */ #define MAXGLITCH 30 /* pps signal glitch max (s) */ -/* LATCH is used in the interval timer and ftape setup. */ -#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ -#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ - -#ifndef __alpha__ /* - * This definitively is wrong for the Alpha and none of the - * kernel code seems to reference this anymore. + * Pick up the architecture specific timex specifications */ -#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */ -#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \ - (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \ - << (SHIFT_SCALE-SHIFT_HZ)) / HZ) -#endif /* !__alpha__ */ +#include + +/* LATCH is used in the interval timer and ftape setup. */ +#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ /* * syscall interface - used (mainly by NTP daemon) diff -u --recursive --new-file v2.1.100/linux/init/main.c linux/init/main.c --- v2.1.100/linux/init/main.c Sat May 2 14:19:54 1998 +++ linux/init/main.c Fri May 8 17:54:39 1998 @@ -64,7 +64,6 @@ extern int kswapd(void *); extern void kswapd_setup(void); -extern void dquot_init(void); extern void init_IRQ(void); extern void init_modules(void); extern long console_init(long, long); @@ -284,6 +283,9 @@ #if defined(CONFIG_SYSVIPC) extern void ipc_init(void); #endif +#if defined(CONFIG_QUOTA) +extern void dquot_init_hash(void); +#endif #ifdef CONFIG_MD_BOOT extern void md_setup(char *str,int *ints) __init; @@ -1060,7 +1062,9 @@ #if defined(CONFIG_SYSVIPC) ipc_init(); #endif - dquot_init(); +#if defined(CONFIG_QUOTA) + dquot_init_hash(); +#endif check_bugs(); printk("POSIX conformance testing by UNIFIX\n"); diff -u --recursive --new-file v2.1.100/linux/kernel/capability.c linux/kernel/capability.c --- v2.1.100/linux/kernel/capability.c Thu May 7 22:51:55 1998 +++ linux/kernel/capability.c Thu May 7 23:44:25 1998 @@ -5,7 +5,6 @@ * Integrated into 2.1.97+, Andrew G. Morgan */ -#include #include #include #include diff -u --recursive --new-file v2.1.100/linux/kernel/exit.c linux/kernel/exit.c --- v2.1.100/linux/kernel/exit.c Wed Apr 1 20:11:54 1998 +++ linux/kernel/exit.c Fri May 8 17:54:39 1998 @@ -20,7 +20,9 @@ #include #include #include +#ifdef CONFIG_BSD_PROCESS_ACCT #include +#endif #include #include @@ -346,7 +348,9 @@ panic("Attempted to kill the idle task!"); fake_volatile: current->flags |= PF_EXITING; +#ifdef CONFIG_BSD_PROCESS_ACCT acct_process(code); +#endif del_timer(¤t->real_timer); sem_exit(); __exit_mm(current); diff -u --recursive --new-file v2.1.100/linux/kernel/kmod.c linux/kernel/kmod.c --- v2.1.100/linux/kernel/kmod.c Sat May 2 14:19:54 1998 +++ linux/kernel/kmod.c Fri May 8 15:58:13 1998 @@ -86,13 +86,12 @@ int pid; int waitpid_result; - pid = kernel_thread(exec_modprobe, (void*) module_name, - CLONE_FS | SIGCHLD); + pid = kernel_thread(exec_modprobe, (void*) module_name, CLONE_FS); if (pid < 0) { printk(KERN_ERR "kmod: fork failed, errno %d\n", -pid); return pid; } - waitpid_result = waitpid(pid, NULL, 0); + waitpid_result = waitpid(pid, NULL, __WCLONE); if (waitpid_result != pid) { printk (KERN_ERR "kmod: waitpid(%d,NULL,0) failed, returning %d.\n", pid, waitpid_result); diff -u --recursive --new-file v2.1.100/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.1.100/linux/kernel/ksyms.c Mon Apr 6 17:41:01 1998 +++ linux/kernel/ksyms.c Fri May 8 00:23:41 1998 @@ -269,8 +269,6 @@ /* interrupt handling */ EXPORT_SYMBOL(request_irq); EXPORT_SYMBOL(free_irq); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(probe_irq_on); EXPORT_SYMBOL(probe_irq_off); EXPORT_SYMBOL(bh_active); diff -u --recursive --new-file v2.1.100/linux/kernel/sched.c linux/kernel/sched.c --- v2.1.100/linux/kernel/sched.c Thu May 7 22:51:55 1998 +++ linux/kernel/sched.c Fri May 8 00:31:10 1998 @@ -399,9 +399,7 @@ need_resched = 0; prev = current; this_cpu = smp_processor_id(); - if (local_irq_count[this_cpu]) - goto scheduling_in_interrupt; - if (local_bh_count[this_cpu]) + if (in_interrupt()) goto scheduling_in_interrupt; release_kernel_lock(prev, this_cpu, lock_depth); if (bh_active & bh_mask) diff -u --recursive --new-file v2.1.100/linux/kernel/sys.c linux/kernel/sys.c --- v2.1.100/linux/kernel/sys.c Thu May 7 22:51:55 1998 +++ linux/kernel/sys.c Fri May 8 00:27:35 1998 @@ -841,9 +841,6 @@ if(copy_from_user(system_utsname.nodename, name, len)) return -EFAULT; system_utsname.nodename[len] = 0; -#ifdef CONFIG_TRANS_NAMES - translations_dirty = 1; -#endif return 0; } @@ -872,9 +869,6 @@ if(copy_from_user(system_utsname.domainname, name, len)) return -EFAULT; system_utsname.domainname[len] = 0; -#ifdef CONFIG_TRANS_NAMES - translations_dirty = 1; -#endif return 0; } diff -u --recursive --new-file v2.1.100/linux/kernel/sysctl.c linux/kernel/sysctl.c --- v2.1.100/linux/kernel/sysctl.c Thu May 7 22:51:55 1998 +++ linux/kernel/sysctl.c Fri May 8 17:54:39 1998 @@ -51,6 +51,9 @@ #ifdef __sparc__ extern char reboot_command []; #endif +#ifdef __powerpc__ +extern unsigned long htab_reclaim_on, zero_paged_on; +#endif static int parse_table(int *, int, void *, size_t *, void *, size_t, ctl_table *, void **); @@ -144,18 +147,6 @@ 0644, NULL, &proc_dostring, &sysctl_string}, {KERN_DOMAINNAME, "domainname", system_utsname.domainname, 64, 0644, NULL, &proc_dostring, &sysctl_string}, - {KERN_NRINODE, "inode-nr", &inodes_stat, 2*sizeof(int), - 0444, NULL, &proc_dointvec}, - {KERN_STATINODE, "inode-state", &inodes_stat, 7*sizeof(int), - 0444, NULL, &proc_dointvec}, - {KERN_MAXINODE, "inode-max", &max_inodes, sizeof(int), - 0644, NULL, &proc_dointvec}, - {KERN_NRFILE, "file-nr", &nr_files, 3*sizeof(int), - 0444, NULL, &proc_dointvec}, - {KERN_MAXFILE, "file-max", &max_files, sizeof(int), - 0644, NULL, &proc_dointvec}, - {KERN_DENTRY, "dentry-state", &dentry_stat, 6*sizeof(int), - 0444, NULL, &proc_dointvec}, {KERN_PANIC, "panic", &panic_timeout, sizeof(int), 0644, NULL, &proc_dointvec}, #ifdef CONFIG_BLK_DEV_INITRD @@ -172,6 +163,12 @@ {KERN_SPARC_REBOOT, "reboot-cmd", reboot_command, 256, 0644, NULL, &proc_dostring, &sysctl_string }, #endif +#ifdef __powerpc__ + {KERN_PPC_HTABRECLAIM, "htab-reclaim", &htab_reclaim_on, sizeof(int), + 0644, NULL, &proc_dointvec}, + {KERN_PPC_ZEROPAGED, "zero-paged", &zero_paged_on, sizeof(int), + 0644, NULL, &proc_dointvec}, +#endif {KERN_CTLALTDEL, "ctrl-alt-del", &C_A_D, sizeof(int), 0644, NULL, &proc_dointvec}, {KERN_PRINTK, "printk", &console_loglevel, 4*sizeof(int), @@ -181,7 +178,7 @@ 0644, NULL, &proc_dostring, &sysctl_string }, #endif #ifdef CONFIG_CHR_DEV_SG - {KERN_NRFILE, "sg-big-buff", &sg_big_buff, sizeof (int), + {KERN_SG_BIG_BUFF, "sg-big-buff", &sg_big_buff, sizeof (int), 0444, NULL, &proc_dointvec}, #endif {0} @@ -213,6 +210,22 @@ }; static ctl_table fs_table[] = { + {FS_NRINODE, "inode-nr", &inodes_stat, 2*sizeof(int), + 0444, NULL, &proc_dointvec}, + {FS_STATINODE, "inode-state", &inodes_stat, 7*sizeof(int), + 0444, NULL, &proc_dointvec}, + {FS_MAXINODE, "inode-max", &max_inodes, sizeof(int), + 0644, NULL, &proc_dointvec}, + {FS_NRFILE, "file-nr", &nr_files, 3*sizeof(int), + 0444, NULL, &proc_dointvec}, + {FS_MAXFILE, "file-max", &max_files, sizeof(int), + 0644, NULL, &proc_dointvec}, + {FS_NRDQUOT, "dquot-nr", &nr_dquots, 2*sizeof(int), + 0444, NULL, &proc_dointvec}, + {FS_MAXDQUOT, "dquot-max", &max_dquots, sizeof(int), + 0644, NULL, &proc_dointvec}, + {FS_DENTRY, "dentry-state", &dentry_stat, 6*sizeof(int), + 0444, NULL, &proc_dointvec}, {0} }; @@ -892,9 +905,6 @@ if (len == table->maxlen) len--; ((char *) table->data)[len] = 0; -#ifdef CONFIG_TRANS_NAMES - translations_dirty = 1; -#endif } return 0; } diff -u --recursive --new-file v2.1.100/linux/mm/mlock.c linux/mm/mlock.c --- v2.1.100/linux/mm/mlock.c Thu May 7 22:51:55 1998 +++ linux/mm/mlock.c Fri May 8 00:32:31 1998 @@ -129,8 +129,8 @@ if (newflags & VM_LOCKED) while (start < end) { - char c; - get_user(c,(char *) start); + int c; + get_user(c,(int *) start); __asm__ __volatile__("": :"r" (c)); start += PAGE_SIZE; } diff -u --recursive --new-file v2.1.100/linux/mm/page_alloc.c linux/mm/page_alloc.c --- v2.1.100/linux/mm/page_alloc.c Thu May 7 22:51:55 1998 +++ linux/mm/page_alloc.c Thu May 7 23:44:25 1998 @@ -98,7 +98,7 @@ * * Hint: -mask = 1+~mask */ -static spinlock_t page_alloc_lock = SPIN_LOCK_UNLOCKED; +spinlock_t page_alloc_lock = SPIN_LOCK_UNLOCKED; /* * This routine is used by the kernel swap deamon to determine diff -u --recursive --new-file v2.1.100/linux/net/802/Makefile linux/net/802/Makefile --- v2.1.100/linux/net/802/Makefile Tue Dec 23 13:52:02 1997 +++ linux/net/802/Makefile Fri May 8 00:08:02 1998 @@ -29,6 +29,10 @@ O_OBJS += fddi.o endif +ifdef CONFIG_HIPPI +O_OBJS += hippi.o +endif + ifdef CONFIG_IPX SNAP=y endif diff -u --recursive --new-file v2.1.100/linux/net/802/hippi.c linux/net/802/hippi.c --- v2.1.100/linux/net/802/hippi.c Wed Dec 31 16:00:00 1969 +++ linux/net/802/hippi.c Fri May 8 00:08:02 1998 @@ -0,0 +1,162 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * HIPPI-type device handling. + * + * Version: @(#)hippi.c 1.0.0 05/29/97 + * + * Authors: Ross Biro, + * Fred N. van Kempen, + * Mark Evans, + * Florian La Roche, + * Alan Cox, + * Jes Sorensen, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * hippi_net_init() + * + * Do nothing, this is just to pursuade the stupid linker to behave. + */ + +void hippi_net_init(void) +{ + return; +} + +/* + * Create the HIPPI MAC header for an arbitrary protocol layer + * + * saddr=NULL means use device source address + * daddr=NULL means leave destination address (eg unresolved arp) + */ + +int hippi_header(struct sk_buff *skb, struct device *dev, + unsigned short type, void *daddr, void *saddr, + unsigned len) +{ + struct hippi_hdr *hip = (struct hippi_hdr *)skb_push(skb, HIPPI_HLEN); + + if (!len){ + len = skb->len - HIPPI_HLEN; + printk("hippi_header(): length not supplied\n"); + } + + /* + * Due to the stupidity of the little endian byte-order we + * have to set the fp field this way. + */ + hip->fp.fixed = __constant_htonl(0x04800018); + hip->fp.d2_size = htonl(len + 8); + hip->le.fc = 0; + hip->le.double_wide = 0; /* only HIPPI 800 for the time being */ + hip->le.message_type = 0; /* Data PDU */ + + hip->le.dest_addr_type = 2; /* 12 bit SC address */ + hip->le.src_addr_type = 2; /* 12 bit SC address */ + +#if 1 + if (saddr) + { + printk("existing saddr - this should not happen, configure ARP please!\n"); + memcpy(hip->le.src_switch_addr, saddr + 3, 3); + }else + memcpy(hip->le.src_switch_addr, dev->dev_addr + 3, 3); + + memset(&hip->le.reserved, 0, 16); +#endif + + hip->snap.dsap = HIPPI_EXTENDED_SAP; + hip->snap.ssap = HIPPI_EXTENDED_SAP; + hip->snap.ctrl = HIPPI_UI_CMD; + hip->snap.oui[0] = 0x00; + hip->snap.oui[1] = 0x00; + hip->snap.oui[2] = 0x00; + hip->snap.ethertype = htons(type); + + if (daddr) + { + memcpy(hip->le.dest_switch_addr, daddr + 3, 3); + memcpy(&skb->private.ifield, daddr + 2, 4); + return(HIPPI_HLEN); + } + return -HIPPI_HLEN; +} + + +/* + * Rebuild the HIPPI MAC header. This is called after an ARP has + * completed on this sk_buff. We now let ARP fill in the other fields. + */ + +int hippi_rebuild_header(struct sk_buff *skb) +{ + struct hippi_hdr *hip = (struct hippi_hdr *)skb->data; + + /* + * Only IP is currently supported + */ + + if(hip->snap.ethertype != __constant_htons(ETH_P_IP)) + { + printk(KERN_DEBUG "%s: unable to resolve type %X addresses.\n",skb->dev->name,ntohs(hip->snap.ethertype)); + return 0; + } + + /* + * We don't support dynamic ARP on HIPPI, but we use the ARP + * static ARP tables to hold the I-FIELDs. + */ + return arp_find(hip->le.daddr, skb); +} + + +/* + * Determine the packet's protocol ID. + */ + +unsigned short hippi_type_trans(struct sk_buff *skb, struct device *dev) +{ + struct hippi_hdr *hip; + + hip = (struct hippi_hdr *) skb->data; + + /* + * This is actually wrong ... question is if we really should + * set the raw address here. + */ + skb->mac.raw = skb->data; + skb_pull(skb, HIPPI_HLEN); + + /* + * No fancy promisc stuff here now. + */ + + return hip->snap.ethertype; +} diff -u --recursive --new-file v2.1.100/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c --- v2.1.100/linux/net/appletalk/ddp.c Thu May 7 22:51:55 1998 +++ linux/net/appletalk/ddp.c Fri May 8 00:08:02 1998 @@ -990,7 +990,7 @@ { struct sock *sk; - sk = sk_alloc(AF_APPLETALK, GFP_KERNEL, 1); + sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, 1); if(sk == NULL) return (-ENOMEM); @@ -1304,7 +1304,7 @@ return (0); } - if(call_in_firewall(AF_APPLETALK, skb->dev, ddp, NULL,&skb)!=FW_ACCEPT) + if(call_in_firewall(PF_APPLETALK, skb->dev, ddp, NULL,&skb)!=FW_ACCEPT) { kfree_skb(skb); return (0); @@ -1338,7 +1338,7 @@ /* * Check firewall allows this routing */ - if(call_fw_firewall(AF_APPLETALK, skb->dev, ddp, NULL, &skb) != FW_ACCEPT) + if(call_fw_firewall(PF_APPLETALK, skb->dev, ddp, NULL, &skb) != FW_ACCEPT) { kfree_skb(skb); return (0); @@ -1452,10 +1452,7 @@ skb->sk = sock; if(sock_queue_rcv_skb(sock, skb) < 0) - { - skb->sk = NULL; kfree_skb(skb); - } return (0); } @@ -1611,8 +1608,8 @@ skb = sock_alloc_send_skb(sk, size, 0, flags&MSG_DONTWAIT, &err); if(skb == NULL) return (err); - - skb->sk = sk; + + skb->sk = sk; skb_reserve(skb, ddp_dl->header_length); skb_reserve(skb, dev->hard_header_len); @@ -1652,7 +1649,7 @@ else ddp->deh_sum = atalk_checksum(ddp, len + sizeof(*ddp)); - if(call_out_firewall(AF_APPLETALK, skb->dev, ddp, NULL, &skb) != FW_ACCEPT) + if(call_out_firewall(PF_APPLETALK, skb->dev, ddp, NULL, &skb) != FW_ACCEPT) { kfree_skb(skb); return (-EPERM); @@ -1859,13 +1856,13 @@ static struct net_proto_family atalk_family_ops= { - AF_APPLETALK, + PF_APPLETALK, atalk_create }; static struct proto_ops atalk_dgram_ops= { - AF_APPLETALK, + PF_APPLETALK, sock_no_dup, atalk_release, @@ -2014,7 +2011,7 @@ dev_remove_pack(<alk_packet_type); dev_remove_pack(&ppptalk_packet_type); unregister_snap_client(ddp_snap_id); - sock_unregister(atalk_family_ops.family); + sock_unregister(PF_APPLETALK); return; } diff -u --recursive --new-file v2.1.100/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c --- v2.1.100/linux/net/ax25/af_ax25.c Tue Apr 14 14:29:26 1998 +++ linux/net/ax25/af_ax25.c Fri May 8 00:08:02 1998 @@ -787,13 +787,13 @@ switch (sock->type) { case SOCK_DGRAM: - if (protocol == 0 || protocol == AF_AX25) + if (protocol == 0 || protocol == PF_AX25) protocol = AX25_P_TEXT; break; case SOCK_SEQPACKET: switch (protocol) { case 0: - case AF_AX25: /* For CLX */ + case PF_AX25: /* For CLX */ protocol = AX25_P_TEXT; break; case AX25_P_SEGMENT: @@ -828,7 +828,7 @@ return -ESOCKTNOSUPPORT; } - if ((sk = sk_alloc(AF_AX25, GFP_ATOMIC, 1)) == NULL) + if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, 1)) == NULL) return -ENOMEM; if ((ax25 = ax25_create_cb()) == NULL) { @@ -854,7 +854,7 @@ struct sock *sk; ax25_cb *ax25; - if ((sk = sk_alloc(AF_AX25, GFP_ATOMIC, 1)) == NULL) + if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, 1)) == NULL) return NULL; if ((ax25 = ax25_create_cb()) == NULL) { @@ -1689,12 +1689,12 @@ static struct net_proto_family ax25_family_ops = { - AF_AX25, + PF_AX25, ax25_create }; static struct proto_ops ax25_proto_ops = { - AF_AX25, + PF_AX25, sock_no_dup, ax25_release, @@ -1820,7 +1820,7 @@ ax25_packet_type.type = htons(ETH_P_AX25); dev_remove_pack(&ax25_packet_type); - sock_unregister(AF_AX25); + sock_unregister(PF_AX25); } #endif diff -u --recursive --new-file v2.1.100/linux/net/core/rtnetlink.c linux/net/core/rtnetlink.c --- v2.1.100/linux/net/core/rtnetlink.c Sat May 2 14:19:54 1998 +++ linux/net/core/rtnetlink.c Fri May 8 00:08:02 1998 @@ -246,7 +246,7 @@ s_idx = 1; for (idx=1; idxnlh->nlmsg_type-RTM_BASE; - if (idx < s_idx || idx == AF_PACKET) + if (idx < s_idx || idx == PF_PACKET) continue; if (rtnetlink_links[idx] == NULL || rtnetlink_links[idx][type].dumpit == NULL) @@ -336,7 +336,7 @@ link_tab = rtnetlink_links[family]; if (link_tab == NULL) - link_tab = rtnetlink_links[AF_UNSPEC]; + link_tab = rtnetlink_links[PF_UNSPEC]; link = &link_tab[type]; sz_idx = type>>2; @@ -349,7 +349,7 @@ if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { if (link->dumpit == NULL) - link = &(rtnetlink_links[AF_UNSPEC][type]); + link = &(rtnetlink_links[PF_UNSPEC][type]); if (link->dumpit == NULL) goto err_inval; @@ -398,7 +398,7 @@ } if (link->doit == NULL) - link = &(rtnetlink_links[AF_UNSPEC][type]); + link = &(rtnetlink_links[PF_UNSPEC][type]); if (link->doit == NULL) goto err_inval; err = link->doit(skb, nlh, (void *)&rta); @@ -538,8 +538,8 @@ if (rtnl == NULL) panic("rtnetlink_init: cannot initialize rtnetlink\n"); register_netdevice_notifier(&rtnetlink_dev_notifier); - rtnetlink_links[AF_UNSPEC] = link_rtnetlink_table; - rtnetlink_links[AF_PACKET] = link_rtnetlink_table; + rtnetlink_links[PF_UNSPEC] = link_rtnetlink_table; + rtnetlink_links[PF_PACKET] = link_rtnetlink_table; } diff -u --recursive --new-file v2.1.100/linux/net/econet/econet.c linux/net/econet/econet.c --- v2.1.100/linux/net/econet/econet.c Sat May 2 14:19:55 1998 +++ linux/net/econet/econet.c Fri May 8 00:08:02 1998 @@ -557,7 +557,7 @@ MOD_INC_USE_COUNT; err = -ENOBUFS; - sk = sk_alloc(AF_ECONET, GFP_KERNEL, 1); + sk = sk_alloc(PF_ECONET, GFP_KERNEL, 1); if (sk == NULL) goto out; @@ -570,7 +570,7 @@ goto out_free; memset(sk->protinfo.af_econet, 0, sizeof(struct econet_opt)); sk->zapped=0; - sk->family = AF_ECONET; + sk->family = PF_ECONET; sk->num = protocol; sklist_insert_socket(&econet_sklist, sk); @@ -727,12 +727,12 @@ } static struct net_proto_family econet_family_ops = { - AF_ECONET, + PF_ECONET, econet_create }; static struct proto_ops econet_ops = { - AF_ECONET, + PF_ECONET, sock_no_dup, econet_release, @@ -1008,7 +1008,7 @@ /* We can count ourselves lucky Acorn machines are too dim to speak IPv6. :-) */ - if ((error = sock_create(AF_INET, SOCK_DGRAM, 0, &udpsock)) < 0) + if ((error = sock_create(PF_INET, SOCK_DGRAM, 0, &udpsock)) < 0) { printk("AUN: socket error %d\n", -error); return error; diff -u --recursive --new-file v2.1.100/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c --- v2.1.100/linux/net/ipv4/af_inet.c Thu May 7 22:51:56 1998 +++ linux/net/ipv4/af_inet.c Fri May 8 00:08:02 1998 @@ -3,9 +3,9 @@ * operating system. INET is implemented using the BSD Socket * interface as the means of communication with the user level. * - * AF_INET protocol family socket handler. + * PF_INET protocol family socket handler. * - * Version: $Id: af_inet.c,v 1.71 1998/04/16 05:38:16 davem Exp $ + * Version: $Id: af_inet.c,v 1.72 1998/05/03 14:30:49 alan Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -330,23 +330,23 @@ /* Compatibility */ if (sock->type == SOCK_PACKET) { static int warned; - if (net_families[AF_PACKET]==NULL) + if (net_families[PF_PACKET]==NULL) { #if defined(CONFIG_KMOD) && defined(CONFIG_PACKET_MODULE) char module_name[30]; - sprintf(module_name,"net-pf-%d", AF_PACKET); + sprintf(module_name,"net-pf-%d", PF_PACKET); request_module(module_name); - if (net_families[AF_PACKET] == NULL) + if (net_families[PF_PACKET] == NULL) #endif return -ESOCKTNOSUPPORT; } if (!warned++) - printk(KERN_INFO "%s uses obsolete (AF_INET,SOCK_PACKET)\n", current->comm); - return net_families[AF_PACKET]->create(sock, protocol); + printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n", current->comm); + return net_families[PF_PACKET]->create(sock, protocol); } sock->state = SS_UNCONNECTED; - sk = sk_alloc(AF_INET, GFP_KERNEL, 1); + sk = sk_alloc(PF_INET, GFP_KERNEL, 1); if (sk == NULL) goto do_oom; @@ -398,7 +398,7 @@ #ifdef CONFIG_TCP_NAGLE_OFF sk->nonagle = 1; #endif - sk->family = AF_INET; + sk->family = PF_INET; sk->protocol = protocol; sk->prot = prot; @@ -958,7 +958,7 @@ } struct proto_ops inet_stream_ops = { - AF_INET, + PF_INET, sock_no_dup, inet_release, @@ -979,7 +979,7 @@ }; struct proto_ops inet_dgram_ops = { - AF_INET, + PF_INET, sock_no_dup, inet_release, @@ -1000,7 +1000,7 @@ }; struct net_proto_family inet_family_ops = { - AF_INET, + PF_INET, inet_create }; diff -u --recursive --new-file v2.1.100/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c --- v2.1.100/linux/net/ipv4/devinet.c Thu May 7 22:51:56 1998 +++ linux/net/ipv4/devinet.c Fri May 8 00:08:02 1998 @@ -1,7 +1,7 @@ /* * NET3 IP device support routines. * - * Version: $Id: devinet.c,v 1.20 1998/03/27 07:02:44 davem Exp $ + * Version: $Id: devinet.c,v 1.21 1998/05/03 14:30:52 alan Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -1014,10 +1014,10 @@ __initfunc(void devinet_init(void)) { - register_gifconf(AF_INET, inet_gifconf); + register_gifconf(PF_INET, inet_gifconf); register_netdevice_notifier(&ip_netdev_notifier); #ifdef CONFIG_RTNETLINK - rtnetlink_links[AF_INET] = inet_rtnetlink_table; + rtnetlink_links[PF_INET] = inet_rtnetlink_table; #endif #ifdef CONFIG_SYSCTL devinet_sysctl.sysctl_header = diff -u --recursive --new-file v2.1.100/linux/net/ipv4/ipconfig.c linux/net/ipv4/ipconfig.c --- v2.1.100/linux/net/ipv4/ipconfig.c Tue Mar 17 22:18:16 1998 +++ linux/net/ipv4/ipconfig.c Fri May 8 00:08:02 1998 @@ -1,5 +1,5 @@ /* - * $Id: ipconfig.c,v 1.11 1998/02/12 07:43:16 davem Exp $ + * $Id: ipconfig.c,v 1.12 1998/05/03 14:30:53 alan Exp $ * * Automatic Configuration of IP -- use BOOTP or RARP or user-supplied * information to configure own IP address and routes. @@ -552,7 +552,7 @@ { int err; - if ((err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, sock)) < 0) + if ((err = sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, sock)) < 0) printk(KERN_ERR "BOOTP: Cannot open UDP socket!\n"); return err; } diff -u --recursive --new-file v2.1.100/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- v2.1.100/linux/net/ipv4/tcp_input.c Thu May 7 22:51:56 1998 +++ linux/net/ipv4/tcp_input.c Fri May 8 00:08:02 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.116 1998/05/02 14:50:11 davem Exp $ + * Version: $Id: tcp_input.c,v 1.118 1998/05/06 04:53:48 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -593,7 +593,7 @@ * connection startup slow start one packet too * quickly. This is severely frowned upon behavior. */ - if(sacked & TCPCB_SACKED_RETRANS && tp->retrans_out) + if((sacked & TCPCB_SACKED_RETRANS) && tp->retrans_out) tp->retrans_out--; if(!(scb->flags & TCPCB_FLAG_SYN)) { acked |= FLAG_DATA_ACKED; @@ -968,7 +968,7 @@ tw->af_specific = sk->tp_pinfo.af_tcp.af_specific; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - if(tw->family == AF_INET6) { + if(tw->family == PF_INET6) { memcpy(&tw->v6_daddr, &sk->net_pinfo.af_inet6.daddr, sizeof(struct in6_addr)); diff -u --recursive --new-file v2.1.100/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c --- v2.1.100/linux/net/ipv4/tcp_ipv4.c Thu May 7 22:51:56 1998 +++ linux/net/ipv4/tcp_ipv4.c Fri May 8 00:08:02 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_ipv4.c,v 1.145 1998/05/02 12:47:13 davem Exp $ + * Version: $Id: tcp_ipv4.c,v 1.146 1998/05/03 14:30:59 alan Exp $ * * IPv4 specific functions * @@ -1155,7 +1155,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, struct sk_buff *skb, int snd_mss) { - struct sock *newsk = sk_alloc(AF_INET, GFP_ATOMIC, 0); + struct sock *newsk = sk_alloc(PF_INET, GFP_ATOMIC, 0); if(newsk != NULL) { struct tcp_opt *newtp; diff -u --recursive --new-file v2.1.100/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c --- v2.1.100/linux/net/ipv4/tcp_output.c Sat May 2 14:19:55 1998 +++ linux/net/ipv4/tcp_output.c Fri May 8 00:08:02 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_output.c,v 1.87 1998/04/26 01:11:35 davem Exp $ + * Version: $Id: tcp_output.c,v 1.90 1998/05/06 04:59:15 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -415,8 +415,7 @@ } /* Update sequence range on original skb. */ - TCP_SKB_CB(skb)->end_seq += - TCP_SKB_CB(next_skb)->end_seq - TCP_SKB_CB(next_skb)->seq; + TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(next_skb)->end_seq; /* Merge over control information. */ flags |= TCP_SKB_CB(next_skb)->flags; /* This moves PSH/FIN etc. over */ @@ -453,7 +452,9 @@ * and not use it for RTT calculation in the absence of * the timestamp option. */ - for (skb = skb_peek(&sk->write_queue); skb != tp->send_head; + for (skb = skb_peek(&sk->write_queue); + ((skb != tp->send_head) && + (skb != (struct sk_buff *)&sk->write_queue)); skb = skb->next) if (skb->len > mss) tcp_retransmit_skb(sk, skb); @@ -536,6 +537,10 @@ if (tp->retrans_head == tp->send_head) tp->retrans_head = NULL; + /* Each time, advance the retrans_head if we got + * a packet out or we skipped one because it was + * SACK'd. -DaveM + */ while ((skb = tp->retrans_head) != NULL) { /* If it has been ack'd by a SACK block, we don't * retransmit it. @@ -544,14 +549,17 @@ /* Send it out, punt if error occurred. */ if(tcp_retransmit_skb(sk, skb)) break; + + update_retrans_head(sk); /* Stop retransmitting if we've hit the congestion * window limit. */ if (tp->retrans_out >= (tp->snd_cwnd >> TCP_CWND_SHIFT)) break; + } else { + update_retrans_head(sk); } - update_retrans_head(sk); } } @@ -732,8 +740,6 @@ mss = min(mss, sk->user_mss); if (req->tstamp_ok) mss -= TCPOLEN_TSTAMP_ALIGNED; - else - req->mss += TCPOLEN_TSTAMP_ALIGNED; /* Don't offer more than they did. * This way we don't have to memorize who said what. diff -u --recursive --new-file v2.1.100/linux/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c --- v2.1.100/linux/net/ipv6/addrconf.c Thu May 7 22:51:56 1998 +++ linux/net/ipv6/addrconf.c Fri May 8 00:08:02 1998 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: addrconf.c,v 1.38 1998/03/20 09:12:14 davem Exp $ + * $Id: addrconf.c,v 1.39 1998/05/03 14:31:04 alan Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -1808,7 +1808,7 @@ addr_chk_timer.expires = jiffies + ADDR_CHECK_FREQUENCY; add_timer(&addr_chk_timer); #ifdef CONFIG_RTNETLINK - rtnetlink_links[AF_INET6] = inet6_rtnetlink_table; + rtnetlink_links[PF_INET6] = inet6_rtnetlink_table; #endif #ifdef CONFIG_SYSCTL addrconf_sysctl.sysctl_header = @@ -1825,7 +1825,7 @@ int i; #ifdef CONFIG_RTNETLINK - rtnetlink_links[AF_INET6] = NULL; + rtnetlink_links[PF_INET6] = NULL; #endif #ifdef CONFIG_SYSCTL addrconf_sysctl_unregister(&ipv6_devconf_dflt); diff -u --recursive --new-file v2.1.100/linux/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c --- v2.1.100/linux/net/ipv6/af_inet6.c Thu May 7 22:51:56 1998 +++ linux/net/ipv6/af_inet6.c Fri May 8 00:08:02 1998 @@ -1,5 +1,5 @@ /* - * AF_INET6 socket family + * PF_INET6 socket protocol family * Linux INET6 implementation * * Authors: @@ -7,7 +7,7 @@ * * Adapted from linux/net/ipv4/af_inet.c * - * $Id: af_inet6.c,v 1.30 1998/03/25 00:23:05 davem Exp $ + * $Id: af_inet6.c,v 1.31 1998/05/03 14:31:06 alan Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -71,7 +71,7 @@ struct sock *sk; struct proto *prot; - sk = sk_alloc(AF_INET6, GFP_KERNEL, 1); + sk = sk_alloc(PF_INET6, GFP_KERNEL, 1); if (sk == NULL) goto do_oom; @@ -105,7 +105,7 @@ sk->destruct = NULL; sk->zapped = 0; - sk->family = AF_INET6; + sk->family = PF_INET6; sk->protocol = protocol; sk->prot = prot; @@ -336,7 +336,7 @@ } struct proto_ops inet6_stream_ops = { - AF_INET6, + PF_INET6, sock_no_dup, inet6_release, @@ -357,7 +357,7 @@ }; struct proto_ops inet6_dgram_ops = { - AF_INET6, + PF_INET6, sock_no_dup, inet6_release, @@ -378,7 +378,7 @@ }; struct net_proto_family inet6_family_ops = { - AF_INET6, + PF_INET6, inet6_create }; @@ -485,7 +485,7 @@ { sit_cleanup(); ipv6_cleanup(); - sock_unregister(AF_INET6); + sock_unregister(PF_INET6); #ifdef CONFIG_PROC_FS proc_net_unregister(proc_net_raw6.low_ino); proc_net_unregister(proc_net_tcp6.low_ino); diff -u --recursive --new-file v2.1.100/linux/net/ipv6/ipv6_sockglue.c linux/net/ipv6/ipv6_sockglue.c --- v2.1.100/linux/net/ipv6/ipv6_sockglue.c Thu May 7 22:51:56 1998 +++ linux/net/ipv6/ipv6_sockglue.c Fri May 8 00:08:02 1998 @@ -7,7 +7,7 @@ * * Based on linux/net/ipv4/ip_sockglue.c * - * $Id: ipv6_sockglue.c,v 1.19 1998/04/30 16:24:26 freitag Exp $ + * $Id: ipv6_sockglue.c,v 1.20 1998/05/03 14:31:07 alan Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -110,7 +110,7 @@ sk->prot = &tcp_prot; tp->af_specific = &ipv4_specific; sk->socket->ops = &inet_stream_ops; - sk->family = AF_INET; + sk->family = PF_INET; } else { sk->prot = &udp_prot; sk->socket->ops = &inet_dgram_ops; diff -u --recursive --new-file v2.1.100/linux/net/ipv6/protocol.c linux/net/ipv6/protocol.c --- v2.1.100/linux/net/ipv6/protocol.c Thu Mar 27 14:40:17 1997 +++ linux/net/ipv6/protocol.c Fri May 8 00:08:02 1998 @@ -3,9 +3,9 @@ * operating system. INET is implemented using the BSD Socket * interface as the means of communication with the user level. * - * AF_INET6 protocol dispatch tables. + * PF_INET6 protocol dispatch tables. * - * Version: $Id: protocol.c,v 1.5 1997/03/18 18:24:44 davem Exp $ + * Version: $Id: protocol.c,v 1.6 1998/05/03 14:31:09 alan Exp $ * * Authors: Pedro Roque * diff -u --recursive --new-file v2.1.100/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c --- v2.1.100/linux/net/ipv6/tcp_ipv6.c Thu May 7 22:51:56 1998 +++ linux/net/ipv6/tcp_ipv6.c Fri May 8 00:08:02 1998 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: tcp_ipv6.c,v 1.80 1998/05/02 12:47:15 davem Exp $ + * $Id: tcp_ipv6.c,v 1.81 1998/05/03 14:31:10 alan Exp $ * * Based on: * linux/net/ipv4/tcp.c @@ -213,7 +213,7 @@ hiscore=0; sk = tcp_listening_hash[tcp_lhashfn(hnum)]; for(; sk; sk = sk->next) { - if((sk->num == hnum) && (sk->family == AF_INET6)) { + if((sk->num == hnum) && (sk->family == PF_INET6)) { struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; score = 1; @@ -272,7 +272,7 @@ /* Must check for a TIME_WAIT'er before going to listener hash. */ for(sk = tcp_established_hash[hash+(TCP_HTABLE_SIZE/2)]; sk; sk = sk->next) { if(*((__u32 *)&(sk->dport)) == ports && - sk->family == AF_INET6) { + sk->family == PF_INET6) { struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sk; if(!ipv6_addr_cmp(&tw->v6_daddr, saddr) && !ipv6_addr_cmp(&tw->v6_rcv_saddr, daddr) && diff -u --recursive --new-file v2.1.100/linux/net/ipv6/udp.c linux/net/ipv6/udp.c --- v2.1.100/linux/net/ipv6/udp.c Thu Mar 26 15:57:13 1998 +++ linux/net/ipv6/udp.c Fri May 8 00:08:02 1998 @@ -7,7 +7,7 @@ * * Based on linux/ipv4/udp.c * - * $Id: udp.c,v 1.27 1998/03/21 07:28:06 davem Exp $ + * $Id: udp.c,v 1.28 1998/05/03 14:31:12 alan Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -147,7 +147,7 @@ for(sk = udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]; sk != NULL; sk = sk->next) { if((sk->num == hnum) && - (sk->family == AF_INET6) && + (sk->family == PF_INET6) && !(sk->dead && (sk->state == TCP_CLOSE))) { struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; int score = 0; diff -u --recursive --new-file v2.1.100/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c --- v2.1.100/linux/net/ipx/af_ipx.c Sat May 2 14:19:55 1998 +++ linux/net/ipx/af_ipx.c Fri May 8 00:08:02 1998 @@ -1732,7 +1732,7 @@ switch(sock->type) { case SOCK_DGRAM: - sk=sk_alloc(AF_IPX, GFP_KERNEL, 1); + sk=sk_alloc(PF_IPX, GFP_KERNEL, 1); if(sk==NULL) return(-ENOMEM); sock->ops = &ipx_dgram_ops; @@ -2300,12 +2300,12 @@ */ static struct net_proto_family ipx_family_ops = { - AF_IPX, + PF_IPX, ipx_create }; static struct proto_ops ipx_dgram_ops = { - AF_IPX, + PF_IPX, sock_no_dup, ipx_release, ipx_bind, diff -u --recursive --new-file v2.1.100/linux/net/ipx/af_spx.c linux/net/ipx/af_spx.c --- v2.1.100/linux/net/ipx/af_spx.c Tue Apr 14 14:29:26 1998 +++ linux/net/ipx/af_spx.c Fri May 8 00:08:02 1998 @@ -83,7 +83,7 @@ { struct sock *sk; - sk = sk_alloc(AF_IPX, GFP_KERNEL, 1); + sk = sk_alloc(PF_IPX, GFP_KERNEL, 1); if(sk == NULL) return (-ENOMEM); @@ -806,7 +806,7 @@ } static struct proto_ops spx_operations = { - AF_IPX, + PF_IPX, sock_no_dup, spx_release, spx_bind, @@ -827,7 +827,7 @@ static struct net_proto_family spx_family_ops= { - AF_IPX, + PF_IPX, spx_create }; @@ -842,7 +842,7 @@ if (error) printk(KERN_ERR "SPX: unable to register with IPX.\n"); - /* route socket(AF_IPX, SOCK_SEQPACKET) calls through spx_create() */ + /* route socket(PF_IPX, SOCK_SEQPACKET) calls through spx_create() */ printk(KERN_INFO "Sequenced Packet eXchange (SPX) 0.01 for Linux NET3.037\n"); return; diff -u --recursive --new-file v2.1.100/linux/net/netlink/af_netlink.c linux/net/netlink/af_netlink.c --- v2.1.100/linux/net/netlink/af_netlink.c Tue Mar 17 22:18:16 1998 +++ linux/net/netlink/af_netlink.c Fri May 8 00:08:02 1998 @@ -147,7 +147,7 @@ sock->ops = &netlink_ops; - sk = sk_alloc(AF_NETLINK, GFP_KERNEL, 1); + sk = sk_alloc(PF_NETLINK, GFP_KERNEL, 1); if (!sk) return -ENOMEM; @@ -980,7 +980,7 @@ #endif struct proto_ops netlink_ops = { - AF_NETLINK, + PF_NETLINK, sock_no_dup, netlink_release, @@ -1001,7 +1001,7 @@ }; struct net_proto_family netlink_family_ops = { - AF_NETLINK, + PF_NETLINK, netlink_create }; diff -u --recursive --new-file v2.1.100/linux/net/netlink/netlink_dev.c linux/net/netlink/netlink_dev.c --- v2.1.100/linux/net/netlink/netlink_dev.c Tue Mar 10 10:03:37 1998 +++ linux/net/netlink/netlink_dev.c Fri May 8 00:08:02 1998 @@ -116,7 +116,7 @@ MOD_INC_USE_COUNT; err = -EINVAL; - if (net_families[AF_NETLINK]==NULL) + if (net_families[PF_NETLINK]==NULL) goto out; err = -ENFILE; @@ -125,7 +125,7 @@ sock->type = SOCK_RAW; - if ((err = net_families[AF_NETLINK]->create(sock, minor)) < 0) + if ((err = net_families[PF_NETLINK]->create(sock, minor)) < 0) { sock_release(sock); goto out; diff -u --recursive --new-file v2.1.100/linux/net/netrom/af_netrom.c linux/net/netrom/af_netrom.c --- v2.1.100/linux/net/netrom/af_netrom.c Tue Apr 14 14:29:26 1998 +++ linux/net/netrom/af_netrom.c Fri May 8 00:08:02 1998 @@ -98,7 +98,7 @@ struct sock *sk; nr_cb *nr; - if ((sk = sk_alloc(AF_NETROM, GFP_ATOMIC, 1)) == NULL) + if ((sk = sk_alloc(PF_NETROM, GFP_ATOMIC, 1)) == NULL) return NULL; if ((nr = kmalloc(sizeof(*nr), GFP_ATOMIC)) == NULL) { @@ -1235,12 +1235,12 @@ static struct net_proto_family nr_family_ops = { - AF_NETROM, + PF_NETROM, nr_create }; static struct proto_ops nr_proto_ops = { - AF_NETROM, + PF_NETROM, sock_no_dup, nr_release, @@ -1363,7 +1363,7 @@ #ifdef CONFIG_SYSCTL nr_unregister_sysctl(); #endif - sock_unregister(AF_NETROM); + sock_unregister(PF_NETROM); for (i = 0; i < nr_ndevs; i++) { if (dev_nr[i].priv != NULL) { diff -u --recursive --new-file v2.1.100/linux/net/netsyms.c linux/net/netsyms.c --- v2.1.100/linux/net/netsyms.c Thu May 7 22:51:56 1998 +++ linux/net/netsyms.c Fri May 8 00:08:02 1998 @@ -17,6 +17,10 @@ #include #include +#ifdef CONFIG_BRIDGE +#include +#endif + #ifdef CONFIG_INET #include #include @@ -190,6 +194,10 @@ EXPORT_SYMBOL(sklist_insert_socket); EXPORT_SYMBOL(scm_detach_fds); + +#ifdef CONFIG_BRIDGE +EXPORT_SYMBOL(br_ioctl); +#endif #ifdef CONFIG_INET /* Internet layer registration */ diff -u --recursive --new-file v2.1.100/linux/net/packet/af_packet.c linux/net/packet/af_packet.c --- v2.1.100/linux/net/packet/af_packet.c Thu May 7 22:51:56 1998 +++ linux/net/packet/af_packet.c Fri May 8 00:08:02 1998 @@ -704,7 +704,7 @@ MOD_INC_USE_COUNT; err = -ENOBUFS; - sk = sk_alloc(AF_PACKET, GFP_KERNEL, 1); + sk = sk_alloc(PF_PACKET, GFP_KERNEL, 1); if (sk == NULL) goto out; @@ -721,7 +721,7 @@ goto out_free; memset(sk->protinfo.af_packet, 0, sizeof(struct packet_opt)); sk->zapped=0; - sk->family = AF_PACKET; + sk->family = PF_PACKET; sk->num = protocol; /* @@ -1176,7 +1176,7 @@ #ifdef CONFIG_SOCK_PACKET struct proto_ops packet_ops_spkt = { - AF_PACKET, + PF_PACKET, sock_no_dup, packet_release, @@ -1198,7 +1198,7 @@ #endif struct proto_ops packet_ops = { - AF_PACKET, + PF_PACKET, sock_no_dup, packet_release, @@ -1223,7 +1223,7 @@ }; static struct net_proto_family packet_family_ops = { - AF_PACKET, + PF_PACKET, packet_create }; @@ -1238,7 +1238,7 @@ void cleanup_module(void) { unregister_netdevice_notifier(&packet_netdev_notifier); - sock_unregister(packet_family_ops.family); + sock_unregister(PF_PACKET); return; } diff -u --recursive --new-file v2.1.100/linux/net/rose/af_rose.c linux/net/rose/af_rose.c --- v2.1.100/linux/net/rose/af_rose.c Thu May 7 22:51:56 1998 +++ linux/net/rose/af_rose.c Fri May 8 00:08:02 1998 @@ -149,7 +149,7 @@ struct sock *sk; rose_cb *rose; - if ((sk = sk_alloc(AF_ROSE, GFP_ATOMIC, 1)) == NULL) + if ((sk = sk_alloc(PF_ROSE, GFP_ATOMIC, 1)) == NULL) return NULL; if ((rose = kmalloc(sizeof(*rose), GFP_ATOMIC)) == NULL) { @@ -1320,12 +1320,12 @@ } static struct net_proto_family rose_family_ops = { - AF_ROSE, + PF_ROSE, rose_create }; static struct proto_ops rose_proto_ops = { - AF_ROSE, + PF_ROSE, sock_no_dup, rose_release, @@ -1462,7 +1462,7 @@ #endif unregister_netdevice_notifier(&rose_dev_notifier); - sock_unregister(AF_ROSE); + sock_unregister(PF_ROSE); for (i = 0; i < rose_ndevs; i++) { if (dev_rose[i].priv != NULL) { diff -u --recursive --new-file v2.1.100/linux/net/sched/cls_api.c linux/net/sched/cls_api.c --- v2.1.100/linux/net/sched/cls_api.c Sat May 2 14:19:55 1998 +++ linux/net/sched/cls_api.c Fri May 8 00:08:02 1998 @@ -395,7 +395,7 @@ __initfunc(int tc_filter_init(void)) { #ifdef CONFIG_RTNETLINK - struct rtnetlink_link *link_p = rtnetlink_links[AF_UNSPEC]; + struct rtnetlink_link *link_p = rtnetlink_links[PF_UNSPEC]; /* Setup rtnetlink links. It is made here to avoid exporting large number of public symbols. diff -u --recursive --new-file v2.1.100/linux/net/sched/sch_api.c linux/net/sched/sch_api.c --- v2.1.100/linux/net/sched/sch_api.c Sat May 2 14:19:55 1998 +++ linux/net/sched/sch_api.c Fri May 8 00:08:02 1998 @@ -928,7 +928,7 @@ #endif #ifdef CONFIG_RTNETLINK - struct rtnetlink_link *link_p = rtnetlink_links[AF_UNSPEC]; + struct rtnetlink_link *link_p = rtnetlink_links[PF_UNSPEC]; /* Setup rtnetlink links. It is made here to avoid exporting large number of public symbols. diff -u --recursive --new-file v2.1.100/linux/net/sunrpc/svcsock.c linux/net/sunrpc/svcsock.c --- v2.1.100/linux/net/sunrpc/svcsock.c Thu Mar 26 15:57:25 1998 +++ linux/net/sunrpc/svcsock.c Fri May 8 00:08:02 1998 @@ -905,7 +905,7 @@ } type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM; - if ((error = sock_create(AF_INET, type, protocol, &sock)) < 0) + if ((error = sock_create(PF_INET, type, protocol, &sock)) < 0) return error; if (sin != NULL) { diff -u --recursive --new-file v2.1.100/linux/net/sunrpc/xprt.c linux/net/sunrpc/xprt.c --- v2.1.100/linux/net/sunrpc/xprt.c Tue Mar 10 10:03:37 1998 +++ linux/net/sunrpc/xprt.c Fri May 8 00:08:02 1998 @@ -1231,7 +1231,7 @@ } sock = &file->f_inode->u.socket_i; - if (sock->ops->family != AF_INET) { + if (sock->ops->family != PF_INET) { printk(KERN_WARNING "RPC: only INET sockets supported\n"); return NULL; } @@ -1284,7 +1284,7 @@ (proto == IPPROTO_UDP)? "udp" : "tcp", proto); type = (proto == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM; - if ((err = sock_create(AF_INET, type, proto, &sock)) < 0) { + if ((err = sock_create(PF_INET, type, proto, &sock)) < 0) { printk("RPC: can't create socket (%d).\n", -err); goto failed; } diff -u --recursive --new-file v2.1.100/linux/net/unix/af_unix.c linux/net/unix/af_unix.c --- v2.1.100/linux/net/unix/af_unix.c Thu Mar 26 15:57:25 1998 +++ linux/net/unix/af_unix.c Fri May 8 00:08:02 1998 @@ -364,14 +364,14 @@ default: return -ESOCKTNOSUPPORT; } - sk = sk_alloc(AF_UNIX, GFP_KERNEL, 1); + sk = sk_alloc(PF_UNIX, GFP_KERNEL, 1); if (!sk) return -ENOMEM; sock_init_data(sock,sk); sk->destruct = unix_destruct_addr; - sk->protinfo.af_unix.family=AF_UNIX; + sk->protinfo.af_unix.family=PF_UNIX; sk->protinfo.af_unix.dentry=NULL; sk->sock_readers=1; /* Us */ sk->protinfo.af_unix.readsem=MUTEX; /* single task reading lock */ @@ -1446,7 +1446,7 @@ #endif struct proto_ops unix_stream_ops = { - AF_UNIX, + PF_UNIX, sock_no_dup, unix_release, @@ -1467,7 +1467,7 @@ }; struct proto_ops unix_dgram_ops = { - AF_UNIX, + PF_UNIX, sock_no_dup, unix_release, @@ -1488,7 +1488,7 @@ }; struct net_proto_family unix_family_ops = { - AF_UNIX, + PF_UNIX, unix_create }; @@ -1534,7 +1534,7 @@ #ifdef MODULE void cleanup_module(void) { - sock_unregister(AF_UNIX); + sock_unregister(PF_UNIX); #ifdef CONFIG_SYSCTL unix_sysctl_unregister(); #endif diff -u --recursive --new-file v2.1.100/linux/net/unix/garbage.c linux/net/unix/garbage.c --- v2.1.100/linux/net/unix/garbage.c Tue Mar 10 10:03:37 1998 +++ linux/net/unix/garbage.c Fri May 8 00:08:02 1998 @@ -72,9 +72,9 @@ struct sock * s = sock->sk; /* - * AF_UNIX ? + * PF_UNIX ? */ - if (s && sock->ops && sock->ops->family == AF_UNIX) + if (s && sock->ops && sock->ops->family == PF_UNIX) u_sock = s; } return u_sock;