Commit ec0de48a authored by Linus Torvalds's avatar Linus Torvalds

Import 2.3.17

parent ba51f1a1
......@@ -6064,17 +6064,29 @@ CONFIG_NET_SB1000
Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support
CONFIG_ACENIC
Say Y here if you have an Alteon AceNIC or 3Com 3C985 PCI Gigabit
Ethernet adapter. The driver allows for using the Jumbo Frame
option (9000 bytes/frame) however it requires that your switches
can handle this as well. To enable Jumbo Frames, add `mtu 9000' to
your ifconfig line.
Say Y here if you have an Alteon AceNIC, 3Com 3C985(B), NetGear
GA620, SGI Gigabit or Farallon PN9000-SX PCI Gigabit Ethernet
adapter. The driver allows for using the Jumbo Frame option (9000
bytes/frame) however it requires that your switches can handle this
as well. To enable Jumbo Frames, add `mtu 9000' to your ifconfig
line.
If you want to compile this driver as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read Documentation/modules.txt. This is recommended.
The module will be called acenic.o.
Omit support for older Tigon I based AceNICs
CONFIG_ACENIC_OMIT_TIGON_I
Say Y here if you only have Tigon II based AceNICs and want to leave
out support for the older Tigon I based cards which are no longer
being sold (ie. the original Alteon AceNIC and 3Com 3C985 (non B
version)). This will reduce the size of the driver object by
app. 100KB. If you are not sure whether your card is a Tigon I or a
Tigon II, say N here.
The safe and default value for this is N.
AMD LANCE and PCnet (AT1500 and NE2100) support
CONFIG_LANCE
If you have a network (Ethernet) card of this type, say Y and read
......@@ -7318,6 +7330,25 @@ CONFIG_JOLIET
like lynx or netscape). Say Y here if you want to be able to read
Joliet CDROMs under Linux.
UDF Filesystem support
CONFIG_UDF_FS
This is the new filesystem used by some CDROMS and DVD drivers.
Say Y if you intend to mount DVD discs or CDRWs written in packet mode,
or if written to by other UDF utilities, such as DirectCD.
This filesystem support is also available as a module ( = code which
can be inserted in and removed from the running kernel whenever you
want). The module is called udf.o. If you want to compile it as a
module, say M here and read Documentation/modules.txt.
If unsure, say N.
UDF read-write support (EXPERIMENTAL)
CONFIG_UDF_RW
Say Y if you want to test write support for UDF filesystems.
Due to lack of support for writing to CDR/CDRW's, this option
is only supported for Hard Discs, DVD-RAM, and loopback files.
fat fs support
CONFIG_FAT_FS
If you want to use one of the FAT-based filesystems (the MS-DOS,
......@@ -10673,11 +10704,23 @@ CONFIG_HP300
If you plan to try to use the kernel on such a machine say Y here.
Everybody else says N.
Sun 3 support
CONFIG_SUN3
This option enables support for the Sun 3 series of workstations.
Be warned that this support is very experimental. You will also
want to say Y to 68020 support and N to the other processors below.
Currently, it is not possible to build a kernel with support for
the Sun 3 and and something else, so make sure you have said N to
all the other machines. This option does not support the sun3x series
of machines (the Sun 3/80 and 3/460). If you don't want to compile a
kernel for a Sun 3, say N.
68020 support
CONFIG_M68020
If you anticipate running this kernel on a computer with a MC68020
processor, say Y. Otherwise, say N. Note that the 68020 requires a
68851 MMU (Memory Management Unit) to run Linux/m68k.
68851 MMU (Memory Management Unit) to run Linux/m68k, except on the
Sun 3, which provides its own version.
68030 support
CONFIG_M68030
......@@ -11129,6 +11172,11 @@ CONFIG_HPLANCE
If you want to use the builtin "LANCE" Ethernet controller on an
HP300 machine, say Y here.
Sun 3 onboard LANCE support
CONFIG_SUN3LANCE
If you want to use the onboard AMD "LANCE" (le) Ethernet hardware
on a Sun 3, you will need to say Y here.
DIO bus support
CONFIG_DIO
Say Y here to enable support for the "DIO" expansion bus used in
......
......@@ -22,6 +22,8 @@ smbfs.txt
- info on using filesystems with the SMB protocol (Windows 3.11 and NT)
sysv-fs.txt
- info on the SystemV/Coherent filesystem.
udf.txt
- info and mount options for the UDF filesystem.
ufs.txt
- info on the ufs filesystem.
umsdos.txt
......
*
* ./Documentation/filesystems/udf.txt
*
UDF Filesystem version 0.8.9
If you encounter problems with reading UDF discs using this driver,
please report them to linux_udf@hootie.lvld.hp.com, which is the
developer's list.
Write support requires a block driver which supports writing. The current
scsi and ide cdrom drivers do not support writing.
-------------------------------------------------------------------------------
The following mount options are supported:
gid= Set the default group.
umask= Set the default umask.
uid= Set the default user.
unhide Show otherwise hidden files.
undelete Show deleted files in lists.
strict Set strict conformance (unused)
utf8 (unused)
iocharset (unused)
The remaining are for debugging and disaster recovery:
bs= Set the block size. (may not work unless 2048)
novrs Skip volume sequence recognition
The following expect a offset from 0.
session= Set the CDROM session (default= last session)
anchor= Override standard anchor location. (default= 256)
volume= Override the VolumeDesc location. (unused)
partition= Override the PartitionDesc location. (unused)
lastblock= Set the last block of the filesystem/
The following expect a offset from the partition root.
fileset= Override the fileset block location. (unused)
rootdir= Override the root directory location. (unused)
WARNING: overriding the rootdir to a non-directory may
yield highly unpredictable results.
-------------------------------------------------------------------------------
For more information see:
http://www.trylinux.com/projects/udf/index.html
For the latest version and toolset see:
http://www.csc.calpoly.edu/~bfennema/udf.html
Documentation on UDF and ECMA 167 is available FREE from:
http://www.osta.org/
http://www.ecma.ch/
Ben Fennema <bfennema@falcon.csc.calpoly.edu>
......@@ -49,17 +49,69 @@ an existing Ethernet. Isn't standard (not even de facto standard, like
SLIP).
Performance
==========
===========
PLIP easily outperforms Ethernet cards....(ups, I was dreaming, but
it *is* getting late. EOB)
PLIP driver details
-------------------
The Linux PLIP driver is an implementation of the original Crynwr protocol,
that uses the parallel port subsystem of the kernel in order to properly
share parallel ports between PLIP and other services.
IRQs and trigger timeouts
=========================
When a parallel port used for a PLIP driver has an IRQ configured to it, the
PLIP driver is signaled whenever data is sent to it via the cable, such that
when no data is available, the driver isn't being used.
However, on some machines it is hard, if not impossible, to configure an IRQ
to a certain parallel port, mainly because it is used by some other device.
On these machines, the PLIP driver can be used in IRQ-less mode, where
the PLIP driver would constantly poll the parallel port for data waiting,
and if such data is available, process it. This mode is less efficient than
the IRQ mode, because the driver has to check the parallel port many times
per second, even when no data at all is sent. Some rough measurements
indicate that there isn't a noticeable performance drop when using IRQ-less
mode as compared to IRQ mode as far as the data transfer speed is involved.
There is a performance drop on the machine hosting the driver.
When the PLIP driver is used in IRQ mode, the timeout used for triggering a
data transfer (the maximal time the PLIP driver would allow the other side
before announcing a timeout, when trying to handshake a transfer of some
data) is, by default, 500usec. As IRQ delivery is more or less immediate,
this timeout is quite sufficient.
When in IRQ-less mode, the PLIP driver polls the parallel port HZ times
per second (where HZ is typically 100 on most platforms, and 1024 on an
Alpha, as of this writing). Between two such polls, there are 10^6/HZ usecs.
On an i386, for example, 10^6/100 = 10000usec. It is easy to see that it is
quite possible for the trigger timeout to expire between two such polls, as
the timeout is only 500usec long. As a result, it is required to change the
trigger timeout on the *other* side of a PLIP connection, to about
10^6/HZ usecs. If both sides of a PLIP connection are used in IRQ-less mode,
this timeout is required on both sides.
It appears that in practice, the trigger timeout can be shorter than in the
above calculation. It isn't an important issue, unless the wire is faulty,
in which case a long timeout would stall the machine when, for whatever
reason, bits are dropped.
A utility that can perform this change in Linux is plipconfig, which is part
of the net-tools package (its location can be found in the
Documentation/Changes file). An example command would be
'plipconfig plipX trigger 10000', where plipX is the appropriate
PLIP device.
PLIP hardware interconnection
-----------------------------
PLIP uses several different data transfer methods. The first (and the
only one implemented in the early version of the code) uses a standard
printer "null" cable to transfers data four bits at a time using
printer "null" cable to transfer data four bits at a time using
data bit outputs connected to status bit inputs.
The second data transfer method relies on both machines having
......@@ -138,18 +190,18 @@ PLIP Mode 0 transfer protocol
The PLIP driver is compatible with the "Crynwr" parallel port transfer
standard in Mode 0. That standard specifies the following protocol:
send header nibble '8'
send header nibble '0x8'
count-low octet
count-high octet
... data octets
checksum octet
Each octet is sent as
<wait for rx. '1'> <send 0x10+(octet&0x0F)>
<wait for rx. '0'> <send 0x00+((octet>>4)&0x0F)>
<wait for rx. '0x1?'> <send 0x10+(octet&0x0F)>
<wait for rx. '0x0?'> <send 0x00+((octet>>4)&0x0F)>
To start a transfer the transmitting machine outputs a nibble 0x08.
The raises the ACK line, triggering an interrupt in the receiving
That raises the ACK line, triggering an interrupt in the receiving
machine. The receiving machine disables interrupts and raises its own ACK
line.
......
To use the IrDA protocols within Linux you will need to get a suitable copy
of the IrDA Utilities. More detailed information about these and associated
programs can be found on http://www.cs.uit.no/~dagb/irda/.
programs can be found on http://www.cs.uit.no/linux-irda/
For more information about the IrDA protocol stack, see the IR-HOWTO
written by Werner Heuser <r2d2c3po@zedat.fu-berlin.de>
For more information about how to use the IrDA protocol stack, see the
IR-HOWTO (http://www.snafu.de/~wehe/IR-HOWTO.html) written by Werner Heuser
<wehe@snafu.de>
There is an active mailing list for discussing Linux IrDA matters called
linux-irda. To subscribe to it, send a message to Majordomo@list.uit.no
with the words "subscribe linux-irda" in the body of the message, the
subject field is ignored.
There is an active mailing list for discussing Linux-IrDA matters called
linux-irda. To subscribe to it, visit:
http://www.pasta.cs.uit.no/mailman/listinfo/linux-irda
Dag Brattli <dagb@cs.uit.no>
......@@ -442,7 +442,7 @@ S: Maintained
IRDA SUBSYSTEM
P: Dag Brattli
M: Dag Brattli <dagb@cs.uit.no>
L: linux-irda@list.uit.no
L: linux-irda@pasta.cs.uit.no
W: http://www.cs.uit.no/linux-irda/
S: Maintained
......@@ -847,6 +847,13 @@ M: dario@milano.europe.dg.com
L: linux-scsi@vger.rutgers.edu
S: Maintained
UDF FILESYSTEM
P: Ben Fennema
M: bfennema@falcon.csc.calpoly.edu
L: linux_udf@hootie.lvld.hp.com
W: http://www.trylinux.com/projects/udf/index.html
S: Maintained
UMSDOS FILESYSTEM
P: Matija Nalis
M: mnalis@jagor.srce.hr
......
......@@ -365,6 +365,7 @@ CONFIG_AUTOFS_FS=y
# CONFIG_VFAT_FS is not set
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
# CONFIG_UDF_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_HPFS_FS is not set
......
......@@ -145,7 +145,30 @@ ENTRY(lcall7)
andl $-8192,%ebx # GET_CURRENT
movl exec_domain(%ebx),%edx # Get the execution domain
movl 4(%edx),%edx # Get the lcall7 handler for the domain
pushl $0x7
call *%edx
addl $4, %esp
popl %eax
jmp ret_from_sys_call
ENTRY(lcall27)
pushfl # We get a different stack layout with call gates,
pushl %eax # which has to be cleaned up later..
SAVE_ALL
movl EIP(%esp),%eax # due to call gates, this is eflags, not eip..
movl CS(%esp),%edx # this is eip..
movl EFLAGS(%esp),%ecx # and this is cs..
movl %eax,EFLAGS(%esp) #
movl %edx,EIP(%esp) # Now we move them to their "normal" places
movl %ecx,CS(%esp) #
movl %esp,%ebx
pushl %ebx
andl $-8192,%ebx # GET_CURRENT
movl exec_domain(%ebx),%edx # Get the execution domain
movl 4(%edx),%edx # Get the lcall7 handler for the domain
pushl $0x27
call *%edx
addl $4, %esp
popl %eax
jmp ret_from_sys_call
......
......@@ -530,10 +530,6 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne
memory_end = 0;
for (i=0; i < e820.nr_map; i++) {
printk("type=%d, addr=%08x, size=%08x",
e820.map[i].type,
e820.map[i].addr,
e820.map[i].size);
/* RAM? */
if (e820.map[i].type == 1) {
unsigned long end = e820.map[i].addr + e820.map[i].size;
......
......@@ -731,7 +731,11 @@ void __init enable_local_APIC(void)
value = apic_read(APIC_SPIV);
value |= (1<<8); /* Enable APIC (bit==1) */
#if 0
value &= ~(1<<9); /* Enable focus processor (bit==0) */
#else
value |= (1<<9); /* Disable focus processor (bit==1) */
#endif
value |= 0xff; /* Set spurious IRQ vector to 0xff */
apic_write(APIC_SPIV,value);
......
......@@ -46,8 +46,10 @@
asmlinkage int system_call(void);
asmlinkage void lcall7(void);
asmlinkage void lcall27(void);
struct desc_struct default_ldt = { 0, 0 };
struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
{ 0, 0 }, { 0, 0 } };
/*
* The IDT has to be page-aligned to simplify the Pentium
......@@ -696,9 +698,11 @@ void __init trap_init(void)
set_system_gate(SYSCALL_VECTOR,&system_call);
/*
* default LDT is a single-entry callgate to lcall7
* default LDT is a single-entry callgate to lcall7 for iBCS
* and a callgate to lcall27 for Solaris/x86 binaries
*/
set_call_gate(&default_ldt,lcall7);
set_call_gate(&default_ldt[0],lcall7);
set_call_gate(&default_ldt[4],lcall27);
/*
* on SMP we do not yet know which CPU is on which TSS,
......
......@@ -375,7 +375,6 @@ void __init mem_init(unsigned long start_mem, unsigned long end_mem)
int datapages = 0;
int initpages = 0;
unsigned long tmp;
unsigned long addr;
int i, avail;
end_mem &= PAGE_MASK;
......@@ -413,17 +412,27 @@ void __init mem_init(unsigned long start_mem, unsigned long end_mem)
/* walk the whitelist, unreserving good memory
*/
for (avail = i = 0; i < e820.nr_map; i++) {
unsigned long addr, end, size;
if (e820.map[i].type != 1) /* not usable memory */
continue;
printk("memory region: %luk @ %08lx\n",
((long)(e820.map[i].size)) / 1024,
(long)(e820.map[i].addr) );
for (addr=PAGE_ALIGN(((long)(e820.map[i].addr)))+PAGE_OFFSET,
tmp = 0;
tmp < (unsigned long)(e820.map[i].size);
tmp += PAGE_SIZE,
addr += PAGE_SIZE) {
addr = e820.map[i].addr;
size = e820.map[i].size;
/* Overflow large memory reasonably gracefully */
if (addr != e820.map[i].addr)
continue;
printk("memory region: %luk @ %08lx\n", size >> 10, addr );
/* Make sure we don't get fractional pages */
end = (addr + size) & PAGE_MASK;
addr = PAGE_ALIGN(addr);
if (end <= addr)
continue;
size = end - addr;
for (addr = addr + PAGE_OFFSET ; size ; addr += PAGE_SIZE, size -= PAGE_SIZE) {
/* this little bit of grossness is for dealing
* with memory borrowing for system bookkeeping
* (smp stacks, zero page, kernel code, etc)
......@@ -437,9 +446,11 @@ void __init mem_init(unsigned long start_mem, unsigned long end_mem)
* in any case, we don't want to hack mem_map
* entries above end_mem.
*/
if ( (addr < start_low_mem)
|| (addr >= HIGH_MEMORY && addr <= start_mem)
|| (addr > end_mem) )
if ( addr < start_low_mem )
continue;
if ( addr > end_mem )
continue;
if ( addr >= HIGH_MEMORY && addr <= start_mem )
continue;
avail++;
......
......@@ -24,7 +24,11 @@ ifneq ($(COMPILE_ARCH),$(ARCH))
CROSS_COMPILE = m68k-linux-
endif
ifndef CONFIG_SUN3
LINKFLAGS = -T $(TOPDIR)/arch/m68k/vmlinux.lds
else
LINKFLAGS = -T $(TOPDIR)/arch/m68k/vmlinux-sun3.lds -N
endif
# without -fno-strength-reduce the 53c7xx.c driver fails ;-(
CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
......@@ -50,7 +54,11 @@ ifdef CONFIG_KGDB
CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -g
endif
ifndef CONFIG_SUN3
HEAD := arch/m68k/kernel/head.o
else
HEAD := arch/m68k/kernel/sun3-head.o
endif
SUBDIRS += arch/m68k/kernel arch/m68k/mm arch/m68k/lib
CORE_FILES := arch/m68k/kernel/kernel.o arch/m68k/mm/mm.o $(CORE_FILES)
......@@ -106,6 +114,11 @@ CORE_FILES := $(CORE_FILES) arch/m68k/sun3x/sun3x.o
SUBDIRS := $(SUBDIRS) arch/m68k/sun3x
endif
ifdef CONFIG_SUN3
CORE_FILES := $(CORE_FILES) arch/m68k/sun3/sun3.o arch/m68k/sun3/prom/promlib.a
SUBDIRS := $(SUBDIRS) arch/m68k/sun3 arch/m68k/sun3/prom
endif
ifdef CONFIG_M68040
CORE_FILES := $(CORE_FILES) arch/m68k/fpsp040/fpsp.o
SUBDIRS := $(SUBDIRS) arch/m68k/fpsp040
......@@ -132,7 +145,7 @@ zImage compressed: vmlinux.gz
vmlinux.gz: vmlinux
ifdef CONFIG_KGDB
ifndef CONFIG_KGDB
cp vmlinux vmlinux.tmp
$(STRIP) vmlinux.tmp
gzip -9c vmlinux.tmp >vmlinux.gz
......@@ -141,8 +154,21 @@ else
gzip -9c vmlinux >vmlinux.gz
endif
bzImage: vmlinux.bz2
vmlinux.bz2: vmlinux
ifndef CONFIG_KGDB
cp vmlinux vmlinux.tmp
$(STRIP) vmlinux.tmp
bzip2 -1c vmlinux.tmp >vmlinux.bz2
rm vmlinux.tmp
else
bzip2 -1c vmlinux >vmlinux.bz2
endif
archclean:
rm -f vmlinux.gz
rm -f vmlinux.gz vmlinux.bz2
rm -f arch/m68k/kernel/m68k_defs.h arch/m68k/kernel/m68k_defs.d
archmrproper:
......
......@@ -117,7 +117,7 @@ void __init amiga_init_IRQ(void)
cia_init_IRQ(&ciab_base);
}
static inline void amiga_insert_irq(irq_node_t **list, irq_node_t *node)
static inline int amiga_insert_irq(irq_node_t **list, irq_node_t *node)
{
unsigned long flags;
irq_node_t *cur;
......@@ -133,7 +133,7 @@ static inline void amiga_insert_irq(irq_node_t **list, irq_node_t *node)
if (node->flags & SA_INTERRUPT) {
if (node->flags & SA_SHIRQ)
return;
return -EBUSY;
/*
* There should never be more than one
*/
......@@ -152,6 +152,7 @@ static inline void amiga_insert_irq(irq_node_t **list, irq_node_t *node)
*list = node;
restore_flags(flags);
return 0;
}
static inline void amiga_delete_irq(irq_node_t **list, void *dev_id)
......@@ -186,6 +187,7 @@ int amiga_request_irq(unsigned int irq,
unsigned long flags, const char *devname, void *dev_id)
{
irq_node_t *node;
int error = 0;
if (irq >= AMI_IRQS) {
printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__,
......@@ -218,7 +220,7 @@ int amiga_request_irq(unsigned int irq,
node->dev_id = dev_id;
node->devname = devname;
node->next = NULL;
amiga_insert_irq(&ami_irq_list[irq], node);
error = amiga_insert_irq(&ami_irq_list[irq], node);
} else {
ami_irq_list[irq]->handler = handler;
ami_irq_list[irq]->flags = flags;
......@@ -230,7 +232,7 @@ int amiga_request_irq(unsigned int irq,
if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq])
custom.intena = IF_SETCLR | ami_intena_vals[irq];
return 0;
return error;
}
void amiga_free_irq(unsigned int irq, void *dev_id)
......
......@@ -29,6 +29,7 @@
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/genhd.h>
#include <linux/sched.h>
#include <linux/init.h>
......
......@@ -198,8 +198,8 @@ if [ "$CONFIG_ATARI" = "y" ]; then
fi
fi
if [ "$CONFIG_MAC" = "y" ]; then
bool 'MAC NCR5380 SCSI' CONFIG_MAC_SCSI
dep_tristate 'MAC NCR53c9[46] SCSI' CONFIG_SCSI_MAC_ESP $CONFIG_SCSI
bool 'Macintosh NCR5380 SCSI' CONFIG_MAC_SCSI
dep_tristate 'Macintosh NCR53c9[46] SCSI' CONFIG_SCSI_MAC_ESP $CONFIG_SCSI
fi
#dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI
......@@ -329,19 +329,19 @@ fi
if [ "$CONFIG_AMIGA" = "y" ]; then
tristate 'Amiga mouse support' CONFIG_AMIGAMOUSE
if [ "$CONFIG_AMIGAMOUSE" != "n" ]; then
define_bool CONFIG_MOUSE y
define_bool CONFIG_BUSMOUSE y
fi
fi
if [ "$CONFIG_ATARI" = "y" ]; then
tristate 'Atari mouse support' CONFIG_ATARIMOUSE
if [ "$CONFIG_ATARIMOUSE" != "n" ]; then
define_bool CONFIG_MOUSE y
define_bool CONFIG_BUSMOUSE y
fi
fi
if [ "$CONFIG_MAC" = "y" ]; then
bool 'Mac ADB mouse support' CONFIG_ADBMOUSE
if [ "$CONFIG_ADBMOUSE" != "n" ]; then
define_bool CONFIG_MOUSE y
define_bool CONFIG_BUSMOUSE y
fi
fi
if [ "$CONFIG_ATARI" = "y" ]; then
......@@ -381,7 +381,7 @@ if [ "$CONFIG_SUN3X" = "y" ]; then
bool 'Sun keyboard support' CONFIG_SUN_KEYBOARD
bool 'Sun mouse support' CONFIG_SUN_MOUSE
if [ "$CONFIG_SUN_MOUSE" != "n" ]; then
define_bool CONFIG_MOUSE y
define_bool CONFIG_BUSMOUSE y
fi
define_bool CONFIG_SBUS y
define_bool CONFIG_SBUSCHAR y
......
......@@ -10,11 +10,16 @@
.S.o:
$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
ifndef CONFIG_SUN3
all: head.o kernel.o
else
all: sun3-head.o kernel.o
endif
O_TARGET := kernel.o
O_OBJS := entry.o process.o traps.o ints.o signal.o ptrace.o \
setup.o sys_m68k.o time.o
OX_OBJS := m68k_ksyms.o
sys_m68k.o time.o semaphore.o
OX_OBJS := setup.o m68k_ksyms.o
ifdef CONFIG_KGDB
O_OBJS += kgdb.o
......@@ -26,6 +31,8 @@ endif
head.o: head.S m68k_defs.h
sun3-head.o: sun3-head.S m68k_defs.h
m68k_defs.h: m68k_defs.c m68k_defs.head
rm -f m68k_defs.d
SUNPRO_DEPENDENCIES="m68k_defs.d m68k_defs.h" \
......
......@@ -72,6 +72,16 @@ ENTRY(reschedule)
pea SYMBOL_NAME(ret_from_exception)
jmp SYMBOL_NAME(schedule)
| After a fork we jump here directly from resume,
| so that %d1 contains the previous task
| Theoretically only needed on SMP, but let's watch
| what happens in schedule_tail() in future...
ENTRY(ret_from_fork)
movel %d1,%sp@-
jsr SYMBOL_NAME(schedule_tail)
addql #4,%sp
jra SYMBOL_NAME(ret_from_exception)
badsys:
movel #-ENOSYS,PT_D0(%sp)
jra SYMBOL_NAME(ret_from_exception)
......@@ -89,16 +99,6 @@ do_trace:
SAVE_SWITCH_STACK
jbsr SYMBOL_NAME(syscall_trace)
| After a fork we jump here directly from resume,
| so that %d1 contains the previous task
| Theoretically only needed on SMP, but let's watch
| what happens in schedule_tail() in future...
ENTRY(ret_from_fork)
movel %d1,%sp@-
jsr SYMBOL_NAME(schedule_tail)
addql #4,%sp
jra SYMBOL_NAME(ret_from_exception)
SYMBOL_NAME_LABEL(ret_from_signal)
RESTORE_SWITCH_STACK
addql #4,%sp
......
......@@ -189,6 +189,11 @@
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#endif
#ifdef CONFIG_MAC
#include <linux/tty.h>
#include <asm/bootinfo.h>
#include <asm/macints.h>
#endif
#undef DEBUG
......@@ -239,6 +244,15 @@ static unsigned char atari_scc_intr( void );
extern int amiga_ser_out( unsigned char c );
extern unsigned char amiga_ser_in( void );
#endif
#ifdef CONFIG_MAC
static unsigned char mac_scca_in( void );
static unsigned char mac_scca_out( unsigned char c );
static unsigned char mac_scca_intr( void );
static unsigned char mac_sccb_in( void );
static unsigned char mac_sccb_out( unsigned char c);
static unsigned char mac_sccb_intr( void );
extern void mac_init_scc_port( int cflag, int port );
#endif
/************************* End of Prototypes **************************/
......@@ -668,6 +682,31 @@ void kgdb_init(void)
}
#endif
#ifdef CONFIG_MAC
if (MACH_IS_MAC) {
if (!strcmp( m68k_debug_device, "ser" ) ||
!strcmp( m68k_debug_device, "ser1" )) {
mac_init_scc_port( B9600|CS8, 0 );
serial_in = mac_scca_in;
serial_out = mac_scca_out;
serial_intr = mac_scca_intr;
} else if (!strcmp( m68k_debug_device, "ser2" )) {
mac_init_scc_port( B9600|CS8, 1 );
serial_in = mac_sccb_in;
serial_out = mac_sccb_out;
serial_intr = mac_sccb_intr;
}
}
if (!serial_in || !serial_out) {
if (*m68k_debug_device)
printk( "kgdb_init failed: no valid serial device!\n" );
else
printk( "kgdb not enabled\n" );
return;
}
request_irq(4, kgdb_intr, IRQ_TYPE_FAST, "kgdb", NULL);
#endif
#ifdef CONFIG_ATARI
if (!serial_in || !serial_out) {
if (*m68k_debug_device)
......@@ -781,8 +820,15 @@ __asm__
/* copy format/vector word */
" movew %a0@("FRAMEOFF_VECTOR"),%a1@("GDBOFF_VECTOR")\n"
/* save FPU regs */
#ifndef CONFIG_M68KFPU_EMU_ONLY
#ifdef CONFIG_M68KFPU_EMU
" tstl "SYMBOL_NAME_STR(m68k_fputype)"\n"
" jeq 1f\n"
#endif
" fmovemx %fp0-%fp7,%a1@("GDBOFF_FP0")\n"
" fmoveml %fpcr/%fpsr/%fpiar,%a1@("GDBOFF_FPCTL")\n"
"1:\n"
#endif /* CONFIG_M68KFPU_EMU_ONLY */
/* set stack to CPU frame */
" addl #"FRAMEOFF_SR",%a0\n"
......@@ -801,8 +847,15 @@ __asm__
/* after return, first restore FPU registers */
" movel #"SYMBOL_NAME_STR(kgdb_registers)",%a0\n" /* source */
#ifndef CONFIG_M68KFPU_EMU_ONLY
#ifdef CONFIG_M68KFPU_EMU
" tstl "SYMBOL_NAME_STR(m68k_fputype)"\n"
" jeq 1f\n"
#endif
" fmovemx %a0@("GDBOFF_FP0"),%fp0-%fp7\n"
" fmoveml %a0@("GDBOFF_FPCTL"),%fpcr/%fpsr/%fpiar\n"
"1:\n"
#endif /* CONFIG_M68KFPU_EMU_ONLY */
/* set new stack pointer */
" movel %a0@("GDBOFF_A7"),%sp\n"
" clrw %sp@-\n" /* fake format $0 frame */
......@@ -849,8 +902,15 @@ __asm__
/* fake format 0 and vector 1 (translated to SIGINT) */
" movew #4,%a1@("GDBOFF_VECTOR")\n"
/* save FPU regs */
#ifndef CONFIG_M68KFPU_EMU_ONLY
#ifdef CONFIG_M68KFPU_EMU
" tstl "SYMBOL_NAME_STR(m68k_fputype)"\n"
" jeq 1f\n"
#endif
" fmovemx %fp0-%fp7,%a1@("GDBOFF_FP0")\n"
" fmoveml %fpcr/%fpsr/%fpiar,%a1@("GDBOFF_FPCTL")\n"
"1:\n"
#endif /* CONFIG_M68KFPU_EMU_ONLY */
/* pop off the CPU stack frame */
" addql #8,%sp\n"
" movel %sp,%a1@("GDBOFF_A7")\n" /* save a7 now */
......@@ -1192,3 +1252,111 @@ static unsigned char atari_scc_intr( void )
}
#endif
/* -------------------- Macintosh serial I/O -------------------- */
#ifdef CONFIG_MAC
struct SCC
{
u_char cha_b_ctrl;
u_char char_dummy1;
u_char cha_a_ctrl;
u_char char_dummy2;
u_char cha_b_data;
u_char char_dummy3;
u_char cha_a_data;
};
#define scc (*((volatile struct SCC*)mac_bi_data.sccbase))
#define uSEC 1
#define LONG_DELAY() \
do { \
int i; \
for( i = 60*uSEC; i > 0; --i ) \
barrier(); \
} while(0)
static unsigned char mac_sccb_out (unsigned char c)
{
int i;
do {
LONG_DELAY();
} while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
for( i = uSEC; i > 0; --i )
barrier();
scc.cha_b_data = c;
}
static unsigned char mac_scca_out (unsigned char c)
{
int i;
do {
LONG_DELAY();
} while (!(scc.cha_a_ctrl & 0x04)); /* wait for tx buf empty */
for( i = uSEC; i > 0; --i )
barrier();
scc.cha_a_data = c;
}
static unsigned char mac_sccb_in( void )
{
do {
LONG_DELAY();
} while( !(scc.cha_b_ctrl & 0x01) ); /* wait for rx buf filled */
LONG_DELAY();
return( scc.cha_b_data );
}
static unsigned char mac_scca_in( void )
{
do {
LONG_DELAY();
} while( !(scc.cha_a_ctrl & 0x01) ); /* wait for rx buf filled */
LONG_DELAY();
return( scc.cha_a_data );
}
static unsigned char mac_sccb_intr( void )
{ unsigned char c, stat;
LONG_DELAY();
scc.cha_b_ctrl = 1; /* RR1 */
LONG_DELAY();
stat = scc.cha_b_ctrl;
LONG_DELAY();
c = scc.cha_b_data;
LONG_DELAY();
if (stat & 0x30) {
scc.cha_b_ctrl = 0x30; /* error reset for overrun and parity */
LONG_DELAY();
}
scc.cha_b_ctrl = 0x38; /* reset highest IUS */
LONG_DELAY();
return( c );
}
static unsigned char mac_scca_intr( void )
{ unsigned char c, stat;
LONG_DELAY();
scc.cha_a_ctrl = 1; /* RR1 */
LONG_DELAY();
stat = scc.cha_a_ctrl;
LONG_DELAY();
c = scc.cha_a_data;
LONG_DELAY();
if (stat & 0x30) {
scc.cha_a_ctrl = 0x30; /* error reset for overrun and parity */
LONG_DELAY();
}
scc.cha_a_ctrl = 0x38; /* reset highest IUS */
LONG_DELAY();
return( c );
}
#endif
......@@ -38,11 +38,14 @@ EXPORT_SYMBOL(mm_vtop);
EXPORT_SYMBOL(mm_ptov);
EXPORT_SYMBOL(mm_end_of_chunk);
#endif
EXPORT_SYMBOL(mm_vtop_fallback);
EXPORT_SYMBOL(m68k_realnum_memory);
EXPORT_SYMBOL(m68k_memory);
#ifndef CONFIG_SUN3
EXPORT_SYMBOL(mm_vtop_fallback);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(kernel_set_cachemode);
#endif
EXPORT_SYMBOL(m68k_debug_device);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(dump_thread);
......@@ -53,7 +56,6 @@ EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(local_bh_count);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(kernel_set_cachemode);
EXPORT_SYMBOL(kernel_thread);
/* Networking helper routines. */
......@@ -67,6 +69,7 @@ EXPORT_SYMBOL_NOVERS(__ashrdi3);
EXPORT_SYMBOL_NOVERS(memcpy);
EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOL_NOVERS(memcmp);
EXPORT_SYMBOL_NOVERS(memscan);
EXPORT_SYMBOL_NOVERS(__down_failed);
EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
......
......@@ -45,7 +45,7 @@ static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM(init_mm);
union task_union init_task_union
__attribute__((section("init_task"), aligned(THREAD_SIZE)))
__attribute__((section("init_task"), aligned(KTHREAD_SIZE)))
= { task: INIT_TASK(init_task_union.task) };
asmlinkage void ret_from_fork(void);
......@@ -90,10 +90,14 @@ void machine_restart(char * __unused)
{
if (mach_reset)
mach_reset();
for (;;);
}
void machine_halt(void)
{
if (mach_halt)
mach_halt();
for (;;);
}
void machine_power_off(void)
......@@ -101,6 +105,10 @@ void machine_power_off(void)
#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
apm_set_power_state(APM_STATE_OFF);
#endif
if (mach_power_off)
mach_power_off();
for (;;);
}
void show_regs(struct pt_regs * regs)
......@@ -138,7 +146,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
"trap #0\n\t" /* Linux/m68k system call */
"tstl %0\n\t" /* child or parent */
"jne 1f\n\t" /* parent - jump */
"lea %%sp@(-8192),%6\n\t" /* reload current */
"lea %%sp@(%c7),%6\n\t" /* reload current */
"movel %3,%%sp@-\n\t" /* push argument */
"jsr %4@\n\t" /* call fn */
"movel %0,%%d1\n\t" /* pass exit value */
......@@ -147,7 +155,8 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
"1:"
: "=d" (retval)
: "0" (__NR_clone), "i" (__NR_exit),
"r" (arg), "a" (fn), "d" (clone_arg), "r" (current)
"r" (arg), "a" (fn), "d" (clone_arg), "r" (current),
"i" (-KTHREAD_SIZE)
: "d0", "d2");
pid = retval;
}
......@@ -204,7 +213,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct switch_stack * childstack, *stack;
unsigned long stack_offset, *retp;
stack_offset = THREAD_SIZE - sizeof(struct pt_regs);
stack_offset = KTHREAD_SIZE - sizeof(struct pt_regs);
childregs = (struct pt_regs *) ((unsigned long) p + stack_offset);
*childregs = *regs;
......
/*
* Generic semaphore code. Buyer beware. Do your own
* specific changes in <asm/semaphore-helper.h>
*/
#include <linux/sched.h>
#include <asm/semaphore-helper.h>
/*
* Semaphores are implemented using a two-way counter:
* The "count" variable is decremented for each process
* that tries to sleep, while the "waking" variable is
* incremented when the "up()" code goes to wake up waiting
* processes.
*
* Notably, the inline "up()" and "down()" functions can
* efficiently test if they need to do any extra work (up
* needs to do something only if count was negative before
* the increment operation.
*
* waking_non_zero() (from asm/semaphore.h) must execute
* atomically.
*
* When __up() is called, the count was negative before
* incrementing it, and we need to wake up somebody.
*
* This routine adds one to the count of processes that need to
* wake up and exit. ALL waiting processes actually wake up but
* only the one that gets to the "waking" field first will gate
* through and acquire the semaphore. The others will go back
* to sleep.
*
* Note that these functions are only called when there is
* contention on the lock, and as such all this is the
* "non-critical" part of the whole semaphore business. The
* critical part is the inline stuff in <asm/semaphore.h>
* where we want to avoid any extra jumps and calls.
*/
void __up(struct semaphore *sem)
{
wake_one_more(sem);
wake_up(&sem->wait);
}
/*
* Perform the "down" function. Return zero for semaphore acquired,
* return negative for signalled out of the function.
*
* If called from __down, the return is ignored and the wait loop is
* not interruptible. This means that a task waiting on a semaphore
* using "down()" cannot be killed until someone does an "up()" on
* the semaphore.
*
* If called from __down_interruptible, the return value gets checked
* upon return. If the return value is negative then the task continues
* with the negative value in the return register (it can be tested by
* the caller).
*
* Either form may be used in conjunction with "up()".
*
*/
#define DOWN_VAR \
struct task_struct *tsk = current; \
wait_queue_t wait; \
init_waitqueue_entry(&wait, tsk);
#define DOWN_HEAD(task_state) \
\
\
tsk->state = (task_state); \
add_wait_queue(&sem->wait, &wait); \
\
/* \
* Ok, we're set up. sem->count is known to be less than zero \
* so we must wait. \
* \
* We can let go the lock for purposes of waiting. \
* We re-acquire it after awaking so as to protect \
* all semaphore operations. \
* \
* If "up()" is called before we call waking_non_zero() then \
* we will catch it right away. If it is called later then \
* we will have to go through a wakeup cycle to catch it. \
* \
* Multiple waiters contend for the semaphore lock to see \
* who gets to gate through and who has to wait some more. \
*/ \
for (;;) {
#define DOWN_TAIL(task_state) \
tsk->state = (task_state); \
} \
tsk->state = TASK_RUNNING; \
remove_wait_queue(&sem->wait, &wait);
void __down(struct semaphore * sem)
{
DOWN_VAR
DOWN_HEAD(TASK_UNINTERRUPTIBLE)
if (waking_non_zero(sem))
break;
schedule();
DOWN_TAIL(TASK_UNINTERRUPTIBLE)
}
int __down_interruptible(struct semaphore * sem)
{
int ret = 0;
DOWN_VAR
DOWN_HEAD(TASK_INTERRUPTIBLE)
ret = waking_non_zero_interruptible(sem, tsk);
if (ret)
{
if (ret == 1)
/* ret != 0 only if we get interrupted -arca */
ret = 0;
break;
}
schedule();
DOWN_TAIL(TASK_INTERRUPTIBLE)
return ret;
}
int __down_trylock(struct semaphore * sem)
{
return waking_non_zero_trylock(sem);
}
......@@ -19,6 +19,7 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/setup.h>
......@@ -76,6 +77,8 @@ void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
int (*mach_set_clock_mmss) (unsigned long) = NULL;
void (*mach_reset)( void );
void (*mach_halt)( void ) = NULL;
void (*mach_power_off)( void ) = NULL;
long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) || defined(CONFIG_BLK_DEV_FD)
void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
......@@ -100,6 +103,9 @@ long m68k_serial_console_init(long, long );
#ifdef CONFIG_HEARTBEAT
void (*mach_heartbeat) (int) = NULL;
#endif
#ifdef CONFIG_M68K_L2_CACHE
void (*mach_l2_flush) (int) = NULL;
#endif
extern void base_trap_init(void);
......@@ -118,7 +124,7 @@ extern int q40_parse_bootinfo(const struct bi_record *);
extern void config_amiga(void);
extern void config_atari(void);
extern void config_mac(void);
extern void config_sun3(void);
extern void config_sun3(unsigned long *, unsigned long *);
extern void config_apollo(void);
extern void config_mvme147(void);
extern void config_mvme16x(void);
......@@ -127,8 +133,10 @@ extern void config_hp300(void);
extern void config_q40(void);
extern void config_sun3x(void);
#define MASK_256K 0xfffc0000
extern void mac_debugging_short (int, short);
extern void mac_debugging_long (int, long);
#define MASK_256K 0xfffc0000
static void __init m68k_parse_bootinfo(const struct bi_record *record)
{
......@@ -205,13 +213,22 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p,
else if (CPU_IS_060)
m68k_is040or060 = 6;
#ifndef CONFIG_SUN3
base_trap_init();
#endif
/* FIXME: m68k_fputype is passed in by Penguin booter, which can
* be confused by software FPU emulation. BEWARE.
* We should really do our own FPU check at startup.
* [what do we do with buggy 68LC040s? if we have problems
* with them, we should add a test to check_bugs() below] */
#ifndef CONFIG_M68KFPU_EMU_ONLY
/* clear the fpu if we have one */
if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
volatile int zero = 0;
asm __volatile__ ("frestore %0" : : "m" (zero));
}
#endif
init_mm.start_code = PAGE_OFFSET;
init_mm.end_code = (unsigned long) &_etext;
......@@ -272,7 +289,7 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p,
#endif
#ifdef CONFIG_SUN3
case MACH_SUN3:
config_sun3();
config_sun3(memory_start_p, memory_end_p);
break;
#endif
#ifdef CONFIG_APOLLO
......@@ -321,10 +338,12 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p,
}
#endif
#ifndef CONFIG_SUN3
*memory_start_p = availmem;
*memory_end_p = 0;
for (i = 0; i < m68k_num_memory; i++)
*memory_end_p += m68k_memory[i].size & MASK_256K;
#endif
}
int get_cpuinfo(char * buffer)
......@@ -354,6 +373,9 @@ int get_cpuinfo(char * buffer)
clockfactor = 0;
}
#ifdef CONFIG_M68KFPU_EMU_ONLY
fpu="none(soft float)";
#else
if (m68k_fputype & FPU_68881)
fpu = "68881";
else if (m68k_fputype & FPU_68882)
......@@ -366,6 +388,7 @@ int get_cpuinfo(char * buffer)
fpu = "Sun FPA";
else
fpu = "none";
#endif
if (m68k_mmutype & MMU_68851)
mmu = "68851";
......@@ -452,6 +475,9 @@ void unregister_serial(int i)
m68k_unregister_serial(i);
#endif
}
EXPORT_SYMBOL(register_serial);
EXPORT_SYMBOL(unregister_serial);
#ifdef CONFIG_SERIAL_CONSOLE
long serial_console_init(long kmem_start, long kmem_end)
{
......@@ -461,6 +487,8 @@ long serial_console_init(long kmem_start, long kmem_end)
#endif
#if defined(M68K_SERIAL) && defined(CONFIG_SERIAL_CONSOLE)
return m68k_serial_console_init(kmem_start, kmem_end);
#else
return kmem_start;
#endif
}
#endif
......@@ -496,7 +524,7 @@ void arch_gettod(int *year, int *mon, int *day, int *hour,
void check_bugs(void)
{
#ifndef CONFIG_FPU_EMU
#ifndef CONFIG_M68KFPU_EMU
if (m68k_fputype == 0) {
printk( KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
"WHICH IS REQUIRED BY LINUX/M68K ***\n" );
......
#include <linux/config.h>
#include <linux/linkage.h>
#include <asm/page.h>
#include <asm/contregs.h>
#include <asm/sun3-head.h>
PSL_HIGHIPL = 0x2700
NBSG = 0x20000
ICACHE_ONLY = 0x00000009
CACHES_OFF = 0x00000008 | actually a clear and disable --m
#define MAS_STACK INT_STACK
ROOT_TABLE_SIZE = 128
PAGESIZE = 8192
.globl SYMBOL_NAME(bootup_user_stack)
.globl SYMBOL_NAME(bootup_kernel_stack)
.globl SYMBOL_NAME(pg0)
.globl SYMBOL_NAME(empty_bad_page)
.globl SYMBOL_NAME(empty_bad_page_table)
.globl SYMBOL_NAME(empty_zero_page)
.globl SYMBOL_NAME(swapper_pg_dir)
.globl SYMBOL_NAME(kernel_pmd_table)
.global SYMBOL_NAME(m68k_pgtable_cachemode)
.global SYMBOL_NAME(kpt)
| todo: all these should be in bss!
SYMBOL_NAME(swapper_pg_dir): .skip 0x2000
SYMBOL_NAME(pg0): .skip 0x2000
SYMBOL_NAME(empty_bad_page): .skip 0x2000
SYMBOL_NAME(empty_bad_page_table): .skip 0x2000
SYMBOL_NAME(kernel_pmd_table): .skip 0x2000
SYMBOL_NAME(empty_zero_page): .skip 0x2000
.globl SYMBOL_NAME(kernel_pg_dir)
.equ SYMBOL_NAME(kernel_pg_dir),SYMBOL_NAME(kernel_pmd_table)
.section .head
ENTRY(_stext)
ENTRY(_start)
/* Firstly, disable interrupts and set up function codes. */
movew #PSL_HIGHIPL, %sr
moveq #FC_CONTROL, %d0
movec %d0, %sfc
movec %d0, %dfc
/* Make sure we're in context zero. */
moveq #0, %d0
movsb %d0, AC_CONTEXT
/* Copy mappings for first megabyte of RAM to address 0xE000000. */
lea (AC_SEGMAP+0),%a0
lea (AC_SEGMAP+KERNBASE),%a1
moveq #(0x140000/NBSG-1),%d0
1: movsb %a0@,%d1
movsb %d1,%a1@
addl #NBSG,%a0
addl #NBSG,%a1
dbf %d0,1b
/* Disable caches and jump to high code. */
moveq #ICACHE_ONLY,%d0 | Cache disabled until we're ready to enable it
movc %d0, %cacr | is this the right value? (yes --m)
jmp 1f:l
/* Following code executes at high addresses (0xE000xxx). */
1: lea SYMBOL_NAME(init_task_union),%a2 | get initial thread...
lea %a2@(KTHREAD_SIZE),%sp | ...and its stack.
/* copy bootinfo records from the loader to _end */
lea SYMBOL_NAME(_end), %a1
lea BI_START, %a0
/* number of longs to copy */
movel %a0@, %d0
1: addl #4, %a0
movel %a0@, %a1@
addl #4, %a1
dbf %d0, 1b
/* Point MSP at an invalid page to trap if it's used. --m */
movl #(PAGESIZE),%d0
movc %d0,%msp
moveq #-1,%d0
movsb %d0,(AC_SEGMAP+0x0)
jbsr SYMBOL_NAME(sun3_init)
jbsr SYMBOL_NAME(start_kernel)
trap #15
.data
.even
SYMBOL_NAME_LABEL(kpt)
.long 0
SYMBOL_NAME_LABEL(availmem)
.long 0
| todo: remove next two. --m
SYMBOL_NAME_LABEL(is_medusa)
.long 0
SYMBOL_NAME_LABEL(m68k_pgtable_cachemode)
.long 0
......@@ -47,7 +47,9 @@ asmlinkage void buserr(void);
asmlinkage void trap(void);
asmlinkage void inthandler(void);
asmlinkage void nmihandler(void);
#ifdef CONFIG_M68KFPU_EMU
asmlinkage void fpu_emu(void);
#endif
e_vector vectors[256] = {
0, 0, buserr, trap, trap, trap, trap, trap,
......@@ -68,8 +70,17 @@ asm(".text\n"
void __init base_trap_init(void)
{
#ifdef CONFIG_SUN3
/* Keep the keyboard interrupt working with PROM for debugging. --m */
e_vector *old_vbr;
__asm__ volatile ("movec %%vbr,%1\n\t"
"movec %0,%%vbr"
: "=&r" (old_vbr) : "r" ((void*)vectors));
vectors[0x1E] = old_vbr[0x1E]; /* Copy int6 vector. */
#else
/* setup the exception vector table */
__asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
#endif
if (CPU_IS_040 && !FPU_IS_EMU) {
/* set up FPSP entry points */
......@@ -143,6 +154,10 @@ void __init trap_init (void)
if (MACH_IS_AMIGA) {
vectors[VEC_INT7] = nmihandler;
}
#ifdef CONFIG_SUN3
/* Moved from setup_arch() */
base_trap_init();
#endif
}
......@@ -175,11 +190,17 @@ static char *vec_names[] = {
"MMU CONFIGURATION ERROR"
};
#ifndef CONFIG_SUN3
static char *space_names[] = {
"Space 0", "User Data", "User Program", "Space 3",
"Space 4", "Super Data", "Super Program", "CPU"
};
#else
static char *space_names[] = {
"Space 0", "User Data", "User Program", "Control",
"Space 4", "Super Data", "Super Program", "CPU"
};
#endif
void die_if_kernel(char *,struct pt_regs *,int);
asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
......@@ -330,6 +351,17 @@ static inline void access_error040 (struct frame *fp)
#endif
errorcode = ((mmusr & MMU_R_040) ? 1 : 0) |
((ssw & RW_040) ? 0 : 2);
#ifdef CONFIG_FTRACE
{
unsigned long flags;
save_flags(flags);
cli();
do_ftrace(0xfa000000 | errorcode);
do_ftrace(mmusr);
restore_flags(flags);
}
#endif
do_page_fault (&fp->ptregs, addr, errorcode);
} else {
printk ("68040 access error, ssw=%x\n", ssw);
......@@ -363,6 +395,132 @@ static inline void access_error040 (struct frame *fp)
}
#endif /* CONFIG_M68040 */
#if defined(CONFIG_SUN3)
#include <asm/sun3mmu.h>
extern int mmu_emu_handle_fault (unsigned long, int, int);
/* sun3 version of bus_error030 */
extern inline void bus_error030 (struct frame *fp)
{
unsigned char buserr_type = sun3_get_buserr ();
unsigned long addr, errorcode;
unsigned short ssw = fp->un.fmtb.ssw;
#if DEBUG
if (ssw & (FC | FB))
printk ("Instruction fault at %#010lx\n",
ssw & FC ?
fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
:
fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
if (ssw & DF)
printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
ssw & RW ? "read" : "write",
fp->un.fmtb.daddr,
space_names[ssw & DFC], fp->ptregs.pc);
#endif
/*
* Check if this page should be demand-mapped. This needs to go before
* the testing for a bad kernel-space access (demand-mapping applies
* to kernel accesses too).
*/
if ((ssw & DF)
&& (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) {
if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0))
return;
}
/* Check for kernel-space pagefault (BAD). */
if (fp->ptregs.sr & PS_S) {
/* kernel fault must be a data fault to user space */
if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
// try checking the kernel mappings before surrender
if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1))
return;
/* instruction fault or kernel data fault! */
if (ssw & (FC | FB))
printk ("Instruction fault at %#010lx\n",
fp->ptregs.pc);
if (ssw & DF) {
printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
ssw & RW ? "read" : "write",
fp->un.fmtb.daddr,
space_names[ssw & DFC], fp->ptregs.pc);
}
printk ("BAD KERNEL BUSERR\n");
die_if_kernel("Oops", &fp->ptregs,0);
force_sig(SIGKILL, current);
return;
}
} else {
/* user fault */
if (!(ssw & (FC | FB)) && !(ssw & DF))
/* not an instruction fault or data fault! BAD */
panic ("USER BUSERR w/o instruction or data fault");
}
/* First handle the data fault, if any. */
if (ssw & DF) {
addr = fp->un.fmtb.daddr;
// errorcode bit 0: 0 -> no page 1 -> protection fault
// errorcode bit 1: 0 -> read fault 1 -> write fault
// (buserr_type & SUN3_BUSERR_PROTERR) -> protection fault
// (buserr_type & SUN3_BUSERR_INVALID) -> invalid page fault
if (buserr_type & SUN3_BUSERR_PROTERR)
errorcode = 0x01;
else if (buserr_type & SUN3_BUSERR_INVALID)
errorcode = 0x00;
else {
printk ("*** unexpected busfault type=%#04x\n", buserr_type);
printk ("invalid %s access at %#lx from pc %#lx\n",
!(ssw & RW) ? "write" : "read", addr,
fp->ptregs.pc);
die_if_kernel ("Oops", &fp->ptregs, buserr_type);
force_sig (SIGSEGV, current);
return;
}
//todo: wtf is RM bit? --m
if (!(ssw & RW) || ssw & RM)
errorcode |= 0x02;
/* Handle page fault. */
do_page_fault (&fp->ptregs, addr, errorcode);
/* Retry the data fault now. */
return;
}
/* Now handle the instruction fault. */
/* Get the fault address. */
if (fp->ptregs.format == 0xA)
addr = fp->ptregs.pc + 4;
else
addr = fp->un.fmtb.baddr;
if (ssw & FC)
addr -= 2;
if (buserr_type & SUN3_BUSERR_INVALID) {
if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
do_page_fault (&fp->ptregs, addr, 0);
} else {
#ifdef DEBUG
printk ("protection fault on insn access (segv).\n");
#endif
force_sig (SIGSEGV, current);
}
}
#else
#if defined(CPU_M68020_OR_M68030)
static inline void bus_error030 (struct frame *fp)
{
......@@ -568,6 +726,7 @@ static inline void bus_error030 (struct frame *fp)
: "a" (addr));
}
#endif /* CPU_M68020_OR_M68030 */
#endif /* !CONFIG_SUN3 */
asmlinkage void buserr_c(struct frame *fp)
{
......
......@@ -7,11 +7,9 @@
#
# Note 2! The CFLAGS definitions are now in the main makefile...
EXTRA_CFLAGS := -Wa,-m68020
O_TARGET := mac.o
O_OBJS := config.o bootparse.o macints.o via6522.o \
mackeyb.o adb-bus.o macboing.o debug.o
OX_OBJS := mac_ksyms.o
O_OBJS := config.o bootparse.o macints.o iop.o via.o oss.o psc.o \
macboing.o debug.o misc.o
include $(TOPDIR)/Rules.make
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/irq.h>
#include <asm/setup.h>
#include <asm/bootinfo.h>
#include <asm/macintosh.h>
......
This diff is collapsed.
......@@ -243,7 +243,7 @@ void mac_scca_console_write (struct console *co, const char *str,
}
}
#ifdef CONFIG_SERIAL_CONSOLE
#if defined(CONFIG_SERIAL_CONSOLE) || defined(DEBUG_SERIAL)
int mac_sccb_console_wait_key(struct console *co)
{
int i;
......@@ -385,6 +385,16 @@ void mac_init_scc_port( int cflag, int port )
}
#endif /* DEBUG_SERIAL */
void mac_init_scca_port( int cflag )
{
mac_init_scc_port(cflag, 0);
}
void mac_init_sccb_port( int cflag )
{
mac_init_scc_port(cflag, 1);
}
void __init mac_debug_init(void)
{
#ifdef CONFIG_KGDB
......
This diff is collapsed.
#include <linux/module.h>
#include <asm/ptrace.h>
#include <asm/traps.h>
/* Hook for mouse driver */
extern void (*adb_mouse_interrupt_hook) (char *);
EXPORT_SYMBOL(adb_mouse_interrupt_hook);
/* Says whether we're using A/UX interrupts or not */
extern int via_alt_mapping;
EXPORT_SYMBOL(via_alt_mapping);
This diff is collapsed.
......@@ -91,14 +91,8 @@ static void mac_init_asc( void )
mac_special_bell = mac_quadra_start_bell;
mac_asc_samplespersec = 22150;
break;
case MAC_MODEL_Q650:
case MAC_MODEL_Q700:
case MAC_MODEL_Q800:
case MAC_MODEL_Q900:
case MAC_MODEL_Q950:
/*
* Currently not implemented!
*/
case MAC_MODEL_C660:
case MAC_MODEL_Q840:
/*
* The Quadra 660AV and 840AV use the "Singer" custom ASIC for sound I/O.
* It appears to be similar to the "AWACS" custom ASIC in the Power Mac
......@@ -126,6 +120,22 @@ static void mac_init_asc( void )
*/
mac_special_bell = mac_av_start_bell;
break;
case MAC_MODEL_Q650:
case MAC_MODEL_Q700:
case MAC_MODEL_Q800:
case MAC_MODEL_Q900:
case MAC_MODEL_Q950:
/*
* Currently not implemented!
*/
mac_special_bell = NULL;
break;
default:
/*
* Every switch needs a default
*/
mac_special_bell = NULL;
break;
}
/*
......@@ -155,6 +165,12 @@ void mac_mksound( unsigned int freq, unsigned int length )
__u32 flags;
int i;
if ( mac_special_bell == NULL )
{
/* Do nothing */
return;
}
if ( !mac_asc_inited )
mac_init_asc();
......
This diff is collapsed.
/*
* OSS handling
* Written by Joshua M. Thompson (funaho@jurai.org)
*
*
* This chip is used in the IIfx in place of VIA #2. It acts like a fancy
* VIA chip with prorammable interrupt levels.
*
* 990502 (jmt) - Major rewrite for new interrupt architecture as well as some
* recent insights into OSS operational details.
* 990610 (jmt) - Now taking fulll advantage of the OSS. Interrupts are mapped
* to mostly match the A/UX interrupt scheme supported on the
* VIA side. Also added support for enabling the ISM irq again
* since we now have a functional IOP manager.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <asm/bootinfo.h>
#include <asm/machw.h>
#include <asm/macintosh.h>
#include <asm/macints.h>
#include <asm/mac_via.h>
#include <asm/mac_oss.h>
int oss_present;
volatile struct mac_oss *oss;
void oss_irq(int, void *, struct pt_regs *);
void oss_nubus_irq(int, void *, struct pt_regs *);
extern void via1_irq(int, void *, struct pt_regs *);
extern void mac_SCC_handler(int, void *, struct pt_regs *);
extern int console_loglevel;
/*
* Initialize the OSS
*
* The OSS "detection" code is actually in via_init() which is always called
* before us. Thus we can count on oss_present being valid on entry.
*/
void __init oss_init(void)
{
int i;
if (!oss_present) return;
oss = (struct mac_oss *) OSS_BASE;
/* Disable all interrupts. Unlike a VIA it looks like we */
/* do this by setting the source's interrupt level to zero. */
for (i = 0; i <= OSS_NUM_SOURCES; i++) {
oss->irq_level[i] = OSS_IRQLEV_DISABLED;
}
/* If we disable VIA1 here, we never really handle it... */
oss->irq_level[OSS_VIA1] = OSS_IRQLEV_VIA1;
}
/*
* Register the OSS and NuBus interrupt dispatchers.
*/
void __init oss_register_interrupts(void)
{
request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
"OSS SCSI Dispatch", (void *) oss);
request_irq(OSS_IRQLEV_IOPSCC, mac_SCC_handler, IRQ_FLG_LOCK,
"SCC Dispatch", mac_SCC_handler);
request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
"Nubus Dispatch", (void *) oss);
request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
"OSS Sound Dispatch", (void *) oss);
request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
"VIA1 Dispatch", (void *) via1);
}
/*
* Initialize OSS for Nubus access
*/
void __init oss_nubus_init(void)
{
}
/*
* Turn off the power via the ROM control register
*
* FIXME: not sure how this is supposed to work exactly...
*/
void oss_poweroff(void)
{
oss->rom_ctrl = OSS_POWEROFF;
/* We should never make it this far... */
printk ("It is now safe to switch off your machine.\n");
while(1);
}
/*
* Handle miscellaneous OSS interrupts. Right now that's just sound
* and SCSI; everything else is routed to its own autovector IRQ.
*/
void oss_irq(int irq, void *dev_id, struct pt_regs *regs)
{
int events;
events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI);
if (!events) return;
#ifdef DEBUG_IRQS
if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) {
printk("oss_irq: irq %d events = 0x%04X\n", irq,
(int) oss->irq_pending);
}
#endif
/* FIXME: how do you clear a pending IRQ? */
if (events & OSS_IP_SOUND) {
/* FIXME: call sound handler */
oss->irq_pending &= ~OSS_IP_SOUND;
} else if (events & OSS_IP_SCSI) {
oss->irq_level[OSS_SCSI] = OSS_IRQLEV_DISABLED;
mac_do_irq_list(IRQ_MAC_SCSI, regs);
oss->irq_pending &= ~OSS_IP_SCSI;
oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI;
} else {
/* FIXME: error check here? */
}
}
/*
* Nubus IRQ handler, OSS style
*
* Unlike the VIA/RBV this is on its own autovector interupt level.
*/
void oss_nubus_irq(int irq, void *dev_id, struct pt_regs *regs)
{
int events, irq_bit, i;
events = oss->irq_pending & OSS_IP_NUBUS;
if (!events) return;
#ifdef DEBUG_NUBUS_INT
if (console_loglevel > 7) {
printk("oss_nubus_irq: events = 0x%04X\n", events);
}
#endif
/* There are only six slots on the OSS, not seven */
for (i = 0, irq_bit = 1 ; i < 6 ; i++, irq_bit <<= 1) {
if (events & irq_bit) {
oss->irq_level[i] = OSS_IRQLEV_DISABLED;
mac_do_irq_list(NUBUS_SOURCE_BASE + i, regs);
oss->irq_pending &= ~irq_bit;
oss->irq_level[i] = OSS_IRQLEV_NUBUS;
}
}
}
/*
* Enable an OSS interrupt
*
* It looks messy but it's rather straightforward. The switch() statement
* just maps the machspec interrupt numbers to the right OSS interrupt
* source (if the OSS handles that interrupt) and then sets the interrupt
* level for that source to nonzero, thus enabling the interrupt.
*/
void oss_irq_enable(int irq) {
#ifdef DEBUG_IRQUSE
printk("oss_irq_enable(%d)\n", irq);
#endif
switch(irq) {
case IRQ_SCC:
case IRQ_SCCA:
case IRQ_SCCB:
oss->irq_level[OSS_IOPSCC] = OSS_IRQLEV_IOPSCC;
break;
case IRQ_MAC_ADB:
oss->irq_level[OSS_IOPISM] = OSS_IRQLEV_IOPISM;
break;
case IRQ_MAC_SCSI:
oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI;
break;
case IRQ_NUBUS_9:
case IRQ_NUBUS_A:
case IRQ_NUBUS_B:
case IRQ_NUBUS_C:
case IRQ_NUBUS_D:
case IRQ_NUBUS_E:
irq -= NUBUS_SOURCE_BASE;
oss->irq_level[irq] = OSS_IRQLEV_NUBUS;
break;
#ifdef DEBUG_IRQUSE
default:
printk("%s unknown irq %d\n",__FUNCTION__, irq);
break;
#endif
}
}
/*
* Disable an OSS interrupt
*
* Same as above except we set the source's interrupt level to zero,
* to disable the interrupt.
*/
void oss_irq_disable(int irq) {
#ifdef DEBUG_IRQUSE
printk("oss_irq_disable(%d)\n", irq);
#endif
switch(irq) {
case IRQ_SCC:
case IRQ_SCCA:
case IRQ_SCCB:
oss->irq_level[OSS_IOPSCC] = OSS_IRQLEV_DISABLED;
break;
case IRQ_MAC_ADB:
oss->irq_level[OSS_IOPISM] = OSS_IRQLEV_DISABLED;
break;
case IRQ_MAC_SCSI:
oss->irq_level[OSS_SCSI] = OSS_IRQLEV_DISABLED;
break;
case IRQ_NUBUS_9:
case IRQ_NUBUS_A:
case IRQ_NUBUS_B:
case IRQ_NUBUS_C:
case IRQ_NUBUS_D:
case IRQ_NUBUS_E:
irq -= NUBUS_SOURCE_BASE;
oss->irq_level[irq] = OSS_IRQLEV_DISABLED;
break;
#ifdef DEBUG_IRQUSE
default:
printk("%s unknown irq %d\n", __FUNCTION__, irq);
break;
#endif
}
}
/*
* Clear an OSS interrupt
*
* Not sure if this works or not but it's the only method I could
* think of based on the contents of the mac_oss structure.
*/
void oss_irq_clear(int irq) {
/* FIXME: how to do this on OSS? */
switch(irq) {
case IRQ_SCC:
case IRQ_SCCA:
case IRQ_SCCB:
oss->irq_pending &= ~OSS_IP_IOPSCC;
break;
case IRQ_MAC_ADB:
oss->irq_pending &= ~OSS_IP_IOPISM;
break;
case IRQ_MAC_SCSI:
oss->irq_pending &= ~OSS_IP_SCSI;
break;
case IRQ_NUBUS_9:
case IRQ_NUBUS_A:
case IRQ_NUBUS_B:
case IRQ_NUBUS_C:
case IRQ_NUBUS_D:
case IRQ_NUBUS_E:
irq -= NUBUS_SOURCE_BASE;
oss->irq_pending &= ~(1 << irq);
break;
}
}
/*
* Check to see if a specific OSS interrupt is pending
*/
int oss_irq_pending(int irq)
{
switch(irq) {
case IRQ_SCC:
case IRQ_SCCA:
case IRQ_SCCB:
return oss->irq_pending & OSS_IP_IOPSCC;
break;
case IRQ_MAC_ADB:
return oss->irq_pending & OSS_IP_IOPISM;
break;
case IRQ_MAC_SCSI:
return oss->irq_pending & OSS_IP_SCSI;
break;
case IRQ_NUBUS_9:
case IRQ_NUBUS_A:
case IRQ_NUBUS_B:
case IRQ_NUBUS_C:
case IRQ_NUBUS_D:
case IRQ_NUBUS_E:
irq -= NUBUS_SOURCE_BASE;
return oss->irq_pending & (1 << irq);
break;
}
return 0;
}
/*
* Apple Peripheral System Controller (PSC)
*
* The PSC is used on the AV Macs to control IO functions not handled
* by the VIAs (Ethernet, DSP, SCC).
*
* TO DO:
*
* Try to figure out what's going on in pIFR5 and pIFR6. There seem to be
* persisant interrupt conditions in those registers and I have no idea what
* they are. Granted it doesn't affect since we're not enabling any interrupts
* on those levels at the moment, but it would be nice to know. I have a feeling
* they aren't actually interrupt lines but data lines (to the DSP?)
*/
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <asm/traps.h>
#include <asm/bootinfo.h>
#include <asm/macintosh.h>
#include <asm/macints.h>
#include <asm/mac_psc.h>
#define DEBUG_PSC
int psc_present;
volatile __u8 *psc;
void psc_irq(int, void *, struct pt_regs *);
extern int console_loglevel;
/*
* Debugging dump, used in various places to see what's going on.
*/
void psc_debug_dump(void)
{
int i;
if (!psc_present) return;
for (i = 0x30 ; i < 0x70 ; i += 0x10) {
printk("PSC #%d: IFR = 0x%02X IER = 0x%02X\n",
i >> 4,
(int) psc_read_byte(pIFRbase + i),
(int) psc_read_byte(pIERbase + i));
}
}
/*
* Try to kill all DMA channels on the PSC. Not sure how this his
* supposed to work; this is code lifted from macmace.c and then
* expanded to cover what I think are the other 7 channels.
*/
void psc_dma_die_die_die(void)
{
int i;
printk("Killing all PSC DMA channels...");
for (i = 0 ; i < 9 ; i++) {
psc_write_word(PSC_CTL_BASE + (i << 4), 0x8800);
psc_write_word(PSC_CTL_BASE + (i << 4), 0x1000);
psc_write_word(PSC_CMD_BASE + (i << 5), 0x1100);
psc_write_word(PSC_CMD_BASE + (i << 5) + 0x10, 0x1100);
}
printk("done!\n");
}
/*
* Initialize the PSC. For now this just involves shutting down all
* interrupt sources using the IERs.
*/
void __init psc_init(void)
{
int i;
if (macintosh_config->ident != MAC_MODEL_C660
&& macintosh_config->ident != MAC_MODEL_Q840)
{
psc = NULL;
psc_present = 0;
return;
}
/*
* The PSC is always at the same spot, but using psc
* keeps things consisant with the psc_xxxx functions.
*/
psc = (void *) PSC_BASE;
psc_present = 1;
printk("PSC detected at %p\n", psc);
psc_dma_die_die_die();
#ifdef DEBUG_PSC
psc_debug_dump();
#endif
/*
* Mask and clear all possible interrupts
*/
for (i = 0x30 ; i < 0x70 ; i += 0x10) {
psc_write_byte(pIERbase + i, 0x0F);
psc_write_byte(pIFRbase + i, 0x0F);
}
}
/*
* Register the PSC interrupt dispatchers for autovector interrupts 3-6.
*/
void __init psc_register_interrupts(void)
{
request_irq(3, psc_irq, IRQ_FLG_LOCK, "PSC Dispatch",
(void *) 0x30);
request_irq(4, psc_irq, IRQ_FLG_LOCK, "PSC Dispatch",
(void *) 0x40);
request_irq(5, psc_irq, IRQ_FLG_LOCK, "PSC Dispatch",
(void *) 0x50);
request_irq(6, psc_irq, IRQ_FLG_LOCK, "PSC Dispatch",
(void *) 0x60);
}
/*
* PSC interrupt handler. It's a lot like the VIA interrupt handler.
*/
void psc_irq(int irq, void *dev_id, struct pt_regs *regs)
{
int pIFR = pIFRbase + ((int) dev_id);
int pIER = pIERbase + ((int) dev_id);
int base_irq;
int irq_bit,i;
unsigned char events;
irq -= VEC_SPUR;
base_irq = irq << 3;
#ifdef DEBUG_IRQS
printk("psc_irq: irq %d pIFR = 0x%02X pIER = 0x%02X\n",
irq, (int) psc_read_byte(pIFR), (int) psc_read_byte(pIER));
#endif
events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF;
if (!events) return;
for (i = 0, irq_bit = 1 ; i < 4 ; i++, irq_bit <<= 1) {
if (events & irq_bit) {
psc_write_byte(pIER, irq_bit);
mac_do_irq_list(base_irq + i, regs);
psc_write_byte(pIFR, irq_bit);
psc_write_byte(pIER, irq_bit | 0x80);
}
}
}
void psc_irq_enable(int irq) {
int irq_src = IRQ_SRC(irq);
int irq_idx = IRQ_IDX(irq);
int pIER = pIERbase + (irq_src << 4);
#ifdef DEBUG_IRQUSE
printk("psc_irq_enable(%d)\n", irq);
#endif
psc_write_byte(pIER, (1 << irq_idx) | 0x80);
}
void psc_irq_disable(int irq) {
int irq_src = IRQ_SRC(irq);
int irq_idx = IRQ_IDX(irq);
int pIER = pIERbase + (irq_src << 4);
#ifdef DEBUG_IRQUSE
printk("psc_irq_disable(%d)\n", irq);
#endif
psc_write_byte(pIER, 1 << irq_idx);
}
void psc_irq_clear(int irq) {
int irq_src = IRQ_SRC(irq);
int irq_idx = IRQ_IDX(irq);
int pIFR = pIERbase + (irq_src << 4);
psc_write_byte(pIFR, 1 << irq_idx);
}
int psc_irq_pending(int irq)
{
int irq_src = IRQ_SRC(irq);
int irq_idx = IRQ_IDX(irq);
int pIFR = pIERbase + (irq_src << 4);
return psc_read_byte(pIFR) & (1 << irq_idx);
}
This diff is collapsed.
/*
* 6522 Versatile Interface Adapter (VIA)
*
* There are two of these on the Mac II. Some IRQ's are vectored
* via them as are assorted bits and bobs - eg rtc, adb.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/delay.h>
#include <asm/adb.h>
#include <asm/bootinfo.h>
#include <asm/macintosh.h>
#include <asm/macints.h>
#include "via6522.h"
#include <asm/mac_psc.h>
volatile unsigned char *via1=(unsigned char *)VIABASE;
volatile unsigned char *via2=(unsigned char *)VIABASE2;
volatile unsigned char *psc=(unsigned char *)PSCBASE;
volatile long *via_memory_bogon=(long *)&via_memory_bogon;
unsigned char via1_clock, via1_datab;
static int rbv=0;
static int oss=0;
extern void adb_interrupt(int slot, void *via, struct pt_regs *regs);
/*
* hardware reset vector
*/
static void (*rom_reset)(void);
/*
* Timer defs.
*/
#define MAC_CLOCK_TICK (783300/HZ) /* ticks per HZ */
#define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF)
#define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8)
void via_configure_base(void)
{
switch(macintosh_config->via_type)
{
/*
* CI, SI, VX, LC
*/
case MAC_VIA_IIci:
via1=(void *)0x50F00000;
via2=(void *)0x50F26000;
rbv=1;
if (macintosh_config->ident == MAC_MODEL_IIFX) {
via2=(void *)0x50F1A000;
oss=1;
}
break;
/*
* Quadra and early MacIIs agree on the VIA locations
*/
case MAC_VIA_QUADRA:
case MAC_VIA_II:
via1=(void *)0x50F00000;
via2=(void *)0x50F02000;
break;
default:
}
}
void via_init_clock(void (*func)(int, void *, struct pt_regs *))
{
unsigned char c;
via1_clock=via_read(via1, vACR);
via1_datab=via_read(via1, vBufB);
/*
* Tell what MacOS left us with
*/
printk("via_init: boot via1 acr=%X pcr=%X buf_a=%X dir_a=%X buf_b=%X dir_b=%X \n",
(int)via1_clock, (int)via_read(via1, vPCR),
(int)via_read(via1, vBufA), (int)via_read(via1, vDirA),
(int)via_read(via1, vBufB), (int)via_read(via1, vDirB));
if (rbv == 0)
printk("via_init: boot via2 acr=%X pcr=%X buf_a=%X dir_a=%X buf_b=%X dir_b=%X \n",
(int)via_read(via2, vACR), (int)via_read(via2, vPCR),
(int)via_read(via2, vBufA), (int)via_read(via2, vDirA),
(int)via_read(via2, vBufB), (int)via_read(via2, vDirB));
/*
* Shut it down
*/
via_write(via1,vIER, 0x7F);
/*
* Kill the timers
*/
via_write(via1,vT1LL,0);
via_write(via1,vT1LH,0);
via_write(via1,vT1CL,0);
via_write(via1,vT1CH,0);
via_write(via1,vT2CL,0);
via_write(via1,vT2CH,0);
/*
* Now do via2
*/
if(rbv==0)
{
via_write(via2,vT1LL,0);
via_write(via2,vT1LH,0);
via_write(via2,vT1CL,0);
via_write(via2,vT1CH,0);
via_write(via2,vT2CL,0);
via_write(via2,vT2CH,0);
via_write(via2,vIER, 0x7F);
}
else if (oss==0)
{
/*
* Init the RBV chip a bit
*/
via_write(via2, rIER,0x7F);
}
/*
* Disable the timer latches
*/
c=via_read(via1,vACR);
via_write(via1,vACR,c&0x3F);
if(rbv==0)
{
c=via_read(via2,vACR);
via_write(via2,vACR,c&0x3F);
}
/*
* Now start the clock - we want 100Hz
*/
via_write(via1,vACR,via_read(via1,vACR)|0x40);
via_write(via1,vT1LL, MAC_CLOCK_LOW);
via_write(via1,vT1LH, MAC_CLOCK_HIGH);
via_write(via1,vT1CL, MAC_CLOCK_LOW);
via_write(via1,vT1CH, MAC_CLOCK_HIGH);
/*
* And enable its interrupt
*/
request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func);
/*
* SE/30: disable video int.
* XXX: testing for SE/30 VBL
*/
if (macintosh_config->ident == MAC_MODEL_SE30) {
c = via_read(via1, vBufB);
via_write(via1, vBufB, c|(0x40));
c = via_read(via1, vDirB);
via_write(via1, vDirB, c|(0x40));
}
#if 0 /* gone to mac_init_IRQ */
/*
* Set vPCR for SCSI interrupts.
*
* That is: CA1 negative edge int., CA2 indep., positive edge int.;
* CB1 negative edge int., CB2 indep., positive edge int..
*/
via_write(via2,vPCR, 0x66);
#endif
}
/*
* TBI: get time offset between scheduling timer ticks
*/
#define TICK_SIZE 10000
/* This is always executed with interrupts disabled. */
unsigned long mac_gettimeoffset (void)
{
unsigned long ticks, offset = 0;
/* read VIA1 timer 2 current value */
ticks = via_read(via1, vT1CL) + (via_read(via1, vT1CH)<<8);
/* The probability of underflow is less than 2% */
if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50)
/* Check for pending timer interrupt in VIA1 IFR */
if (via_read(via1, vIFR) & 0x40)
offset = TICK_SIZE;
ticks = MAC_CLOCK_TICK - ticks;
ticks = ticks * 10000L / MAC_CLOCK_TICK;
return ticks + offset;
}
/*
* PSC (AV Macs; level 3-6): initialize interrupt enable registers
*/
void psc_init(void)
{
via_write(psc, pIER3, 0x01);
via_write(psc, pIER4, 0x09);
via_write(psc, pIER4, 0x86);
via_write(psc, pIER5, 0x03);
via_write(psc, pIER6, 0x07);
}
/*
* The power switch - yes it's software!
*/
void mac_poweroff(void)
{
/*
* MAC_ADB_IISI may need to be moved up here if it doesn't actually
* work using the ADB packet method. --David Kilzer
*/
if (macintosh_config->adb_type == MAC_ADB_II)
{
if(rbv) {
via_write(via2, rBufB, via_read(via2, rBufB)&~0x04);
} else {
/* Direction of vDirB is output */
via_write(via2,vDirB,via_read(via2,vDirB)|0x04);
/* Send a value of 0 on that line */
via_write(via2,vBufB,via_read(via2,vBufB)&~0x04);
/* Otherwise it prints "It is now.." then shuts off */
mdelay(1000);
}
/* We should never make it this far... */
printk ("It is now safe to switch off your machine.\n");
/* XXX - delay do we need to spin here ? */
while(1); /* Just in case .. */
}
/*
* Initially discovered this technique in the Mach kernel of MkLinux in
* osfmk/src/mach_kernel/ppc/POWERMAC/cuda_power.c. Found equivalent LinuxPPC
* code in arch/ppc/kernel/setup.c, which also has a PMU technique for PowerBooks!
* --David Kilzer
*/
else if (macintosh_config->adb_type == MAC_ADB_IISI
|| macintosh_config->adb_type == MAC_ADB_CUDA)
{
struct adb_request req;
/*
* Print our "safe" message before we send the request
* just in case the request never returns.
*/
printk ("It is now safe to switch off your machine.\n");
adb_request (&req, NULL, 2, CUDA_PACKET, CUDA_POWERDOWN);
printk ("ADB powerdown request sent.\n");
for (;;)
{
adb_poll();
}
}
}
/*
* Not all Macs support software power down; for the rest, just
* try the ROM reset vector ...
*/
void mac_reset(void)
{
/*
* MAC_ADB_IISI may need to be moved up here if it doesn't actually
* work using the ADB packet method. --David Kilzer
*/
if (macintosh_config->adb_type == MAC_ADB_II)
{
unsigned long flags;
unsigned long *reset_hook;
/* need ROMBASE in booter */
/* indeed, plus need to MAP THE ROM !! */
if (mac_bi_data.rombase == 0)
mac_bi_data.rombase = 0x40800000;
/* works on some */
rom_reset = (void *) (mac_bi_data.rombase + 0xa);
#if 0
/* testing, doesn't work on SE/30 either */
reset_hook = (unsigned long *) (mac_bi_data.rombase + 0x4);
printk("ROM reset hook: %p\n", *reset_hook);
rom_reset = *reset_hook;
#endif
if (macintosh_config->ident == MAC_MODEL_SE30) {
/*
* MSch: Machines known to crash on ROM reset ...
*/
printk("System halted.\n");
while(1);
} else {
save_flags(flags);
cli();
rom_reset();
restore_flags(flags);
}
/* We never make it this far... it usually panics above. */
printk ("Restart failed. Please restart manually.\n");
/* XXX - delay do we need to spin here ? */
while(1); /* Just in case .. */
}
/*
* Initially discovered this technique in the Mach kernel of MkLinux in
* osfmk/src/mach_kernel/ppc/POWERMAC/cuda_power.c. Found equivalent LinuxPPC
* code in arch/ppc/kernel/setup.c, which also has a PMU technique!
* --David Kilzer
*
* I suspect the MAC_ADB_CUDA code might work with other ADB types of machines
* but have no way to test this myself. --DDK
*/
else if (macintosh_config->adb_type == MAC_ADB_IISI
|| macintosh_config->adb_type == MAC_ADB_CUDA)
{
struct adb_request req;
adb_request (&req, NULL, 2, CUDA_PACKET, CUDA_RESET_SYSTEM);
printk ("Restart failed. Please restart manually.\n");
for (;;)
{
adb_poll();
}
}
}
/*
* Set up the keyboard
*/
void via_setup_keyboard(void)
{
#if 0 /* moved to adb */
via1_func_tab.vector[2]=adb_interrupt;
#else
request_irq(IRQ_MAC_ADB, adb_interrupt, IRQ_FLG_LOCK, "adb interrupt",
adb_interrupt);
#endif
}
/*
* Floppy hook
*/
void via1_set_head(int head)
{
if(head==0)
via_write(via1, vBufA, via_read(via1, vBufA)&~0x20);
else
via_write(via1, vBufA, via_read(via1, vBufA)|0x20);
}
void nubus_init_via(void)
{
if (rbv) {
if (oss==0) {
via_write(via2, rBufB, via_read(via2, rBufB)|0x02);
via_write(via2, rIER, 0x82); /* Interrupts on */
}
} else {
/* Assert the nubus active */
via_write(via2, vDirB, via_read(via2, vDirB)|0x02);
via_write(via2, vBufB, via_read(via2, vBufB)|0x02);
/* Make the nubus interrupt source register all output (disable) */
/* via_write(via2, vDirA, 0xFF); */
via_write(via2, vIER, 0x82); /* Interrupts on */
}
printk("nubus_init_via: via1 acr=%X datab=%X pcr=%X\n",
(int)via_read(via1, vACR), (int)via_read(via1, vBufB),
(int)via_read(via1, vPCR));
if (rbv==0)
printk("nubus_init_via: via2 acr=%X datab=%X pcr=%X\n",
(int)via_read(via2, vACR), (int)via_read(via2, vBufB),
(int)via_read(via2, vPCR));
}
This diff is collapsed.
......@@ -35,7 +35,6 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/config.h>
#include <linux/linkage.h>
#include <asm/entry.h>
......
......@@ -35,8 +35,6 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/config.h>
#include "fp_emu.h"
/*
......
......@@ -8,6 +8,13 @@
# Note 2! The CFLAGS definition is now in the main makefile...
O_TARGET := mm.o
O_OBJS := init.o fault.o memory.o kmap.o extable.o hwtest.o
O_OBJS := init.o fault.o extable.o hwtest.o
ifndef CONFIG_SUN3
O_OBJS += kmap.o memory.o motorola.o
else
O_OBJS += sun3mmu.o
endif
include $(TOPDIR)/Rules.make
This diff is collapsed.
......@@ -385,7 +385,7 @@ unsigned long mm_vtop_fallback(unsigned long vaddr)
}
#ifndef CONFIG_SINGLE_MEMORY_CHUNK
void *mm_ptov (unsigned long paddr)
unsigned long mm_ptov (unsigned long paddr)
{
int i = 0;
unsigned long poff, voff = PAGE_OFFSET;
......@@ -396,7 +396,7 @@ void *mm_ptov (unsigned long paddr)
#ifdef DEBUGPV
printk ("PTOV(%lx)=%lx\n", paddr, poff + voff);
#endif
return (void *)(poff + voff);
return poff + voff;
}
voff += m68k_memory[i].size;
} while (++i < m68k_num_memory);
......@@ -429,9 +429,9 @@ void *mm_ptov (unsigned long paddr)
* to the ZTWO_VADDR range
*/
if (MACH_IS_AMIGA && paddr < 16*1024*1024)
return (void *)ZTWO_VADDR(paddr);
return ZTWO_VADDR(paddr);
#endif
return (void *)-1;
return -1;
}
#endif
......@@ -491,14 +491,7 @@ void *mm_ptov (unsigned long paddr)
* this?). So we have to push first and then additionally to invalidate.
*/
#ifdef CONFIG_M68K_L2_CACHE
/*
* Jes was worried about performance (urhh ???) so its optional
*/
void (*mach_l2_flush)(int) = NULL;
#endif
/*
* cache_clear() semantics: Clear any cache entries for the area in question,
* without writing back dirty entries first. This is useful if the data will
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment