Commit 847f9c60 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k: (24 commits)
  m68k: Define sigcontext ABI of ColdFire
  m68knommu: NPTL support for uClinux
  m68k: Add NPTL support
  m68k: Eliminate unused variable in page_to_phys()
  m68k: Switch to generic siginfo layout
  macfb: fix 24-bit visual and stuff
  macfb: cleanup
  fbdev: add some missing mac modes
  mac68k: start CUDA early
  valkyriefb: various fixes
  fbdev: mac_var_to_mode() fix
  mac68k: move macsonic and macmace platform devices
  mac68k: move mac_esp platform device
  mac68k: replace mac68k SCC code with platform device
  pmac-zilog: add platform driver
  pmac-zilog: cleanup
  mac68k: rework SWIM platform device
  mac68k: cleanup
  ataflop: Killl warning about unused variable flags
  m68k: Use DIV_ROUND_CLOSEST
  ...
parents 79811647 00ebfe58
......@@ -44,8 +44,8 @@ void cache_push_v (unsigned long vaddr, int len)
{
}
/* Map some physical address range into the kernel address space. The
* code is copied and adapted from map_chunk().
/*
* Map some physical address range into the kernel address space.
*/
unsigned long kernel_map(unsigned long paddr, unsigned long size,
......
......@@ -536,10 +536,6 @@ config GVPIOEXT_PLIP
Say Y to enable doing IP over the parallel port on your GVP
IO-Extender card, N otherwise.
config MAC_SCC
tristate "Macintosh serial support"
depends on MAC
config MAC_HID
bool
depends on INPUT_ADBHID
......@@ -595,7 +591,7 @@ config DN_SERIAL
config SERIAL_CONSOLE
bool "Support for serial port console"
depends on (AMIGA || ATARI || MAC || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_MIDI=y || MAC_SCC=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL)
depends on (AMIGA || ATARI || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_MIDI=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL)
---help---
If you say Y here, it will be possible to use a serial port as the
system console (the system console is the device which receives all
......
......@@ -480,7 +480,7 @@ static void __init amiga_sched_init(irq_handler_t timer_routine)
static struct resource sched_res = {
.name = "timer", .start = 0x00bfd400, .end = 0x00bfd5ff,
};
jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
jiffy_ticks = DIV_ROUND_CLOSEST(amiga_eclock, HZ);
if (request_resource(&mb_resources._ciab, &sched_res))
printk("Cannot allocate ciab.ta{lo,hi}\n");
......
......@@ -701,6 +701,11 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
#
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_PMACZILOG=y
CONFIG_SERIAL_PMACZILOG_TTYS=y
CONFIG_SERIAL_PMACZILOG_CONSOLE=y
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
......@@ -834,9 +839,7 @@ CONFIG_HIDRAW=y
#
# Character devices
#
CONFIG_MAC_SCC=y
CONFIG_MAC_HID=y
CONFIG_SERIAL_CONSOLE=y
#
# File systems
......
......@@ -822,6 +822,11 @@ CONFIG_A2232=y
#
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_PMACZILOG=y
CONFIG_SERIAL_PMACZILOG_TTYS=y
CONFIG_SERIAL_PMACZILOG_CONSOLE=y
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
......@@ -982,7 +987,6 @@ CONFIG_ATARI_MIDI=y
CONFIG_ATARI_DSP56K=m
CONFIG_AMIGA_BUILTIN_SERIAL=y
CONFIG_MULTIFACE_III_TTY=m
CONFIG_MAC_SCC=y
CONFIG_MAC_HID=y
CONFIG_MVME147_SCC=y
CONFIG_SERIAL167=y
......
......@@ -21,29 +21,4 @@
#define VIDEOMEMSIZE (4096*1024)
#define VIDEOMEMMASK (-4096*1024)
#ifndef __ASSEMBLY__
#include <linux/types.h>
#if 0
/*
** SCC Z8530
*/
#define MAC_SCC_BAS (0x50F04000)
struct MAC_SCC
{
u_char cha_a_ctrl;
u_char char_dummy1;
u_char cha_a_data;
u_char char_dummy2;
u_char cha_b_ctrl;
u_char char_dummy3;
u_char cha_b_data;
};
# define mac_scc ((*(volatile struct SCC*)MAC_SCC_BAS))
#endif
#endif /* __ASSEMBLY__ */
#endif /* linux/machw.h */
......@@ -37,7 +37,6 @@
#define VIA1_SOURCE_BASE 8
#define VIA2_SOURCE_BASE 16
#define MAC_SCC_SOURCE_BASE 24
#define PSC3_SOURCE_BASE 24
#define PSC4_SOURCE_BASE 32
#define PSC5_SOURCE_BASE 40
......@@ -96,26 +95,12 @@
#define IRQ_PSC3_2 (26)
#define IRQ_PSC3_3 (27)
/* Level 4 (SCC) interrupts */
#define IRQ_SCC (32)
#define IRQ_SCCA (33)
#define IRQ_SCCB (34)
#if 0 /* FIXME: are there multiple interrupt conditions on the SCC ?? */
/* SCC interrupts */
#define IRQ_SCCB_TX (32)
#define IRQ_SCCB_STAT (33)
#define IRQ_SCCB_RX (34)
#define IRQ_SCCB_SPCOND (35)
#define IRQ_SCCA_TX (36)
#define IRQ_SCCA_STAT (37)
#define IRQ_SCCA_RX (38)
#define IRQ_SCCA_SPCOND (39)
#endif
/* Level 4 (PSC, AV Macs only) interrupts */
#define IRQ_PSC4_0 (32)
#define IRQ_PSC4_1 (33)
#define IRQ_MAC_SCC_A IRQ_PSC4_1
#define IRQ_PSC4_2 (34)
#define IRQ_MAC_SCC_B IRQ_PSC4_2
#define IRQ_PSC4_3 (35)
#define IRQ_MAC_MACE_DMA IRQ_PSC4_3
......@@ -146,6 +131,9 @@
#define IRQ_BABOON_2 (66)
#define IRQ_BABOON_3 (67)
/* On non-PSC machines, the serial ports share an IRQ */
#define IRQ_MAC_SCC IRQ_AUTO_4
#define SLOT2IRQ(x) (x + 47)
#define IRQ2SLOT(x) (x - 47)
......
......@@ -71,6 +71,8 @@ struct switch_stack {
#define PTRACE_GETFPREGS 14
#define PTRACE_SETFPREGS 15
#define PTRACE_GET_THREAD_AREA 25
#define PTRACE_SINGLEBLOCK 33 /* resume execution until next branch */
#ifdef __KERNEL__
......
......@@ -15,9 +15,15 @@ struct sigcontext {
unsigned long sc_pc;
unsigned short sc_formatvec;
#ifndef __uClinux__
# ifdef __mcoldfire__
unsigned long sc_fpregs[2][2]; /* room for two fp registers */
unsigned long sc_fpcntl[3];
unsigned char sc_fpstate[16+6*8];
# else
unsigned long sc_fpregs[2*3]; /* room for two fp registers */
unsigned long sc_fpcntl[3];
unsigned char sc_fpstate[216];
# endif
#endif
};
......
#ifndef _M68K_SIGINFO_H
#define _M68K_SIGINFO_H
#ifndef __uClinux__
#define HAVE_ARCH_SIGINFO_T
#define HAVE_ARCH_COPY_SIGINFO
#endif
#include <asm-generic/siginfo.h>
#ifndef __uClinux__
typedef struct siginfo {
int si_signo;
int si_errno;
int si_code;
union {
int _pad[SI_PAD_SIZE];
/* kill() */
struct {
__kernel_pid_t _pid; /* sender's pid */
__kernel_uid_t _uid; /* backwards compatibility */
__kernel_uid32_t _uid32; /* sender's uid */
} _kill;
/* POSIX.1b timers */
struct {
timer_t _tid; /* timer id */
int _overrun; /* overrun count */
char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
sigval_t _sigval; /* same as below */
int _sys_private; /* not to be passed to user */
} _timer;
/* POSIX.1b signals */
struct {
__kernel_pid_t _pid; /* sender's pid */
__kernel_uid_t _uid; /* backwards compatibility */
sigval_t _sigval;
__kernel_uid32_t _uid32; /* sender's uid */
} _rt;
/* SIGCHLD */
struct {
__kernel_pid_t _pid; /* which child */
__kernel_uid_t _uid; /* backwards compatibility */
int _status; /* exit code */
clock_t _utime;
clock_t _stime;
__kernel_uid32_t _uid32; /* sender's uid */
} _sigchld;
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
struct {
void *_addr; /* faulting insn/memory ref. */
} _sigfault;
/* SIGPOLL */
struct {
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd;
} _sigpoll;
} _sifields;
} siginfo_t;
#define UID16_SIGINFO_COMPAT_NEEDED
/*
* How these fields are to be accessed.
*/
#undef si_uid
#ifdef __KERNEL__
#define si_uid _sifields._kill._uid32
#define si_uid16 _sifields._kill._uid
#else
#define si_uid _sifields._kill._uid
#endif
#ifdef __KERNEL__
#include <linux/string.h>
static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)
{
if (from->si_code < 0)
memcpy(to, from, sizeof(*to));
else
/* _sigchld is currently the largest know union member */
memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld));
}
#endif /* __KERNEL__ */
#endif /* !__uClinux__ */
#endif
......@@ -14,7 +14,7 @@ static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
}
#define __arch_swab32 __arch_swab32
#elif !defined(__uClinux__)
#elif !defined(__mcoldfire__)
static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
{
......
......@@ -16,6 +16,7 @@ struct thread_info {
struct exec_domain *exec_domain; /* execution domain */
int preempt_count; /* 0 => preemptable, <0 => BUG */
__u32 cpu; /* should always be 0 on m68k */
unsigned long tp_value; /* thread pointer */
struct restart_block restart_block;
};
#endif /* __ASSEMBLY__ */
......
......@@ -37,6 +37,7 @@ struct thread_info {
unsigned long flags; /* low level flags */
int cpu; /* cpu we're on */
int preempt_count; /* 0 => preemptable, <0 => BUG */
unsigned long tp_value; /* thread pointer */
struct restart_block restart_block;
};
......
......@@ -7,7 +7,11 @@ typedef greg_t gregset_t[NGREG];
typedef struct fpregset {
int f_fpcntl[3];
#ifdef __mcoldfire__
int f_fpregs[8][2];
#else
int f_fpregs[8*3];
#endif
} fpregset_t;
struct mcontext {
......
......@@ -336,10 +336,14 @@
#define __NR_pwritev 330
#define __NR_rt_tgsigqueueinfo 331
#define __NR_perf_event_open 332
#define __NR_get_thread_area 333
#define __NR_set_thread_area 334
#define __NR_atomic_cmpxchg_32 335
#define __NR_atomic_barrier 336
#ifdef __KERNEL__
#define NR_syscalls 333
#define NR_syscalls 337
#define __ARCH_WANT_IPC_PARSE_VERSION
#define __ARCH_WANT_OLD_READDIR
......
......@@ -31,12 +31,7 @@ static inline void *phys_to_virt(unsigned long address)
#define page_to_phys(page) \
__pa(PAGE_OFFSET + (((page) - pg_data_map[0].node_mem_map) << PAGE_SHIFT))
#else
#define page_to_phys(_page) ({ \
struct page *__page = _page; \
struct pglist_data *pgdat; \
pgdat = pg_data_table[page_to_nid(__page)]; \
page_to_pfn(__page) << PAGE_SHIFT; \
})
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
#endif
#else
#define page_to_phys(page) (((page) - mem_map) << PAGE_SHIFT)
......
......@@ -761,4 +761,8 @@ sys_call_table:
.long sys_pwritev /* 330 */
.long sys_rt_tgsigqueueinfo
.long sys_perf_event_open
.long sys_get_thread_area
.long sys_set_thread_area
.long sys_atomic_cmpxchg_32 /* 335 */
.long sys_atomic_barrier
......@@ -251,6 +251,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
p->thread.usp = usp;
p->thread.ksp = (unsigned long)childstack;
if (clone_flags & CLONE_SETTLS)
task_thread_info(p)->tp_value = regs->d5;
/*
* Must save the current SFC/DFC value, NOT the value when
* the parent was last descheduled - RGH 10-08-96
......
......@@ -245,6 +245,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = -EFAULT;
break;
case PTRACE_GET_THREAD_AREA:
ret = put_user(task_thread_info(child)->tp_value,
(unsigned long __user *)data);
break;
default:
ret = ptrace_request(child, request, addr, data);
break;
......
......@@ -897,10 +897,17 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up to return from userspace. */
err |= __put_user(frame->retcode, &frame->pretcode);
#ifdef __mcoldfire__
/* movel #__NR_rt_sigreturn,d0; trap #0 */
err |= __put_user(0x203c0000, (long __user *)(frame->retcode + 0));
err |= __put_user(0x00004e40 + (__NR_rt_sigreturn << 16),
(long __user *)(frame->retcode + 4));
#else
/* moveq #,d0; notb d0; trap #0 */
err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
(long __user *)(frame->retcode + 0));
err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4));
#endif
if (err)
goto give_sigsegv;
......
......@@ -28,6 +28,11 @@
#include <asm/traps.h>
#include <asm/page.h>
#include <asm/unistd.h>
#include <linux/elf.h>
#include <asm/tlb.h>
asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
unsigned long error_code);
asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
......@@ -595,3 +600,79 @@ int kernel_execve(const char *filename, char *const argv[], char *const envp[])
: "d" (__a), "d" (__b), "d" (__c));
return __res;
}
asmlinkage unsigned long sys_get_thread_area(void)
{
return current_thread_info()->tp_value;
}
asmlinkage int sys_set_thread_area(unsigned long tp)
{
current_thread_info()->tp_value = tp;
return 0;
}
/* This syscall gets its arguments in A0 (mem), D2 (oldval) and
D1 (newval). */
asmlinkage int
sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
unsigned long __user * mem)
{
/* This was borrowed from ARM's implementation. */
for (;;) {
struct mm_struct *mm = current->mm;
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
spinlock_t *ptl;
unsigned long mem_value;
down_read(&mm->mmap_sem);
pgd = pgd_offset(mm, (unsigned long)mem);
if (!pgd_present(*pgd))
goto bad_access;
pmd = pmd_offset(pgd, (unsigned long)mem);
if (!pmd_present(*pmd))
goto bad_access;
pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl);
if (!pte_present(*pte) || !pte_dirty(*pte)
|| !pte_write(*pte)) {
pte_unmap_unlock(pte, ptl);
goto bad_access;
}
mem_value = *mem;
if (mem_value == oldval)
*mem = newval;
pte_unmap_unlock(pte, ptl);
up_read(&mm->mmap_sem);
return mem_value;
bad_access:
up_read(&mm->mmap_sem);
/* This is not necessarily a bad access, we can get here if
a memory we're trying to write to should be copied-on-write.
Make the kernel do the necessary page stuff, then re-iterate.
Simulate a write access fault to do that. */
{
/* The first argument of the function corresponds to
D1, which is the first field of struct pt_regs. */
struct pt_regs *fp = (struct pt_regs *)&newval;
/* '3' is an RMW flag. */
if (do_page_fault(fp, (unsigned long)mem, 3))
/* If the do_page_fault() failed, we don't
have anything meaningful to return.
There should be a SIGSEGV pending for
the process. */
return 0xdeadbeef;
}
}
}
asmlinkage int sys_atomic_barrier(void)
{
/* no code needed for uniprocs */
return 0;
}
......@@ -3,4 +3,4 @@
#
obj-y := config.o macints.o iop.o via.o oss.o psc.o \
baboon.o macboing.o debug.o misc.o
baboon.o macboing.o misc.o
This diff is collapsed.
/*
* linux/arch/m68k/mac/debug.c
*
* Shamelessly stolen (SCC code and general framework) from:
*
* linux/arch/m68k/atari/debug.c
*
* Atari debugging and serial console stuff
*
* Assembled of parts of former atari/config.c 97-12-18 by Roman Hodek
*
* 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.
*/
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/init.h>
#include <linux/delay.h>
#define BOOTINFO_COMPAT_1_0
#include <asm/setup.h>
#include <asm/bootinfo.h>
#include <asm/macints.h>
extern unsigned long mac_videobase;
extern unsigned long mac_rowbytes;
extern void mac_serial_print(const char *);
#define DEBUG_HEADS
#undef DEBUG_SCREEN
#define DEBUG_SERIAL
/*
* These two auxiliary debug functions should go away ASAP. Only usage:
* before the console output is up (after head.S come some other crucial
* setup routines :-) it permits writing 'data' to the screen as bit patterns
* (good luck reading those). Helped to figure that the bootinfo contained
* garbage data on the amount and size of memory chunks ...
*
* The 'pos' argument now simply means 'linefeed after print' ...
*/
#ifdef DEBUG_SCREEN
static int peng, line;
#endif
#if 0
void mac_debugging_short(int pos, short num)
{
#ifdef DEBUG_SCREEN
unsigned char *pengoffset;
unsigned char *pptr;
int i;
#endif
#ifdef DEBUG_SERIAL
printk("debug: %d !\n", num);
#endif
#ifdef DEBUG_SCREEN
if (!MACH_IS_MAC) {
/* printk("debug: %d !\n", num); */
return;
}
/* calculate current offset */
pengoffset = (unsigned char *)mac_videobase +
(150+line*2) * mac_rowbytes + 80 * peng;
pptr = pengoffset;
for (i = 0; i < 8 * sizeof(short); i++) { /* # of bits */
/* value mask for bit i, reverse order */
*pptr++ = (num & (1 << (8*sizeof(short)-i-1)) ? 0xFF : 0x00);
}
peng++;
if (pos) {
line++;
peng = 0;
}
#endif
}
void mac_debugging_long(int pos, long addr)
{
#ifdef DEBUG_SCREEN
unsigned char *pengoffset;
unsigned char *pptr;
int i;
#endif
#ifdef DEBUG_SERIAL
printk("debug: #%ld !\n", addr);
#endif
#ifdef DEBUG_SCREEN
if (!MACH_IS_MAC) {
/* printk("debug: #%ld !\n", addr); */
return;
}
pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes)
+80*peng;
pptr = pengoffset;
for (i = 0; i < 8 * sizeof(long); i++) { /* # of bits */
*pptr++ = (addr & (1 << (8*sizeof(long)-i-1)) ? 0xFF : 0x00);
}
peng++;
if (pos) {
line++;
peng = 0;
}
#endif
}
#endif /* 0 */
#ifdef DEBUG_SERIAL
/*
* TODO: serial debug code
*/
struct mac_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 mac_SCC*)mac_bi_data.sccbase))
static int scc_port = -1;
static struct console mac_console_driver = {
.name = "debug",
.flags = CON_PRINTBUFFER,
.index = -1,
};
/*
* Crude hack to get console output to the screen before the framebuffer
* is initialized (happens a lot later in 2.1!).
* We just use the console routines declared in head.S, this will interfere
* with regular framebuffer console output and should be used exclusively
* to debug kernel problems manifesting before framebuffer init (aka WSOD)
*
* To keep this hack from interfering with the regular console driver, either
* deregister this driver before/on framebuffer console init, or silence this
* function after the fbcon driver is running (will lose console messages!?).
* To debug real early bugs, need to write a 'mac_register_console_hack()'
* that is called from start_kernel() before setup_arch() and just registers
* this driver if Mac.
*/
static void mac_debug_console_write(struct console *co, const char *str,
unsigned int count)
{
mac_serial_print(str);
}
/* Mac: loops_per_jiffy min. 19000 ^= .5 us; MFPDELAY was 0.6 us*/
#define uSEC 1
static inline void mac_sccb_out(char c)
{
int i;
do {
for (i = uSEC; i > 0; --i)
barrier();
} while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
for (i = uSEC; i > 0; --i)
barrier();
scc.cha_b_data = c;
}
static inline void mac_scca_out(char c)
{
int i;
do {
for (i = uSEC; i > 0; --i)
barrier();
} while (!(scc.cha_a_ctrl & 0x04)); /* wait for tx buf empty */
for (i = uSEC; i > 0; --i)
barrier();
scc.cha_a_data = c;
}
static void mac_sccb_console_write(struct console *co, const char *str,
unsigned int count)
{
while (count--) {
if (*str == '\n')
mac_sccb_out('\r');
mac_sccb_out(*str++);
}
}
static void mac_scca_console_write(struct console *co, const char *str,
unsigned int count)
{
while (count--) {
if (*str == '\n')
mac_scca_out('\r');
mac_scca_out(*str++);
}
}
/* The following two functions do a quick'n'dirty initialization of the MFP or
* SCC serial ports. They're used by the debugging interface, kgdb, and the
* serial console code. */
#define SCCB_WRITE(reg,val) \
do { \
int i; \
scc.cha_b_ctrl = (reg); \
for (i = uSEC; i > 0; --i) \
barrier(); \
scc.cha_b_ctrl = (val); \
for (i = uSEC; i > 0; --i) \
barrier(); \
} while(0)
#define SCCA_WRITE(reg,val) \
do { \
int i; \
scc.cha_a_ctrl = (reg); \
for (i = uSEC; i > 0; --i) \
barrier(); \
scc.cha_a_ctrl = (val); \
for (i = uSEC; i > 0; --i) \
barrier(); \
} while(0)
/* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a
* delay of ~ 60us. */
/* Mac: loops_per_jiffy min. 19000 ^= .5 us; MFPDELAY was 0.6 us*/
#define LONG_DELAY() \
do { \
int i; \
for (i = 60*uSEC; i > 0; --i) \
barrier(); \
} while(0)
static void __init mac_init_scc_port(int cflag, int port)
{
/*
* baud rates: 1200, 1800, 2400, 4800, 9600, 19.2k, 38.4k, 57.6k, 115.2k
*/
static int clksrc_table[9] =
/* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */
{ 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 };
static int clkmode_table[9] =
/* reg 4: 0x40 = x16, 0x80 = x32, 0xc0 = x64 */
{ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x80 };
static int div_table[9] =
/* reg12 (BRG low) */
{ 94, 62, 46, 22, 10, 4, 1, 0, 0 };
int baud = cflag & CBAUD;
int clksrc, clkmode, div, reg3, reg5;
if (cflag & CBAUDEX)
baud += B38400;
if (baud < B1200 || baud > B38400+2)
baud = B9600; /* use default 9600bps for non-implemented rates */
baud -= B1200; /* tables starts at 1200bps */
clksrc = clksrc_table[baud];
clkmode = clkmode_table[baud];
div = div_table[baud];
reg3 = (((cflag & CSIZE) == CS8) ? 0xc0 : 0x40);
reg5 = (((cflag & CSIZE) == CS8) ? 0x60 : 0x20) | 0x82 /* assert DTR/RTS */;
if (port == 1) {
(void)scc.cha_b_ctrl; /* reset reg pointer */
SCCB_WRITE(9, 0xc0); /* reset */
LONG_DELAY(); /* extra delay after WR9 access */
SCCB_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
0x04 /* 1 stopbit */ |
clkmode);
SCCB_WRITE(3, reg3);
SCCB_WRITE(5, reg5);
SCCB_WRITE(9, 0); /* no interrupts */
LONG_DELAY(); /* extra delay after WR9 access */
SCCB_WRITE(10, 0); /* NRZ mode */
SCCB_WRITE(11, clksrc); /* main clock source */
SCCB_WRITE(12, div); /* BRG value */
SCCB_WRITE(13, 0); /* BRG high byte */
SCCB_WRITE(14, 1);
SCCB_WRITE(3, reg3 | 1);
SCCB_WRITE(5, reg5 | 8);
} else if (port == 0) {
(void)scc.cha_a_ctrl; /* reset reg pointer */
SCCA_WRITE(9, 0xc0); /* reset */
LONG_DELAY(); /* extra delay after WR9 access */
SCCA_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
0x04 /* 1 stopbit */ |
clkmode);
SCCA_WRITE(3, reg3);
SCCA_WRITE(5, reg5);
SCCA_WRITE(9, 0); /* no interrupts */
LONG_DELAY(); /* extra delay after WR9 access */
SCCA_WRITE(10, 0); /* NRZ mode */
SCCA_WRITE(11, clksrc); /* main clock source */
SCCA_WRITE(12, div); /* BRG value */
SCCA_WRITE(13, 0); /* BRG high byte */
SCCA_WRITE(14, 1);
SCCA_WRITE(3, reg3 | 1);
SCCA_WRITE(5, reg5 | 8);
}
}
#endif /* DEBUG_SERIAL */
static int __init mac_debug_setup(char *arg)
{
if (!MACH_IS_MAC)
return 0;
#ifdef DEBUG_SERIAL
if (!strcmp(arg, "ser") || !strcmp(arg, "ser1")) {
/* Mac modem port */
mac_init_scc_port(B9600|CS8, 0);
mac_console_driver.write = mac_scca_console_write;
scc_port = 0;
} else if (!strcmp(arg, "ser2")) {
/* Mac printer port */
mac_init_scc_port(B9600|CS8, 1);
mac_console_driver.write = mac_sccb_console_write;
scc_port = 1;
}
#endif
#ifdef DEBUG_HEADS
if (!strcmp(arg, "scn") || !strcmp(arg, "con")) {
/* display, using head.S console routines */
mac_console_driver.write = mac_debug_console_write;
}
#endif
if (mac_console_driver.write)
register_console(&mac_console_driver);
return 0;
}
early_param("debug", mac_debug_setup);
......@@ -34,9 +34,7 @@
*
* 3 - unused (?)
*
* 4 - SCC (slot number determined by reading RR3 on the SSC itself)
* - slot 1: SCC channel A
* - slot 2: SCC channel B
* 4 - SCC
*
* 5 - unused (?)
* [serial errors or special conditions seem to raise level 6
......@@ -55,8 +53,6 @@
* - slot 5: Slot $E
*
* 4 - SCC IOP
* - slot 1: SCC channel A
* - slot 2: SCC channel B
*
* 5 - ISM IOP (ADB?)
*
......@@ -136,13 +132,8 @@
#include <asm/irq_regs.h>
#include <asm/mac_oss.h>
#define DEBUG_SPURIOUS
#define SHUTUP_SONIC
/* SCC interrupt mask */
static int scc_mask;
/*
* VIA/RBV hooks
*/
......@@ -190,13 +181,6 @@ extern void baboon_irq_enable(int);
extern void baboon_irq_disable(int);
extern void baboon_irq_clear(int);
/*
* SCC interrupt routines
*/
static void scc_irq_enable(unsigned int);
static void scc_irq_disable(unsigned int);
/*
* console_loglevel determines NMI handler function
*/
......@@ -221,8 +205,6 @@ void __init mac_init_IRQ(void)
#ifdef DEBUG_MACINTS
printk("mac_init_IRQ(): Setting things up...\n");
#endif
scc_mask = 0;
m68k_setup_irq_controller(&mac_irq_controller, IRQ_USER,
NUM_MAC_SOURCES - IRQ_USER);
/* Make sure the SONIC interrupt is cleared or things get ugly */
......@@ -283,15 +265,16 @@ void mac_enable_irq(unsigned int irq)
via_irq_enable(irq);
break;
case 3:
case 4:
case 5:
case 6:
if (psc_present)
psc_irq_enable(irq);
else if (oss_present)
oss_irq_enable(irq);
else if (irq_src == 4)
scc_irq_enable(irq);
break;
case 4:
if (psc_present)
psc_irq_enable(irq);
break;
case 8:
if (baboon_present)
......@@ -316,15 +299,16 @@ void mac_disable_irq(unsigned int irq)
via_irq_disable(irq);
break;
case 3:
case 4:
case 5:
case 6:
if (psc_present)
psc_irq_disable(irq);
else if (oss_present)
oss_irq_disable(irq);
else if (irq_src == 4)
scc_irq_disable(irq);
break;
case 4:
if (psc_present)
psc_irq_disable(irq);
break;
case 8:
if (baboon_present)
......@@ -347,7 +331,6 @@ void mac_clear_irq(unsigned int irq)
via_irq_clear(irq);
break;
case 3:
case 4:
case 5:
case 6:
if (psc_present)
......@@ -355,6 +338,10 @@ void mac_clear_irq(unsigned int irq)
else if (oss_present)
oss_irq_clear(irq);
break;
case 4:
if (psc_present)
psc_irq_clear(irq);
break;
case 8:
if (baboon_present)
baboon_irq_clear(irq);
......@@ -374,13 +361,17 @@ int mac_irq_pending(unsigned int irq)
else
return via_irq_pending(irq);
case 3:
case 4:
case 5:
case 6:
if (psc_present)
return psc_irq_pending(irq);
else if (oss_present)
return oss_irq_pending(irq);
break;
case 4:
if (psc_present)
psc_irq_pending(irq);
break;
}
return 0;
}
......@@ -448,59 +439,3 @@ irqreturn_t mac_nmi_handler(int irq, void *dev_id)
in_nmi--;
return IRQ_HANDLED;
}
/*
* Simple routines for masking and unmasking
* SCC interrupts in cases where this can't be
* done in hardware (only the PSC can do that.)
*/
static void scc_irq_enable(unsigned int irq)
{
int irq_idx = IRQ_IDX(irq);
scc_mask |= (1 << irq_idx);
}
static void scc_irq_disable(unsigned int irq)
{
int irq_idx = IRQ_IDX(irq);
scc_mask &= ~(1 << irq_idx);
}
/*
* SCC master interrupt handler. We have to do a bit of magic here
* to figure out what channel gave us the interrupt; putting this
* here is cleaner than hacking it into drivers/char/macserial.c.
*/
void mac_scc_dispatch(int irq, void *dev_id)
{
volatile unsigned char *scc = (unsigned char *) mac_bi_data.sccbase + 2;
unsigned char reg;
unsigned long flags;
/* Read RR3 from the chip. Always do this on channel A */
/* This must be an atomic operation so disable irqs. */
local_irq_save(flags);
*scc = 3;
reg = *scc;
local_irq_restore(flags);
/* Now dispatch. Bits 0-2 are for channel B and */
/* bits 3-5 are for channel A. We can safely */
/* ignore the remaining bits here. */
/* */
/* Note that we're ignoring scc_mask for now. */
/* If we actually mask the ints then we tend to */
/* get hammered by very persistent SCC irqs, */
/* and since they're autovector interrupts they */
/* pretty much kill the system. */
if (reg & 0x38)
m68k_handle_int(IRQ_SCCA);
if (reg & 0x07)
m68k_handle_int(IRQ_SCCB);
}
......@@ -33,7 +33,6 @@ static irqreturn_t oss_irq(int, void *);
static irqreturn_t oss_nubus_irq(int, void *);
extern irqreturn_t via1_irq(int, void *);
extern irqreturn_t mac_scc_dispatch(int, void *);
/*
* Initialize the OSS
......@@ -69,9 +68,6 @@ void __init oss_register_interrupts(void)
if (request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
"scsi", (void *) oss))
pr_err("Couldn't register %s interrupt\n", "scsi");
if (request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
"scc", mac_scc_dispatch))
pr_err("Couldn't register %s interrupt\n", "scc");
if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
"nubus", (void *) oss))
pr_err("Couldn't register %s interrupt\n", "nubus");
......@@ -172,9 +168,7 @@ void oss_irq_enable(int irq) {
printk("oss_irq_enable(%d)\n", irq);
#endif
switch(irq) {
case IRQ_SCC:
case IRQ_SCCA:
case IRQ_SCCB:
case IRQ_MAC_SCC:
oss->irq_level[OSS_IOPSCC] = OSS_IRQLEV_IOPSCC;
break;
case IRQ_MAC_ADB:
......@@ -212,9 +206,7 @@ void oss_irq_disable(int irq) {
printk("oss_irq_disable(%d)\n", irq);
#endif
switch(irq) {
case IRQ_SCC:
case IRQ_SCCA:
case IRQ_SCCB:
case IRQ_MAC_SCC:
oss->irq_level[OSS_IOPSCC] = OSS_IRQLEV_DISABLED;
break;
case IRQ_MAC_ADB:
......@@ -250,9 +242,7 @@ void oss_irq_disable(int irq) {
void oss_irq_clear(int irq) {
/* FIXME: how to do this on OSS? */
switch(irq) {
case IRQ_SCC:
case IRQ_SCCA:
case IRQ_SCCB:
case IRQ_MAC_SCC:
oss->irq_pending &= ~OSS_IP_IOPSCC;
break;
case IRQ_MAC_ADB:
......@@ -280,9 +270,7 @@ void oss_irq_clear(int irq) {
int oss_irq_pending(int irq)
{
switch(irq) {
case IRQ_SCC:
case IRQ_SCCA:
case IRQ_SCCB:
case IRQ_MAC_SCC:
return oss->irq_pending & OSS_IP_IOPSCC;
break;
case IRQ_MAC_ADB:
......
......@@ -84,8 +84,6 @@ void via_irq_enable(int irq);
void via_irq_disable(int irq);
void via_irq_clear(int irq);
extern irqreturn_t mac_scc_dispatch(int, void *);
/*
* Initialize the VIAs
*
......@@ -311,11 +309,6 @@ void __init via_register_interrupts(void)
if (request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
"via2", (void *) via2))
pr_err("Couldn't register %s interrupt\n", "via2");
if (!psc_present) {
if (request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
"scc", mac_scc_dispatch))
pr_err("Couldn't register %s interrupt\n", "scc");
}
if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq,
IRQ_FLG_LOCK|IRQ_FLG_FAST, "nubus", (void *) via2))
pr_err("Couldn't register %s interrupt\n", "nubus");
......
......@@ -99,8 +99,7 @@ static inline void free_io_area(void *addr)
#endif
/*
* Map some physical address range into the kernel address space. The
* code is copied and adapted from map_chunk().
* Map some physical address range into the kernel address space.
*/
/* Rewritten by Andreas Schwab to remove all races. */
......@@ -116,7 +115,7 @@ void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cachefla
/*
* Don't allow mappings that wrap..
*/
if (!size || size > physaddr + size)
if (!size || physaddr > (unsigned long)(-size))
return NULL;
#ifdef CONFIG_AMIGA
......
......@@ -221,6 +221,10 @@ int copy_thread(unsigned long clone_flags,
p->thread.usp = usp;
p->thread.ksp = (unsigned long)childstack;
if (clone_flags & CLONE_SETTLS)
task_thread_info(p)->tp_value = regs->d5;
/*
* Must save the current SFC/DFC value, NOT the value when
* the parent was last descheduled - RGH 10-08-96
......
......@@ -319,6 +319,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
#endif
case PTRACE_GET_THREAD_AREA:
ret = put_user(task_thread_info(child)->tp_value,
(unsigned long __user *)data);
break;
default:
ret = -EIO;
break;
......
......@@ -190,3 +190,39 @@ int kernel_execve(const char *filename, char *const argv[], char *const envp[])
: "d" (__a), "d" (__b), "d" (__c));
return __res;
}
asmlinkage unsigned long sys_get_thread_area(void)
{
return current_thread_info()->tp_value;
}
asmlinkage int sys_set_thread_area(unsigned long tp)
{
current_thread_info()->tp_value = tp;
return 0;
}
/* This syscall gets its arguments in A0 (mem), D2 (oldval) and
D1 (newval). */
asmlinkage int
sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
unsigned long __user * mem)
{
struct mm_struct *mm = current->mm;
unsigned long mem_value;
down_read(&mm->mmap_sem);
mem_value = *mem;
if (mem_value == oldval)
*mem = newval;
up_read(&mm->mmap_sem);
return mem_value;
}
asmlinkage int sys_atomic_barrier(void)
{
/* no code needed for uniprocs */
return 0;
}
......@@ -351,6 +351,10 @@ ENTRY(sys_call_table)
.long sys_pwritev /* 330 */
.long sys_rt_tgsigqueueinfo
.long sys_perf_event_open
.long sys_get_thread_area
.long sys_set_thread_area
.long sys_atomic_cmpxchg_32 /* 335 */
.long sys_atomic_barrier
.rept NR_syscalls-(.-sys_call_table)/4
.long sys_ni_syscall
......
......@@ -24,7 +24,6 @@
/*
* Map some physical address range into the kernel address space.
* The code is copied and adapted from map_chunk().
*/
unsigned long kernel_map(unsigned long paddr, unsigned long size,
......
......@@ -1470,8 +1470,6 @@ static void redo_fd_request(void)
void do_fd_request(struct request_queue * q)
{
unsigned long flags;
DPRINT(("do_fd_request for pid %d\n",current->pid));
while( fdc_busy ) sleep_on( &fdc_wait );
fdc_busy = 1;
......
......@@ -864,7 +864,7 @@ static int __devinit swim_probe(struct platform_device *dev)
struct swim_priv *swd;
int ret;
res = platform_get_resource_byname(dev, IORESOURCE_MEM, "swim-regs");
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!res) {
ret = -ENODEV;
goto out;
......@@ -942,7 +942,7 @@ static int __devexit swim_remove(struct platform_device *dev)
iounmap(swd->base);
res = platform_get_resource_byname(dev, IORESOURCE_MEM, "swim-regs");
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (res)
release_mem_region(res->start, resource_size(res));
......
......@@ -136,7 +136,7 @@ static const struct tty_port_operations scc_port_ops = {
* vme_scc_init() and support functions
*---------------------------------------------------------------------------*/
static int scc_init_drivers(void)
static int __init scc_init_drivers(void)
{
int error;
......@@ -172,7 +172,7 @@ static int scc_init_drivers(void)
/* ports[] array is indexed by line no (i.e. [0] for ttyS0, [1] for ttyS1).
*/
static void scc_init_portstructs(void)
static void __init scc_init_portstructs(void)
{
struct scc_port *port;
int i;
......@@ -195,7 +195,7 @@ static void scc_init_portstructs(void)
#ifdef CONFIG_MVME147_SCC
static int mvme147_scc_init(void)
static int __init mvme147_scc_init(void)
{
struct scc_port *port;
int error;
......@@ -298,7 +298,7 @@ static int mvme147_scc_init(void)
#ifdef CONFIG_MVME162_SCC
static int mvme162_scc_init(void)
static int __init mvme162_scc_init(void)
{
struct scc_port *port;
int error;
......@@ -404,7 +404,7 @@ static int mvme162_scc_init(void)
#ifdef CONFIG_BVME6000_SCC
static int bvme6000_scc_init(void)
static int __init bvme6000_scc_init(void)
{
struct scc_port *port;
int error;
......@@ -503,7 +503,7 @@ static int bvme6000_scc_init(void)
#endif
static int vme_scc_init(void)
static int __init vme_scc_init(void)
{
int res = -ENODEV;
......
......@@ -317,9 +317,11 @@ static int __init adb_init(void)
break;
}
}
if ((adb_controller == NULL) || adb_controller->init()) {
printk(KERN_WARNING "Warning: no ADB interface detected\n");
if (adb_controller != NULL && adb_controller->init &&
adb_controller->init())
adb_controller = NULL;
if (adb_controller == NULL) {
printk(KERN_WARNING "Warning: no ADB interface detected\n");
} else {
#ifdef CONFIG_PPC
if (of_machine_is_compatible("AAPL,PowerBook1998") ||
......
......@@ -89,7 +89,6 @@ static int cuda_fully_inited;
#ifdef CONFIG_ADB
static int cuda_probe(void);
static int cuda_init(void);
static int cuda_send_request(struct adb_request *req, int sync);
static int cuda_adb_autopoll(int devs);
static int cuda_reset_adb_bus(void);
......@@ -107,17 +106,42 @@ int cuda_request(struct adb_request *req,
#ifdef CONFIG_ADB
struct adb_driver via_cuda_driver = {
"CUDA",
cuda_probe,
cuda_init,
cuda_send_request,
cuda_adb_autopoll,
cuda_poll,
cuda_reset_adb_bus
.name = "CUDA",
.probe = cuda_probe,
.send_request = cuda_send_request,
.autopoll = cuda_adb_autopoll,
.poll = cuda_poll,
.reset_bus = cuda_reset_adb_bus,
};
#endif /* CONFIG_ADB */
#ifdef CONFIG_PPC
#ifdef CONFIG_MAC
int __init find_via_cuda(void)
{
struct adb_request req;
int err;
if (macintosh_config->adb_type != MAC_ADB_CUDA)
return 0;
via = via1;
cuda_state = idle;
err = cuda_init_via();
if (err) {
printk(KERN_ERR "cuda_init_via() failed\n");
via = NULL;
return 0;
}
/* enable autopoll */
cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
while (!req.complete)
cuda_poll();
return 1;
}
#else
int __init find_via_cuda(void)
{
struct adb_request req;
......@@ -175,7 +199,7 @@ int __init find_via_cuda(void)
vias = NULL;
return 0;
}
#endif /* CONFIG_PPC */
#endif /* !defined CONFIG_MAC */
static int __init via_cuda_start(void)
{
......@@ -184,14 +208,14 @@ static int __init via_cuda_start(void)
#ifdef CONFIG_MAC
cuda_irq = IRQ_MAC_ADB;
#else /* CONFIG_MAC */
#else
cuda_irq = irq_of_parse_and_map(vias, 0);
if (cuda_irq == NO_IRQ) {
printk(KERN_ERR "via-cuda: can't map interrupts for %s\n",
vias->full_name);
return -ENODEV;
}
#endif /* CONFIG_MAC */
#endif
if (request_irq(cuda_irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
printk(KERN_ERR "via-cuda: can't request irq %d\n", cuda_irq);
......@@ -216,28 +240,10 @@ cuda_probe(void)
#else
if (macintosh_config->adb_type != MAC_ADB_CUDA)
return -ENODEV;
via = via1;
#endif
return 0;
}
static int __init
cuda_init(void)
{
#ifdef CONFIG_PPC
if (via == NULL)
return -ENODEV;
return 0;
#else
int err = cuda_init_via();
if (err) {
printk(KERN_ERR "cuda_init_via() failed\n");
return -ENODEV;
}
out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */
return via_cuda_start();
#endif
}
#endif /* CONFIG_ADB */
......@@ -430,8 +436,10 @@ cuda_poll(void)
/* cuda_interrupt only takes a normal lock, we disable
* interrupts here to avoid re-entering and thus deadlocking.
*/
if (cuda_irq)
disable_irq(cuda_irq);
cuda_interrupt(0, NULL);
if (cuda_irq)
enable_irq(cuda_irq);
}
......@@ -446,7 +454,7 @@ cuda_interrupt(int irq, void *arg)
spin_lock(&cuda_lock);
/* On powermacs, this handler is registered for the VIA IRQ. But it uses
/* On powermacs, this handler is registered for the VIA IRQ. But they use
* just the shift register IRQ -- other VIA interrupt sources are disabled.
* On m68k macs, the VIA IRQ sources are dispatched individually. Unless
* we are polling, the shift register IRQ flag has already been cleared.
......
......@@ -39,7 +39,6 @@
#include "mace.h"
static char mac_mace_string[] = "macmace";
static struct platform_device *mac_mace_device;
#define N_TX_BUFF_ORDER 0
#define N_TX_RING (1 << N_TX_BUFF_ORDER)
......@@ -752,6 +751,7 @@ static irqreturn_t mace_dma_intr(int irq, void *dev_id)
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Macintosh MACE ethernet driver");
MODULE_ALIAS("platform:macmace");
static int __devexit mac_mace_device_remove (struct platform_device *pdev)
{
......@@ -778,46 +778,21 @@ static struct platform_driver mac_mace_driver = {
.remove = __devexit_p(mac_mace_device_remove),
.driver = {
.name = mac_mace_string,
.owner = THIS_MODULE,
},
};
static int __init mac_mace_init_module(void)
{
int err;
if (!MACH_IS_MAC)
return -ENODEV;
if ((err = platform_driver_register(&mac_mace_driver))) {
printk(KERN_ERR "Driver registration failed\n");
return err;
}
mac_mace_device = platform_device_alloc(mac_mace_string, 0);
if (!mac_mace_device)
goto out_unregister;
if (platform_device_add(mac_mace_device)) {
platform_device_put(mac_mace_device);
mac_mace_device = NULL;
}
return 0;
out_unregister:
platform_driver_unregister(&mac_mace_driver);
return -ENOMEM;
return platform_driver_register(&mac_mace_driver);
}
static void __exit mac_mace_cleanup_module(void)
{
platform_driver_unregister(&mac_mace_driver);
if (mac_mace_device) {
platform_device_unregister(mac_mace_device);
mac_mace_device = NULL;
}
}
module_init(mac_mace_init_module);
......
......@@ -62,7 +62,6 @@
#include <asm/mac_via.h>
static char mac_sonic_string[] = "macsonic";
static struct platform_device *mac_sonic_device;
#include "sonic.h"
......@@ -607,6 +606,7 @@ static int __devinit mac_sonic_probe(struct platform_device *pdev)
MODULE_DESCRIPTION("Macintosh SONIC ethernet driver");
module_param(sonic_debug, int, 0);
MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)");
MODULE_ALIAS("platform:macsonic");
#include "sonic.c"
......@@ -628,43 +628,18 @@ static struct platform_driver mac_sonic_driver = {
.remove = __devexit_p(mac_sonic_device_remove),
.driver = {
.name = mac_sonic_string,
.owner = THIS_MODULE,
},
};
static int __init mac_sonic_init_module(void)
{
int err;
if ((err = platform_driver_register(&mac_sonic_driver))) {
printk(KERN_ERR "Driver registration failed\n");
return err;
}
mac_sonic_device = platform_device_alloc(mac_sonic_string, 0);
if (!mac_sonic_device)
goto out_unregister;
if (platform_device_add(mac_sonic_device)) {
platform_device_put(mac_sonic_device);
mac_sonic_device = NULL;
}
return 0;
out_unregister:
platform_driver_unregister(&mac_sonic_driver);
return -ENOMEM;
return platform_driver_register(&mac_sonic_driver);
}
static void __exit mac_sonic_cleanup_module(void)
{
platform_driver_unregister(&mac_sonic_driver);
if (mac_sonic_device) {
platform_device_unregister(mac_sonic_device);
mac_sonic_device = NULL;
}
}
module_init(mac_sonic_init_module);
......
......@@ -52,7 +52,6 @@ struct mac_esp_priv {
void __iomem *pdma_io;
int error;
};
static struct platform_device *internal_pdev, *external_pdev;
static struct esp *esp_chips[2];
#define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \
......@@ -495,29 +494,12 @@ static int __devinit esp_mac_probe(struct platform_device *dev)
struct Scsi_Host *host;
struct esp *esp;
int err;
int chips_present;
struct mac_esp_priv *mep;
if (!MACH_IS_MAC)
return -ENODEV;
switch (macintosh_config->scsi_type) {
case MAC_SCSI_QUADRA:
case MAC_SCSI_QUADRA3:
chips_present = 1;
break;
case MAC_SCSI_QUADRA2:
if ((macintosh_config->ident == MAC_MODEL_Q900) ||
(macintosh_config->ident == MAC_MODEL_Q950))
chips_present = 2;
else
chips_present = 1;
break;
default:
chips_present = 0;
}
if (dev->id + 1 > chips_present)
if (dev->id > 1)
return -ENODEV;
host = scsi_host_alloc(tpnt, sizeof(struct esp));
......@@ -643,54 +625,25 @@ static struct platform_driver esp_mac_driver = {
.remove = __devexit_p(esp_mac_remove),
.driver = {
.name = DRV_MODULE_NAME,
.owner = THIS_MODULE,
},
};
static int __init mac_esp_init(void)
{
int err;
err = platform_driver_register(&esp_mac_driver);
if (err)
return err;
internal_pdev = platform_device_alloc(DRV_MODULE_NAME, 0);
if (internal_pdev && platform_device_add(internal_pdev)) {
platform_device_put(internal_pdev);
internal_pdev = NULL;
}
external_pdev = platform_device_alloc(DRV_MODULE_NAME, 1);
if (external_pdev && platform_device_add(external_pdev)) {
platform_device_put(external_pdev);
external_pdev = NULL;
}
if (internal_pdev || external_pdev) {
return 0;
} else {
platform_driver_unregister(&esp_mac_driver);
return -ENOMEM;
}
return platform_driver_register(&esp_mac_driver);
}
static void __exit mac_esp_exit(void)
{
platform_driver_unregister(&esp_mac_driver);
if (internal_pdev) {
platform_device_unregister(internal_pdev);
internal_pdev = NULL;
}
if (external_pdev) {
platform_device_unregister(external_pdev);
external_pdev = NULL;
}
}
MODULE_DESCRIPTION("Mac ESP SCSI driver");
MODULE_AUTHOR("Finn Thain <fthain@telegraphics.com.au>");
MODULE_LICENSE("GPL v2");
MODULE_VERSION(DRV_VERSION);
MODULE_ALIAS("platform:" DRV_MODULE_NAME);
module_init(mac_esp_init);
module_exit(mac_esp_exit);
......@@ -1086,12 +1086,12 @@ config SERIAL_68360
default y
config SERIAL_PMACZILOG
tristate "PowerMac z85c30 ESCC support"
depends on PPC_OF && PPC_PMAC
tristate "Mac or PowerMac z85c30 ESCC support"
depends on (M68K && MAC) || (PPC_OF && PPC_PMAC)
select SERIAL_CORE
help
This driver supports the Zilog z85C30 serial ports found on
PowerMac machines.
(Power)Mac machines.
Say Y or M if you want to be able to these serial ports.
config SERIAL_PMACZILOG_TTYS
......@@ -1116,16 +1116,16 @@ config SERIAL_PMACZILOG_TTYS
unable to use the 8250 module for PCMCIA or other 16C550-style
UARTs.
Say N unless you need the z85c30 ports on your powermac
Say N unless you need the z85c30 ports on your (Power)Mac
to appear as /dev/ttySn.
config SERIAL_PMACZILOG_CONSOLE
bool "Console on PowerMac z85c30 serial port"
bool "Console on Mac or PowerMac z85c30 serial port"
depends on SERIAL_PMACZILOG=y
select SERIAL_CORE_CONSOLE
help
If you would like to be able to use the z85c30 serial port
on your PowerMac as the console, you can do so by answering
on your (Power)Mac as the console, you can do so by answering
Y to this option.
config SERIAL_LH7A40X
......
......@@ -63,11 +63,17 @@
#include <asm/sections.h>
#include <asm/io.h>
#include <asm/irq.h>
#ifdef CONFIG_PPC_PMAC
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/pmac_feature.h>
#include <asm/dbdma.h>
#include <asm/macio.h>
#else
#include <linux/platform_device.h>
#define of_machine_is_compatible(x) (0)
#endif
#if defined (CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
......@@ -83,11 +89,9 @@
static char version[] __initdata = "pmac_zilog: 0.6 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
MODULE_DESCRIPTION("Driver for the PowerMac serial ports.");
MODULE_DESCRIPTION("Driver for the Mac and PowerMac serial ports.");
MODULE_LICENSE("GPL");
#define PWRDBG(fmt, arg...) printk(KERN_DEBUG fmt , ## arg)
#ifdef CONFIG_SERIAL_PMACZILOG_TTYS
#define PMACZILOG_MAJOR TTY_MAJOR
#define PMACZILOG_MINOR 64
......@@ -341,7 +345,7 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap)
uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
write_zsreg(uap, R1, uap->curregs[R1]);
zssync(uap);
dev_err(&uap->dev->ofdev.dev, "pmz: rx irq flood !\n");
pmz_error("pmz: rx irq flood !\n");
return tty;
}
......@@ -757,6 +761,8 @@ static void pmz_break_ctl(struct uart_port *port, int break_state)
spin_unlock_irqrestore(&port->lock, flags);
}
#ifdef CONFIG_PPC_PMAC
/*
* Turn power on or off to the SCC and associated stuff
* (port drivers, modem, IR port, etc.)
......@@ -792,6 +798,15 @@ static int pmz_set_scc_power(struct uart_pmac_port *uap, int state)
return delay;
}
#else
static int pmz_set_scc_power(struct uart_pmac_port *uap, int state)
{
return 0;
}
#endif /* !CONFIG_PPC_PMAC */
/*
* FixZeroBug....Works around a bug in the SCC receving channel.
* Inspired from Darwin code, 15 Sept. 2000 -DanM
......@@ -908,7 +923,6 @@ static int __pmz_startup(struct uart_pmac_port *uap)
/* Remember status for DCD/CTS changes */
uap->prev_status = read_zsreg(uap, R0);
return pwr_delay;
}
......@@ -955,9 +969,9 @@ static int pmz_startup(struct uart_port *port)
}
pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON;
if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED, "PowerMac Zilog", uap)) {
dev_err(&uap->dev->ofdev.dev,
"Unable to register zs interrupt handler.\n");
if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED,
"SCC", uap)) {
pmz_error("Unable to register zs interrupt handler.\n");
pmz_set_scc_power(uap, 0);
mutex_unlock(&pmz_irq_mutex);
return -ENXIO;
......@@ -1051,7 +1065,6 @@ static void pmz_convert_to_zs(struct uart_pmac_port *uap, unsigned int cflag,
{
int brg;
/* Switch to external clocking for IrDA high clock rates. That
* code could be re-used for Midi interfaces with different
* multipliers
......@@ -1198,7 +1211,7 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud)
while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0
|| (read_zsreg(uap, R1) & ALL_SNT) == 0) {
if (--t <= 0) {
dev_err(&uap->dev->ofdev.dev, "transmitter didn't drain\n");
pmz_error("transmitter didn't drain\n");
return;
}
udelay(10);
......@@ -1214,7 +1227,7 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud)
read_zsdata(uap);
mdelay(10);
if (--t <= 0) {
dev_err(&uap->dev->ofdev.dev, "receiver didn't drain\n");
pmz_error("receiver didn't drain\n");
return;
}
}
......@@ -1235,8 +1248,7 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud)
t = 5000;
while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) {
if (--t <= 0) {
dev_err(&uap->dev->ofdev.dev,
"irda_setup timed out on get_version byte\n");
pmz_error("irda_setup timed out on get_version byte\n");
goto out;
}
udelay(10);
......@@ -1244,8 +1256,7 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud)
version = read_zsdata(uap);
if (version < 4) {
dev_info(&uap->dev->ofdev.dev, "IrDA: dongle version %d not supported\n",
version);
pmz_info("IrDA: dongle version %d not supported\n", version);
goto out;
}
......@@ -1254,18 +1265,16 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud)
t = 5000;
while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) {
if (--t <= 0) {
dev_err(&uap->dev->ofdev.dev,
"irda_setup timed out on speed mode byte\n");
pmz_error("irda_setup timed out on speed mode byte\n");
goto out;
}
udelay(10);
}
t = read_zsdata(uap);
if (t != cmdbyte)
dev_err(&uap->dev->ofdev.dev,
"irda_setup speed mode byte = %x (%x)\n", t, cmdbyte);
pmz_error("irda_setup speed mode byte = %x (%x)\n", t, cmdbyte);
dev_info(&uap->dev->ofdev.dev, "IrDA setup for %ld bps, dongle version: %d\n",
pmz_info("IrDA setup for %ld bps, dongle version: %d\n",
*baud, version);
(void)read_zsdata(uap);
......@@ -1415,7 +1424,7 @@ static void pmz_poll_put_char(struct uart_port *port, unsigned char c)
write_zsdata(uap, c);
}
#endif
#endif /* CONFIG_CONSOLE_POLL */
static struct uart_ops pmz_pops = {
.tx_empty = pmz_tx_empty,
......@@ -1440,6 +1449,8 @@ static struct uart_ops pmz_pops = {
#endif
};
#ifdef CONFIG_PPC_PMAC
/*
* Setup one port structure after probing, HW is down at this point,
* Unlike sunzilog, we don't need to pre-init the spinlock as we don't
......@@ -1590,7 +1601,7 @@ static void pmz_dispose_port(struct uart_pmac_port *uap)
}
/*
* Called upon match with an escc node in the devive-tree.
* Called upon match with an escc node in the device-tree.
*/
static int pmz_attach(struct macio_dev *mdev, const struct of_device_id *match)
{
......@@ -1836,6 +1847,88 @@ static int __init pmz_probe(void)
return 0;
}
#else
extern struct platform_device scc_a_pdev, scc_b_pdev;
static int __init pmz_init_port(struct uart_pmac_port *uap)
{
struct resource *r_ports;
int irq;
r_ports = platform_get_resource(uap->node, IORESOURCE_MEM, 0);
irq = platform_get_irq(uap->node, 0);
if (!r_ports || !irq)
return -ENODEV;
uap->port.mapbase = r_ports->start;
uap->port.membase = (unsigned char __iomem *) r_ports->start;
uap->port.iotype = UPIO_MEM;
uap->port.irq = irq;
uap->port.uartclk = ZS_CLOCK;
uap->port.fifosize = 1;
uap->port.ops = &pmz_pops;
uap->port.type = PORT_PMAC_ZILOG;
uap->port.flags = 0;
uap->control_reg = uap->port.membase;
uap->data_reg = uap->control_reg + 4;
uap->port_type = 0;
pmz_convert_to_zs(uap, CS8, 0, 9600);
return 0;
}
static int __init pmz_probe(void)
{
int err;
pmz_ports_count = 0;
pmz_ports[0].mate = &pmz_ports[1];
pmz_ports[0].port.line = 0;
pmz_ports[0].flags = PMACZILOG_FLAG_IS_CHANNEL_A;
pmz_ports[0].node = &scc_a_pdev;
err = pmz_init_port(&pmz_ports[0]);
if (err)
return err;
pmz_ports_count++;
pmz_ports[1].mate = &pmz_ports[0];
pmz_ports[1].port.line = 1;
pmz_ports[1].flags = 0;
pmz_ports[1].node = &scc_b_pdev;
err = pmz_init_port(&pmz_ports[1]);
if (err)
return err;
pmz_ports_count++;
return 0;
}
static void pmz_dispose_port(struct uart_pmac_port *uap)
{
memset(uap, 0, sizeof(struct uart_pmac_port));
}
static int __init pmz_attach(struct platform_device *pdev)
{
int i;
for (i = 0; i < pmz_ports_count; i++)
if (pmz_ports[i].node == pdev)
return 0;
return -ENODEV;
}
static int __exit pmz_detach(struct platform_device *pdev)
{
return 0;
}
#endif /* !CONFIG_PPC_PMAC */
#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
static void pmz_console_write(struct console *con, const char *s, unsigned int count);
......@@ -1896,6 +1989,8 @@ static int __init pmz_register(void)
return rc;
}
#ifdef CONFIG_PPC_PMAC
static struct of_device_id pmz_match[] =
{
{
......@@ -1908,8 +2003,7 @@ static struct of_device_id pmz_match[] =
};
MODULE_DEVICE_TABLE (of, pmz_match);
static struct macio_driver pmz_driver =
{
static struct macio_driver pmz_driver = {
.name = "pmac_zilog",
.match_table = pmz_match,
.probe = pmz_attach,
......@@ -1918,6 +2012,18 @@ static struct macio_driver pmz_driver =
.resume = pmz_resume,
};
#else
static struct platform_driver pmz_driver = {
.remove = __exit_p(pmz_detach),
.driver = {
.name = "scc",
.owner = THIS_MODULE,
},
};
#endif /* !CONFIG_PPC_PMAC */
static int __init init_pmz(void)
{
int rc, i;
......@@ -1956,15 +2062,23 @@ static int __init init_pmz(void)
/*
* Then we register the macio driver itself
*/
#ifdef CONFIG_PPC_PMAC
return macio_register_driver(&pmz_driver);
#else
return platform_driver_probe(&pmz_driver, pmz_attach);
#endif
}
static void __exit exit_pmz(void)
{
int i;
#ifdef CONFIG_PPC_PMAC
/* Get rid of macio-driver (detach from macio) */
macio_unregister_driver(&pmz_driver);
#else
platform_driver_unregister(&pmz_driver);
#endif
for (i = 0; i < pmz_ports_count; i++) {
struct uart_pmac_port *uport = &pmz_ports[i];
......
#ifndef __PMAC_ZILOG_H__
#define __PMAC_ZILOG_H__
#define pmz_debug(fmt,arg...) dev_dbg(&uap->dev->ofdev.dev, fmt, ## arg)
#ifdef CONFIG_PPC_PMAC
#define pmz_debug(fmt, arg...) dev_dbg(&uap->dev->ofdev.dev, fmt, ## arg)
#define pmz_error(fmt, arg...) dev_err(&uap->dev->ofdev.dev, fmt, ## arg)
#define pmz_info(fmt, arg...) dev_info(&uap->dev->ofdev.dev, fmt, ## arg)
#else
#define pmz_debug(fmt, arg...) dev_dbg(&uap->node->dev, fmt, ## arg)
#define pmz_error(fmt, arg...) dev_err(&uap->node->dev, fmt, ## arg)
#define pmz_info(fmt, arg...) dev_info(&uap->node->dev, fmt, ## arg)
#endif
/*
* At most 2 ESCCs with 2 ports each
......@@ -17,6 +25,7 @@ struct uart_pmac_port {
struct uart_port port;
struct uart_pmac_port *mate;
#ifdef CONFIG_PPC_PMAC
/* macio_dev for the escc holding this port (maybe be null on
* early inited port)
*/
......@@ -25,6 +34,9 @@ struct uart_pmac_port {
* of "escc" node (ie. ch-a or ch-b)
*/
struct device_node *node;
#else
struct platform_device *node;
#endif
/* Port type as obtained from device tree (IRDA, modem, ...) */
int port_type;
......@@ -55,10 +67,12 @@ struct uart_pmac_port {
volatile u8 __iomem *control_reg;
volatile u8 __iomem *data_reg;
#ifdef CONFIG_PPC_PMAC
unsigned int tx_dma_irq;
unsigned int rx_dma_irq;
volatile struct dbdma_regs __iomem *tx_dma_regs;
volatile struct dbdma_regs __iomem *rx_dma_regs;
#endif
struct ktermios termios_cache;
};
......
This diff is collapsed.
......@@ -33,6 +33,10 @@
static const struct fb_videomode mac_modedb[] = {
{
/* 512x384, 60Hz, Non-Interlaced (15.67 MHz dot clock) */
"mac2", 60, 512, 384, 63828, 80, 16, 19, 1, 32, 3,
0, FB_VMODE_NONINTERLACED
}, {
/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
"mac5", 60, 640, 480, 39722, 32, 32, 33, 10, 96, 2,
0, FB_VMODE_NONINTERLACED
......@@ -40,6 +44,10 @@ static const struct fb_videomode mac_modedb[] = {
/* 640x480, 67Hz, Non-Interlaced (30.0 MHz dotclock) */
"mac6", 67, 640, 480, 33334, 80, 80, 39, 3, 64, 3,
0, FB_VMODE_NONINTERLACED
}, {
/* 640x870, 75Hz (portrait), Non-Interlaced (57.28 MHz dot clock) */
"mac7", 75, 640, 870, 17457, 80, 32, 42, 3, 80, 3,
0, FB_VMODE_NONINTERLACED
}, {
/* 800x600, 56 Hz, Non-Interlaced (36.00 MHz dotclock) */
"mac9", 56, 800, 600, 27778, 112, 40, 22, 1, 72, 2,
......@@ -104,10 +112,6 @@ static const struct fb_videomode mac_modedb[] = {
/* VMODE_512_384_60I: 512x384, 60Hz, Interlaced (NTSC) */
"mac1", 60, 512, 384, pixclock, left, right, upper, lower, hslen, vslen,
sync, FB_VMODE_INTERLACED
}, {
/* VMODE_512_384_60: 512x384, 60Hz, Non-Interlaced */
"mac2", 60, 512, 384, pixclock, left, right, upper, lower, hslen, vslen,
sync, FB_VMODE_NONINTERLACED
}, {
/* VMODE_640_480_50I: 640x480, 50Hz, Interlaced (PAL) */
"mac3", 50, 640, 480, pixclock, left, right, upper, lower, hslen, vslen,
......@@ -116,10 +120,6 @@ static const struct fb_videomode mac_modedb[] = {
/* VMODE_640_480_60I: 640x480, 60Hz, Interlaced (NTSC) */
"mac4", 60, 640, 480, pixclock, left, right, upper, lower, hslen, vslen,
sync, FB_VMODE_INTERLACED
}, {
/* VMODE_640_870_75P: 640x870, 75Hz (portrait), Non-Interlaced */
"mac7", 75, 640, 870, pixclock, left, right, upper, lower, hslen, vslen,
sync, FB_VMODE_NONINTERLACED
}, {
/* VMODE_768_576_50I: 768x576, 50Hz (PAL full frame), Interlaced */
"mac8", 50, 768, 576, pixclock, left, right, upper, lower, hslen, vslen,
......@@ -134,38 +134,42 @@ static const struct fb_videomode mac_modedb[] = {
*
* These MUST be ordered in
* - increasing resolution
* - decreasing refresh rate
* - decreasing pixel clock period
*/
static const struct mode_map {
int vmode;
const struct fb_videomode *mode;
} mac_modes[] = {
/* 512x384 */
{ VMODE_512_384_60, &mac_modedb[0] },
/* 640x480 */
{ VMODE_640_480_67, &mac_modedb[1] },
{ VMODE_640_480_60, &mac_modedb[0] },
{ VMODE_640_480_60, &mac_modedb[1] },
{ VMODE_640_480_67, &mac_modedb[2] },
/* 640x870 */
{ VMODE_640_870_75P, &mac_modedb[3] },
/* 800x600 */
{ VMODE_800_600_75, &mac_modedb[5] },
{ VMODE_800_600_72, &mac_modedb[4] },
{ VMODE_800_600_60, &mac_modedb[3] },
{ VMODE_800_600_56, &mac_modedb[2] },
{ VMODE_800_600_56, &mac_modedb[4] },
{ VMODE_800_600_60, &mac_modedb[5] },
{ VMODE_800_600_75, &mac_modedb[7] },
{ VMODE_800_600_72, &mac_modedb[6] },
/* 832x624 */
{ VMODE_832_624_75, &mac_modedb[6] },
{ VMODE_832_624_75, &mac_modedb[8] },
/* 1024x768 */
{ VMODE_1024_768_75, &mac_modedb[10] },
{ VMODE_1024_768_75V, &mac_modedb[9] },
{ VMODE_1024_768_70, &mac_modedb[8] },
{ VMODE_1024_768_60, &mac_modedb[7] },
{ VMODE_1024_768_60, &mac_modedb[9] },
{ VMODE_1024_768_70, &mac_modedb[10] },
{ VMODE_1024_768_75V, &mac_modedb[11] },
{ VMODE_1024_768_75, &mac_modedb[12] },
/* 1152x768 */
{ VMODE_1152_768_60, &mac_modedb[14] },
{ VMODE_1152_768_60, &mac_modedb[16] },
/* 1152x870 */
{ VMODE_1152_870_75, &mac_modedb[11] },
{ VMODE_1152_870_75, &mac_modedb[13] },
/* 1280x960 */
{ VMODE_1280_960_75, &mac_modedb[12] },
{ VMODE_1280_960_75, &mac_modedb[14] },
/* 1280x1024 */
{ VMODE_1280_1024_75, &mac_modedb[13] },
{ VMODE_1280_1024_75, &mac_modedb[15] },
/* 1600x1024 */
{ VMODE_1600_1024_60, &mac_modedb[15] },
{ VMODE_1600_1024_60, &mac_modedb[17] },
{ -1, NULL }
};
......@@ -299,7 +303,6 @@ EXPORT_SYMBOL(mac_vmode_to_var);
int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
int *cmode)
{
const struct fb_videomode *mode = NULL;
const struct mode_map *map;
if (var->bits_per_pixel <= 8)
......@@ -311,8 +314,13 @@ int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
else
return -EINVAL;
/*
* Find the mac_mode with a matching resolution or failing that, the
* closest larger resolution. Skip modes with a shorter pixel clock period.
*/
for (map = mac_modes; map->vmode != -1; map++) {
mode = map->mode;
const struct fb_videomode *mode = map->mode;
if (var->xres > mode->xres || var->yres > mode->yres)
continue;
if (var->xres_virtual > mode->xres || var->yres_virtual > mode->yres)
......@@ -322,6 +330,24 @@ int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
if ((var->vmode & FB_VMODE_MASK) != mode->vmode)
continue;
*vmode = map->vmode;
/*
* Having found a good resolution, find the matching pixel clock
* or failing that, the closest longer pixel clock period.
*/
map++;
while (map->vmode != -1) {
const struct fb_videomode *clk_mode = map->mode;
if (mode->xres != clk_mode->xres || mode->yres != clk_mode->yres)
break;
if (var->pixclock > mode->pixclock)
break;
if (mode->vmode != clk_mode->vmode)
continue;
*vmode = map->vmode;
map++;
}
return 0;
}
return -EINVAL;
......
......@@ -69,7 +69,7 @@
#ifdef CONFIG_MAC
/* We don't yet have functions to read the PRAM... perhaps we can
adapt them from the PPC code? */
static int default_vmode = VMODE_640_480_67;
static int default_vmode = VMODE_CHOOSE;
static int default_cmode = CMODE_8;
#else
static int default_vmode = VMODE_NVRAM;
......@@ -326,11 +326,11 @@ int __init valkyriefb_init(void)
#ifdef CONFIG_MAC
if (!MACH_IS_MAC)
return 0;
return -ENODEV;
if (!(mac_bi_data.id == MAC_MODEL_Q630
/* I'm not sure about this one */
|| mac_bi_data.id == MAC_MODEL_P588))
return 0;
return -ENODEV;
/* Hardcoded addresses... welcome to 68k Macintosh country :-) */
frame_buffer_phys = 0xf9000000;
......
......@@ -134,15 +134,7 @@ static struct valkyrie_regvals valkyrie_reg_init_14 = {
{ 1024, 0 },
1024, 768
};
/* Register values for 800x600, 72Hz mode (11) */
static struct valkyrie_regvals valkyrie_reg_init_11 = {
13,
{ 17, 27, 3 }, /* pixel clock = 49.63MHz for V=71.66Hz */
{ 800, 0 },
800, 600
};
#endif /* CONFIG_MAC */
#endif /* !defined CONFIG_MAC */
/* Register values for 832x624, 75Hz mode (13) */
static struct valkyrie_regvals valkyrie_reg_init_13 = {
......@@ -152,6 +144,14 @@ static struct valkyrie_regvals valkyrie_reg_init_13 = {
832, 624
};
/* Register values for 800x600, 72Hz mode (11) */
static struct valkyrie_regvals valkyrie_reg_init_11 = {
13,
{ 17, 27, 3 }, /* pixel clock = 49.63MHz for V=71.66Hz */
{ 800, 0 },
800, 600
};
/* Register values for 800x600, 60Hz mode (10) */
static struct valkyrie_regvals valkyrie_reg_init_10 = {
12,
......@@ -188,24 +188,13 @@ static struct valkyrie_regvals *valkyrie_reg_init[VMODE_MAX] = {
NULL,
NULL,
&valkyrie_reg_init_10,
#ifdef CONFIG_MAC
NULL,
NULL,
&valkyrie_reg_init_13,
NULL,
NULL,
NULL,
NULL,
#else
&valkyrie_reg_init_11,
NULL,
&valkyrie_reg_init_13,
#ifndef CONFIG_MAC
&valkyrie_reg_init_14,
&valkyrie_reg_init_15,
NULL,
&valkyrie_reg_init_17,
#endif
NULL,
NULL,
NULL
};
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