aboutsummaryrefslogtreecommitdiff
path: root/arch/m68k/atari
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/atari')
-rw-r--r--arch/m68k/atari/Makefile6
-rw-r--r--arch/m68k/atari/ataints.c673
-rw-r--r--arch/m68k/atari/atakeyb.c638
-rw-r--r--arch/m68k/atari/atari_ksyms.c35
-rw-r--r--arch/m68k/atari/atasound.c3
-rw-r--r--arch/m68k/atari/atasound.h33
-rw-r--r--arch/m68k/atari/config.c1264
-rw-r--r--arch/m68k/atari/debug.c498
-rw-r--r--arch/m68k/atari/hades-pci.c444
-rw-r--r--arch/m68k/atari/stdma.c21
-rw-r--r--arch/m68k/atari/stram.c1242
-rw-r--r--arch/m68k/atari/time.c67
12 files changed, 1955 insertions, 2969 deletions
diff --git a/arch/m68k/atari/Makefile b/arch/m68k/atari/Makefile
index 8cb6236b39d..0cac723306f 100644
--- a/arch/m68k/atari/Makefile
+++ b/arch/m68k/atari/Makefile
@@ -3,8 +3,6 @@
#
obj-y := config.o time.o debug.o ataints.o stdma.o \
- atasound.o stram.o atari_ksyms.o
+ atasound.o stram.o
-ifeq ($(CONFIG_PCI),y)
-obj-$(CONFIG_HADES) += hades-pci.o
-endif
+obj-$(CONFIG_ATARI_KBD_CORE) += atakeyb.o
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index 076f4791784..3d2b63bedf0 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -40,8 +40,9 @@
#include <linux/kernel_stat.h>
#include <linux/init.h>
#include <linux/seq_file.h>
+#include <linux/module.h>
+#include <linux/irq.h>
-#include <asm/system.h>
#include <asm/traps.h>
#include <asm/atarihw.h>
@@ -49,6 +50,7 @@
#include <asm/atari_stdma.h>
#include <asm/irq.h>
#include <asm/entry.h>
+#include <asm/io.h>
/*
@@ -59,266 +61,197 @@
* <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP,
* TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can
* be allocated by atari_register_vme_int().
- *
- * Each interrupt can be of three types:
- *
- * - SLOW: The handler runs with all interrupts enabled, except the one it
- * was called by (to avoid reentering). This should be the usual method.
- * But it is currently possible only for MFP ints, since only the MFP
- * offers an easy way to mask interrupts.
- *
- * - FAST: The handler runs with all interrupts disabled. This should be used
- * only for really fast handlers, that just do actions immediately
- * necessary, and let the rest do a bottom half or task queue.
- *
- * - PRIORITIZED: The handler can be interrupted by higher-level ints
- * (greater IPL, no MFP priorities!). This is the method of choice for ints
- * which should be slow, but are not from a MFP.
- *
- * The feature of more than one handler for one int source is still there, but
- * only applicable if all handers are of the same type. To not slow down
- * processing of ints with only one handler by the chaining feature, the list
- * calling function atari_call_irq_list() is only plugged in at the time the
- * second handler is registered.
- *
- * Implementation notes: For fast-as-possible int handling, there are separate
- * entry points for each type (slow/fast/prio). The assembler handler calls
- * the irq directly in the usual case, no C wrapper is involved. In case of
- * multiple handlers, atari_call_irq_list() is registered as handler and calls
- * in turn the real irq's. To ease access from assembler level to the irq
- * function pointer and accompanying data, these two are stored in a separate
- * array, irq_handler[]. The rest of data (type, name) are put into a second
- * array, irq_param, that is accessed from C only. For each slow interrupt (32
- * in all) there are separate handler functions, which makes it possible to
- * hard-code the MFP register address and value, are necessary to mask the
- * int. If there'd be only one generic function, lots of calculations would be
- * needed to determine MFP register and int mask from the vector number :-(
- *
- * Furthermore, slow ints may not lower the IPL below its previous value
- * (before the int happened). This is needed so that an int of class PRIO, on
- * that this int may be stacked, cannot be reentered. This feature is
- * implemented as follows: If the stack frame format is 1 (throwaway), the int
- * is not stacked, and the IPL is anded with 0xfbff, resulting in a new level
- * 2, which still blocks the HSYNC, but no interrupts of interest. If the
- * frame format is 0, the int is nested, and the old IPL value can be found in
- * the sr copy in the frame.
*/
+/*
+ * Bitmap for free interrupt vector numbers
+ * (new vectors starting from 0x70 can be allocated by
+ * atari_register_vme_int())
+ */
+static int free_vme_vec_bitmap;
-#define NUM_INT_SOURCES (8 + NUM_ATARI_SOURCES)
+/* GK:
+ * HBL IRQ handler for Falcon. Nobody needs it :-)
+ * ++andreas: raise ipl to disable further HBLANK interrupts.
+ */
+asmlinkage void falcon_hblhandler(void);
+asm(".text\n"
+__ALIGN_STR "\n\t"
+"falcon_hblhandler:\n\t"
+ "orw #0x200,%sp@\n\t" /* set saved ipl to 2 */
+ "rte");
-typedef void (*asm_irq_handler)(void);
+extern void atari_microwire_cmd(int cmd);
-struct irqhandler {
- irqreturn_t (*handler)(int, void *, struct pt_regs *);
- void *dev_id;
-};
+static unsigned int atari_irq_startup(struct irq_data *data)
+{
+ unsigned int irq = data->irq;
+
+ m68k_irq_startup(data);
+ atari_turnon_irq(irq);
+ atari_enable_irq(irq);
+ return 0;
+}
+
+static void atari_irq_shutdown(struct irq_data *data)
+{
+ unsigned int irq = data->irq;
+
+ atari_disable_irq(irq);
+ atari_turnoff_irq(irq);
+ m68k_irq_shutdown(data);
+
+ if (irq == IRQ_AUTO_4)
+ vectors[VEC_INT4] = falcon_hblhandler;
+}
+
+static void atari_irq_enable(struct irq_data *data)
+{
+ atari_enable_irq(data->irq);
+}
-struct irqparam {
- unsigned long flags;
- const char *devname;
+static void atari_irq_disable(struct irq_data *data)
+{
+ atari_disable_irq(data->irq);
+}
+
+static struct irq_chip atari_irq_chip = {
+ .name = "atari",
+ .irq_startup = atari_irq_startup,
+ .irq_shutdown = atari_irq_shutdown,
+ .irq_enable = atari_irq_enable,
+ .irq_disable = atari_irq_disable,
};
/*
- * Array with irq's and their parameter data. This array is accessed from low
- * level assembler code, so an element size of 8 allows usage of index scaling
- * addressing mode.
+ * ST-MFP timer D chained interrupts - each driver gets its own timer
+ * interrupt instance.
*/
-static struct irqhandler irq_handler[NUM_INT_SOURCES];
-/*
- * This array hold the rest of parameters of int handlers: type
- * (slow,fast,prio) and the name of the handler. These values are only
- * accessed from C
- */
-static struct irqparam irq_param[NUM_INT_SOURCES];
+struct mfptimerbase {
+ volatile struct MFP *mfp;
+ unsigned char mfp_mask, mfp_data;
+ unsigned short int_mask;
+ int handler_irq, mfptimer_irq, server_irq;
+ char *name;
+} stmfp_base = {
+ .mfp = &st_mfp,
+ .int_mask = 0x0,
+ .handler_irq = IRQ_MFP_TIMD,
+ .mfptimer_irq = IRQ_MFP_TIMER1,
+ .name = "MFP Timer D"
+};
-/*
- * Bitmap for free interrupt vector numbers
- * (new vectors starting from 0x70 can be allocated by
- * atari_register_vme_int())
- */
-static int free_vme_vec_bitmap;
+static irqreturn_t mfptimer_handler(int irq, void *dev_id)
+{
+ struct mfptimerbase *base = dev_id;
+ int mach_irq;
+ unsigned char ints;
+
+ mach_irq = base->mfptimer_irq;
+ ints = base->int_mask;
+ for (; ints; mach_irq++, ints >>= 1) {
+ if (ints & 1)
+ generic_handle_irq(mach_irq);
+ }
+ return IRQ_HANDLED;
+}
-/* check for valid int number (complex, sigh...) */
-#define IS_VALID_INTNO(n) \
- ((n) > 0 && \
- /* autovec and ST-MFP ok anyway */ \
- (((n) < TTMFP_SOURCE_BASE) || \
- /* TT-MFP ok if present */ \
- ((n) >= TTMFP_SOURCE_BASE && (n) < SCC_SOURCE_BASE && \
- ATARIHW_PRESENT(TT_MFP)) || \
- /* SCC ok if present and number even */ \
- ((n) >= SCC_SOURCE_BASE && (n) < VME_SOURCE_BASE && \
- !((n) & 1) && ATARIHW_PRESENT(SCC)) || \
- /* greater numbers ok if they are registered VME vectors */ \
- ((n) >= VME_SOURCE_BASE && (n) < VME_SOURCE_BASE + VME_MAX_SOURCES && \
- free_vme_vec_bitmap & (1 << ((n) - VME_SOURCE_BASE)))))
+
+static void atari_mfptimer_enable(struct irq_data *data)
+{
+ int mfp_num = data->irq - IRQ_MFP_TIMER1;
+ stmfp_base.int_mask |= 1 << mfp_num;
+ atari_enable_irq(IRQ_MFP_TIMD);
+}
+
+static void atari_mfptimer_disable(struct irq_data *data)
+{
+ int mfp_num = data->irq - IRQ_MFP_TIMER1;
+ stmfp_base.int_mask &= ~(1 << mfp_num);
+ if (!stmfp_base.int_mask)
+ atari_disable_irq(IRQ_MFP_TIMD);
+}
+
+static struct irq_chip atari_mfptimer_chip = {
+ .name = "timer_d",
+ .irq_enable = atari_mfptimer_enable,
+ .irq_disable = atari_mfptimer_disable,
+};
/*
- * Here start the assembler entry points for interrupts
+ * EtherNAT CPLD interrupt handling
+ * CPLD interrupt register is at phys. 0x80000023
+ * Need this mapped in at interrupt startup time
+ * Possibly need this mapped on demand anyway -
+ * EtherNAT USB driver needs to disable IRQ before
+ * startup!
*/
-#define IRQ_NAME(nr) atari_slow_irq_##nr##_handler(void)
-
-#define BUILD_SLOW_IRQ(n) \
-asmlinkage void IRQ_NAME(n); \
-/* Dummy function to allow asm with operands. */ \
-void atari_slow_irq_##n##_dummy (void) { \
-__asm__ (__ALIGN_STR "\n" \
-"atari_slow_irq_" #n "_handler:\t" \
-" addl %6,%5\n" /* preempt_count() += HARDIRQ_OFFSET */ \
- SAVE_ALL_INT "\n" \
- GET_CURRENT(%%d0) "\n" \
-" andb #~(1<<(%c3&7)),%a4:w\n" /* mask this interrupt */ \
- /* get old IPL from stack frame */ \
-" bfextu %%sp@(%c2){#5,#3},%%d0\n" \
-" movew %%sr,%%d1\n" \
-" bfins %%d0,%%d1{#21,#3}\n" \
-" movew %%d1,%%sr\n" /* set IPL = previous value */ \
-" addql #1,%a0\n" \
-" lea %a1,%%a0\n" \
-" pea %%sp@\n" /* push addr of frame */ \
-" movel %%a0@(4),%%sp@-\n" /* push handler data */ \
-" pea (%c3+8)\n" /* push int number */ \
-" movel %%a0@,%%a0\n" \
-" jbsr %%a0@\n" /* call the handler */ \
-" addql #8,%%sp\n" \
-" addql #4,%%sp\n" \
-" orw #0x0600,%%sr\n" \
-" andw #0xfeff,%%sr\n" /* set IPL = 6 again */ \
-" orb #(1<<(%c3&7)),%a4:w\n" /* now unmask the int again */ \
-" jbra ret_from_interrupt\n" \
- : : "i" (&kstat_cpu(0).irqs[n+8]), "i" (&irq_handler[n+8]), \
- "n" (PT_OFF_SR), "n" (n), \
- "i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &mfp.int_mk_a) \
- : (n & 16 ? &tt_mfp.int_mk_b : &mfp.int_mk_b)), \
- "m" (preempt_count()), "di" (HARDIRQ_OFFSET) \
-); \
- for (;;); /* fake noreturn */ \
-}
+static unsigned char *enat_cpld;
-BUILD_SLOW_IRQ(0);
-BUILD_SLOW_IRQ(1);
-BUILD_SLOW_IRQ(2);
-BUILD_SLOW_IRQ(3);
-BUILD_SLOW_IRQ(4);
-BUILD_SLOW_IRQ(5);
-BUILD_SLOW_IRQ(6);
-BUILD_SLOW_IRQ(7);
-BUILD_SLOW_IRQ(8);
-BUILD_SLOW_IRQ(9);
-BUILD_SLOW_IRQ(10);
-BUILD_SLOW_IRQ(11);
-BUILD_SLOW_IRQ(12);
-BUILD_SLOW_IRQ(13);
-BUILD_SLOW_IRQ(14);
-BUILD_SLOW_IRQ(15);
-BUILD_SLOW_IRQ(16);
-BUILD_SLOW_IRQ(17);
-BUILD_SLOW_IRQ(18);
-BUILD_SLOW_IRQ(19);
-BUILD_SLOW_IRQ(20);
-BUILD_SLOW_IRQ(21);
-BUILD_SLOW_IRQ(22);
-BUILD_SLOW_IRQ(23);
-BUILD_SLOW_IRQ(24);
-BUILD_SLOW_IRQ(25);
-BUILD_SLOW_IRQ(26);
-BUILD_SLOW_IRQ(27);
-BUILD_SLOW_IRQ(28);
-BUILD_SLOW_IRQ(29);
-BUILD_SLOW_IRQ(30);
-BUILD_SLOW_IRQ(31);
-
-asm_irq_handler slow_handlers[32] = {
- [0] = atari_slow_irq_0_handler,
- [1] = atari_slow_irq_1_handler,
- [2] = atari_slow_irq_2_handler,
- [3] = atari_slow_irq_3_handler,
- [4] = atari_slow_irq_4_handler,
- [5] = atari_slow_irq_5_handler,
- [6] = atari_slow_irq_6_handler,
- [7] = atari_slow_irq_7_handler,
- [8] = atari_slow_irq_8_handler,
- [9] = atari_slow_irq_9_handler,
- [10] = atari_slow_irq_10_handler,
- [11] = atari_slow_irq_11_handler,
- [12] = atari_slow_irq_12_handler,
- [13] = atari_slow_irq_13_handler,
- [14] = atari_slow_irq_14_handler,
- [15] = atari_slow_irq_15_handler,
- [16] = atari_slow_irq_16_handler,
- [17] = atari_slow_irq_17_handler,
- [18] = atari_slow_irq_18_handler,
- [19] = atari_slow_irq_19_handler,
- [20] = atari_slow_irq_20_handler,
- [21] = atari_slow_irq_21_handler,
- [22] = atari_slow_irq_22_handler,
- [23] = atari_slow_irq_23_handler,
- [24] = atari_slow_irq_24_handler,
- [25] = atari_slow_irq_25_handler,
- [26] = atari_slow_irq_26_handler,
- [27] = atari_slow_irq_27_handler,
- [28] = atari_slow_irq_28_handler,
- [29] = atari_slow_irq_29_handler,
- [30] = atari_slow_irq_30_handler,
- [31] = atari_slow_irq_31_handler
-};
+static unsigned int atari_ethernat_startup(struct irq_data *data)
+{
+ int enat_num = 140 - data->irq + 1;
+
+ m68k_irq_startup(data);
+ /*
+ * map CPLD interrupt register
+ */
+ if (!enat_cpld)
+ enat_cpld = (unsigned char *)ioremap((ATARI_ETHERNAT_PHYS_ADDR+0x23), 0x2);
+ /*
+ * do _not_ enable the USB chip interrupt here - causes interrupt storm
+ * and triggers dead interrupt watchdog
+ * Need to reset the USB chip to a sane state in early startup before
+ * removing this hack
+ */
+ if (enat_num == 1)
+ *enat_cpld |= 1 << enat_num;
-asmlinkage void atari_fast_irq_handler( void );
-asmlinkage void atari_prio_irq_handler( void );
-
-/* Dummy function to allow asm with operands. */
-void atari_fast_prio_irq_dummy (void) {
-__asm__ (__ALIGN_STR "\n"
-"atari_fast_irq_handler:\n\t"
- "orw #0x700,%%sr\n" /* disable all interrupts */
-"atari_prio_irq_handler:\n\t"
- "addl %3,%2\n\t" /* preempt_count() += HARDIRQ_OFFSET */
- SAVE_ALL_INT "\n\t"
- GET_CURRENT(%%d0) "\n\t"
- /* get vector number from stack frame and convert to source */
- "bfextu %%sp@(%c1){#4,#10},%%d0\n\t"
- "subw #(0x40-8),%%d0\n\t"
- "jpl 1f\n\t"
- "addw #(0x40-8-0x18),%%d0\n"
- "1:\tlea %a0,%%a0\n\t"
- "addql #1,%%a0@(%%d0:l:4)\n\t"
- "lea irq_handler,%%a0\n\t"
- "lea %%a0@(%%d0:l:8),%%a0\n\t"
- "pea %%sp@\n\t" /* push frame address */
- "movel %%a0@(4),%%sp@-\n\t" /* push handler data */
- "movel %%d0,%%sp@-\n\t" /* push int number */
- "movel %%a0@,%%a0\n\t"
- "jsr %%a0@\n\t" /* and call the handler */
- "addql #8,%%sp\n\t"
- "addql #4,%%sp\n\t"
- "jbra ret_from_interrupt"
- : : "i" (&kstat_cpu(0).irqs), "n" (PT_OFF_FORMATVEC),
- "m" (preempt_count()), "di" (HARDIRQ_OFFSET)
-);
- for (;;);
+ return 0;
}
-/* GK:
- * HBL IRQ handler for Falcon. Nobody needs it :-)
- * ++andreas: raise ipl to disable further HBLANK interrupts.
- */
-asmlinkage void falcon_hblhandler(void);
-asm(".text\n"
-__ALIGN_STR "\n\t"
-"falcon_hblhandler:\n\t"
- "orw #0x200,%sp@\n\t" /* set saved ipl to 2 */
- "rte");
+static void atari_ethernat_enable(struct irq_data *data)
+{
+ int enat_num = 140 - data->irq + 1;
+ /*
+ * map CPLD interrupt register
+ */
+ if (!enat_cpld)
+ enat_cpld = (unsigned char *)ioremap((ATARI_ETHERNAT_PHYS_ADDR+0x23), 0x2);
+ *enat_cpld |= 1 << enat_num;
+}
-/* Defined in entry.S; only increments 'num_spurious' */
-asmlinkage void bad_interrupt(void);
+static void atari_ethernat_disable(struct irq_data *data)
+{
+ int enat_num = 140 - data->irq + 1;
+ /*
+ * map CPLD interrupt register
+ */
+ if (!enat_cpld)
+ enat_cpld = (unsigned char *)ioremap((ATARI_ETHERNAT_PHYS_ADDR+0x23), 0x2);
+ *enat_cpld &= ~(1 << enat_num);
+}
-extern void atari_microwire_cmd( int cmd );
+static void atari_ethernat_shutdown(struct irq_data *data)
+{
+ int enat_num = 140 - data->irq + 1;
+ if (enat_cpld) {
+ *enat_cpld &= ~(1 << enat_num);
+ iounmap(enat_cpld);
+ enat_cpld = NULL;
+ }
+}
-extern int atari_SCC_reset_done;
+static struct irq_chip atari_ethernat_chip = {
+ .name = "ethernat",
+ .irq_startup = atari_ethernat_startup,
+ .irq_shutdown = atari_ethernat_shutdown,
+ .irq_enable = atari_ethernat_enable,
+ .irq_disable = atari_ethernat_disable,
+};
/*
* void atari_init_IRQ (void)
@@ -333,24 +266,21 @@ extern int atari_SCC_reset_done;
void __init atari_init_IRQ(void)
{
- int i;
-
- /* initialize the vector table */
- for (i = 0; i < NUM_INT_SOURCES; ++i) {
- vectors[IRQ_SOURCE_TO_VECTOR(i)] = bad_interrupt;
- }
+ m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER);
+ m68k_setup_irq_controller(&atari_irq_chip, handle_simple_irq, 1,
+ NUM_ATARI_SOURCES - 1);
/* Initialize the MFP(s) */
#ifdef ATARI_USE_SOFTWARE_EOI
- mfp.vec_adr = 0x48; /* Software EOI-Mode */
+ st_mfp.vec_adr = 0x48; /* Software EOI-Mode */
#else
- mfp.vec_adr = 0x40; /* Automatic EOI-Mode */
+ st_mfp.vec_adr = 0x40; /* Automatic EOI-Mode */
#endif
- mfp.int_en_a = 0x00; /* turn off MFP-Ints */
- mfp.int_en_b = 0x00;
- mfp.int_mk_a = 0xff; /* no Masking */
- mfp.int_mk_b = 0xff;
+ st_mfp.int_en_a = 0x00; /* turn off MFP-Ints */
+ st_mfp.int_en_b = 0x00;
+ st_mfp.int_mk_a = 0xff; /* no Masking */
+ st_mfp.int_mk_b = 0xff;
if (ATARIHW_PRESENT(TT_MFP)) {
#ifdef ATARI_USE_SOFTWARE_EOI
@@ -365,9 +295,9 @@ void __init atari_init_IRQ(void)
}
if (ATARIHW_PRESENT(SCC) && !atari_SCC_reset_done) {
- scc.cha_a_ctrl = 9;
+ atari_scc.cha_a_ctrl = 9;
MFPDELAY();
- scc.cha_a_ctrl = (char) 0xc0; /* hardware reset */
+ atari_scc.cha_a_ctrl = (char) 0xc0; /* hardware reset */
}
if (ATARIHW_PRESENT(SCU)) {
@@ -378,15 +308,14 @@ void __init atari_init_IRQ(void)
* enabled in VME mask
*/
tt_scu.vme_mask = 0x60; /* enable MFP and SCC ints */
- }
- else {
+ } else {
/* If no SCU and no Hades, the HSYNC interrupt needs to be
* disabled this way. (Else _inthandler in kernel/sys_call.S
* gets overruns)
*/
- if (!MACH_IS_HADES)
- vectors[VEC_INT2] = falcon_hblhandler;
+ vectors[VEC_INT2] = falcon_hblhandler;
+ vectors[VEC_INT4] = falcon_hblhandler;
}
if (ATARIHW_PRESENT(PCM_8BIT) && ATARIHW_PRESENT(MICROWIRE)) {
@@ -401,184 +330,30 @@ void __init atari_init_IRQ(void)
/* Initialize the PSG: all sounds off, both ports output */
sound_ym.rd_data_reg_sel = 7;
sound_ym.wd_data = 0xff;
-}
-
-
-static irqreturn_t atari_call_irq_list( int irq, void *dev_id, struct pt_regs *fp )
-{
- irq_node_t *node;
- for (node = (irq_node_t *)dev_id; node; node = node->next)
- node->handler(irq, node->dev_id, fp);
- return IRQ_HANDLED;
-}
-
-
-/*
- * atari_request_irq : add an interrupt service routine for a particular
- * machine specific interrupt source.
- * If the addition was successful, it returns 0.
- */
-
-int atari_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
- unsigned long flags, const char *devname, void *dev_id)
-{
- int vector;
- unsigned long oflags = flags;
+ m68k_setup_irq_controller(&atari_mfptimer_chip, handle_simple_irq,
+ IRQ_MFP_TIMER1, 8);
- /*
- * The following is a hack to make some PCI card drivers work,
- * which set the SA_SHIRQ flag.
- */
+ irq_set_status_flags(IRQ_MFP_TIMER1, IRQ_IS_POLLED);
+ irq_set_status_flags(IRQ_MFP_TIMER2, IRQ_IS_POLLED);
- flags &= ~SA_SHIRQ;
+ /* prepare timer D data for use as poll interrupt */
+ /* set Timer D data Register - needs to be > 0 */
+ st_mfp.tim_dt_d = 254; /* < 100 Hz */
+ /* start timer D, div = 1:100 */
+ st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 0xf0) | 0x6;
- if (flags == SA_INTERRUPT) {
- printk ("%s: SA_INTERRUPT changed to IRQ_TYPE_SLOW for %s\n",
- __FUNCTION__, devname);
- flags = IRQ_TYPE_SLOW;
- }
- if (flags < IRQ_TYPE_SLOW || flags > IRQ_TYPE_PRIO) {
- printk ("%s: Bad irq type 0x%lx <0x%lx> requested from %s\n",
- __FUNCTION__, flags, oflags, devname);
- return -EINVAL;
- }
- if (!IS_VALID_INTNO(irq)) {
- printk ("%s: Unknown irq %d requested from %s\n",
- __FUNCTION__, irq, devname);
- return -ENXIO;
- }
- vector = IRQ_SOURCE_TO_VECTOR(irq);
+ /* request timer D dispatch handler */
+ if (request_irq(IRQ_MFP_TIMD, mfptimer_handler, IRQF_SHARED,
+ stmfp_base.name, &stmfp_base))
+ pr_err("Couldn't register %s interrupt\n", stmfp_base.name);
/*
- * Check type/source combination: slow ints are (currently)
- * only possible for MFP-interrupts.
+ * EtherNAT ethernet / USB interrupt handlers
*/
- if (flags == IRQ_TYPE_SLOW &&
- (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE)) {
- printk ("%s: Slow irq requested for non-MFP source %d from %s\n",
- __FUNCTION__, irq, devname);
- return -EINVAL;
- }
-
- if (vectors[vector] == bad_interrupt) {
- /* int has no handler yet */
- irq_handler[irq].handler = handler;
- irq_handler[irq].dev_id = dev_id;
- irq_param[irq].flags = flags;
- irq_param[irq].devname = devname;
- vectors[vector] =
- (flags == IRQ_TYPE_SLOW) ? slow_handlers[irq-STMFP_SOURCE_BASE] :
- (flags == IRQ_TYPE_FAST) ? atari_fast_irq_handler :
- atari_prio_irq_handler;
- /* If MFP int, also enable and umask it */
- atari_turnon_irq(irq);
- atari_enable_irq(irq);
- return 0;
- }
- else if (irq_param[irq].flags == flags) {
- /* old handler is of same type -> handlers can be chained */
- irq_node_t *node;
- unsigned long flags;
-
- local_irq_save(flags);
-
- if (irq_handler[irq].handler != atari_call_irq_list) {
- /* Only one handler yet, make a node for this first one */
- if (!(node = new_irq_node()))
- return -ENOMEM;
- node->handler = irq_handler[irq].handler;
- node->dev_id = irq_handler[irq].dev_id;
- node->devname = irq_param[irq].devname;
- node->next = NULL;
-
- irq_handler[irq].handler = atari_call_irq_list;
- irq_handler[irq].dev_id = node;
- irq_param[irq].devname = "chained";
- }
-
- if (!(node = new_irq_node()))
- return -ENOMEM;
- node->handler = handler;
- node->dev_id = dev_id;
- node->devname = devname;
- /* new handlers are put in front of the queue */
- node->next = irq_handler[irq].dev_id;
- irq_handler[irq].dev_id = node;
-
- local_irq_restore(flags);
- return 0;
- } else {
- printk ("%s: Irq %d allocated by other type int (call from %s)\n",
- __FUNCTION__, irq, devname);
- return -EBUSY;
- }
-}
-
-void atari_free_irq(unsigned int irq, void *dev_id)
-{
- unsigned long flags;
- int vector;
- irq_node_t **list, *node;
-
- if (!IS_VALID_INTNO(irq)) {
- printk("%s: Unknown irq %d\n", __FUNCTION__, irq);
- return;
- }
-
- vector = IRQ_SOURCE_TO_VECTOR(irq);
- if (vectors[vector] == bad_interrupt)
- goto not_found;
-
- local_irq_save(flags);
-
- if (irq_handler[irq].handler != atari_call_irq_list) {
- /* It's the only handler for the interrupt */
- if (irq_handler[irq].dev_id != dev_id) {
- local_irq_restore(flags);
- goto not_found;
- }
- irq_handler[irq].handler = NULL;
- irq_handler[irq].dev_id = NULL;
- irq_param[irq].devname = NULL;
- vectors[vector] = bad_interrupt;
- /* If MFP int, also disable it */
- atari_disable_irq(irq);
- atari_turnoff_irq(irq);
-
- local_irq_restore(flags);
- return;
- }
-
- /* The interrupt is chained, find the irq on the list */
- for(list = (irq_node_t **)&irq_handler[irq].dev_id; *list; list = &(*list)->next) {
- if ((*list)->dev_id == dev_id) break;
- }
- if (!*list) {
- local_irq_restore(flags);
- goto not_found;
- }
-
- (*list)->handler = NULL; /* Mark it as free for reallocation */
- *list = (*list)->next;
-
- /* If there's now only one handler, unchain the interrupt, i.e. plug in
- * the handler directly again and omit atari_call_irq_list */
- node = (irq_node_t *)irq_handler[irq].dev_id;
- if (node && !node->next) {
- irq_handler[irq].handler = node->handler;
- irq_handler[irq].dev_id = node->dev_id;
- irq_param[irq].devname = node->devname;
- node->handler = NULL; /* Mark it as free for reallocation */
- }
-
- local_irq_restore(flags);
- return;
-
-not_found:
- printk("%s: tried to remove invalid irq\n", __FUNCTION__);
- return;
+ m68k_setup_irq_controller(&atari_ethernat_chip, handle_simple_irq,
+ 139, 2);
}
@@ -587,62 +362,30 @@ not_found:
* hardware with a programmable int vector (probably a VME board).
*/
-unsigned long atari_register_vme_int(void)
+unsigned int atari_register_vme_int(void)
{
int i;
- for(i = 0; i < 32; i++)
- if((free_vme_vec_bitmap & (1 << i)) == 0)
+ for (i = 0; i < 32; i++)
+ if ((free_vme_vec_bitmap & (1 << i)) == 0)
break;
- if(i == 16)
+ if (i == 16)
return 0;
free_vme_vec_bitmap |= 1 << i;
- return (VME_SOURCE_BASE + i);
+ return VME_SOURCE_BASE + i;
}
+EXPORT_SYMBOL(atari_register_vme_int);
-void atari_unregister_vme_int(unsigned long irq)
+void atari_unregister_vme_int(unsigned int irq)
{
- if(irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) {
+ if (irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) {
irq -= VME_SOURCE_BASE;
free_vme_vec_bitmap &= ~(1 << irq);
}
}
-
-
-int show_atari_interrupts(struct seq_file *p, void *v)
-{
- int i;
-
- for (i = 0; i < NUM_INT_SOURCES; ++i) {
- if (vectors[IRQ_SOURCE_TO_VECTOR(i)] == bad_interrupt)
- continue;
- if (i < STMFP_SOURCE_BASE)
- seq_printf(p, "auto %2d: %10u ",
- i, kstat_cpu(0).irqs[i]);
- else
- seq_printf(p, "vec $%02x: %10u ",
- IRQ_SOURCE_TO_VECTOR(i),
- kstat_cpu(0).irqs[i]);
-
- if (irq_handler[i].handler != atari_call_irq_list) {
- seq_printf(p, "%s\n", irq_param[i].devname);
- }
- else {
- irq_node_t *n;
- for( n = (irq_node_t *)irq_handler[i].dev_id; n; n = n->next ) {
- seq_printf(p, "%s\n", n->devname);
- if (n->next)
- seq_puts(p, " " );
- }
- }
- }
- if (num_spurious)
- seq_printf(p, "spurio.: %10u\n", num_spurious);
-
- return 0;
-}
+EXPORT_SYMBOL(atari_unregister_vme_int);
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c
new file mode 100644
index 00000000000..95022b04b62
--- /dev/null
+++ b/arch/m68k/atari/atakeyb.c
@@ -0,0 +1,638 @@
+/*
+ * Atari Keyboard driver for 680x0 Linux
+ *
+ * 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.
+ */
+
+/*
+ * Atari support by Robert de Vries
+ * enhanced by Bjoern Brauel and Roman Hodek
+ *
+ * 2.6 and input cleanup (removed autorepeat stuff) for 2.6.21
+ * 06/07 Michael Schmitz
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/keyboard.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/kd.h>
+#include <linux/random.h>
+#include <linux/init.h>
+#include <linux/kbd_kern.h>
+
+#include <asm/atariints.h>
+#include <asm/atarihw.h>
+#include <asm/atarikb.h>
+#include <asm/atari_joystick.h>
+#include <asm/irq.h>
+
+
+/* Hook for MIDI serial driver */
+void (*atari_MIDI_interrupt_hook) (void);
+/* Hook for keyboard inputdev driver */
+void (*atari_input_keyboard_interrupt_hook) (unsigned char, char);
+/* Hook for mouse inputdev driver */
+void (*atari_input_mouse_interrupt_hook) (char *);
+EXPORT_SYMBOL(atari_input_keyboard_interrupt_hook);
+EXPORT_SYMBOL(atari_input_mouse_interrupt_hook);
+
+/* variables for IKBD self test: */
+
+/* state: 0: off; >0: in progress; >1: 0xf1 received */
+static volatile int ikbd_self_test;
+/* timestamp when last received a char */
+static volatile unsigned long self_test_last_rcv;
+/* bitmap of keys reported as broken */
+static unsigned long broken_keys[128/(sizeof(unsigned long)*8)] = { 0, };
+
+#define BREAK_MASK (0x80)
+
+/*
+ * ++roman: The following changes were applied manually:
+ *
+ * - The Alt (= Meta) key works in combination with Shift and
+ * Control, e.g. Alt+Shift+a sends Meta-A (0xc1), Alt+Control+A sends
+ * Meta-Ctrl-A (0x81) ...
+ *
+ * - The parentheses on the keypad send '(' and ')' with all
+ * modifiers (as would do e.g. keypad '+'), but they cannot be used as
+ * application keys (i.e. sending Esc O c).
+ *
+ * - HELP and UNDO are mapped to be F21 and F24, resp, that send the
+ * codes "\E[M" and "\E[P". (This is better than the old mapping to
+ * F11 and F12, because these codes are on Shift+F1/2 anyway.) This
+ * way, applications that allow their own keyboard mappings
+ * (e.g. tcsh, X Windows) can be configured to use them in the way
+ * the label suggests (providing help or undoing).
+ *
+ * - Console switching is done with Alt+Fx (consoles 1..10) and
+ * Shift+Alt+Fx (consoles 11..20).
+ *
+ * - The misc. special function implemented in the kernel are mapped
+ * to the following key combinations:
+ *
+ * ClrHome -> Home/Find
+ * Shift + ClrHome -> End/Select
+ * Shift + Up -> Page Up
+ * Shift + Down -> Page Down
+ * Alt + Help -> show system status
+ * Shift + Help -> show memory info
+ * Ctrl + Help -> show registers
+ * Ctrl + Alt + Del -> Reboot
+ * Alt + Undo -> switch to last console
+ * Shift + Undo -> send interrupt
+ * Alt + Insert -> stop/start output (same as ^S/^Q)
+ * Alt + Up -> Scroll back console (if implemented)
+ * Alt + Down -> Scroll forward console (if implemented)
+ * Alt + CapsLock -> NumLock
+ *
+ * ++Andreas:
+ *
+ * - Help mapped to K_HELP
+ * - Undo mapped to K_UNDO (= K_F246)
+ * - Keypad Left/Right Parenthesis mapped to new K_PPAREN[LR]
+ */
+
+typedef enum kb_state_t {
+ KEYBOARD, AMOUSE, RMOUSE, JOYSTICK, CLOCK, RESYNC
+} KB_STATE_T;
+
+#define IS_SYNC_CODE(sc) ((sc) >= 0x04 && (sc) <= 0xfb)
+
+typedef struct keyboard_state {
+ unsigned char buf[6];
+ int len;
+ KB_STATE_T state;
+} KEYBOARD_STATE;
+
+KEYBOARD_STATE kb_state;
+
+/* ++roman: If a keyboard overrun happened, we can't tell in general how much
+ * bytes have been lost and in which state of the packet structure we are now.
+ * This usually causes keyboards bytes to be interpreted as mouse movements
+ * and vice versa, which is very annoying. It seems better to throw away some
+ * bytes (that are usually mouse bytes) than to misinterpret them. Therefore I
+ * introduced the RESYNC state for IKBD data. In this state, the bytes up to
+ * one that really looks like a key event (0x04..0xf2) or the start of a mouse
+ * packet (0xf8..0xfb) are thrown away, but at most 2 bytes. This at least
+ * speeds up the resynchronization of the event structure, even if maybe a
+ * mouse movement is lost. However, nothing is perfect. For bytes 0x01..0x03,
+ * it's really hard to decide whether they're mouse or keyboard bytes. Since
+ * overruns usually occur when moving the Atari mouse rapidly, they're seen as
+ * mouse bytes here. If this is wrong, only a make code of the keyboard gets
+ * lost, which isn't too bad. Losing a break code would be disastrous,
+ * because then the keyboard repeat strikes...
+ */
+
+static irqreturn_t atari_keyboard_interrupt(int irq, void *dummy)
+{
+ u_char acia_stat;
+ int scancode;
+ int break_flag;
+
+repeat:
+ if (acia.mid_ctrl & ACIA_IRQ)
+ if (atari_MIDI_interrupt_hook)
+ atari_MIDI_interrupt_hook();
+ acia_stat = acia.key_ctrl;
+ /* check out if the interrupt came from this ACIA */
+ if (!((acia_stat | acia.mid_ctrl) & ACIA_IRQ))
+ return IRQ_HANDLED;
+
+ if (acia_stat & ACIA_OVRN) {
+ /* a very fast typist or a slow system, give a warning */
+ /* ...happens often if interrupts were disabled for too long */
+ printk(KERN_DEBUG "Keyboard overrun\n");
+ scancode = acia.key_data;
+ if (ikbd_self_test)
+ /* During self test, don't do resyncing, just process the code */
+ goto interpret_scancode;
+ else if (IS_SYNC_CODE(scancode)) {
+ /* This code seem already to be the start of a new packet or a
+ * single scancode */
+ kb_state.state = KEYBOARD;
+ goto interpret_scancode;
+ } else {
+ /* Go to RESYNC state and skip this byte */
+ kb_state.state = RESYNC;
+ kb_state.len = 1; /* skip max. 1 another byte */
+ goto repeat;
+ }
+ }
+
+ if (acia_stat & ACIA_RDRF) {
+ /* received a character */
+ scancode = acia.key_data; /* get it or reset the ACIA, I'll get it! */
+ tasklet_schedule(&keyboard_tasklet);
+ interpret_scancode:
+ switch (kb_state.state) {
+ case KEYBOARD:
+ switch (scancode) {
+ case 0xF7:
+ kb_state.state = AMOUSE;
+ kb_state.len = 0;
+ break;
+
+ case 0xF8:
+ case 0xF9:
+ case 0xFA:
+ case 0xFB:
+ kb_state.state = RMOUSE;
+ kb_state.len = 1;
+ kb_state.buf[0] = scancode;
+ break;
+
+ case 0xFC:
+ kb_state.state = CLOCK;
+ kb_state.len = 0;
+ break;
+
+ case 0xFE:
+ case 0xFF:
+ kb_state.state = JOYSTICK;
+ kb_state.len = 1;
+ kb_state.buf[0] = scancode;
+ break;
+
+ case 0xF1:
+ /* during self-test, note that 0xf1 received */
+ if (ikbd_self_test) {
+ ++ikbd_self_test;
+ self_test_last_rcv = jiffies;
+ break;
+ }
+ /* FALL THROUGH */
+
+ default:
+ break_flag = scancode & BREAK_MASK;
+ scancode &= ~BREAK_MASK;
+ if (ikbd_self_test) {
+ /* Scancodes sent during the self-test stand for broken
+ * keys (keys being down). The code *should* be a break
+ * code, but nevertheless some AT keyboard interfaces send
+ * make codes instead. Therefore, simply ignore
+ * break_flag...
+ */
+ int keyval, keytyp;
+
+ set_bit(scancode, broken_keys);
+ self_test_last_rcv = jiffies;
+ /* new Linux scancodes; approx. */
+ keyval = scancode;
+ keytyp = KTYP(keyval) - 0xf0;
+ keyval = KVAL(keyval);
+
+ printk(KERN_WARNING "Key with scancode %d ", scancode);
+ if (keytyp == KT_LATIN || keytyp == KT_LETTER) {
+ if (keyval < ' ')
+ printk("('^%c') ", keyval + '@');
+ else
+ printk("('%c') ", keyval);
+ }
+ printk("is broken -- will be ignored.\n");
+ break;
+ } else if (test_bit(scancode, broken_keys))
+ break;
+
+ if (atari_input_keyboard_interrupt_hook)
+ atari_input_keyboard_interrupt_hook((unsigned char)scancode, !break_flag);
+ break;
+ }
+ break;
+
+ case AMOUSE:
+ kb_state.buf[kb_state.len++] = scancode;
+ if (kb_state.len == 5) {
+ kb_state.state = KEYBOARD;
+ /* not yet used */
+ /* wake up someone waiting for this */
+ }
+ break;
+
+ case RMOUSE:
+ kb_state.buf[kb_state.len++] = scancode;
+ if (kb_state.len == 3) {
+ kb_state.state = KEYBOARD;
+ if (atari_input_mouse_interrupt_hook)
+ atari_input_mouse_interrupt_hook(kb_state.buf);
+ }
+ break;
+
+ case JOYSTICK:
+ kb_state.buf[1] = scancode;
+ kb_state.state = KEYBOARD;
+#ifdef FIXED_ATARI_JOYSTICK
+ atari_joystick_interrupt(kb_state.buf);
+#endif
+ break;
+
+ case CLOCK:
+ kb_state.buf[kb_state.len++] = scancode;
+ if (kb_state.len == 6) {
+ kb_state.state = KEYBOARD;
+ /* wake up someone waiting for this.
+ But will this ever be used, as Linux keeps its own time.
+ Perhaps for synchronization purposes? */
+ /* wake_up_interruptible(&clock_wait); */
+ }
+ break;
+
+ case RESYNC:
+ if (kb_state.len <= 0 || IS_SYNC_CODE(scancode)) {
+ kb_state.state = KEYBOARD;
+ goto interpret_scancode;
+ }
+ kb_state.len--;
+ break;
+ }
+ }
+
+#if 0
+ if (acia_stat & ACIA_CTS)
+ /* cannot happen */;
+#endif
+
+ if (acia_stat & (ACIA_FE | ACIA_PE)) {
+ printk("Error in keyboard communication\n");
+ }
+
+ /* handle_scancode() can take a lot of time, so check again if
+ * some character arrived
+ */
+ goto repeat;
+}
+
+/*
+ * I write to the keyboard without using interrupts, I poll instead.
+ * This takes for the maximum length string allowed (7) at 7812.5 baud
+ * 8 data 1 start 1 stop bit: 9.0 ms
+ * If this takes too long for normal operation, interrupt driven writing
+ * is the solution. (I made a feeble attempt in that direction but I
+ * kept it simple for now.)
+ */
+void ikbd_write(const char *str, int len)
+{
+ u_char acia_stat;
+
+ if ((len < 1) || (len > 7))
+ panic("ikbd: maximum string length exceeded");
+ while (len) {
+ acia_stat = acia.key_ctrl;
+ if (acia_stat & ACIA_TDRE) {
+ acia.key_data = *str++;
+ len--;
+ }
+ }
+}
+
+/* Reset (without touching the clock) */
+void ikbd_reset(void)
+{
+ static const char cmd[2] = { 0x80, 0x01 };
+
+ ikbd_write(cmd, 2);
+
+ /*
+ * if all's well code 0xF1 is returned, else the break codes of
+ * all keys making contact
+ */
+}
+
+/* Set mouse button action */
+void ikbd_mouse_button_action(int mode)
+{
+ char cmd[2] = { 0x07, mode };
+
+ ikbd_write(cmd, 2);
+}
+
+/* Set relative mouse position reporting */
+void ikbd_mouse_rel_pos(void)
+{
+ static const char cmd[1] = { 0x08 };
+
+ ikbd_write(cmd, 1);
+}
+EXPORT_SYMBOL(ikbd_mouse_rel_pos);
+
+/* Set absolute mouse position reporting */
+void ikbd_mouse_abs_pos(int xmax, int ymax)
+{
+ char cmd[5] = { 0x09, xmax>>8, xmax&0xFF, ymax>>8, ymax&0xFF };
+
+ ikbd_write(cmd, 5);
+}
+
+/* Set mouse keycode mode */
+void ikbd_mouse_kbd_mode(int dx, int dy)
+{
+ char cmd[3] = { 0x0A, dx, dy };
+
+ ikbd_write(cmd, 3);
+}
+
+/* Set mouse threshold */
+void ikbd_mouse_thresh(int x, int y)
+{
+ char cmd[3] = { 0x0B, x, y };
+
+ ikbd_write(cmd, 3);
+}
+EXPORT_SYMBOL(ikbd_mouse_thresh);
+
+/* Set mouse scale */
+void ikbd_mouse_scale(int x, int y)
+{
+ char cmd[3] = { 0x0C, x, y };
+
+ ikbd_write(cmd, 3);
+}
+
+/* Interrogate mouse position */
+void ikbd_mouse_pos_get(int *x, int *y)
+{
+ static const char cmd[1] = { 0x0D };
+
+ ikbd_write(cmd, 1);
+
+ /* wait for returning bytes */
+}
+
+/* Load mouse position */
+void ikbd_mouse_pos_set(int x, int y)
+{
+ char cmd[6] = { 0x0E, 0x00, x>>8, x&0xFF, y>>8, y&0xFF };
+
+ ikbd_write(cmd, 6);
+}
+
+/* Set Y=0 at bottom */
+void ikbd_mouse_y0_bot(void)
+{
+ static const char cmd[1] = { 0x0F };
+
+ ikbd_write(cmd, 1);
+}
+
+/* Set Y=0 at top */
+void ikbd_mouse_y0_top(void)
+{
+ static const char cmd[1] = { 0x10 };
+
+ ikbd_write(cmd, 1);
+}
+EXPORT_SYMBOL(ikbd_mouse_y0_top);
+
+/* Resume */
+void ikbd_resume(void)
+{
+ static const char cmd[1] = { 0x11 };
+
+ ikbd_write(cmd, 1);
+}
+
+/* Disable mouse */
+void ikbd_mouse_disable(void)
+{
+ static const char cmd[1] = { 0x12 };
+
+ ikbd_write(cmd, 1);
+}
+EXPORT_SYMBOL(ikbd_mouse_disable);
+
+/* Pause output */
+void ikbd_pause(void)
+{
+ static const char cmd[1] = { 0x13 };
+
+ ikbd_write(cmd, 1);
+}
+
+/* Set joystick event reporting */
+void ikbd_joystick_event_on(void)
+{
+ static const char cmd[1] = { 0x14 };
+
+ ikbd_write(cmd, 1);
+}
+
+/* Set joystick interrogation mode */
+void ikbd_joystick_event_off(void)
+{
+ static const char cmd[1] = { 0x15 };
+
+ ikbd_write(cmd, 1);
+}
+
+/* Joystick interrogation */
+void ikbd_joystick_get_state(void)
+{
+ static const char cmd[1] = { 0x16 };
+
+ ikbd_write(cmd, 1);
+}
+
+#if 0
+/* This disables all other ikbd activities !!!! */
+/* Set joystick monitoring */
+void ikbd_joystick_monitor(int rate)
+{
+ static const char cmd[2] = { 0x17, rate };
+
+ ikbd_write(cmd, 2);
+
+ kb_state.state = JOYSTICK_MONITOR;
+}
+#endif
+
+/* some joystick routines not in yet (0x18-0x19) */
+
+/* Disable joysticks */
+void ikbd_joystick_disable(void)
+{
+ static const char cmd[1] = { 0x1A };
+
+ ikbd_write(cmd, 1);
+}
+
+/* Time-of-day clock set */
+void ikbd_clock_set(int year, int month, int day, int hour, int minute, int second)
+{
+ char cmd[7] = { 0x1B, year, month, day, hour, minute, second };
+
+ ikbd_write(cmd, 7);
+}
+
+/* Interrogate time-of-day clock */
+void ikbd_clock_get(int *year, int *month, int *day, int *hour, int *minute, int second)
+{
+ static const char cmd[1] = { 0x1C };
+
+ ikbd_write(cmd, 1);
+}
+
+/* Memory load */
+void ikbd_mem_write(int address, int size, char *data)
+{
+ panic("Attempt to write data into keyboard memory");
+}
+
+/* Memory read */
+void ikbd_mem_read(int address, char data[6])
+{
+ char cmd[3] = { 0x21, address>>8, address&0xFF };
+
+ ikbd_write(cmd, 3);
+
+ /* receive data and put it in data */
+}
+
+/* Controller execute */
+void ikbd_exec(int address)
+{
+ char cmd[3] = { 0x22, address>>8, address&0xFF };
+
+ ikbd_write(cmd, 3);
+}
+
+/* Status inquiries (0x87-0x9A) not yet implemented */
+
+/* Set the state of the caps lock led. */
+void atari_kbd_leds(unsigned int leds)
+{
+ char cmd[6] = {32, 0, 4, 1, 254 + ((leds & 4) != 0), 0};
+
+ ikbd_write(cmd, 6);
+}
+
+/*
+ * The original code sometimes left the interrupt line of
+ * the ACIAs low forever. I hope, it is fixed now.
+ *
+ * Martin Rogge, 20 Aug 1995
+ */
+
+static int atari_keyb_done = 0;
+
+int atari_keyb_init(void)
+{
+ int error;
+
+ if (atari_keyb_done)
+ return 0;
+
+ kb_state.state = KEYBOARD;
+ kb_state.len = 0;
+
+ error = request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt,
+ IRQ_TYPE_SLOW, "keyboard,mouse,MIDI",
+ atari_keyboard_interrupt);
+ if (error)
+ return error;
+
+ atari_turnoff_irq(IRQ_MFP_ACIA);
+ do {
+ /* reset IKBD ACIA */
+ acia.key_ctrl = ACIA_RESET |
+ ((atari_switches & ATARI_SWITCH_IKBD) ?
+ ACIA_RHTID : 0);
+ (void)acia.key_ctrl;
+ (void)acia.key_data;
+
+ /* reset MIDI ACIA */
+ acia.mid_ctrl = ACIA_RESET |
+ ((atari_switches & ATARI_SWITCH_MIDI) ?
+ ACIA_RHTID : 0);
+ (void)acia.mid_ctrl;
+ (void)acia.mid_data;
+
+ /* divide 500kHz by 64 gives 7812.5 baud */
+ /* 8 data no parity 1 start 1 stop bit */
+ /* receive interrupt enabled */
+ /* RTS low (except if switch selected), transmit interrupt disabled */
+ acia.key_ctrl = (ACIA_DIV64|ACIA_D8N1S|ACIA_RIE) |
+ ((atari_switches & ATARI_SWITCH_IKBD) ?
+ ACIA_RHTID : ACIA_RLTID);
+
+ acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S |
+ ((atari_switches & ATARI_SWITCH_MIDI) ?
+ ACIA_RHTID : 0);
+
+ /* make sure the interrupt line is up */
+ } while ((st_mfp.par_dt_reg & 0x10) == 0);
+
+ /* enable ACIA Interrupts */
+ st_mfp.active_edge &= ~0x10;
+ atari_turnon_irq(IRQ_MFP_ACIA);
+
+ ikbd_self_test = 1;
+ ikbd_reset();
+ /* wait for a period of inactivity (here: 0.25s), then assume the IKBD's
+ * self-test is finished */
+ self_test_last_rcv = jiffies;
+ while (time_before(jiffies, self_test_last_rcv + HZ/4))
+ barrier();
+ /* if not incremented: no 0xf1 received */
+ if (ikbd_self_test == 1)
+ printk(KERN_ERR "WARNING: keyboard self test failed!\n");
+ ikbd_self_test = 0;
+
+ ikbd_mouse_disable();
+ ikbd_joystick_disable();
+
+#ifdef FIXED_ATARI_JOYSTICK
+ atari_joystick_init();
+#endif
+
+ // flag init done
+ atari_keyb_done = 1;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(atari_keyb_init);
diff --git a/arch/m68k/atari/atari_ksyms.c b/arch/m68k/atari/atari_ksyms.c
deleted file mode 100644
index a0475715153..00000000000
--- a/arch/m68k/atari/atari_ksyms.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <linux/module.h>
-
-#include <asm/ptrace.h>
-#include <asm/traps.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atarikb.h>
-#include <asm/atari_joystick.h>
-#include <asm/atari_stdma.h>
-#include <asm/atari_stram.h>
-
-extern void atari_microwire_cmd( int cmd );
-extern int atari_MFP_init_done;
-extern int atari_SCC_init_done;
-extern int atari_SCC_reset_done;
-
-EXPORT_SYMBOL(atari_mch_cookie);
-EXPORT_SYMBOL(atari_mch_type);
-EXPORT_SYMBOL(atari_hw_present);
-EXPORT_SYMBOL(atari_switches);
-EXPORT_SYMBOL(atari_dont_touch_floppy_select);
-EXPORT_SYMBOL(atari_register_vme_int);
-EXPORT_SYMBOL(atari_unregister_vme_int);
-EXPORT_SYMBOL(stdma_lock);
-EXPORT_SYMBOL(stdma_release);
-EXPORT_SYMBOL(stdma_others_waiting);
-EXPORT_SYMBOL(stdma_islocked);
-EXPORT_SYMBOL(atari_stram_alloc);
-EXPORT_SYMBOL(atari_stram_free);
-
-EXPORT_SYMBOL(atari_MFP_init_done);
-EXPORT_SYMBOL(atari_SCC_init_done);
-EXPORT_SYMBOL(atari_SCC_reset_done);
-
-EXPORT_SYMBOL(atari_microwire_cmd);
diff --git a/arch/m68k/atari/atasound.c b/arch/m68k/atari/atasound.c
index ee04250eb56..1c1181ebb94 100644
--- a/arch/m68k/atari/atasound.c
+++ b/arch/m68k/atari/atasound.c
@@ -22,9 +22,9 @@
#include <linux/fcntl.h>
#include <linux/errno.h>
#include <linux/mm.h>
+#include <linux/module.h>
#include <asm/atarihw.h>
-#include <asm/system.h>
#include <asm/irq.h>
#include <asm/pgtable.h>
#include <asm/atariints.h>
@@ -43,6 +43,7 @@ void atari_microwire_cmd (int cmd)
while( tt_microwire.mask != 0x7ff)
;
}
+EXPORT_SYMBOL(atari_microwire_cmd);
/* PSG base frequency */
diff --git a/arch/m68k/atari/atasound.h b/arch/m68k/atari/atasound.h
deleted file mode 100644
index 1362762b8c0..00000000000
--- a/arch/m68k/atari/atasound.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Minor numbers for the sound driver.
- *
- * Unfortunately Creative called the codec chip of SB as a DSP. For this
- * reason the /dev/dsp is reserved for digitized audio use. There is a
- * device for true DSP processors but it will be called something else.
- * In v3.0 it's /dev/sndproc but this could be a temporary solution.
- */
-
-#define SND_NDEVS 256 /* Number of supported devices */
-#define SND_DEV_CTL 0 /* Control port /dev/mixer */
-#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM
- synthesizer and MIDI output) */
-#define SND_DEV_MIDIN 2 /* Raw midi access */
-#define SND_DEV_DSP 3 /* Digitized voice /dev/dsp */
-#define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */
-#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */
-#define SND_DEV_STATUS 6 /* /dev/sndstat */
-/* #7 not in use now. Was in 2.4. Free for use after v3.0. */
-#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */
-#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */
-#define SND_DEV_PSS SND_DEV_SNDPROC
-
-#define DSP_DEFAULT_SPEED 8000
-
-#define ON 1
-#define OFF 0
-
-#define MAX_AUDIO_DEV 5
-#define MAX_MIXER_DEV 2
-#define MAX_SYNTH_DEV 3
-#define MAX_MIDI_DEV 6
-#define MAX_TIMER_DEV 3
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index 9261d2deeaf..01a62161b08 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -24,106 +24,66 @@
* Miscellaneous atari stuff
*/
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/mm.h>
+#include <linux/seq_file.h>
#include <linux/console.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/usb/isp116x.h>
#include <linux/vt_kern.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
+#include <asm/bootinfo-atari.h>
+#include <asm/byteorder.h>
#include <asm/setup.h>
#include <asm/atarihw.h>
#include <asm/atariints.h>
#include <asm/atari_stram.h>
-#include <asm/system.h>
#include <asm/machdep.h>
#include <asm/hwtest.h>
#include <asm/io.h>
u_long atari_mch_cookie;
+EXPORT_SYMBOL(atari_mch_cookie);
+
u_long atari_mch_type;
+EXPORT_SYMBOL(atari_mch_type);
+
struct atari_hw_present atari_hw_present;
+EXPORT_SYMBOL(atari_hw_present);
+
u_long atari_switches;
+EXPORT_SYMBOL(atari_switches);
+
int atari_dont_touch_floppy_select;
+EXPORT_SYMBOL(atari_dont_touch_floppy_select);
+
int atari_rtc_year_offset;
/* local function prototypes */
-static void atari_reset( void );
-#ifdef CONFIG_ATARI_FLOPPY
-extern void atari_floppy_setup(char *, int *);
-#endif
+static void atari_reset(void);
static void atari_get_model(char *model);
-static int atari_get_hardware_list(char *buffer);
+static void atari_get_hardware_list(struct seq_file *m);
/* atari specific irq functions */
extern void atari_init_IRQ (void);
-extern int atari_request_irq (unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
- unsigned long flags, const char *devname, void *dev_id);
-extern void atari_free_irq (unsigned int irq, void *dev_id);
-extern void atari_enable_irq (unsigned int);
-extern void atari_disable_irq (unsigned int);
-extern int show_atari_interrupts (struct seq_file *, void *);
-extern void atari_mksound( unsigned int count, unsigned int ticks );
+extern void atari_mksound(unsigned int count, unsigned int ticks);
#ifdef CONFIG_HEARTBEAT
-static void atari_heartbeat( int on );
+static void atari_heartbeat(int on);
#endif
/* atari specific timer functions (in time.c) */
-extern void atari_sched_init(irqreturn_t (*)(int, void *, struct pt_regs *));
-extern unsigned long atari_gettimeoffset (void);
+extern void atari_sched_init(irq_handler_t);
+extern u32 atari_gettimeoffset(void);
extern int atari_mste_hwclk (int, struct rtc_time *);
extern int atari_tt_hwclk (int, struct rtc_time *);
extern int atari_mste_set_clock_mmss (unsigned long);
extern int atari_tt_set_clock_mmss (unsigned long);
-/* atari specific debug functions (in debug.c) */
-extern void atari_debug_init(void);
-
-
-/* I've moved hwreg_present() and hwreg_present_bywrite() out into
- * mm/hwtest.c, to avoid having multiple copies of the same routine
- * in the kernel [I wanted them in hp300 and they were already used
- * in the nubus code. NB: I don't have an Atari so this might (just
- * conceivably) break something.
- * I've preserved the #if 0 version of hwreg_present_bywrite() here
- * for posterity.
- * -- Peter Maydell <pmaydell@chiark.greenend.org.uk>, 05/1998
- */
-
-#if 0
-static int __init
-hwreg_present_bywrite(volatile void *regp, unsigned char val)
-{
- int ret;
- long save_sp, save_vbr;
- static long tmp_vectors[3] = { [2] = (long)&&after_test };
-
- __asm__ __volatile__
- ( "movec %/vbr,%2\n\t" /* save vbr value */
- "movec %4,%/vbr\n\t" /* set up temporary vectors */
- "movel %/sp,%1\n\t" /* save sp */
- "moveq #0,%0\n\t" /* assume not present */
- "moveb %5,%3@\n\t" /* write the hardware reg */
- "cmpb %3@,%5\n\t" /* compare it */
- "seq %0" /* comes here only if reg */
- /* is present */
- : "=d&" (ret), "=r&" (save_sp), "=r&" (save_vbr)
- : "a" (regp), "r" (tmp_vectors), "d" (val)
- );
- after_test:
- __asm__ __volatile__
- ( "movel %0,%/sp\n\t" /* restore sp */
- "movec %1,%/vbr" /* restore vbr */
- : : "r" (save_sp), "r" (save_vbr) : "sp"
- );
-
- return( ret );
-}
-#endif
-
/* ++roman: This is a more elaborate test for an SCC chip, since the plain
* Medusa board generates DTACK at the SCC's standard addresses, but a SCC
@@ -133,26 +93,34 @@ hwreg_present_bywrite(volatile void *regp, unsigned char val)
* should be readable without trouble (from channel A!).
*/
-static int __init scc_test( volatile char *ctla )
+static int __init scc_test(volatile char *ctla)
{
- if (!hwreg_present( ctla ))
- return( 0 );
+ if (!hwreg_present(ctla))
+ return 0;
MFPDELAY();
- *ctla = 2; MFPDELAY();
- *ctla = 0x40; MFPDELAY();
+ *ctla = 2;
+ MFPDELAY();
+ *ctla = 0x40;
+ MFPDELAY();
- *ctla = 2; MFPDELAY();
- if (*ctla != 0x40) return( 0 );
+ *ctla = 2;
+ MFPDELAY();
+ if (*ctla != 0x40)
+ return 0;
MFPDELAY();
- *ctla = 2; MFPDELAY();
- *ctla = 0x60; MFPDELAY();
+ *ctla = 2;
+ MFPDELAY();
+ *ctla = 0x60;
+ MFPDELAY();
- *ctla = 2; MFPDELAY();
- if (*ctla != 0x60) return( 0 );
+ *ctla = 2;
+ MFPDELAY();
+ if (*ctla != 0x60)
+ return 0;
- return( 1 );
+ return 1;
}
@@ -162,61 +130,66 @@ static int __init scc_test( volatile char *ctla )
int __init atari_parse_bootinfo(const struct bi_record *record)
{
- int unknown = 0;
- const u_long *data = record->data;
+ int unknown = 0;
+ const void *data = record->data;
- switch (record->tag) {
+ switch (be16_to_cpu(record->tag)) {
case BI_ATARI_MCH_COOKIE:
- atari_mch_cookie = *data;
- break;
+ atari_mch_cookie = be32_to_cpup(data);
+ break;
case BI_ATARI_MCH_TYPE:
- atari_mch_type = *data;
- break;
+ atari_mch_type = be32_to_cpup(data);
+ break;
default:
- unknown = 1;
- }
- return(unknown);
+ unknown = 1;
+ break;
+ }
+ return unknown;
}
/* Parse the Atari-specific switches= option. */
-void __init atari_switches_setup( const char *str, unsigned len )
+static int __init atari_switches_setup(char *str)
{
- char switches[len+1];
- char *p;
- int ovsc_shift;
- char *args = switches;
-
- /* copy string to local array, strsep works destructively... */
- strlcpy( switches, str, sizeof(switches) );
- atari_switches = 0;
-
- /* parse the options */
- while ((p = strsep(&args, ",")) != NULL) {
- if (!*p) continue;
- ovsc_shift = 0;
- if (strncmp( p, "ov_", 3 ) == 0) {
- p += 3;
- ovsc_shift = ATARI_SWITCH_OVSC_SHIFT;
- }
-
- if (strcmp( p, "ikbd" ) == 0) {
- /* RTS line of IKBD ACIA */
- atari_switches |= ATARI_SWITCH_IKBD << ovsc_shift;
- }
- else if (strcmp( p, "midi" ) == 0) {
- /* RTS line of MIDI ACIA */
- atari_switches |= ATARI_SWITCH_MIDI << ovsc_shift;
- }
- else if (strcmp( p, "snd6" ) == 0) {
- atari_switches |= ATARI_SWITCH_SND6 << ovsc_shift;
+ char switches[strlen(str) + 1];
+ char *p;
+ int ovsc_shift;
+ char *args = switches;
+
+ if (!MACH_IS_ATARI)
+ return 0;
+
+ /* copy string to local array, strsep works destructively... */
+ strcpy(switches, str);
+ atari_switches = 0;
+
+ /* parse the options */
+ while ((p = strsep(&args, ",")) != NULL) {
+ if (!*p)
+ continue;
+ ovsc_shift = 0;
+ if (strncmp(p, "ov_", 3) == 0) {
+ p += 3;
+ ovsc_shift = ATARI_SWITCH_OVSC_SHIFT;
+ }
+
+ if (strcmp(p, "ikbd") == 0) {
+ /* RTS line of IKBD ACIA */
+ atari_switches |= ATARI_SWITCH_IKBD << ovsc_shift;
+ } else if (strcmp(p, "midi") == 0) {
+ /* RTS line of MIDI ACIA */
+ atari_switches |= ATARI_SWITCH_MIDI << ovsc_shift;
+ } else if (strcmp(p, "snd6") == 0) {
+ atari_switches |= ATARI_SWITCH_SND6 << ovsc_shift;
+ } else if (strcmp(p, "snd7") == 0) {
+ atari_switches |= ATARI_SWITCH_SND7 << ovsc_shift;
+ }
}
- else if (strcmp( p, "snd7" ) == 0) {
- atari_switches |= ATARI_SWITCH_SND7 << ovsc_shift;
- }
- }
+ return 0;
}
+early_param("switches", atari_switches_setup);
+
/*
* Setup the Atari configuration info
@@ -224,295 +197,271 @@ void __init atari_switches_setup( const char *str, unsigned len )
void __init config_atari(void)
{
- unsigned short tos_version;
-
- memset(&atari_hw_present, 0, sizeof(atari_hw_present));
-
- atari_debug_init();
-
- ioport_resource.end = 0xFFFFFFFF; /* Change size of I/O space from 64KB
- to 4GB. */
-
- mach_sched_init = atari_sched_init;
- mach_init_IRQ = atari_init_IRQ;
- mach_request_irq = atari_request_irq;
- mach_free_irq = atari_free_irq;
- enable_irq = atari_enable_irq;
- disable_irq = atari_disable_irq;
- mach_get_model = atari_get_model;
- mach_get_hardware_list = atari_get_hardware_list;
- mach_get_irq_list = show_atari_interrupts;
- mach_gettimeoffset = atari_gettimeoffset;
- mach_reset = atari_reset;
-#ifdef CONFIG_ATARI_FLOPPY
- mach_floppy_setup = atari_floppy_setup;
-#endif
-#ifdef CONFIG_DUMMY_CONSOLE
- conswitchp = &dummy_con;
-#endif
- mach_max_dma_address = 0xffffff;
+ unsigned short tos_version;
+
+ memset(&atari_hw_present, 0, sizeof(atari_hw_present));
+
+ /* Change size of I/O space from 64KB to 4GB. */
+ ioport_resource.end = 0xFFFFFFFF;
+
+ mach_sched_init = atari_sched_init;
+ mach_init_IRQ = atari_init_IRQ;
+ mach_get_model = atari_get_model;
+ mach_get_hardware_list = atari_get_hardware_list;
+ arch_gettimeoffset = atari_gettimeoffset;
+ mach_reset = atari_reset;
+ mach_max_dma_address = 0xffffff;
#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
- mach_beep = atari_mksound;
+ mach_beep = atari_mksound;
#endif
#ifdef CONFIG_HEARTBEAT
- mach_heartbeat = atari_heartbeat;
+ mach_heartbeat = atari_heartbeat;
#endif
- /* Set switches as requested by the user */
- if (atari_switches & ATARI_SWITCH_IKBD)
- acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID;
- if (atari_switches & ATARI_SWITCH_MIDI)
- acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
- if (atari_switches & (ATARI_SWITCH_SND6|ATARI_SWITCH_SND7)) {
- sound_ym.rd_data_reg_sel = 14;
- sound_ym.wd_data = sound_ym.rd_data_reg_sel |
- ((atari_switches&ATARI_SWITCH_SND6) ? 0x40 : 0) |
- ((atari_switches&ATARI_SWITCH_SND7) ? 0x80 : 0);
- }
-
- /* ++bjoern:
- * Determine hardware present
- */
+ /* Set switches as requested by the user */
+ if (atari_switches & ATARI_SWITCH_IKBD)
+ acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID;
+ if (atari_switches & ATARI_SWITCH_MIDI)
+ acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
+ if (atari_switches & (ATARI_SWITCH_SND6|ATARI_SWITCH_SND7)) {
+ sound_ym.rd_data_reg_sel = 14;
+ sound_ym.wd_data = sound_ym.rd_data_reg_sel |
+ ((atari_switches&ATARI_SWITCH_SND6) ? 0x40 : 0) |
+ ((atari_switches&ATARI_SWITCH_SND7) ? 0x80 : 0);
+ }
- printk( "Atari hardware found: " );
- if (MACH_IS_MEDUSA || MACH_IS_HADES) {
- /* There's no Atari video hardware on the Medusa, but all the
- * addresses below generate a DTACK so no bus error occurs! */
- }
- else if (hwreg_present( f030_xreg )) {
- ATARIHW_SET(VIDEL_SHIFTER);
- printk( "VIDEL " );
- /* This is a temporary hack: If there is Falcon video
- * hardware, we assume that the ST-DMA serves SCSI instead of
- * ACSI. In the future, there should be a better method for
- * this...
- */
- ATARIHW_SET(ST_SCSI);
- printk( "STDMA-SCSI " );
- }
- else if (hwreg_present( tt_palette )) {
- ATARIHW_SET(TT_SHIFTER);
- printk( "TT_SHIFTER " );
- }
- else if (hwreg_present( &shifter.bas_hi )) {
- if (hwreg_present( &shifter.bas_lo ) &&
- (shifter.bas_lo = 0x0aau, shifter.bas_lo == 0x0aau)) {
- ATARIHW_SET(EXTD_SHIFTER);
- printk( "EXTD_SHIFTER " );
- }
- else {
- ATARIHW_SET(STND_SHIFTER);
- printk( "STND_SHIFTER " );
- }
- }
- if (hwreg_present( &mfp.par_dt_reg )) {
- ATARIHW_SET(ST_MFP);
- printk( "ST_MFP " );
- }
- if (hwreg_present( &tt_mfp.par_dt_reg )) {
- ATARIHW_SET(TT_MFP);
- printk( "TT_MFP " );
- }
- if (hwreg_present( &tt_scsi_dma.dma_addr_hi )) {
- ATARIHW_SET(SCSI_DMA);
- printk( "TT_SCSI_DMA " );
- }
- if (!MACH_IS_HADES && hwreg_present( &st_dma.dma_hi )) {
- ATARIHW_SET(STND_DMA);
- printk( "STND_DMA " );
- }
- if (MACH_IS_MEDUSA || /* The ST-DMA address registers aren't readable
- * on all Medusas, so the test below may fail */
- (hwreg_present( &st_dma.dma_vhi ) &&
- (st_dma.dma_vhi = 0x55) && (st_dma.dma_hi = 0xaa) &&
- st_dma.dma_vhi == 0x55 && st_dma.dma_hi == 0xaa &&
- (st_dma.dma_vhi = 0xaa) && (st_dma.dma_hi = 0x55) &&
- st_dma.dma_vhi == 0xaa && st_dma.dma_hi == 0x55)) {
- ATARIHW_SET(EXTD_DMA);
- printk( "EXTD_DMA " );
- }
- if (hwreg_present( &tt_scsi.scsi_data )) {
- ATARIHW_SET(TT_SCSI);
- printk( "TT_SCSI " );
- }
- if (hwreg_present( &sound_ym.rd_data_reg_sel )) {
- ATARIHW_SET(YM_2149);
- printk( "YM2149 " );
- }
- if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
- hwreg_present( &tt_dmasnd.ctrl )) {
- ATARIHW_SET(PCM_8BIT);
- printk( "PCM " );
- }
- if (!MACH_IS_HADES && hwreg_present( &falcon_codec.unused5 )) {
- ATARIHW_SET(CODEC);
- printk( "CODEC " );
- }
- if (hwreg_present( &dsp56k_host_interface.icr )) {
- ATARIHW_SET(DSP56K);
- printk( "DSP56K " );
- }
- if (hwreg_present( &tt_scc_dma.dma_ctrl ) &&
+ /* ++bjoern:
+ * Determine hardware present
+ */
+
+ printk("Atari hardware found: ");
+ if (MACH_IS_MEDUSA) {
+ /* There's no Atari video hardware on the Medusa, but all the
+ * addresses below generate a DTACK so no bus error occurs! */
+ } else if (hwreg_present(f030_xreg)) {
+ ATARIHW_SET(VIDEL_SHIFTER);
+ printk("VIDEL ");
+ /* This is a temporary hack: If there is Falcon video
+ * hardware, we assume that the ST-DMA serves SCSI instead of
+ * ACSI. In the future, there should be a better method for
+ * this...
+ */
+ ATARIHW_SET(ST_SCSI);
+ printk("STDMA-SCSI ");
+ } else if (hwreg_present(tt_palette)) {
+ ATARIHW_SET(TT_SHIFTER);
+ printk("TT_SHIFTER ");
+ } else if (hwreg_present(&shifter.bas_hi)) {
+ if (hwreg_present(&shifter.bas_lo) &&
+ (shifter.bas_lo = 0x0aau, shifter.bas_lo == 0x0aau)) {
+ ATARIHW_SET(EXTD_SHIFTER);
+ printk("EXTD_SHIFTER ");
+ } else {
+ ATARIHW_SET(STND_SHIFTER);
+ printk("STND_SHIFTER ");
+ }
+ }
+ if (hwreg_present(&st_mfp.par_dt_reg)) {
+ ATARIHW_SET(ST_MFP);
+ printk("ST_MFP ");
+ }
+ if (hwreg_present(&tt_mfp.par_dt_reg)) {
+ ATARIHW_SET(TT_MFP);
+ printk("TT_MFP ");
+ }
+ if (hwreg_present(&tt_scsi_dma.dma_addr_hi)) {
+ ATARIHW_SET(SCSI_DMA);
+ printk("TT_SCSI_DMA ");
+ }
+ /*
+ * The ST-DMA address registers aren't readable
+ * on all Medusas, so the test below may fail
+ */
+ if (MACH_IS_MEDUSA ||
+ (hwreg_present(&st_dma.dma_vhi) &&
+ (st_dma.dma_vhi = 0x55) && (st_dma.dma_hi = 0xaa) &&
+ st_dma.dma_vhi == 0x55 && st_dma.dma_hi == 0xaa &&
+ (st_dma.dma_vhi = 0xaa) && (st_dma.dma_hi = 0x55) &&
+ st_dma.dma_vhi == 0xaa && st_dma.dma_hi == 0x55)) {
+ ATARIHW_SET(EXTD_DMA);
+ printk("EXTD_DMA ");
+ }
+ if (hwreg_present(&tt_scsi.scsi_data)) {
+ ATARIHW_SET(TT_SCSI);
+ printk("TT_SCSI ");
+ }
+ if (hwreg_present(&sound_ym.rd_data_reg_sel)) {
+ ATARIHW_SET(YM_2149);
+ printk("YM2149 ");
+ }
+ if (!MACH_IS_MEDUSA && hwreg_present(&tt_dmasnd.ctrl)) {
+ ATARIHW_SET(PCM_8BIT);
+ printk("PCM ");
+ }
+ if (hwreg_present(&falcon_codec.unused5)) {
+ ATARIHW_SET(CODEC);
+ printk("CODEC ");
+ }
+ if (hwreg_present(&dsp56k_host_interface.icr)) {
+ ATARIHW_SET(DSP56K);
+ printk("DSP56K ");
+ }
+ if (hwreg_present(&tt_scc_dma.dma_ctrl) &&
#if 0
- /* This test sucks! Who knows some better? */
- (tt_scc_dma.dma_ctrl = 0x01, (tt_scc_dma.dma_ctrl & 1) == 1) &&
- (tt_scc_dma.dma_ctrl = 0x00, (tt_scc_dma.dma_ctrl & 1) == 0)
+ /* This test sucks! Who knows some better? */
+ (tt_scc_dma.dma_ctrl = 0x01, (tt_scc_dma.dma_ctrl & 1) == 1) &&
+ (tt_scc_dma.dma_ctrl = 0x00, (tt_scc_dma.dma_ctrl & 1) == 0)
#else
- !MACH_IS_MEDUSA && !MACH_IS_HADES
+ !MACH_IS_MEDUSA
#endif
- ) {
- ATARIHW_SET(SCC_DMA);
- printk( "SCC_DMA " );
- }
- if (scc_test( &scc.cha_a_ctrl )) {
- ATARIHW_SET(SCC);
- printk( "SCC " );
- }
- if (scc_test( &st_escc.cha_b_ctrl )) {
- ATARIHW_SET( ST_ESCC );
- printk( "ST_ESCC " );
- }
- if (MACH_IS_HADES)
- {
- ATARIHW_SET( VME );
- printk( "VME " );
- }
- else if (hwreg_present( &tt_scu.sys_mask )) {
- ATARIHW_SET(SCU);
- /* Assume a VME bus if there's a SCU */
- ATARIHW_SET( VME );
- printk( "VME SCU " );
- }
- if (hwreg_present( (void *)(0xffff9210) )) {
- ATARIHW_SET(ANALOG_JOY);
- printk( "ANALOG_JOY " );
- }
- if (!MACH_IS_HADES && hwreg_present( blitter.halftone )) {
- ATARIHW_SET(BLITTER);
- printk( "BLITTER " );
- }
- if (hwreg_present((void *)0xfff00039)) {
- ATARIHW_SET(IDE);
- printk( "IDE " );
- }
+ ) {
+ ATARIHW_SET(SCC_DMA);
+ printk("SCC_DMA ");
+ }
+ if (scc_test(&atari_scc.cha_a_ctrl)) {
+ ATARIHW_SET(SCC);
+ printk("SCC ");
+ }
+ if (scc_test(&st_escc.cha_b_ctrl)) {
+ ATARIHW_SET(ST_ESCC);
+ printk("ST_ESCC ");
+ }
+ if (hwreg_present(&tt_scu.sys_mask)) {
+ ATARIHW_SET(SCU);
+ /* Assume a VME bus if there's a SCU */
+ ATARIHW_SET(VME);
+ printk("VME SCU ");
+ }
+ if (hwreg_present((void *)(0xffff9210))) {
+ ATARIHW_SET(ANALOG_JOY);
+ printk("ANALOG_JOY ");
+ }
+ if (hwreg_present(blitter.halftone)) {
+ ATARIHW_SET(BLITTER);
+ printk("BLITTER ");
+ }
+ if (hwreg_present((void *)0xfff00039)) {
+ ATARIHW_SET(IDE);
+ printk("IDE ");
+ }
#if 1 /* This maybe wrong */
- if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
- hwreg_present( &tt_microwire.data ) &&
- hwreg_present( &tt_microwire.mask ) &&
- (tt_microwire.mask = 0x7ff,
- udelay(1),
- tt_microwire.data = MW_LM1992_PSG_HIGH | MW_LM1992_ADDR,
- udelay(1),
- tt_microwire.data != 0)) {
- ATARIHW_SET(MICROWIRE);
- while (tt_microwire.mask != 0x7ff) ;
- printk( "MICROWIRE " );
- }
+ if (!MACH_IS_MEDUSA && hwreg_present(&tt_microwire.data) &&
+ hwreg_present(&tt_microwire.mask) &&
+ (tt_microwire.mask = 0x7ff,
+ udelay(1),
+ tt_microwire.data = MW_LM1992_PSG_HIGH | MW_LM1992_ADDR,
+ udelay(1),
+ tt_microwire.data != 0)) {
+ ATARIHW_SET(MICROWIRE);
+ while (tt_microwire.mask != 0x7ff)
+ ;
+ printk("MICROWIRE ");
+ }
#endif
- if (hwreg_present( &tt_rtc.regsel )) {
- ATARIHW_SET(TT_CLK);
- printk( "TT_CLK " );
- mach_hwclk = atari_tt_hwclk;
- mach_set_clock_mmss = atari_tt_set_clock_mmss;
- }
- if (!MACH_IS_HADES && hwreg_present( &mste_rtc.sec_ones)) {
- ATARIHW_SET(MSTE_CLK);
- printk( "MSTE_CLK ");
- mach_hwclk = atari_mste_hwclk;
- mach_set_clock_mmss = atari_mste_set_clock_mmss;
- }
- if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
- hwreg_present( &dma_wd.fdc_speed ) &&
- hwreg_write( &dma_wd.fdc_speed, 0 )) {
- ATARIHW_SET(FDCSPEED);
- printk( "FDC_SPEED ");
- }
- if (!MACH_IS_HADES && !ATARIHW_PRESENT(ST_SCSI)) {
- ATARIHW_SET(ACSI);
- printk( "ACSI " );
- }
- printk("\n");
-
- if (CPU_IS_040_OR_060)
- /* Now it seems to be safe to turn of the tt0 transparent
- * translation (the one that must not be turned off in
- * head.S...)
- */
- __asm__ volatile ("moveq #0,%/d0\n\t"
- ".chip 68040\n\t"
- "movec %%d0,%%itt0\n\t"
- "movec %%d0,%%dtt0\n\t"
- ".chip 68k"
- : /* no outputs */
- : /* no inputs */
- : "d0");
-
- /* allocator for memory that must reside in st-ram */
- atari_stram_init ();
-
- /* Set up a mapping for the VMEbus address region:
- *
- * VME is either at phys. 0xfexxxxxx (TT) or 0xa00000..0xdfffff
- * (MegaSTE) In both cases, the whole 16 MB chunk is mapped at
- * 0xfe000000 virt., because this can be done with a single
- * transparent translation. On the 68040, lots of often unused
- * page tables would be needed otherwise. On a MegaSTE or similar,
- * the highest byte is stripped off by hardware due to the 24 bit
- * design of the bus.
- */
+ if (hwreg_present(&tt_rtc.regsel)) {
+ ATARIHW_SET(TT_CLK);
+ printk("TT_CLK ");
+ mach_hwclk = atari_tt_hwclk;
+ mach_set_clock_mmss = atari_tt_set_clock_mmss;
+ }
+ if (hwreg_present(&mste_rtc.sec_ones)) {
+ ATARIHW_SET(MSTE_CLK);
+ printk("MSTE_CLK ");
+ mach_hwclk = atari_mste_hwclk;
+ mach_set_clock_mmss = atari_mste_set_clock_mmss;
+ }
+ if (!MACH_IS_MEDUSA && hwreg_present(&dma_wd.fdc_speed) &&
+ hwreg_write(&dma_wd.fdc_speed, 0)) {
+ ATARIHW_SET(FDCSPEED);
+ printk("FDC_SPEED ");
+ }
+ if (!ATARIHW_PRESENT(ST_SCSI)) {
+ ATARIHW_SET(ACSI);
+ printk("ACSI ");
+ }
+ printk("\n");
+
+ if (CPU_IS_040_OR_060)
+ /* Now it seems to be safe to turn of the tt0 transparent
+ * translation (the one that must not be turned off in
+ * head.S...)
+ */
+ asm volatile ("\n"
+ " moveq #0,%%d0\n"
+ " .chip 68040\n"
+ " movec %%d0,%%itt0\n"
+ " movec %%d0,%%dtt0\n"
+ " .chip 68k"
+ : /* no outputs */
+ : /* no inputs */
+ : "d0");
+
+ /* allocator for memory that must reside in st-ram */
+ atari_stram_init();
+
+ /* Set up a mapping for the VMEbus address region:
+ *
+ * VME is either at phys. 0xfexxxxxx (TT) or 0xa00000..0xdfffff
+ * (MegaSTE) In both cases, the whole 16 MB chunk is mapped at
+ * 0xfe000000 virt., because this can be done with a single
+ * transparent translation. On the 68040, lots of often unused
+ * page tables would be needed otherwise. On a MegaSTE or similar,
+ * the highest byte is stripped off by hardware due to the 24 bit
+ * design of the bus.
+ */
+
+ if (CPU_IS_020_OR_030) {
+ unsigned long tt1_val;
+ tt1_val = 0xfe008543; /* Translate 0xfexxxxxx, enable, cache
+ * inhibit, read and write, FDC mask = 3,
+ * FDC val = 4 -> Supervisor only */
+ asm volatile ("\n"
+ " .chip 68030\n"
+ " pmove %0,%/tt1\n"
+ " .chip 68k"
+ : : "m" (tt1_val));
+ } else {
+ asm volatile ("\n"
+ " .chip 68040\n"
+ " movec %0,%%itt1\n"
+ " movec %0,%%dtt1\n"
+ " .chip 68k"
+ :
+ : "d" (0xfe00a040)); /* Translate 0xfexxxxxx, enable,
+ * supervisor only, non-cacheable/
+ * serialized, writable */
- if (CPU_IS_020_OR_030) {
- unsigned long tt1_val;
- tt1_val = 0xfe008543; /* Translate 0xfexxxxxx, enable, cache
- * inhibit, read and write, FDC mask = 3,
- * FDC val = 4 -> Supervisor only */
- __asm__ __volatile__ ( ".chip 68030\n\t"
- "pmove %0@,%/tt1\n\t"
- ".chip 68k"
- : : "a" (&tt1_val) );
- }
- else {
- __asm__ __volatile__
- ( "movel %0,%/d0\n\t"
- ".chip 68040\n\t"
- "movec %%d0,%%itt1\n\t"
- "movec %%d0,%%dtt1\n\t"
- ".chip 68k"
- :
- : "g" (0xfe00a040) /* Translate 0xfexxxxxx, enable,
- * supervisor only, non-cacheable/
- * serialized, writable */
- : "d0" );
-
- }
-
- /* Fetch tos version at Physical 2 */
- /* We my not be able to access this address if the kernel is
- loaded to st ram, since the first page is unmapped. On the
- Medusa this is always the case and there is nothing we can do
- about this, so we just assume the smaller offset. For the TT
- we use the fact that in head.S we have set up a mapping
- 0xFFxxxxxx -> 0x00xxxxxx, so that the first 16MB is accessible
- in the last 16MB of the address space. */
- tos_version = (MACH_IS_MEDUSA || MACH_IS_HADES) ?
- 0xfff : *(unsigned short *)0xff000002;
- atari_rtc_year_offset = (tos_version < 0x306) ? 70 : 68;
+ }
+
+ /* Fetch tos version at Physical 2 */
+ /*
+ * We my not be able to access this address if the kernel is
+ * loaded to st ram, since the first page is unmapped. On the
+ * Medusa this is always the case and there is nothing we can do
+ * about this, so we just assume the smaller offset. For the TT
+ * we use the fact that in head.S we have set up a mapping
+ * 0xFFxxxxxx -> 0x00xxxxxx, so that the first 16MB is accessible
+ * in the last 16MB of the address space.
+ */
+ tos_version = (MACH_IS_MEDUSA) ?
+ 0xfff : *(unsigned short *)0xff000002;
+ atari_rtc_year_offset = (tos_version < 0x306) ? 70 : 68;
}
#ifdef CONFIG_HEARTBEAT
-static void atari_heartbeat( int on )
+static void atari_heartbeat(int on)
{
- unsigned char tmp;
- unsigned long flags;
+ unsigned char tmp;
+ unsigned long flags;
- if (atari_dont_touch_floppy_select)
- return;
+ if (atari_dont_touch_floppy_select)
+ return;
- local_irq_save(flags);
- sound_ym.rd_data_reg_sel = 14; /* Select PSG Port A */
- tmp = sound_ym.rd_data_reg_sel;
- sound_ym.wd_data = on ? (tmp & ~0x02) : (tmp | 0x02);
- local_irq_restore(flags);
+ local_irq_save(flags);
+ sound_ym.rd_data_reg_sel = 14; /* Select PSG Port A */
+ tmp = sound_ym.rd_data_reg_sel;
+ sound_ym.wd_data = on ? (tmp & ~0x02) : (tmp | 0x02);
+ local_irq_restore(flags);
}
#endif
@@ -547,180 +496,403 @@ static void atari_heartbeat( int on )
/* ++andreas: no need for complicated code, just depend on prefetch */
-static void atari_reset (void)
+static void atari_reset(void)
{
- long tc_val = 0;
- long reset_addr;
-
- /* On the Medusa, phys. 0x4 may contain garbage because it's no
- ROM. See above for explanation why we cannot use PTOV(4). */
- reset_addr = MACH_IS_HADES ? 0x7fe00030 :
- MACH_IS_MEDUSA || MACH_IS_AB40 ? 0xe00030 :
- *(unsigned long *) 0xff000004;
-
- /* reset ACIA for switch off OverScan, if it's active */
- if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
- acia.key_ctrl = ACIA_RESET;
- if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
- acia.mid_ctrl = ACIA_RESET;
-
- /* processor independent: turn off interrupts and reset the VBR;
- * the caches must be left enabled, else prefetching the final jump
- * instruction doesn't work. */
- local_irq_disable();
- __asm__ __volatile__
- ("moveq #0,%/d0\n\t"
- "movec %/d0,%/vbr"
- : : : "d0" );
-
- if (CPU_IS_040_OR_060) {
- unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040);
- if (CPU_IS_060) {
- /* 68060: clear PCR to turn off superscalar operation */
- __asm__ __volatile__
- ("moveq #0,%/d0\n\t"
- ".chip 68060\n\t"
- "movec %%d0,%%pcr\n\t"
- ".chip 68k"
- : : : "d0" );
- }
-
- __asm__ __volatile__
- ("movel %0,%/d0\n\t"
- "andl #0xff000000,%/d0\n\t"
- "orw #0xe020,%/d0\n\t" /* map 16 MB, enable, cacheable */
- ".chip 68040\n\t"
- "movec %%d0,%%itt0\n\t"
- "movec %%d0,%%dtt0\n\t"
- ".chip 68k\n\t"
- "jmp %0@\n\t"
- : /* no outputs */
- : "a" (jmp_addr040)
- : "d0" );
- jmp_addr_label040:
- __asm__ __volatile__
- ("moveq #0,%/d0\n\t"
- "nop\n\t"
- ".chip 68040\n\t"
- "cinva %%bc\n\t"
- "nop\n\t"
- "pflusha\n\t"
- "nop\n\t"
- "movec %%d0,%%tc\n\t"
- "nop\n\t"
- /* the following setup of transparent translations is needed on the
- * Afterburner040 to successfully reboot. Other machines shouldn't
- * care about a different tt regs setup, they also didn't care in
- * the past that the regs weren't turned off. */
- "movel #0xffc000,%%d0\n\t" /* whole insn space cacheable */
- "movec %%d0,%%itt0\n\t"
- "movec %%d0,%%itt1\n\t"
- "orw #0x40,%/d0\n\t" /* whole data space non-cacheable/ser. */
- "movec %%d0,%%dtt0\n\t"
- "movec %%d0,%%dtt1\n\t"
- ".chip 68k\n\t"
- "jmp %0@"
- : /* no outputs */
- : "a" (reset_addr)
- : "d0");
- }
- else
- __asm__ __volatile__
- ("pmove %0@,%/tc\n\t"
- "jmp %1@"
- : /* no outputs */
- : "a" (&tc_val), "a" (reset_addr));
+ long tc_val = 0;
+ long reset_addr;
+
+ /*
+ * On the Medusa, phys. 0x4 may contain garbage because it's no
+ * ROM. See above for explanation why we cannot use PTOV(4).
+ */
+ reset_addr = MACH_IS_MEDUSA || MACH_IS_AB40 ? 0xe00030 :
+ *(unsigned long *) 0xff000004;
+
+ /* reset ACIA for switch off OverScan, if it's active */
+ if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
+ acia.key_ctrl = ACIA_RESET;
+ if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
+ acia.mid_ctrl = ACIA_RESET;
+
+ /* processor independent: turn off interrupts and reset the VBR;
+ * the caches must be left enabled, else prefetching the final jump
+ * instruction doesn't work.
+ */
+ local_irq_disable();
+ asm volatile ("movec %0,%%vbr"
+ : : "d" (0));
+
+ if (CPU_IS_040_OR_060) {
+ unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040);
+ if (CPU_IS_060) {
+ /* 68060: clear PCR to turn off superscalar operation */
+ asm volatile ("\n"
+ " .chip 68060\n"
+ " movec %0,%%pcr\n"
+ " .chip 68k"
+ : : "d" (0));
+ }
+
+ asm volatile ("\n"
+ " move.l %0,%%d0\n"
+ " and.l #0xff000000,%%d0\n"
+ " or.w #0xe020,%%d0\n" /* map 16 MB, enable, cacheable */
+ " .chip 68040\n"
+ " movec %%d0,%%itt0\n"
+ " movec %%d0,%%dtt0\n"
+ " .chip 68k\n"
+ " jmp %0@"
+ : : "a" (jmp_addr040)
+ : "d0");
+ jmp_addr_label040:
+ asm volatile ("\n"
+ " moveq #0,%%d0\n"
+ " nop\n"
+ " .chip 68040\n"
+ " cinva %%bc\n"
+ " nop\n"
+ " pflusha\n"
+ " nop\n"
+ " movec %%d0,%%tc\n"
+ " nop\n"
+ /* the following setup of transparent translations is needed on the
+ * Afterburner040 to successfully reboot. Other machines shouldn't
+ * care about a different tt regs setup, they also didn't care in
+ * the past that the regs weren't turned off. */
+ " move.l #0xffc000,%%d0\n" /* whole insn space cacheable */
+ " movec %%d0,%%itt0\n"
+ " movec %%d0,%%itt1\n"
+ " or.w #0x40,%/d0\n" /* whole data space non-cacheable/ser. */
+ " movec %%d0,%%dtt0\n"
+ " movec %%d0,%%dtt1\n"
+ " .chip 68k\n"
+ " jmp %0@"
+ : /* no outputs */
+ : "a" (reset_addr)
+ : "d0");
+ } else
+ asm volatile ("\n"
+ " pmove %0,%%tc\n"
+ " jmp %1@"
+ : /* no outputs */
+ : "m" (tc_val), "a" (reset_addr));
}
static void atari_get_model(char *model)
{
- strcpy(model, "Atari ");
- switch (atari_mch_cookie >> 16) {
+ strcpy(model, "Atari ");
+ switch (atari_mch_cookie >> 16) {
case ATARI_MCH_ST:
- if (ATARIHW_PRESENT(MSTE_CLK))
- strcat (model, "Mega ST");
- else
- strcat (model, "ST");
- break;
+ if (ATARIHW_PRESENT(MSTE_CLK))
+ strcat(model, "Mega ST");
+ else
+ strcat(model, "ST");
+ break;
case ATARI_MCH_STE:
- if (MACH_IS_MSTE)
- strcat (model, "Mega STE");
- else
- strcat (model, "STE");
- break;
+ if (MACH_IS_MSTE)
+ strcat(model, "Mega STE");
+ else
+ strcat(model, "STE");
+ break;
case ATARI_MCH_TT:
- if (MACH_IS_MEDUSA)
- /* Medusa has TT _MCH cookie */
- strcat (model, "Medusa");
- else if (MACH_IS_HADES)
- strcat(model, "Hades");
- else
- strcat (model, "TT");
- break;
+ if (MACH_IS_MEDUSA)
+ /* Medusa has TT _MCH cookie */
+ strcat(model, "Medusa");
+ else
+ strcat(model, "TT");
+ break;
case ATARI_MCH_FALCON:
- strcat (model, "Falcon");
- if (MACH_IS_AB40)
- strcat (model, " (with Afterburner040)");
- break;
+ strcat(model, "Falcon");
+ if (MACH_IS_AB40)
+ strcat(model, " (with Afterburner040)");
+ break;
default:
- sprintf (model + strlen (model), "(unknown mach cookie 0x%lx)",
- atari_mch_cookie);
- break;
- }
+ sprintf(model + strlen(model), "(unknown mach cookie 0x%lx)",
+ atari_mch_cookie);
+ break;
+ }
}
-static int atari_get_hardware_list(char *buffer)
+static void atari_get_hardware_list(struct seq_file *m)
{
- int len = 0, i;
-
- for (i = 0; i < m68k_num_memory; i++)
- len += sprintf (buffer+len, "\t%3ld MB at 0x%08lx (%s)\n",
- m68k_memory[i].size >> 20, m68k_memory[i].addr,
- (m68k_memory[i].addr & 0xff000000 ?
- "alternate RAM" : "ST-RAM"));
-
-#define ATARIHW_ANNOUNCE(name,str) \
- if (ATARIHW_PRESENT(name)) \
- len += sprintf (buffer + len, "\t%s\n", str)
-
- len += sprintf (buffer + len, "Detected hardware:\n");
- ATARIHW_ANNOUNCE(STND_SHIFTER, "ST Shifter");
- ATARIHW_ANNOUNCE(EXTD_SHIFTER, "STe Shifter");
- ATARIHW_ANNOUNCE(TT_SHIFTER, "TT Shifter");
- ATARIHW_ANNOUNCE(VIDEL_SHIFTER, "Falcon Shifter");
- ATARIHW_ANNOUNCE(YM_2149, "Programmable Sound Generator");
- ATARIHW_ANNOUNCE(PCM_8BIT, "PCM 8 Bit Sound");
- ATARIHW_ANNOUNCE(CODEC, "CODEC Sound");
- ATARIHW_ANNOUNCE(TT_SCSI, "SCSI Controller NCR5380 (TT style)");
- ATARIHW_ANNOUNCE(ST_SCSI, "SCSI Controller NCR5380 (Falcon style)");
- ATARIHW_ANNOUNCE(ACSI, "ACSI Interface");
- ATARIHW_ANNOUNCE(IDE, "IDE Interface");
- ATARIHW_ANNOUNCE(FDCSPEED, "8/16 Mhz Switch for FDC");
- ATARIHW_ANNOUNCE(ST_MFP, "Multi Function Peripheral MFP 68901");
- ATARIHW_ANNOUNCE(TT_MFP, "Second Multi Function Peripheral MFP 68901");
- ATARIHW_ANNOUNCE(SCC, "Serial Communications Controller SCC 8530");
- ATARIHW_ANNOUNCE(ST_ESCC, "Extended Serial Communications Controller SCC 85230");
- ATARIHW_ANNOUNCE(ANALOG_JOY, "Paddle Interface");
- ATARIHW_ANNOUNCE(MICROWIRE, "MICROWIRE(tm) Interface");
- ATARIHW_ANNOUNCE(STND_DMA, "DMA Controller (24 bit)");
- ATARIHW_ANNOUNCE(EXTD_DMA, "DMA Controller (32 bit)");
- ATARIHW_ANNOUNCE(SCSI_DMA, "DMA Controller for NCR5380");
- ATARIHW_ANNOUNCE(SCC_DMA, "DMA Controller for SCC");
- ATARIHW_ANNOUNCE(TT_CLK, "Clock Chip MC146818A");
- ATARIHW_ANNOUNCE(MSTE_CLK, "Clock Chip RP5C15");
- ATARIHW_ANNOUNCE(SCU, "System Control Unit");
- ATARIHW_ANNOUNCE(BLITTER, "Blitter");
- ATARIHW_ANNOUNCE(VME, "VME Bus");
- ATARIHW_ANNOUNCE(DSP56K, "DSP56001 processor");
-
- return(len);
+ int i;
+
+ for (i = 0; i < m68k_num_memory; i++)
+ seq_printf(m, "\t%3ld MB at 0x%08lx (%s)\n",
+ m68k_memory[i].size >> 20, m68k_memory[i].addr,
+ (m68k_memory[i].addr & 0xff000000 ?
+ "alternate RAM" : "ST-RAM"));
+
+#define ATARIHW_ANNOUNCE(name, str) \
+ if (ATARIHW_PRESENT(name)) \
+ seq_printf(m, "\t%s\n", str)
+
+ seq_printf(m, "Detected hardware:\n");
+ ATARIHW_ANNOUNCE(STND_SHIFTER, "ST Shifter");
+ ATARIHW_ANNOUNCE(EXTD_SHIFTER, "STe Shifter");
+ ATARIHW_ANNOUNCE(TT_SHIFTER, "TT Shifter");
+ ATARIHW_ANNOUNCE(VIDEL_SHIFTER, "Falcon Shifter");
+ ATARIHW_ANNOUNCE(YM_2149, "Programmable Sound Generator");
+ ATARIHW_ANNOUNCE(PCM_8BIT, "PCM 8 Bit Sound");
+ ATARIHW_ANNOUNCE(CODEC, "CODEC Sound");
+ ATARIHW_ANNOUNCE(TT_SCSI, "SCSI Controller NCR5380 (TT style)");
+ ATARIHW_ANNOUNCE(ST_SCSI, "SCSI Controller NCR5380 (Falcon style)");
+ ATARIHW_ANNOUNCE(ACSI, "ACSI Interface");
+ ATARIHW_ANNOUNCE(IDE, "IDE Interface");
+ ATARIHW_ANNOUNCE(FDCSPEED, "8/16 Mhz Switch for FDC");
+ ATARIHW_ANNOUNCE(ST_MFP, "Multi Function Peripheral MFP 68901");
+ ATARIHW_ANNOUNCE(TT_MFP, "Second Multi Function Peripheral MFP 68901");
+ ATARIHW_ANNOUNCE(SCC, "Serial Communications Controller SCC 8530");
+ ATARIHW_ANNOUNCE(ST_ESCC, "Extended Serial Communications Controller SCC 85230");
+ ATARIHW_ANNOUNCE(ANALOG_JOY, "Paddle Interface");
+ ATARIHW_ANNOUNCE(MICROWIRE, "MICROWIRE(tm) Interface");
+ ATARIHW_ANNOUNCE(STND_DMA, "DMA Controller (24 bit)");
+ ATARIHW_ANNOUNCE(EXTD_DMA, "DMA Controller (32 bit)");
+ ATARIHW_ANNOUNCE(SCSI_DMA, "DMA Controller for NCR5380");
+ ATARIHW_ANNOUNCE(SCC_DMA, "DMA Controller for SCC");
+ ATARIHW_ANNOUNCE(TT_CLK, "Clock Chip MC146818A");
+ ATARIHW_ANNOUNCE(MSTE_CLK, "Clock Chip RP5C15");
+ ATARIHW_ANNOUNCE(SCU, "System Control Unit");
+ ATARIHW_ANNOUNCE(BLITTER, "Blitter");
+ ATARIHW_ANNOUNCE(VME, "VME Bus");
+ ATARIHW_ANNOUNCE(DSP56K, "DSP56001 processor");
}
/*
- * Local variables:
- * c-indent-level: 4
- * tab-width: 8
- * End:
+ * MSch: initial platform device support for Atari,
+ * required for EtherNAT/EtherNEC/NetUSBee drivers
*/
+
+#if defined(CONFIG_ATARI_ETHERNAT) || defined(CONFIG_ATARI_ETHERNEC)
+static void isp1160_delay(struct device *dev, int delay)
+{
+ ndelay(delay);
+}
+#endif
+
+#ifdef CONFIG_ATARI_ETHERNAT
+/*
+ * EtherNAT: SMC91C111 Ethernet chipset, handled by smc91x driver
+ */
+
+#define ATARI_ETHERNAT_IRQ 140
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .name = "smc91x-regs",
+ .start = ATARI_ETHERNAT_PHYS_ADDR,
+ .end = ATARI_ETHERNAT_PHYS_ADDR + 0xfffff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "smc91x-irq",
+ .start = ATARI_ETHERNAT_IRQ,
+ .end = ATARI_ETHERNAT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+/*
+ * ISP 1160 - using the isp116x-hcd module
+ */
+
+#define ATARI_USB_PHYS_ADDR 0x80000012
+#define ATARI_USB_IRQ 139
+
+static struct resource isp1160_resources[] = {
+ [0] = {
+ .name = "isp1160-data",
+ .start = ATARI_USB_PHYS_ADDR,
+ .end = ATARI_USB_PHYS_ADDR + 0x1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "isp1160-regs",
+ .start = ATARI_USB_PHYS_ADDR + 0x4,
+ .end = ATARI_USB_PHYS_ADDR + 0x5,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .name = "isp1160-irq",
+ .start = ATARI_USB_IRQ,
+ .end = ATARI_USB_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* (DataBusWidth16|AnalogOCEnable|DREQOutputPolarity|DownstreamPort15KRSel ) */
+static struct isp116x_platform_data isp1160_platform_data = {
+ /* Enable internal resistors on downstream ports */
+ .sel15Kres = 1,
+ /* On-chip overcurrent protection */
+ .oc_enable = 1,
+ /* INT output polarity */
+ .int_act_high = 1,
+ /* INT edge or level triggered */
+ .int_edge_triggered = 0,
+
+ /* WAKEUP pin connected - NOT SUPPORTED */
+ /* .remote_wakeup_connected = 0, */
+ /* Wakeup by devices on usb bus enabled */
+ .remote_wakeup_enable = 0,
+ .delay = isp1160_delay,
+};
+
+static struct platform_device isp1160_device = {
+ .name = "isp116x-hcd",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(isp1160_resources),
+ .resource = isp1160_resources,
+ .dev = {
+ .platform_data = &isp1160_platform_data,
+ },
+};
+
+static struct platform_device *atari_ethernat_devices[] __initdata = {
+ &smc91x_device,
+ &isp1160_device
+};
+#endif /* CONFIG_ATARI_ETHERNAT */
+
+#ifdef CONFIG_ATARI_ETHERNEC
+/*
+ * EtherNEC: RTL8019 (NE2000 compatible) Ethernet chipset,
+ * handled by ne.c driver
+ */
+
+#define ATARI_ETHERNEC_PHYS_ADDR 0xfffa0000
+#define ATARI_ETHERNEC_BASE 0x300
+#define ATARI_ETHERNEC_IRQ IRQ_MFP_TIMER1
+
+static struct resource rtl8019_resources[] = {
+ [0] = {
+ .name = "rtl8019-regs",
+ .start = ATARI_ETHERNEC_BASE,
+ .end = ATARI_ETHERNEC_BASE + 0x20 - 1,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ .name = "rtl8019-irq",
+ .start = ATARI_ETHERNEC_IRQ,
+ .end = ATARI_ETHERNEC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rtl8019_device = {
+ .name = "ne",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtl8019_resources),
+ .resource = rtl8019_resources,
+};
+
+/*
+ * NetUSBee: ISP1160 USB host adapter via ROM-port adapter
+ */
+
+#define ATARI_NETUSBEE_PHYS_ADDR 0xfffa8000
+#define ATARI_NETUSBEE_BASE 0x340
+#define ATARI_NETUSBEE_IRQ IRQ_MFP_TIMER2
+
+static struct resource netusbee_resources[] = {
+ [0] = {
+ .name = "isp1160-data",
+ .start = ATARI_NETUSBEE_BASE,
+ .end = ATARI_NETUSBEE_BASE + 0x1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "isp1160-regs",
+ .start = ATARI_NETUSBEE_BASE + 0x20,
+ .end = ATARI_NETUSBEE_BASE + 0x21,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .name = "isp1160-irq",
+ .start = ATARI_NETUSBEE_IRQ,
+ .end = ATARI_NETUSBEE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* (DataBusWidth16|AnalogOCEnable|DREQOutputPolarity|DownstreamPort15KRSel ) */
+static struct isp116x_platform_data netusbee_platform_data = {
+ /* Enable internal resistors on downstream ports */
+ .sel15Kres = 1,
+ /* On-chip overcurrent protection */
+ .oc_enable = 1,
+ /* INT output polarity */
+ .int_act_high = 1,
+ /* INT edge or level triggered */
+ .int_edge_triggered = 0,
+
+ /* WAKEUP pin connected - NOT SUPPORTED */
+ /* .remote_wakeup_connected = 0, */
+ /* Wakeup by devices on usb bus enabled */
+ .remote_wakeup_enable = 0,
+ .delay = isp1160_delay,
+};
+
+static struct platform_device netusbee_device = {
+ .name = "isp116x-hcd",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(netusbee_resources),
+ .resource = netusbee_resources,
+ .dev = {
+ .platform_data = &netusbee_platform_data,
+ },
+};
+
+static struct platform_device *atari_netusbee_devices[] __initdata = {
+ &rtl8019_device,
+ &netusbee_device
+};
+#endif /* CONFIG_ATARI_ETHERNEC */
+
+int __init atari_platform_init(void)
+{
+ int rv = 0;
+
+ if (!MACH_IS_ATARI)
+ return -ENODEV;
+
+#ifdef CONFIG_ATARI_ETHERNAT
+ {
+ unsigned char *enatc_virt;
+ enatc_virt = (unsigned char *)ioremap((ATARI_ETHERNAT_PHYS_ADDR+0x23), 0xf);
+ if (hwreg_present(enatc_virt)) {
+ rv = platform_add_devices(atari_ethernat_devices,
+ ARRAY_SIZE(atari_ethernat_devices));
+ }
+ iounmap(enatc_virt);
+ }
+#endif
+
+#ifdef CONFIG_ATARI_ETHERNEC
+ {
+ int error;
+ unsigned char *enec_virt;
+ enec_virt = (unsigned char *)ioremap((ATARI_ETHERNEC_PHYS_ADDR), 0xf);
+ if (hwreg_present(enec_virt)) {
+ error = platform_add_devices(atari_netusbee_devices,
+ ARRAY_SIZE(atari_netusbee_devices));
+ if (error && !rv)
+ rv = error;
+ }
+ iounmap(enec_virt);
+ }
+#endif
+
+ return rv;
+}
+
+arch_initcall(atari_platform_init);
diff --git a/arch/m68k/atari/debug.c b/arch/m68k/atari/debug.c
index ace05f79d96..03cb5e08d7c 100644
--- a/arch/m68k/atari/debug.c
+++ b/arch/m68k/atari/debug.c
@@ -10,338 +10,320 @@
* for more details.
*/
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <asm/atarihw.h>
#include <asm/atariints.h>
-extern char m68k_debug_device[];
-
-/* Flag that Modem1 port is already initialized and used */
-int atari_MFP_init_done;
-/* Flag that Modem1 port is already initialized and used */
-int atari_SCC_init_done;
/* Can be set somewhere, if a SCC master reset has already be done and should
* not be repeated; used by kgdb */
int atari_SCC_reset_done;
+EXPORT_SYMBOL(atari_SCC_reset_done);
static struct console atari_console_driver = {
- .name = "debug",
- .flags = CON_PRINTBUFFER,
- .index = -1,
+ .name = "debug",
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
};
-static inline void ata_mfp_out (char c)
+static inline void ata_mfp_out(char c)
{
- while (!(mfp.trn_stat & 0x80)) /* wait for tx buf empty */
- barrier ();
- mfp.usart_dta = c;
+ while (!(st_mfp.trn_stat & 0x80)) /* wait for tx buf empty */
+ barrier();
+ st_mfp.usart_dta = c;
}
-void atari_mfp_console_write (struct console *co, const char *str,
- unsigned int count)
+static void atari_mfp_console_write(struct console *co, const char *str,
+ unsigned int count)
{
- while (count--) {
- if (*str == '\n')
- ata_mfp_out( '\r' );
- ata_mfp_out( *str++ );
- }
+ while (count--) {
+ if (*str == '\n')
+ ata_mfp_out('\r');
+ ata_mfp_out(*str++);
+ }
}
-static inline void ata_scc_out (char c)
+static inline void ata_scc_out(char c)
{
- do {
+ do {
+ MFPDELAY();
+ } while (!(atari_scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
MFPDELAY();
- } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
- MFPDELAY();
- scc.cha_b_data = c;
+ atari_scc.cha_b_data = c;
}
-void atari_scc_console_write (struct console *co, const char *str,
- unsigned int count)
+static void atari_scc_console_write(struct console *co, const char *str,
+ unsigned int count)
{
- while (count--) {
- if (*str == '\n')
- ata_scc_out( '\r' );
- ata_scc_out( *str++ );
- }
+ while (count--) {
+ if (*str == '\n')
+ ata_scc_out('\r');
+ ata_scc_out(*str++);
+ }
}
-static inline void ata_midi_out (char c)
+static inline void ata_midi_out(char c)
{
- while (!(acia.mid_ctrl & ACIA_TDRE)) /* wait for tx buf empty */
- barrier ();
- acia.mid_data = c;
+ while (!(acia.mid_ctrl & ACIA_TDRE)) /* wait for tx buf empty */
+ barrier();
+ acia.mid_data = c;
}
-void atari_midi_console_write (struct console *co, const char *str,
- unsigned int count)
+static void atari_midi_console_write(struct console *co, const char *str,
+ unsigned int count)
{
- while (count--) {
- if (*str == '\n')
- ata_midi_out( '\r' );
- ata_midi_out( *str++ );
- }
+ while (count--) {
+ if (*str == '\n')
+ ata_midi_out('\r');
+ ata_midi_out(*str++);
+ }
}
-static int ata_par_out (char c)
+static int ata_par_out(char c)
{
- unsigned char tmp;
- /* This a some-seconds timeout in case no printer is connected */
- unsigned long i = loops_per_jiffy > 1 ? loops_per_jiffy : 10000000/HZ;
-
- while( (mfp.par_dt_reg & 1) && --i ) /* wait for BUSY == L */
- ;
- if (!i) return( 0 );
-
- sound_ym.rd_data_reg_sel = 15; /* select port B */
- sound_ym.wd_data = c; /* put char onto port */
- sound_ym.rd_data_reg_sel = 14; /* select port A */
- tmp = sound_ym.rd_data_reg_sel;
- sound_ym.wd_data = tmp & ~0x20; /* set strobe L */
- MFPDELAY(); /* wait a bit */
- sound_ym.wd_data = tmp | 0x20; /* set strobe H */
- return( 1 );
+ unsigned char tmp;
+ /* This a some-seconds timeout in case no printer is connected */
+ unsigned long i = loops_per_jiffy > 1 ? loops_per_jiffy : 10000000/HZ;
+
+ while ((st_mfp.par_dt_reg & 1) && --i) /* wait for BUSY == L */
+ ;
+ if (!i)
+ return 0;
+
+ sound_ym.rd_data_reg_sel = 15; /* select port B */
+ sound_ym.wd_data = c; /* put char onto port */
+ sound_ym.rd_data_reg_sel = 14; /* select port A */
+ tmp = sound_ym.rd_data_reg_sel;
+ sound_ym.wd_data = tmp & ~0x20; /* set strobe L */
+ MFPDELAY(); /* wait a bit */
+ sound_ym.wd_data = tmp | 0x20; /* set strobe H */
+ return 1;
}
-static void atari_par_console_write (struct console *co, const char *str,
- unsigned int count)
+static void atari_par_console_write(struct console *co, const char *str,
+ unsigned int count)
{
- static int printer_present = 1;
-
- if (!printer_present)
- return;
+ static int printer_present = 1;
- while (count--) {
- if (*str == '\n')
- if (!ata_par_out( '\r' )) {
- printer_present = 0;
+ if (!printer_present)
return;
- }
- if (!ata_par_out( *str++ )) {
- printer_present = 0;
- return;
+
+ while (count--) {
+ if (*str == '\n') {
+ if (!ata_par_out('\r')) {
+ printer_present = 0;
+ return;
+ }
+ }
+ if (!ata_par_out(*str++)) {
+ printer_present = 0;
+ return;
+ }
}
- }
}
-#ifdef CONFIG_SERIAL_CONSOLE
+#if 0
int atari_mfp_console_wait_key(struct console *co)
{
- while( !(mfp.rcv_stat & 0x80) ) /* wait for rx buf filled */
- barrier();
- return( mfp.usart_dta );
+ while (!(st_mfp.rcv_stat & 0x80)) /* wait for rx buf filled */
+ barrier();
+ return st_mfp.usart_dta;
}
int atari_scc_console_wait_key(struct console *co)
{
- do {
+ do {
+ MFPDELAY();
+ } while (!(atari_scc.cha_b_ctrl & 0x01)); /* wait for rx buf filled */
MFPDELAY();
- } while( !(scc.cha_b_ctrl & 0x01) ); /* wait for rx buf filled */
- MFPDELAY();
- return( scc.cha_b_data );
+ return atari_scc.cha_b_data;
}
int atari_midi_console_wait_key(struct console *co)
{
- while( !(acia.mid_ctrl & ACIA_RDRF) ) /* wait for rx buf filled */
- barrier();
- return( acia.mid_data );
+ while (!(acia.mid_ctrl & ACIA_RDRF)) /* wait for rx buf filled */
+ barrier();
+ return acia.mid_data;
}
#endif
-/* The following two functions do a quick'n'dirty initialization of the MFP or
+/*
+ * 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. */
-#ifndef CONFIG_SERIAL_CONSOLE
-static void __init atari_init_mfp_port( int cflag )
-#else
-void atari_init_mfp_port( int cflag )
-#endif
+ * serial console code.
+ */
+static void __init atari_init_mfp_port(int cflag)
{
- /* timer values for 1200...115200 bps; > 38400 select 110, 134, or 150
- * bps, resp., and work only correct if there's a RSVE or RSSPEED */
- static int baud_table[9] = { 16, 11, 8, 4, 2, 1, 175, 143, 128 };
- int baud = cflag & CBAUD;
- int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x04 : 0x06) : 0;
- int csize = ((cflag & CSIZE) == CS7) ? 0x20 : 0x00;
-
- if (cflag & CBAUDEX)
- baud += B38400;
- if (baud < B1200 || baud > B38400+2)
- baud = B9600; /* use default 9600bps for non-implemented rates */
- baud -= B1200; /* baud_table[] starts at 1200bps */
-
- mfp.trn_stat &= ~0x01; /* disable TX */
- mfp.usart_ctr = parity | csize | 0x88; /* 1:16 clk mode, 1 stop bit */
- mfp.tim_ct_cd &= 0x70; /* stop timer D */
- mfp.tim_dt_d = baud_table[baud];
- mfp.tim_ct_cd |= 0x01; /* start timer D, 1:4 */
- mfp.trn_stat |= 0x01; /* enable TX */
-
- atari_MFP_init_done = 1;
+ /*
+ * timer values for 1200...115200 bps; > 38400 select 110, 134, or 150
+ * bps, resp., and work only correct if there's a RSVE or RSSPEED
+ */
+ static int baud_table[9] = { 16, 11, 8, 4, 2, 1, 175, 143, 128 };
+ int baud = cflag & CBAUD;
+ int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x04 : 0x06) : 0;
+ int csize = ((cflag & CSIZE) == CS7) ? 0x20 : 0x00;
+
+ if (cflag & CBAUDEX)
+ baud += B38400;
+ if (baud < B1200 || baud > B38400+2)
+ baud = B9600; /* use default 9600bps for non-implemented rates */
+ baud -= B1200; /* baud_table[] starts at 1200bps */
+
+ st_mfp.trn_stat &= ~0x01; /* disable TX */
+ st_mfp.usart_ctr = parity | csize | 0x88; /* 1:16 clk mode, 1 stop bit */
+ st_mfp.tim_ct_cd &= 0x70; /* stop timer D */
+ st_mfp.tim_dt_d = baud_table[baud];
+ st_mfp.tim_ct_cd |= 0x01; /* start timer D, 1:4 */
+ st_mfp.trn_stat |= 0x01; /* enable TX */
}
-#define SCC_WRITE(reg,val) \
- do { \
- scc.cha_b_ctrl = (reg); \
- MFPDELAY(); \
- scc.cha_b_ctrl = (val); \
- MFPDELAY(); \
- } while(0)
+#define SCC_WRITE(reg, val) \
+ do { \
+ atari_scc.cha_b_ctrl = (reg); \
+ MFPDELAY(); \
+ atari_scc.cha_b_ctrl = (val); \
+ MFPDELAY(); \
+ } while (0)
/* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a
* delay of ~ 60us. */
-#define LONG_DELAY() \
- do { \
- int i; \
- for( i = 100; i > 0; --i ) \
- MFPDELAY(); \
- } while(0)
-
-#ifndef CONFIG_SERIAL_CONSOLE
-static void __init atari_init_scc_port( int cflag )
-#else
-void atari_init_scc_port( int cflag )
-#endif
+#define LONG_DELAY() \
+ do { \
+ int i; \
+ for (i = 100; i > 0; --i) \
+ MFPDELAY(); \
+ } while (0)
+
+static void __init atari_init_scc_port(int cflag)
{
- extern int atari_SCC_reset_done;
- static int clksrc_table[9] =
- /* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */
- { 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 };
- static int brgsrc_table[9] =
- /* reg 14: 0 = RTxC, 2 = PCLK */
- { 2, 2, 2, 2, 2, 2, 0, 2, 2 };
- 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) */
- { 208, 138, 103, 50, 24, 11, 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];
- if (ATARIHW_PRESENT(TT_MFP) && baud >= 6) {
- /* special treatment for TT, where rates >= 38400 are done via TRxC */
- clksrc = 0x28; /* TRxC */
- clkmode = baud == 6 ? 0xc0 :
- baud == 7 ? 0x80 : /* really 76800bps */
- 0x40; /* really 153600bps */
- div = 0;
- }
-
- reg3 = (cflag & CSIZE) == CS8 ? 0xc0 : 0x40;
- reg5 = (cflag & CSIZE) == CS8 ? 0x60 : 0x20 | 0x82 /* assert DTR/RTS */;
-
- (void)scc.cha_b_ctrl; /* reset reg pointer */
- SCC_WRITE( 9, 0xc0 ); /* reset */
- LONG_DELAY(); /* extra delay after WR9 access */
- SCC_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
- 0x04 /* 1 stopbit */ |
- clkmode );
- SCC_WRITE( 3, reg3 );
- SCC_WRITE( 5, reg5 );
- SCC_WRITE( 9, 0 ); /* no interrupts */
- LONG_DELAY(); /* extra delay after WR9 access */
- SCC_WRITE( 10, 0 ); /* NRZ mode */
- SCC_WRITE( 11, clksrc ); /* main clock source */
- SCC_WRITE( 12, div ); /* BRG value */
- SCC_WRITE( 13, 0 ); /* BRG high byte */
- SCC_WRITE( 14, brgsrc_table[baud] );
- SCC_WRITE( 14, brgsrc_table[baud] | (div ? 1 : 0) );
- SCC_WRITE( 3, reg3 | 1 );
- SCC_WRITE( 5, reg5 | 8 );
-
- atari_SCC_reset_done = 1;
- atari_SCC_init_done = 1;
+ static int clksrc_table[9] =
+ /* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */
+ { 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 };
+ static int brgsrc_table[9] =
+ /* reg 14: 0 = RTxC, 2 = PCLK */
+ { 2, 2, 2, 2, 2, 2, 0, 2, 2 };
+ 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) */
+ { 208, 138, 103, 50, 24, 11, 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];
+ if (ATARIHW_PRESENT(TT_MFP) && baud >= 6) {
+ /* special treatment for TT, where rates >= 38400 are done via TRxC */
+ clksrc = 0x28; /* TRxC */
+ clkmode = baud == 6 ? 0xc0 :
+ baud == 7 ? 0x80 : /* really 76800bps */
+ 0x40; /* really 153600bps */
+ div = 0;
+ }
+
+ reg3 = (cflag & CSIZE) == CS8 ? 0xc0 : 0x40;
+ reg5 = (cflag & CSIZE) == CS8 ? 0x60 : 0x20 | 0x82 /* assert DTR/RTS */;
+
+ (void)atari_scc.cha_b_ctrl; /* reset reg pointer */
+ SCC_WRITE(9, 0xc0); /* reset */
+ LONG_DELAY(); /* extra delay after WR9 access */
+ SCC_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03)
+ : 0 | 0x04 /* 1 stopbit */ | clkmode);
+ SCC_WRITE(3, reg3);
+ SCC_WRITE(5, reg5);
+ SCC_WRITE(9, 0); /* no interrupts */
+ LONG_DELAY(); /* extra delay after WR9 access */
+ SCC_WRITE(10, 0); /* NRZ mode */
+ SCC_WRITE(11, clksrc); /* main clock source */
+ SCC_WRITE(12, div); /* BRG value */
+ SCC_WRITE(13, 0); /* BRG high byte */
+ SCC_WRITE(14, brgsrc_table[baud]);
+ SCC_WRITE(14, brgsrc_table[baud] | (div ? 1 : 0));
+ SCC_WRITE(3, reg3 | 1);
+ SCC_WRITE(5, reg5 | 8);
+
+ atari_SCC_reset_done = 1;
}
-#ifndef CONFIG_SERIAL_CONSOLE
-static void __init atari_init_midi_port( int cflag )
-#else
-void atari_init_midi_port( int cflag )
-#endif
+static void __init atari_init_midi_port(int cflag)
{
- int baud = cflag & CBAUD;
- int csize = ((cflag & CSIZE) == CS8) ? 0x10 : 0x00;
- /* warning 7N1 isn't possible! (instead 7O2 is used...) */
- int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x0c : 0x08) : 0x04;
- int div;
-
- /* 4800 selects 7812.5, 115200 selects 500000, all other (incl. 9600 as
- * default) the standard MIDI speed 31250. */
- if (cflag & CBAUDEX)
- baud += B38400;
- if (baud == B4800)
- div = ACIA_DIV64; /* really 7812.5 bps */
- else if (baud == B38400+2 /* 115200 */)
- div = ACIA_DIV1; /* really 500 kbps (does that work??) */
- else
- div = ACIA_DIV16; /* 31250 bps, standard for MIDI */
-
- /* RTS low, ints disabled */
- acia.mid_ctrl = div | csize | parity |
+ int baud = cflag & CBAUD;
+ int csize = ((cflag & CSIZE) == CS8) ? 0x10 : 0x00;
+ /* warning 7N1 isn't possible! (instead 7O2 is used...) */
+ int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x0c : 0x08) : 0x04;
+ int div;
+
+ /* 4800 selects 7812.5, 115200 selects 500000, all other (incl. 9600 as
+ * default) the standard MIDI speed 31250. */
+ if (cflag & CBAUDEX)
+ baud += B38400;
+ if (baud == B4800)
+ div = ACIA_DIV64; /* really 7812.5 bps */
+ else if (baud == B38400+2 /* 115200 */)
+ div = ACIA_DIV1; /* really 500 kbps (does that work??) */
+ else
+ div = ACIA_DIV16; /* 31250 bps, standard for MIDI */
+
+ /* RTS low, ints disabled */
+ acia.mid_ctrl = div | csize | parity |
((atari_switches & ATARI_SWITCH_MIDI) ?
ACIA_RHTID : ACIA_RLTID);
}
-void __init atari_debug_init(void)
+static int __init atari_debug_setup(char *arg)
{
- if (!strcmp( m68k_debug_device, "ser" )) {
- /* defaults to ser2 for a Falcon and ser1 otherwise */
- strcpy( m68k_debug_device, MACH_IS_FALCON ? "ser2" : "ser1" );
-
- }
-
- if (!strcmp( m68k_debug_device, "ser1" )) {
- /* ST-MFP Modem1 serial port */
- atari_init_mfp_port( B9600|CS8 );
- atari_console_driver.write = atari_mfp_console_write;
- }
- else if (!strcmp( m68k_debug_device, "ser2" )) {
- /* SCC Modem2 serial port */
- atari_init_scc_port( B9600|CS8 );
- atari_console_driver.write = atari_scc_console_write;
- }
- else if (!strcmp( m68k_debug_device, "midi" )) {
- /* MIDI port */
- atari_init_midi_port( B9600|CS8 );
- atari_console_driver.write = atari_midi_console_write;
- }
- else if (!strcmp( m68k_debug_device, "par" )) {
- /* parallel printer */
- atari_turnoff_irq( IRQ_MFP_BUSY ); /* avoid ints */
- sound_ym.rd_data_reg_sel = 7; /* select mixer control */
- sound_ym.wd_data = 0xff; /* sound off, ports are output */
- sound_ym.rd_data_reg_sel = 15; /* select port B */
- sound_ym.wd_data = 0; /* no char */
- sound_ym.rd_data_reg_sel = 14; /* select port A */
- sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */
- atari_console_driver.write = atari_par_console_write;
- }
- if (atari_console_driver.write)
- register_console(&atari_console_driver);
+ bool registered;
+
+ if (!MACH_IS_ATARI)
+ return 0;
+
+ if (!strcmp(arg, "ser"))
+ /* defaults to ser2 for a Falcon and ser1 otherwise */
+ arg = MACH_IS_FALCON ? "ser2" : "ser1";
+
+ registered = !!atari_console_driver.write;
+ if (!strcmp(arg, "ser1")) {
+ /* ST-MFP Modem1 serial port */
+ atari_init_mfp_port(B9600|CS8);
+ atari_console_driver.write = atari_mfp_console_write;
+ } else if (!strcmp(arg, "ser2")) {
+ /* SCC Modem2 serial port */
+ atari_init_scc_port(B9600|CS8);
+ atari_console_driver.write = atari_scc_console_write;
+ } else if (!strcmp(arg, "midi")) {
+ /* MIDI port */
+ atari_init_midi_port(B9600|CS8);
+ atari_console_driver.write = atari_midi_console_write;
+ } else if (!strcmp(arg, "par")) {
+ /* parallel printer */
+ atari_turnoff_irq(IRQ_MFP_BUSY); /* avoid ints */
+ sound_ym.rd_data_reg_sel = 7; /* select mixer control */
+ sound_ym.wd_data = 0xff; /* sound off, ports are output */
+ sound_ym.rd_data_reg_sel = 15; /* select port B */
+ sound_ym.wd_data = 0; /* no char */
+ sound_ym.rd_data_reg_sel = 14; /* select port A */
+ sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */
+ atari_console_driver.write = atari_par_console_write;
+ }
+ if (atari_console_driver.write && !registered)
+ register_console(&atari_console_driver);
+
+ return 0;
}
-/*
- * Local variables:
- * c-indent-level: 4
- * tab-width: 8
- * End:
- */
+early_param("debug", atari_debug_setup);
diff --git a/arch/m68k/atari/hades-pci.c b/arch/m68k/atari/hades-pci.c
deleted file mode 100644
index 8888debf71e..00000000000
--- a/arch/m68k/atari/hades-pci.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * hades-pci.c - Hardware specific PCI BIOS functions the Hades Atari clone.
- *
- * Written by Wout Klaren.
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <asm/io.h>
-
-#if 0
-# define DBG_DEVS(args) printk args
-#else
-# define DBG_DEVS(args)
-#endif
-
-#if defined(CONFIG_PCI) && defined(CONFIG_HADES)
-
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/pci.h>
-
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/byteorder.h>
-#include <asm/pci.h>
-
-#define HADES_MEM_BASE 0x80000000
-#define HADES_MEM_SIZE 0x20000000
-#define HADES_CONFIG_BASE 0xA0000000
-#define HADES_CONFIG_SIZE 0x10000000
-#define HADES_IO_BASE 0xB0000000
-#define HADES_IO_SIZE 0x10000000
-#define HADES_VIRT_IO_SIZE 0x00010000 /* Only 64k is remapped and actually used. */
-
-#define N_SLOTS 4 /* Number of PCI slots. */
-
-static const char pci_mem_name[] = "PCI memory space";
-static const char pci_io_name[] = "PCI I/O space";
-static const char pci_config_name[] = "PCI config space";
-
-static struct resource config_space = {
- .name = pci_config_name,
- .start = HADES_CONFIG_BASE,
- .end = HADES_CONFIG_BASE + HADES_CONFIG_SIZE - 1
-};
-static struct resource io_space = {
- .name = pci_io_name,
- .start = HADES_IO_BASE,
- .end = HADES_IO_BASE + HADES_IO_SIZE - 1
-};
-
-static const unsigned long pci_conf_base_phys[] = {
- 0xA0080000, 0xA0040000, 0xA0020000, 0xA0010000
-};
-static unsigned long pci_conf_base_virt[N_SLOTS];
-static unsigned long pci_io_base_virt;
-
-/*
- * static void *mk_conf_addr(unsigned char bus, unsigned char device_fn,
- * unsigned char where)
- *
- * Calculate the address of the PCI configuration area of the given
- * device.
- *
- * BUG: boards with multiple functions are probably not correctly
- * supported.
- */
-
-static void *mk_conf_addr(struct pci_dev *dev, int where)
-{
- int device = dev->devfn >> 3, function = dev->devfn & 7;
- void *result;
-
- DBG_DEVS(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, pci_addr=0x%p)\n",
- dev->bus->number, dev->devfn, where, pci_addr));
-
- if (device > 3)
- {
- DBG_DEVS(("mk_conf_addr: device (%d) > 3, returning NULL\n", device));
- return NULL;
- }
-
- if (dev->bus->number != 0)
- {
- DBG_DEVS(("mk_conf_addr: bus (%d) > 0, returning NULL\n", device));
- return NULL;
- }
-
- result = (void *) (pci_conf_base_virt[device] | (function << 8) | (where));
- DBG_DEVS(("mk_conf_addr: returning pci_addr 0x%lx\n", (unsigned long) result));
- return result;
-}
-
-static int hades_read_config_byte(struct pci_dev *dev, int where, u8 *value)
-{
- volatile unsigned char *pci_addr;
-
- *value = 0xff;
-
- if ((pci_addr = (unsigned char *) mk_conf_addr(dev, where)) == NULL)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- *value = *pci_addr;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int hades_read_config_word(struct pci_dev *dev, int where, u16 *value)
-{
- volatile unsigned short *pci_addr;
-
- *value = 0xffff;
-
- if (where & 0x1)
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- if ((pci_addr = (unsigned short *) mk_conf_addr(dev, where)) == NULL)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- *value = le16_to_cpu(*pci_addr);
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int hades_read_config_dword(struct pci_dev *dev, int where, u32 *value)
-{
- volatile unsigned int *pci_addr;
- unsigned char header_type;
- int result;
-
- *value = 0xffffffff;
-
- if (where & 0x3)
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- if ((pci_addr = (unsigned int *) mk_conf_addr(dev, where)) == NULL)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- *value = le32_to_cpu(*pci_addr);
-
- /*
- * Check if the value is an address on the bus. If true, add the
- * base address of the PCI memory or PCI I/O area on the Hades.
- */
-
- if ((result = hades_read_config_byte(dev, PCI_HEADER_TYPE,
- &header_type)) != PCIBIOS_SUCCESSFUL)
- return result;
-
- if (((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_1)) ||
- ((header_type != PCI_HEADER_TYPE_BRIDGE) && ((where >= PCI_BASE_ADDRESS_2) &&
- (where <= PCI_BASE_ADDRESS_5))))
- {
- if ((*value & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
- {
- /*
- * Base address register that contains an I/O address. If the
- * address is valid on the Hades (0 <= *value < HADES_VIRT_IO_SIZE),
- * add 'pci_io_base_virt' to the value.
- */
-
- if (*value < HADES_VIRT_IO_SIZE)
- *value += pci_io_base_virt;
- }
- else
- {
- /*
- * Base address register that contains an memory address. If the
- * address is valid on the Hades (0 <= *value < HADES_MEM_SIZE),
- * add HADES_MEM_BASE to the value.
- */
-
- if (*value == 0)
- {
- /*
- * Base address is 0. Test if this base
- * address register is used.
- */
-
- *pci_addr = 0xffffffff;
- if (*pci_addr != 0)
- {
- *pci_addr = *value;
- if (*value < HADES_MEM_SIZE)
- *value += HADES_MEM_BASE;
- }
- }
- else
- {
- if (*value < HADES_MEM_SIZE)
- *value += HADES_MEM_BASE;
- }
- }
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int hades_write_config_byte(struct pci_dev *dev, int where, u8 value)
-{
- volatile unsigned char *pci_addr;
-
- if ((pci_addr = (unsigned char *) mk_conf_addr(dev, where)) == NULL)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- *pci_addr = value;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int hades_write_config_word(struct pci_dev *dev, int where, u16 value)
-{
- volatile unsigned short *pci_addr;
-
- if ((pci_addr = (unsigned short *) mk_conf_addr(dev, where)) == NULL)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- *pci_addr = cpu_to_le16(value);
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int hades_write_config_dword(struct pci_dev *dev, int where, u32 value)
-{
- volatile unsigned int *pci_addr;
- unsigned char header_type;
- int result;
-
- if ((pci_addr = (unsigned int *) mk_conf_addr(dev, where)) == NULL)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- /*
- * Check if the value is an address on the bus. If true, subtract the
- * base address of the PCI memory or PCI I/O area on the Hades.
- */
-
- if ((result = hades_read_config_byte(dev, PCI_HEADER_TYPE,
- &header_type)) != PCIBIOS_SUCCESSFUL)
- return result;
-
- if (((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_1)) ||
- ((header_type != PCI_HEADER_TYPE_BRIDGE) && ((where >= PCI_BASE_ADDRESS_2) &&
- (where <= PCI_BASE_ADDRESS_5))))
- {
- if ((value & PCI_BASE_ADDRESS_SPACE) ==
- PCI_BASE_ADDRESS_SPACE_IO)
- {
- /*
- * I/O address. Check if the address is valid address on
- * the Hades (pci_io_base_virt <= value < pci_io_base_virt +
- * HADES_VIRT_IO_SIZE) or if the value is 0xffffffff. If not
- * true do not write the base address register. If it is a
- * valid base address subtract 'pci_io_base_virt' from the value.
- */
-
- if ((value >= pci_io_base_virt) && (value < (pci_io_base_virt +
- HADES_VIRT_IO_SIZE)))
- value -= pci_io_base_virt;
- else
- {
- if (value != 0xffffffff)
- return PCIBIOS_SET_FAILED;
- }
- }
- else
- {
- /*
- * Memory address. Check if the address is valid address on
- * the Hades (HADES_MEM_BASE <= value < HADES_MEM_BASE + HADES_MEM_SIZE) or
- * if the value is 0xffffffff. If not true do not write
- * the base address register. If it is a valid base address
- * subtract HADES_MEM_BASE from the value.
- */
-
- if ((value >= HADES_MEM_BASE) && (value < (HADES_MEM_BASE + HADES_MEM_SIZE)))
- value -= HADES_MEM_BASE;
- else
- {
- if (value != 0xffffffff)
- return PCIBIOS_SET_FAILED;
- }
- }
- }
-
- *pci_addr = cpu_to_le32(value);
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-/*
- * static inline void hades_fixup(void)
- *
- * Assign IRQ numbers as used by Linux to the interrupt pins
- * of the PCI cards.
- */
-
-static void __init hades_fixup(int pci_modify)
-{
- char irq_tab[4] = {
- [0] = IRQ_TT_MFP_IO0, /* Slot 0. */
- [1] = IRQ_TT_MFP_IO1, /* Slot 1. */
- [2] = IRQ_TT_MFP_SCC, /* Slot 2. */
- [3] = IRQ_TT_MFP_SCSIDMA /* Slot 3. */
- };
- struct pci_dev *dev = NULL;
- unsigned char slot;
-
- /*
- * Go through all devices, fixing up irqs as we see fit:
- */
-
- while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
- {
- if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE)
- {
- slot = PCI_SLOT(dev->devfn); /* Determine slot number. */
- dev->irq = irq_tab[slot];
- if (pci_modify)
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
- }
- }
-}
-
-/*
- * static void hades_conf_device(struct pci_dev *dev)
- *
- * Machine dependent Configure the given device.
- *
- * Parameters:
- *
- * dev - the pci device.
- */
-
-static void __init hades_conf_device(struct pci_dev *dev)
-{
- pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0);
-}
-
-static struct pci_ops hades_pci_ops = {
- .read_byte = hades_read_config_byte,
- .read_word = hades_read_config_word,
- .read_dword = hades_read_config_dword,
- .write_byte = hades_write_config_byte,
- .write_word = hades_write_config_word,
- .write_dword = hades_write_config_dword
-};
-
-/*
- * struct pci_bus_info *init_hades_pci(void)
- *
- * Machine specific initialisation:
- *
- * - Allocate and initialise a 'pci_bus_info' structure
- * - Initialise hardware
- *
- * Result: pointer to 'pci_bus_info' structure.
- */
-
-struct pci_bus_info * __init init_hades_pci(void)
-{
- struct pci_bus_info *bus;
- int i;
-
- /*
- * Remap I/O and configuration space.
- */
-
- pci_io_base_virt = (unsigned long) ioremap(HADES_IO_BASE, HADES_VIRT_IO_SIZE);
-
- for (i = 0; i < N_SLOTS; i++)
- pci_conf_base_virt[i] = (unsigned long) ioremap(pci_conf_base_phys[i], 0x10000);
-
- /*
- * Allocate memory for bus info structure.
- */
-
- bus = kmalloc(sizeof(struct pci_bus_info), GFP_KERNEL);
- if (!bus)
- return NULL;
- memset(bus, 0, sizeof(struct pci_bus_info));
-
- /*
- * Claim resources. The m68k has no separate I/O space, both
- * PCI memory space and PCI I/O space are in memory space. Therefore
- * the I/O resources are requested in memory space as well.
- */
-
- if (request_resource(&iomem_resource, &config_space) != 0)
- {
- kfree(bus);
- return NULL;
- }
-
- if (request_resource(&iomem_resource, &io_space) != 0)
- {
- release_resource(&config_space);
- kfree(bus);
- return NULL;
- }
-
- bus->mem_space.start = HADES_MEM_BASE;
- bus->mem_space.end = HADES_MEM_BASE + HADES_MEM_SIZE - 1;
- bus->mem_space.name = pci_mem_name;
-#if 1
- if (request_resource(&iomem_resource, &bus->mem_space) != 0)
- {
- release_resource(&io_space);
- release_resource(&config_space);
- kfree(bus);
- return NULL;
- }
-#endif
- bus->io_space.start = pci_io_base_virt;
- bus->io_space.end = pci_io_base_virt + HADES_VIRT_IO_SIZE - 1;
- bus->io_space.name = pci_io_name;
-#if 1
- if (request_resource(&ioport_resource, &bus->io_space) != 0)
- {
- release_resource(&bus->mem_space);
- release_resource(&io_space);
- release_resource(&config_space);
- kfree(bus);
- return NULL;
- }
-#endif
- /*
- * Set hardware dependent functions.
- */
-
- bus->m68k_pci_ops = &hades_pci_ops;
- bus->fixup = hades_fixup;
- bus->conf_device = hades_conf_device;
-
- /*
- * Select high to low edge for PCI interrupts.
- */
-
- tt_mfp.active_edge &= ~0x27;
-
- return bus;
-}
-#endif
diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
index 288f5e6a124..ddbf43ca885 100644
--- a/arch/m68k/atari/stdma.c
+++ b/arch/m68k/atari/stdma.c
@@ -35,6 +35,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
+#include <linux/module.h>
#include <asm/atari_stdma.h>
#include <asm/atariints.h>
@@ -44,7 +45,7 @@
static int stdma_locked; /* the semaphore */
/* int func to be called */
-static irqreturn_t (*stdma_isr)(int, void *, struct pt_regs *);
+static irq_handler_t stdma_isr;
static void *stdma_isr_data; /* data passed to isr */
static DECLARE_WAIT_QUEUE_HEAD(stdma_wait); /* wait queue for ST-DMA */
@@ -53,7 +54,7 @@ static DECLARE_WAIT_QUEUE_HEAD(stdma_wait); /* wait queue for ST-DMA */
/***************************** Prototypes *****************************/
-static irqreturn_t stdma_int (int irq, void *dummy, struct pt_regs *fp);
+static irqreturn_t stdma_int (int irq, void *dummy);
/************************* End of Prototypes **************************/
@@ -75,8 +76,7 @@ static irqreturn_t stdma_int (int irq, void *dummy, struct pt_regs *fp);
*
*/
-void stdma_lock(irqreturn_t (*handler)(int, void *, struct pt_regs *),
- void *data)
+void stdma_lock(irq_handler_t handler, void *data)
{
unsigned long flags;
@@ -92,6 +92,7 @@ void stdma_lock(irqreturn_t (*handler)(int, void *, struct pt_regs *),
stdma_isr_data = data;
local_irq_restore(flags);
}
+EXPORT_SYMBOL(stdma_lock);
/*
@@ -118,6 +119,7 @@ void stdma_release(void)
local_irq_restore(flags);
}
+EXPORT_SYMBOL(stdma_release);
/*
@@ -135,6 +137,7 @@ int stdma_others_waiting(void)
{
return waitqueue_active(&stdma_wait);
}
+EXPORT_SYMBOL(stdma_others_waiting);
/*
@@ -156,6 +159,7 @@ int stdma_islocked(void)
{
return stdma_locked;
}
+EXPORT_SYMBOL(stdma_islocked);
/*
@@ -175,8 +179,9 @@ int stdma_islocked(void)
void __init stdma_init(void)
{
stdma_isr = NULL;
- request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW,
- "ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int);
+ if (request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | IRQF_SHARED,
+ "ST-DMA floppy,ACSI,IDE,Falcon-SCSI", stdma_int))
+ pr_err("Couldn't register ST-DMA interrupt\n");
}
@@ -188,9 +193,9 @@ void __init stdma_init(void)
*
*/
-static irqreturn_t stdma_int(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t stdma_int(int irq, void *dummy)
{
if (stdma_isr)
- (*stdma_isr)(irq, stdma_isr_data, fp);
+ (*stdma_isr)(irq, stdma_isr_data);
return IRQ_HANDLED;
}
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index 5a3c106b40c..5f8cb5a234d 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -1,5 +1,5 @@
/*
- * arch/m68k/atari/stram.c: Functions for ST-RAM allocations
+ * Functions for ST-RAM allocations
*
* Copyright 1994-97 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
*
@@ -8,21 +8,19 @@
* for more details.
*/
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/kdev_t.h>
#include <linux/major.h>
#include <linux/init.h>
-#include <linux/swap.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
-#include <linux/shm.h>
#include <linux/bootmem.h>
#include <linux/mount.h>
#include <linux/blkdev.h>
+#include <linux/module.h>
#include <asm/setup.h>
#include <asm/machdep.h>
@@ -31,218 +29,37 @@
#include <asm/atarihw.h>
#include <asm/atari_stram.h>
#include <asm/io.h>
-#include <asm/semaphore.h>
-#include <linux/swapops.h>
-
-#undef DEBUG
-
-#ifdef DEBUG
-#define DPRINTK(fmt,args...) printk( fmt, ##args )
-#else
-#define DPRINTK(fmt,args...)
-#endif
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_STRAM_PROC)
-/* abbrev for the && above... */
-#define DO_PROC
-#include <linux/proc_fs.h>
-#endif
-
-/* Pre-swapping comments:
- *
- * ++roman:
- *
- * New version of ST-Ram buffer allocation. Instead of using the
- * 1 MB - 4 KB that remain when the ST-Ram chunk starts at $1000
- * (1 MB granularity!), such buffers are reserved like this:
- *
- * - If the kernel resides in ST-Ram anyway, we can take the buffer
- * from behind the current kernel data space the normal way
- * (incrementing start_mem).
- *
- * - If the kernel is in TT-Ram, stram_init() initializes start and
- * end of the available region. Buffers are allocated from there
- * and mem_init() later marks the such used pages as reserved.
- * Since each TT-Ram chunk is at least 4 MB in size, I hope there
- * won't be an overrun of the ST-Ram region by normal kernel data
- * space.
- *
- * For that, ST-Ram may only be allocated while kernel initialization
- * is going on, or exactly: before mem_init() is called. There is also
- * no provision now for freeing ST-Ram buffers. It seems that isn't
- * really needed.
- *
- */
/*
- * New Nov 1997: Use ST-RAM as swap space!
- *
- * In the past, there were often problems with modules that require ST-RAM
- * buffers. Such drivers have to use __get_dma_pages(), which unfortunately
- * often isn't very successful in allocating more than 1 page :-( [1] The net
- * result was that most of the time you couldn't insmod such modules (ataflop,
- * ACSI, SCSI on Falcon, Atari internal framebuffer, not to speak of acsi_slm,
- * which needs a 1 MB buffer... :-).
- *
- * To overcome this limitation, ST-RAM can now be turned into a very
- * high-speed swap space. If a request for an ST-RAM buffer comes, the kernel
- * now tries to unswap some pages on that swap device to make some free (and
- * contiguous) space. This works much better in comparison to
- * __get_dma_pages(), since used swap pages can be selectively freed by either
- * moving them to somewhere else in swap space, or by reading them back into
- * system memory. Ok, there operation of unswapping isn't really cheap (for
- * each page, one has to go through the page tables of all processes), but it
- * doesn't happen that often (only when allocation ST-RAM, i.e. when loading a
- * module that needs ST-RAM). But it at least makes it possible to load such
- * modules!
- *
- * It could also be that overall system performance increases a bit due to
- * ST-RAM swapping, since slow ST-RAM isn't used anymore for holding data or
- * executing code in. It's then just a (very fast, compared to disk) back
- * storage for not-so-often needed data. (But this effect must be compared
- * with the loss of total memory...) Don't know if the effect is already
- * visible on a TT, where the speed difference between ST- and TT-RAM isn't
- * that dramatic, but it should on machines where TT-RAM is really much faster
- * (e.g. Afterburner).
- *
- * [1]: __get_free_pages() does a fine job if you only want one page, but if
- * you want more (contiguous) pages, it can give you such a block only if
- * there's already a free one. The algorithm can't try to free buffers or swap
- * out something in order to make more free space, since all that page-freeing
- * mechanisms work "target-less", i.e. they just free something, but not in a
- * specific place. I.e., __get_free_pages() can't do anything to free
- * *adjacent* pages :-( This situation becomes even worse for DMA memory,
- * since the freeing algorithms are also blind to DMA capability of pages.
+ * The ST-RAM allocator allocates memory from a pool of reserved ST-RAM of
+ * configurable size, set aside on ST-RAM init.
+ * As long as this pool is not exhausted, allocation of real ST-RAM can be
+ * guaranteed.
*/
-/* 1998-10-20: ++andreas
- unswap_by_move disabled because it does not handle swapped shm pages.
-*/
-
-/* 2000-05-01: ++andreas
- Integrated with bootmem. Remove all traces of unswap_by_move.
-*/
-
-#ifdef CONFIG_STRAM_SWAP
-#define ALIGN_IF_SWAP(x) PAGE_ALIGN(x)
-#else
-#define ALIGN_IF_SWAP(x) (x)
-#endif
-
-/* get index of swap page at address 'addr' */
-#define SWAP_NR(addr) (((addr) - swap_start) >> PAGE_SHIFT)
-
-/* get address of swap page #'nr' */
-#define SWAP_ADDR(nr) (swap_start + ((nr) << PAGE_SHIFT))
-
-/* get number of pages for 'n' bytes (already page-aligned) */
-#define N_PAGES(n) ((n) >> PAGE_SHIFT)
-
-/* The following two numbers define the maximum fraction of ST-RAM in total
- * memory, below that the kernel would automatically use ST-RAM as swap
- * space. This decision can be overridden with stram_swap= */
-#define MAX_STRAM_FRACTION_NOM 1
-#define MAX_STRAM_FRACTION_DENOM 3
-
-/* Start and end (virtual) of ST-RAM */
-static void *stram_start, *stram_end;
-
-/* set after memory_init() executed and allocations via start_mem aren't
- * possible anymore */
-static int mem_init_done;
-
/* set if kernel is in ST-RAM */
static int kernel_in_stram;
-typedef struct stram_block {
- struct stram_block *next;
- void *start;
- unsigned long size;
- unsigned flags;
- const char *owner;
-} BLOCK;
-
-/* values for flags field */
-#define BLOCK_FREE 0x01 /* free structure in the BLOCKs pool */
-#define BLOCK_KMALLOCED 0x02 /* structure allocated by kmalloc() */
-#define BLOCK_GFP 0x08 /* block allocated with __get_dma_pages() */
-#define BLOCK_INSWAP 0x10 /* block allocated in swap space */
-
-/* list of allocated blocks */
-static BLOCK *alloc_list;
-
-/* We can't always use kmalloc() to allocate BLOCK structures, since
- * stram_alloc() can be called rather early. So we need some pool of
- * statically allocated structures. 20 of them is more than enough, so in most
- * cases we never should need to call kmalloc(). */
-#define N_STATIC_BLOCKS 20
-static BLOCK static_blocks[N_STATIC_BLOCKS];
-
-#ifdef CONFIG_STRAM_SWAP
-/* max. number of bytes to use for swapping
- * 0 = no ST-RAM swapping
- * -1 = do swapping (to whole ST-RAM) if it's less than MAX_STRAM_FRACTION of
- * total memory
- */
-static int max_swap_size = -1;
-
-/* start and end of swapping area */
-static void *swap_start, *swap_end;
-
-/* The ST-RAM's swap info structure */
-static struct swap_info_struct *stram_swap_info;
-
-/* The ST-RAM's swap type */
-static int stram_swap_type;
-
-/* Semaphore for get_stram_region. */
-static DECLARE_MUTEX(stram_swap_sem);
-
-/* major and minor device number of the ST-RAM device; for the major, we use
- * the same as Amiga z2ram, which is really similar and impossible on Atari,
- * and for the minor a relatively odd number to avoid the user creating and
- * using that device. */
-#define STRAM_MAJOR Z2RAM_MAJOR
-#define STRAM_MINOR 13
-
-/* Some impossible pointer value */
-#define MAGIC_FILE_P (struct file *)0xffffdead
+static struct resource stram_pool = {
+ .name = "ST-RAM Pool"
+};
-#ifdef DO_PROC
-static unsigned stat_swap_read;
-static unsigned stat_swap_write;
-static unsigned stat_swap_force;
-#endif /* DO_PROC */
+static unsigned long pool_size = 1024*1024;
-#endif /* CONFIG_STRAM_SWAP */
+static unsigned long stram_virt_offset;
-/***************************** Prototypes *****************************/
+static int __init atari_stram_setup(char *arg)
+{
+ if (!MACH_IS_ATARI)
+ return 0;
-#ifdef CONFIG_STRAM_SWAP
-static int swap_init(void *start_mem, void *swap_data);
-static void *get_stram_region( unsigned long n_pages );
-static void free_stram_region( unsigned long offset, unsigned long n_pages
- );
-static int in_some_region(void *addr);
-static unsigned long find_free_region( unsigned long n_pages, unsigned long
- *total_free, unsigned long
- *region_free );
-static void do_stram_request(request_queue_t *);
-static int stram_open( struct inode *inode, struct file *filp );
-static int stram_release( struct inode *inode, struct file *filp );
-static void reserve_region(void *start, void *end);
-#endif
-static BLOCK *add_region( void *addr, unsigned long size );
-static BLOCK *find_region( void *addr );
-static int remove_region( BLOCK *block );
+ pool_size = memparse(arg, NULL);
+ return 0;
+}
-/************************* End of Prototypes **************************/
+early_param("stram_pool", atari_stram_setup);
-
-/* ------------------------------------------------------------------------ */
-/* Public Interface */
-/* ------------------------------------------------------------------------ */
/*
* This init function is called very early by atari/config.c
@@ -252,996 +69,129 @@ void __init atari_stram_init(void)
{
int i;
- /* initialize static blocks */
- for( i = 0; i < N_STATIC_BLOCKS; ++i )
- static_blocks[i].flags = BLOCK_FREE;
-
- /* determine whether kernel code resides in ST-RAM (then ST-RAM is the
- * first memory block at virtual 0x0) */
- stram_start = phys_to_virt(0);
- kernel_in_stram = (stram_start == 0);
+ /*
+ * determine whether kernel code resides in ST-RAM
+ * (then ST-RAM is the first memory block at virtual 0x0)
+ */
+ kernel_in_stram = (m68k_memory[0].addr == 0);
- for( i = 0; i < m68k_num_memory; ++i ) {
+ for (i = 0; i < m68k_num_memory; ++i) {
if (m68k_memory[i].addr == 0) {
- /* skip first 2kB or page (supervisor-only!) */
- stram_end = stram_start + m68k_memory[i].size;
return;
}
}
+
/* Should never come here! (There is always ST-Ram!) */
- panic( "atari_stram_init: no ST-RAM found!" );
+ panic("atari_stram_init: no ST-RAM found!");
}
/*
* This function is called from setup_arch() to reserve the pages needed for
- * ST-RAM management.
+ * ST-RAM management, if the kernel resides in ST-RAM.
*/
void __init atari_stram_reserve_pages(void *start_mem)
{
-#ifdef CONFIG_STRAM_SWAP
- /* if max_swap_size is negative (i.e. no stram_swap= option given),
- * determine at run time whether to use ST-RAM swapping */
- if (max_swap_size < 0)
- /* Use swapping if ST-RAM doesn't make up more than MAX_STRAM_FRACTION
- * of total memory. In that case, the max. size is set to 16 MB,
- * because ST-RAM can never be bigger than that.
- * Also, never use swapping on a Hades, there's no separate ST-RAM in
- * that machine. */
- max_swap_size =
- (!MACH_IS_HADES &&
- (N_PAGES(stram_end-stram_start)*MAX_STRAM_FRACTION_DENOM <=
- ((unsigned long)high_memory>>PAGE_SHIFT)*MAX_STRAM_FRACTION_NOM)) ? 16*1024*1024 : 0;
- DPRINTK( "atari_stram_reserve_pages: max_swap_size = %d\n", max_swap_size );
-#endif
-
- /* always reserve first page of ST-RAM, the first 2 kB are
- * supervisor-only! */
- if (!kernel_in_stram)
- reserve_bootmem (0, PAGE_SIZE);
-
-#ifdef CONFIG_STRAM_SWAP
- {
- void *swap_data;
-
- start_mem = (void *) PAGE_ALIGN ((unsigned long) start_mem);
- /* determine first page to use as swap: if the kernel is
- in TT-RAM, this is the first page of (usable) ST-RAM;
- otherwise just use the end of kernel data (= start_mem) */
- swap_start = !kernel_in_stram ? stram_start + PAGE_SIZE : start_mem;
- /* decrement by one page, rest of kernel assumes that first swap page
- * is always reserved and maybe doesn't handle swp_entry == 0
- * correctly */
- swap_start -= PAGE_SIZE;
- swap_end = stram_end;
- if (swap_end-swap_start > max_swap_size)
- swap_end = swap_start + max_swap_size;
- DPRINTK( "atari_stram_reserve_pages: swapping enabled; "
- "swap=%p-%p\n", swap_start, swap_end);
-
- /* reserve some amount of memory for maintainance of
- * swapping itself: one page for each 2048 (PAGE_SIZE/2)
- * swap pages. (2 bytes for each page) */
- swap_data = start_mem;
- start_mem += ((SWAP_NR(swap_end) + PAGE_SIZE/2 - 1)
- >> (PAGE_SHIFT-1)) << PAGE_SHIFT;
- /* correct swap_start if necessary */
- if (swap_start + PAGE_SIZE == swap_data)
- swap_start = start_mem - PAGE_SIZE;
-
- if (!swap_init( start_mem, swap_data )) {
- printk( KERN_ERR "ST-RAM swap space initialization failed\n" );
- max_swap_size = 0;
- return;
- }
- /* reserve region for swapping meta-data */
- reserve_region(swap_data, start_mem);
- /* reserve swapping area itself */
- reserve_region(swap_start + PAGE_SIZE, swap_end);
-
- /*
- * If the whole ST-RAM is used for swapping, there are no allocatable
- * dma pages left. But unfortunately, some shared parts of the kernel
- * (particularly the SCSI mid-level) call __get_dma_pages()
- * unconditionally :-( These calls then fail, and scsi.c even doesn't
- * check for NULL return values and just crashes. The quick fix for
- * this (instead of doing much clean up work in the SCSI code) is to
- * pretend all pages are DMA-able by setting mach_max_dma_address to
- * ULONG_MAX. This doesn't change any functionality so far, since
- * get_dma_pages() shouldn't be used on Atari anyway anymore (better
- * use atari_stram_alloc()), and the Atari SCSI drivers don't need DMA
- * memory. But unfortunately there's now no kind of warning (even not
- * a NULL return value) if you use get_dma_pages() nevertheless :-(
- * You just will get non-DMA-able memory...
- */
- mach_max_dma_address = 0xffffffff;
+ if (kernel_in_stram) {
+ pr_debug("atari_stram pool: kernel in ST-RAM, using alloc_bootmem!\n");
+ stram_pool.start = (resource_size_t)alloc_bootmem_low_pages(pool_size);
+ stram_pool.end = stram_pool.start + pool_size - 1;
+ request_resource(&iomem_resource, &stram_pool);
+ stram_virt_offset = 0;
+ pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n",
+ pool_size, &stram_pool);
+ pr_debug("atari_stram pool: stram_virt_offset = %lx\n",
+ stram_virt_offset);
}
-#endif
-}
-
-void atari_stram_mem_init_hook (void)
-{
- mem_init_done = 1;
}
/*
- * This is main public interface: somehow allocate a ST-RAM block
- * There are three strategies:
- *
- * - If we're before mem_init(), we have to make a static allocation. The
- * region is taken in the kernel data area (if the kernel is in ST-RAM) or
- * from the start of ST-RAM (if the kernel is in TT-RAM) and added to the
- * rsvd_stram_* region. The ST-RAM is somewhere in the middle of kernel
- * address space in the latter case.
- *
- * - If mem_init() already has been called and ST-RAM swapping is enabled,
- * try to get the memory from the (pseudo) swap-space, either free already
- * or by moving some other pages out of the swap.
- *
- * - If mem_init() already has been called, and ST-RAM swapping is not
- * enabled, the only possibility is to try with __get_dma_pages(). This has
- * the disadvantage that it's very hard to get more than 1 page, and it is
- * likely to fail :-(
- *
+ * This function is called as arch initcall to reserve the pages needed for
+ * ST-RAM management, if the kernel does not reside in ST-RAM.
*/
-void *atari_stram_alloc(long size, const char *owner)
+int __init atari_stram_map_pages(void)
{
- void *addr = NULL;
- BLOCK *block;
- int flags;
-
- DPRINTK("atari_stram_alloc(size=%08lx,owner=%s)\n", size, owner);
-
- size = ALIGN_IF_SWAP(size);
- DPRINTK( "atari_stram_alloc: rounded size = %08lx\n", size );
-#ifdef CONFIG_STRAM_SWAP
- if (max_swap_size) {
- /* If swapping is active: make some free space in the swap
- "device". */
- DPRINTK( "atari_stram_alloc: after mem_init, swapping ok, "
- "calling get_region\n" );
- addr = get_stram_region( N_PAGES(size) );
- flags = BLOCK_INSWAP;
- }
- else
-#endif
- if (!mem_init_done)
- return alloc_bootmem_low(size);
- else {
- /* After mem_init() and no swapping: can only resort to
- * __get_dma_pages() */
- addr = (void *)__get_dma_pages(GFP_KERNEL, get_order(size));
- flags = BLOCK_GFP;
- DPRINTK( "atari_stram_alloc: after mem_init, swapping off, "
- "get_pages=%p\n", addr );
- }
-
- if (addr) {
- if (!(block = add_region( addr, size ))) {
- /* out of memory for BLOCK structure :-( */
- DPRINTK( "atari_stram_alloc: out of mem for BLOCK -- "
- "freeing again\n" );
-#ifdef CONFIG_STRAM_SWAP
- if (flags == BLOCK_INSWAP)
- free_stram_region( SWAP_NR(addr), N_PAGES(size) );
- else
-#endif
- free_pages((unsigned long)addr, get_order(size));
- return( NULL );
- }
- block->owner = owner;
- block->flags |= flags;
- }
- return( addr );
-}
-
-void atari_stram_free( void *addr )
-
-{
- BLOCK *block;
-
- DPRINTK( "atari_stram_free(addr=%p)\n", addr );
-
- if (!(block = find_region( addr ))) {
- printk( KERN_ERR "Attempt to free non-allocated ST-RAM block at %p "
- "from %p\n", addr, __builtin_return_address(0) );
- return;
- }
- DPRINTK( "atari_stram_free: found block (%p): size=%08lx, owner=%s, "
- "flags=%02x\n", block, block->size, block->owner, block->flags );
-
-#ifdef CONFIG_STRAM_SWAP
- if (!max_swap_size) {
-#endif
- if (block->flags & BLOCK_GFP) {
- DPRINTK("atari_stram_free: is kmalloced, order_size=%d\n",
- get_order(block->size));
- free_pages((unsigned long)addr, get_order(block->size));
- }
- else
- goto fail;
-#ifdef CONFIG_STRAM_SWAP
- }
- else if (block->flags & BLOCK_INSWAP) {
- DPRINTK( "atari_stram_free: is swap-alloced\n" );
- free_stram_region( SWAP_NR(block->start), N_PAGES(block->size) );
- }
- else
- goto fail;
-#endif
- remove_region( block );
- return;
-
- fail:
- printk( KERN_ERR "atari_stram_free: cannot free block at %p "
- "(called from %p)\n", addr, __builtin_return_address(0) );
-}
-
-
-#ifdef CONFIG_STRAM_SWAP
-
-
-/* ------------------------------------------------------------------------ */
-/* Main Swapping Functions */
-/* ------------------------------------------------------------------------ */
-
-
-/*
- * Initialize ST-RAM swap device
- * (lots copied and modified from sys_swapon() in mm/swapfile.c)
- */
-static int __init swap_init(void *start_mem, void *swap_data)
-{
- static struct dentry fake_dentry;
- static struct vfsmount fake_vfsmnt;
- struct swap_info_struct *p;
- struct inode swap_inode;
- unsigned int type;
- void *addr;
- int i, j, k, prev;
-
- DPRINTK("swap_init(start_mem=%p, swap_data=%p)\n",
- start_mem, swap_data);
-
- /* need at least one page for swapping to (and this also isn't very
- * much... :-) */
- if (swap_end - swap_start < 2*PAGE_SIZE) {
- printk( KERN_WARNING "stram_swap_init: swap space too small\n" );
- return( 0 );
- }
-
- /* find free slot in swap_info */
- for( p = swap_info, type = 0; type < nr_swapfiles; type++, p++ )
- if (!(p->flags & SWP_USED))
- break;
- if (type >= MAX_SWAPFILES) {
- printk( KERN_WARNING "stram_swap_init: max. number of "
- "swap devices exhausted\n" );
- return( 0 );
- }
- if (type >= nr_swapfiles)
- nr_swapfiles = type+1;
-
- stram_swap_info = p;
- stram_swap_type = type;
-
- /* fake some dir cache entries to give us some name in /dev/swaps */
- fake_dentry.d_parent = &fake_dentry;
- fake_dentry.d_name.name = "stram (internal)";
- fake_dentry.d_name.len = 16;
- fake_vfsmnt.mnt_parent = &fake_vfsmnt;
-
- p->flags = SWP_USED;
- p->swap_file = &fake_dentry;
- p->swap_vfsmnt = &fake_vfsmnt;
- p->swap_map = swap_data;
- p->cluster_nr = 0;
- p->next = -1;
- p->prio = 0x7ff0; /* a rather high priority, but not the higest
- * to give the user a chance to override */
-
- /* call stram_open() directly, avoids at least the overhead in
- * constructing a dummy file structure... */
- swap_inode.i_rdev = MKDEV( STRAM_MAJOR, STRAM_MINOR );
- stram_open( &swap_inode, MAGIC_FILE_P );
- p->max = SWAP_NR(swap_end);
-
- /* initialize swap_map: set regions that are already allocated or belong
- * to kernel data space to SWAP_MAP_BAD, otherwise to free */
- j = 0; /* # of free pages */
- k = 0; /* # of already allocated pages (from pre-mem_init stram_alloc()) */
- p->lowest_bit = 0;
- p->highest_bit = 0;
- for( i = 1, addr = SWAP_ADDR(1); i < p->max;
- i++, addr += PAGE_SIZE ) {
- if (in_some_region( addr )) {
- p->swap_map[i] = SWAP_MAP_BAD;
- ++k;
- }
- else if (kernel_in_stram && addr < start_mem ) {
- p->swap_map[i] = SWAP_MAP_BAD;
- }
- else {
- p->swap_map[i] = 0;
- ++j;
- if (!p->lowest_bit) p->lowest_bit = i;
- p->highest_bit = i;
- }
- }
- /* first page always reserved (and doesn't really belong to swap space) */
- p->swap_map[0] = SWAP_MAP_BAD;
-
- /* now swapping to this device ok */
- p->pages = j + k;
- swap_list_lock();
- nr_swap_pages += j;
- p->flags = SWP_WRITEOK;
-
- /* insert swap space into swap_list */
- prev = -1;
- for (i = swap_list.head; i >= 0; i = swap_info[i].next) {
- if (p->prio >= swap_info[i].prio) {
- break;
- }
- prev = i;
- }
- p->next = i;
- if (prev < 0) {
- swap_list.head = swap_list.next = p - swap_info;
- } else {
- swap_info[prev].next = p - swap_info;
- }
- swap_list_unlock();
-
- printk( KERN_INFO "Using %dk (%d pages) of ST-RAM as swap space.\n",
- p->pages << 2, p->pages );
- return( 1 );
-}
-
-
-/*
- * The swap entry has been read in advance, and we return 1 to indicate
- * that the page has been used or is no longer needed.
- *
- * Always set the resulting pte to be nowrite (the same as COW pages
- * after one process has exited). We don't know just how many PTEs will
- * share this swap entry, so be cautious and let do_wp_page work out
- * what to do if a write is requested later.
- */
-static inline void unswap_pte(struct vm_area_struct * vma, unsigned long
- address, pte_t *dir, swp_entry_t entry,
- struct page *page)
-{
- pte_t pte = *dir;
-
- if (pte_none(pte))
- return;
- if (pte_present(pte)) {
- /* If this entry is swap-cached, then page must already
- hold the right address for any copies in physical
- memory */
- if (pte_page(pte) != page)
- return;
- /* We will be removing the swap cache in a moment, so... */
- set_pte(dir, pte_mkdirty(pte));
- return;
- }
- if (pte_val(pte) != entry.val)
- return;
-
- DPRINTK("unswap_pte: replacing entry %08lx by new page %p",
- entry.val, page);
- set_pte(dir, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- swap_free(entry);
- get_page(page);
- inc_mm_counter(vma->vm_mm, rss);
-}
-
-static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir,
- unsigned long address, unsigned long size,
- unsigned long offset, swp_entry_t entry,
- struct page *page)
-{
- pte_t * pte;
- unsigned long end;
-
- if (pmd_none(*dir))
- return;
- if (pmd_bad(*dir)) {
- pmd_ERROR(*dir);
- pmd_clear(dir);
- return;
- }
- pte = pte_offset_kernel(dir, address);
- offset += address & PMD_MASK;
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- do {
- unswap_pte(vma, offset+address-vma->vm_start, pte, entry, page);
- address += PAGE_SIZE;
- pte++;
- } while (address < end);
-}
-
-static inline void unswap_pgd(struct vm_area_struct * vma, pgd_t *dir,
- unsigned long address, unsigned long size,
- swp_entry_t entry, struct page *page)
-{
- pmd_t * pmd;
- unsigned long offset, end;
-
- if (pgd_none(*dir))
- return;
- if (pgd_bad(*dir)) {
- pgd_ERROR(*dir);
- pgd_clear(dir);
- return;
- }
- pmd = pmd_offset(dir, address);
- offset = address & PGDIR_MASK;
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- do {
- unswap_pmd(vma, pmd, address, end - address, offset, entry,
- page);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address < end);
-}
-
-static void unswap_vma(struct vm_area_struct * vma, pgd_t *pgdir,
- swp_entry_t entry, struct page *page)
-{
- unsigned long start = vma->vm_start, end = vma->vm_end;
-
- do {
- unswap_pgd(vma, pgdir, start, end - start, entry, page);
- start = (start + PGDIR_SIZE) & PGDIR_MASK;
- pgdir++;
- } while (start < end);
-}
-
-static void unswap_process(struct mm_struct * mm, swp_entry_t entry,
- struct page *page)
-{
- struct vm_area_struct* vma;
-
- /*
- * Go through process' page directory.
- */
- if (!mm)
- return;
- for (vma = mm->mmap; vma; vma = vma->vm_next) {
- pgd_t * pgd = pgd_offset(mm, vma->vm_start);
- unswap_vma(vma, pgd, entry, page);
- }
-}
-
-
-static int unswap_by_read(unsigned short *map, unsigned long max,
- unsigned long start, unsigned long n_pages)
-{
- struct task_struct *p;
- struct page *page;
- swp_entry_t entry;
- unsigned long i;
-
- DPRINTK( "unswapping %lu..%lu by reading in\n",
- start, start+n_pages-1 );
-
- for( i = start; i < start+n_pages; ++i ) {
- if (map[i] == SWAP_MAP_BAD) {
- printk( KERN_ERR "get_stram_region: page %lu already "
- "reserved??\n", i );
- continue;
- }
-
- if (map[i]) {
- entry = swp_entry(stram_swap_type, i);
- DPRINTK("unswap: map[i=%lu]=%u nr_swap=%ld\n",
- i, map[i], nr_swap_pages);
-
- swap_device_lock(stram_swap_info);
- map[i]++;
- swap_device_unlock(stram_swap_info);
- /* Get a page for the entry, using the existing
- swap cache page if there is one. Otherwise,
- get a clean page and read the swap into it. */
- page = read_swap_cache_async(entry, NULL, 0);
- if (!page) {
- swap_free(entry);
- return -ENOMEM;
- }
- read_lock(&tasklist_lock);
- for_each_process(p)
- unswap_process(p->mm, entry, page);
- read_unlock(&tasklist_lock);
- shmem_unuse(entry, page);
- /* Now get rid of the extra reference to the
- temporary page we've been using. */
- if (PageSwapCache(page))
- delete_from_swap_cache(page);
- __free_page(page);
- #ifdef DO_PROC
- stat_swap_force++;
- #endif
- }
-
- DPRINTK( "unswap: map[i=%lu]=%u nr_swap=%ld\n",
- i, map[i], nr_swap_pages );
- swap_list_lock();
- swap_device_lock(stram_swap_info);
- map[i] = SWAP_MAP_BAD;
- if (stram_swap_info->lowest_bit == i)
- stram_swap_info->lowest_bit++;
- if (stram_swap_info->highest_bit == i)
- stram_swap_info->highest_bit--;
- --nr_swap_pages;
- swap_device_unlock(stram_swap_info);
- swap_list_unlock();
+ if (!kernel_in_stram) {
+ /*
+ * Skip page 0, as the fhe first 2 KiB are supervisor-only!
+ */
+ pr_debug("atari_stram pool: kernel not in ST-RAM, using ioremap!\n");
+ stram_pool.start = PAGE_SIZE;
+ stram_pool.end = stram_pool.start + pool_size - 1;
+ request_resource(&iomem_resource, &stram_pool);
+ stram_virt_offset = (unsigned long) ioremap(stram_pool.start,
+ resource_size(&stram_pool)) - stram_pool.start;
+ pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n",
+ pool_size, &stram_pool);
+ pr_debug("atari_stram pool: stram_virt_offset = %lx\n",
+ stram_virt_offset);
}
-
return 0;
}
-
-/*
- * reserve a region in ST-RAM swap space for an allocation
- */
-static void *get_stram_region( unsigned long n_pages )
-{
- unsigned short *map = stram_swap_info->swap_map;
- unsigned long max = stram_swap_info->max;
- unsigned long start, total_free, region_free;
- int err;
- void *ret = NULL;
-
- DPRINTK( "get_stram_region(n_pages=%lu)\n", n_pages );
-
- down(&stram_swap_sem);
-
- /* disallow writing to the swap device now */
- stram_swap_info->flags = SWP_USED;
-
- /* find a region of n_pages pages in the swap space including as much free
- * pages as possible (and excluding any already-reserved pages). */
- if (!(start = find_free_region( n_pages, &total_free, &region_free )))
- goto end;
- DPRINTK( "get_stram_region: region starts at %lu, has %lu free pages\n",
- start, region_free );
-
- err = unswap_by_read(map, max, start, n_pages);
- if (err)
- goto end;
-
- ret = SWAP_ADDR(start);
- end:
- /* allow using swap device again */
- stram_swap_info->flags = SWP_WRITEOK;
- up(&stram_swap_sem);
- DPRINTK( "get_stram_region: returning %p\n", ret );
- return( ret );
-}
-
-
-/*
- * free a reserved region in ST-RAM swap space
- */
-static void free_stram_region( unsigned long offset, unsigned long n_pages )
-{
- unsigned short *map = stram_swap_info->swap_map;
-
- DPRINTK( "free_stram_region(offset=%lu,n_pages=%lu)\n", offset, n_pages );
-
- if (offset < 1 || offset + n_pages > stram_swap_info->max) {
- printk( KERN_ERR "free_stram_region: Trying to free non-ST-RAM\n" );
- return;
- }
-
- swap_list_lock();
- swap_device_lock(stram_swap_info);
- /* un-reserve the freed pages */
- for( ; n_pages > 0; ++offset, --n_pages ) {
- if (map[offset] != SWAP_MAP_BAD)
- printk( KERN_ERR "free_stram_region: Swap page %lu was not "
- "reserved\n", offset );
- map[offset] = 0;
- }
-
- /* update swapping meta-data */
- if (offset < stram_swap_info->lowest_bit)
- stram_swap_info->lowest_bit = offset;
- if (offset+n_pages-1 > stram_swap_info->highest_bit)
- stram_swap_info->highest_bit = offset+n_pages-1;
- if (stram_swap_info->prio > swap_info[swap_list.next].prio)
- swap_list.next = swap_list.head;
- nr_swap_pages += n_pages;
- swap_device_unlock(stram_swap_info);
- swap_list_unlock();
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Utility Functions for Swapping */
-/* ------------------------------------------------------------------------ */
-
-
-/* is addr in some of the allocated regions? */
-static int in_some_region(void *addr)
-{
- BLOCK *p;
-
- for( p = alloc_list; p; p = p->next ) {
- if (p->start <= addr && addr < p->start + p->size)
- return( 1 );
- }
- return( 0 );
-}
-
-
-static unsigned long find_free_region(unsigned long n_pages,
- unsigned long *total_free,
- unsigned long *region_free)
-{
- unsigned short *map = stram_swap_info->swap_map;
- unsigned long max = stram_swap_info->max;
- unsigned long head, tail, max_start;
- long nfree, max_free;
-
- /* first scan the swap space for a suitable place for the allocation */
- head = 1;
- max_start = 0;
- max_free = -1;
- *total_free = 0;
-
- start_over:
- /* increment tail until final window size reached, and count free pages */
- nfree = 0;
- for( tail = head; tail-head < n_pages && tail < max; ++tail ) {
- if (map[tail] == SWAP_MAP_BAD) {
- head = tail+1;
- goto start_over;
- }
- if (!map[tail]) {
- ++nfree;
- ++*total_free;
- }
- }
- if (tail-head < n_pages)
- goto out;
- if (nfree > max_free) {
- max_start = head;
- max_free = nfree;
- if (max_free >= n_pages)
- /* don't need more free pages... :-) */
- goto out;
- }
-
- /* now shift the window and look for the area where as much pages as
- * possible are free */
- while( tail < max ) {
- nfree -= (map[head++] == 0);
- if (map[tail] == SWAP_MAP_BAD) {
- head = tail+1;
- goto start_over;
- }
- if (!map[tail]) {
- ++nfree;
- ++*total_free;
- }
- ++tail;
- if (nfree > max_free) {
- max_start = head;
- max_free = nfree;
- if (max_free >= n_pages)
- /* don't need more free pages... :-) */
- goto out;
- }
- }
-
- out:
- if (max_free < 0) {
- printk( KERN_NOTICE "get_stram_region: ST-RAM too full or fragmented "
- "-- can't allocate %lu pages\n", n_pages );
- return( 0 );
- }
-
- *region_free = max_free;
- return( max_start );
-}
-
-
-/* setup parameters from command line */
-void __init stram_swap_setup(char *str, int *ints)
-{
- if (ints[0] >= 1)
- max_swap_size = ((ints[1] < 0 ? 0 : ints[1]) * 1024) & PAGE_MASK;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* ST-RAM device */
-/* ------------------------------------------------------------------------ */
-
-static int refcnt;
-
-static void do_stram_request(request_queue_t *q)
-{
- struct request *req;
-
- while ((req = elv_next_request(q)) != NULL) {
- void *start = swap_start + (req->sector << 9);
- unsigned long len = req->current_nr_sectors << 9;
- if ((start + len) > swap_end) {
- printk( KERN_ERR "stram: bad access beyond end of device: "
- "block=%ld, count=%d\n",
- req->sector,
- req->current_nr_sectors );
- end_request(req, 0);
- continue;
- }
-
- if (req->cmd == READ) {
- memcpy(req->buffer, start, len);
-#ifdef DO_PROC
- stat_swap_read += N_PAGES(len);
-#endif
- }
- else {
- memcpy(start, req->buffer, len);
-#ifdef DO_PROC
- stat_swap_write += N_PAGES(len);
-#endif
- }
- end_request(req, 1);
- }
-}
+arch_initcall(atari_stram_map_pages);
-static int stram_open( struct inode *inode, struct file *filp )
+void *atari_stram_to_virt(unsigned long phys)
{
- if (filp != MAGIC_FILE_P) {
- printk( KERN_NOTICE "Only kernel can open ST-RAM device\n" );
- return( -EPERM );
- }
- if (refcnt)
- return( -EBUSY );
- ++refcnt;
- return( 0 );
-}
-
-static int stram_release( struct inode *inode, struct file *filp )
-{
- if (filp != MAGIC_FILE_P) {
- printk( KERN_NOTICE "Only kernel can close ST-RAM device\n" );
- return( -EPERM );
- }
- if (refcnt > 0)
- --refcnt;
- return( 0 );
-}
-
-
-static struct block_device_operations stram_fops = {
- .open = stram_open,
- .release = stram_release,
-};
-
-static struct gendisk *stram_disk;
-static struct request_queue *stram_queue;
-static DEFINE_SPINLOCK(stram_lock);
-
-int __init stram_device_init(void)
-{
- if (!MACH_IS_ATARI)
- /* no point in initializing this, I hope */
- return -ENXIO;
-
- if (!max_swap_size)
- /* swapping not enabled */
- return -ENXIO;
- stram_disk = alloc_disk(1);
- if (!stram_disk)
- return -ENOMEM;
-
- if (register_blkdev(STRAM_MAJOR, "stram")) {
- put_disk(stram_disk);
- return -ENXIO;
- }
-
- stram_queue = blk_init_queue(do_stram_request, &stram_lock);
- if (!stram_queue) {
- unregister_blkdev(STRAM_MAJOR, "stram");
- put_disk(stram_disk);
- return -ENOMEM;
- }
-
- stram_disk->major = STRAM_MAJOR;
- stram_disk->first_minor = STRAM_MINOR;
- stram_disk->fops = &stram_fops;
- stram_disk->queue = stram_queue;
- sprintf(stram_disk->disk_name, "stram");
- set_capacity(stram_disk, (swap_end - swap_start)/512);
- add_disk(stram_disk);
- return 0;
+ return (void *)(phys + stram_virt_offset);
}
+EXPORT_SYMBOL(atari_stram_to_virt);
-
-/* ------------------------------------------------------------------------ */
-/* Misc Utility Functions */
-/* ------------------------------------------------------------------------ */
-
-/* reserve a range of pages */
-static void reserve_region(void *start, void *end)
+unsigned long atari_stram_to_phys(void *virt)
{
- reserve_bootmem (virt_to_phys(start), end - start);
+ return (unsigned long)(virt - stram_virt_offset);
}
+EXPORT_SYMBOL(atari_stram_to_phys);
-#endif /* CONFIG_STRAM_SWAP */
-
-
-/* ------------------------------------------------------------------------ */
-/* Region Management */
-/* ------------------------------------------------------------------------ */
-
-/* insert a region into the alloced list (sorted) */
-static BLOCK *add_region( void *addr, unsigned long size )
+void *atari_stram_alloc(unsigned long size, const char *owner)
{
- BLOCK **p, *n = NULL;
- int i;
-
- for( i = 0; i < N_STATIC_BLOCKS; ++i ) {
- if (static_blocks[i].flags & BLOCK_FREE) {
- n = &static_blocks[i];
- n->flags = 0;
- break;
- }
- }
- if (!n && mem_init_done) {
- /* if statics block pool exhausted and we can call kmalloc() already
- * (after mem_init()), try that */
- n = kmalloc( sizeof(BLOCK), GFP_KERNEL );
- if (n)
- n->flags = BLOCK_KMALLOCED;
- }
- if (!n) {
- printk( KERN_ERR "Out of memory for ST-RAM descriptor blocks\n" );
- return( NULL );
- }
- n->start = addr;
- n->size = size;
+ struct resource *res;
+ int error;
- for( p = &alloc_list; *p; p = &((*p)->next) )
- if ((*p)->start > addr) break;
- n->next = *p;
- *p = n;
+ pr_debug("atari_stram_alloc: allocate %lu bytes\n", size);
- return( n );
-}
+ /* round up */
+ size = PAGE_ALIGN(size);
+ res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+ if (!res)
+ return NULL;
-/* find a region (by start addr) in the alloced list */
-static BLOCK *find_region( void *addr )
-{
- BLOCK *p;
-
- for( p = alloc_list; p; p = p->next ) {
- if (p->start == addr)
- return( p );
- if (p->start > addr)
- break;
+ res->name = owner;
+ error = allocate_resource(&stram_pool, res, size, 0, UINT_MAX,
+ PAGE_SIZE, NULL, NULL);
+ if (error < 0) {
+ pr_err("atari_stram_alloc: allocate_resource() failed %d!\n",
+ error);
+ kfree(res);
+ return NULL;
}
- return( NULL );
-}
-
-/* remove a block from the alloced list */
-static int remove_region( BLOCK *block )
-{
- BLOCK **p;
-
- for( p = &alloc_list; *p; p = &((*p)->next) )
- if (*p == block) break;
- if (!*p)
- return( 0 );
-
- *p = block->next;
- if (block->flags & BLOCK_KMALLOCED)
- kfree( block );
- else
- block->flags |= BLOCK_FREE;
- return( 1 );
+ pr_debug("atari_stram_alloc: returning %pR\n", res);
+ return atari_stram_to_virt(res->start);
}
+EXPORT_SYMBOL(atari_stram_alloc);
-
-/* ------------------------------------------------------------------------ */
-/* /proc statistics file stuff */
-/* ------------------------------------------------------------------------ */
-
-#ifdef DO_PROC
-
-#define PRINT_PROC(fmt,args...) len += sprintf( buf+len, fmt, ##args )
-
-int get_stram_list( char *buf )
+void atari_stram_free(void *addr)
{
- int len = 0;
- BLOCK *p;
-#ifdef CONFIG_STRAM_SWAP
- int i;
- unsigned short *map = stram_swap_info->swap_map;
- unsigned long max = stram_swap_info->max;
- unsigned free = 0, used = 0, rsvd = 0;
-#endif
-
-#ifdef CONFIG_STRAM_SWAP
- if (max_swap_size) {
- for( i = 1; i < max; ++i ) {
- if (!map[i])
- ++free;
- else if (map[i] == SWAP_MAP_BAD)
- ++rsvd;
- else
- ++used;
- }
- PRINT_PROC(
- "Total ST-RAM: %8u kB\n"
- "Total ST-RAM swap: %8lu kB\n"
- "Free swap: %8u kB\n"
- "Used swap: %8u kB\n"
- "Allocated swap: %8u kB\n"
- "Swap Reads: %8u\n"
- "Swap Writes: %8u\n"
- "Swap Forced Reads: %8u\n",
- (stram_end - stram_start) >> 10,
- (max-1) << (PAGE_SHIFT-10),
- free << (PAGE_SHIFT-10),
- used << (PAGE_SHIFT-10),
- rsvd << (PAGE_SHIFT-10),
- stat_swap_read,
- stat_swap_write,
- stat_swap_force );
- }
- else {
-#endif
- PRINT_PROC( "ST-RAM swapping disabled\n" );
- PRINT_PROC("Total ST-RAM: %8u kB\n",
- (stram_end - stram_start) >> 10);
-#ifdef CONFIG_STRAM_SWAP
- }
-#endif
+ unsigned long start = atari_stram_to_phys(addr);
+ struct resource *res;
+ unsigned long size;
- PRINT_PROC( "Allocated regions:\n" );
- for( p = alloc_list; p; p = p->next ) {
- if (len + 50 >= PAGE_SIZE)
- break;
- PRINT_PROC("0x%08lx-0x%08lx: %s (",
- virt_to_phys(p->start),
- virt_to_phys(p->start+p->size-1),
- p->owner);
- if (p->flags & BLOCK_GFP)
- PRINT_PROC( "page-alloced)\n" );
- else if (p->flags & BLOCK_INSWAP)
- PRINT_PROC( "in swap)\n" );
- else
- PRINT_PROC( "??)\n" );
+ res = lookup_resource(&stram_pool, start);
+ if (!res) {
+ pr_err("atari_stram_free: trying to free nonexistent region "
+ "at %p\n", addr);
+ return;
}
- return( len );
+ size = resource_size(res);
+ pr_debug("atari_stram_free: free %lu bytes at %p\n", size, addr);
+ release_resource(res);
+ kfree(res);
}
-
-#endif
-
-
-/*
- * Local variables:
- * c-indent-level: 4
- * tab-width: 4
- * End:
- */
+EXPORT_SYMBOL(atari_stram_free);
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index 6df7fb60dfe..da8f981c36d 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -16,19 +16,25 @@
#include <linux/init.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
+#include <linux/delay.h>
+#include <linux/export.h>
#include <asm/atariints.h>
+DEFINE_SPINLOCK(rtc_lock);
+EXPORT_SYMBOL_GPL(rtc_lock);
+
void __init
-atari_sched_init(irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
+atari_sched_init(irq_handler_t timer_routine)
{
/* set Timer C data Register */
- mfp.tim_dt_c = INT_TICKS;
+ st_mfp.tim_dt_c = INT_TICKS;
/* start timer C, div = 1:100 */
- mfp.tim_ct_cd = (mfp.tim_ct_cd & 15) | 0x60;
+ st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 15) | 0x60;
/* install interrupt service routine for MFP Timer C */
- request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
- "timer", timer_routine);
+ if (request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
+ "timer", timer_routine))
+ pr_err("Couldn't register timer interrupt\n");
}
/* ++andreas: gettimeoffset fixed to check for pending interrupt */
@@ -36,22 +42,22 @@ atari_sched_init(irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
#define TICK_SIZE 10000
/* This is always executed with interrupts disabled. */
-unsigned long atari_gettimeoffset (void)
+u32 atari_gettimeoffset(void)
{
- unsigned long ticks, offset = 0;
+ u32 ticks, offset = 0;
/* read MFP timer C current value */
- ticks = mfp.tim_dt_c;
+ ticks = st_mfp.tim_dt_c;
/* The probability of underflow is less than 2% */
if (ticks > INT_TICKS - INT_TICKS / 50)
/* Check for pending timer interrupt */
- if (mfp.int_pn_b & (1 << 5))
+ if (st_mfp.int_pn_b & (1 << 5))
offset = TICK_SIZE;
ticks = INT_TICKS - ticks;
ticks = ticks * 10000L / INT_TICKS;
- return ticks + offset;
+ return (ticks + offset) * 1000;
}
@@ -190,13 +196,14 @@ int atari_tt_hwclk( int op, struct rtc_time *t )
}
if (!(ctrl & RTC_DM_BINARY)) {
- BIN_TO_BCD(sec);
- BIN_TO_BCD(min);
- BIN_TO_BCD(hour);
- BIN_TO_BCD(day);
- BIN_TO_BCD(mon);
- BIN_TO_BCD(year);
- if (wday >= 0) BIN_TO_BCD(wday);
+ sec = bin2bcd(sec);
+ min = bin2bcd(min);
+ hour = bin2bcd(hour);
+ day = bin2bcd(day);
+ mon = bin2bcd(mon);
+ year = bin2bcd(year);
+ if (wday >= 0)
+ wday = bin2bcd(wday);
}
}
@@ -213,8 +220,10 @@ int atari_tt_hwclk( int op, struct rtc_time *t )
*/
while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP ) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HWCLK_POLL_INTERVAL);
+ if (in_atomic() || irqs_disabled())
+ mdelay(1);
+ else
+ schedule_timeout_interruptible(HWCLK_POLL_INTERVAL);
}
local_irq_save(flags);
@@ -249,13 +258,13 @@ int atari_tt_hwclk( int op, struct rtc_time *t )
}
if (!(ctrl & RTC_DM_BINARY)) {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- BCD_TO_BIN(wday);
+ sec = bcd2bin(sec);
+ min = bcd2bin(min);
+ hour = bcd2bin(hour);
+ day = bcd2bin(day);
+ mon = bcd2bin(mon);
+ year = bcd2bin(year);
+ wday = bcd2bin(wday);
}
if (!(ctrl & RTC_24H)) {
@@ -315,7 +324,7 @@ int atari_tt_set_clock_mmss (unsigned long nowtime)
rtc_minutes = RTC_READ (RTC_MINUTES);
if (!(save_control & RTC_DM_BINARY))
- BCD_TO_BIN (rtc_minutes);
+ rtc_minutes = bcd2bin(rtc_minutes);
/* Since we're only adjusting minutes and seconds, don't interfere
with hour overflow. This avoids messing with unknown time zones
@@ -326,8 +335,8 @@ int atari_tt_set_clock_mmss (unsigned long nowtime)
{
if (!(save_control & RTC_DM_BINARY))
{
- BIN_TO_BCD (real_seconds);
- BIN_TO_BCD (real_minutes);
+ real_seconds = bin2bcd(real_seconds);
+ real_minutes = bin2bcd(real_minutes);
}
RTC_WRITE (RTC_SECONDS, real_seconds);
RTC_WRITE (RTC_MINUTES, real_minutes);