diff options
Diffstat (limited to 'arch/m68k')
34 files changed, 2240 insertions, 83 deletions
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile index cb60ea268..3a5957b09 100644 --- a/arch/m68k/Makefile +++ b/arch/m68k/Makefile @@ -56,6 +56,11 @@ SUBDIRS += arch/m68k/kernel arch/m68k/mm arch/m68k/lib CORE_FILES := arch/m68k/kernel/kernel.o arch/m68k/mm/mm.o $(CORE_FILES) LIBS += arch/m68k/lib/lib.a +ifdef CONFIG_Q40 +CORE_FILES := $(CORE_FILES) arch/m68k/q40/q40.o +SUBDIRS := $(SUBDIRS) arch/m68k/q40 +endif + ifdef CONFIG_AMIGA CORE_FILES := $(CORE_FILES) arch/m68k/amiga/amiga.o SUBDIRS := $(SUBDIRS) arch/m68k/amiga @@ -81,6 +86,11 @@ CORE_FILES := $(CORE_FILES) arch/m68k/apollo/apollo.o SUBDIRS := $(SUBDIRS) arch/m68k/apollo endif +ifdef CONFIG_MVME147 +CORE_FILES := $(CORE_FILES) arch/m68k/mvme147/mvme147.o +SUBDIRS := $(SUBDIRS) arch/m68k/mvme147 +endif + ifdef CONFIG_MVME16x CORE_FILES := $(CORE_FILES) arch/m68k/mvme16x/mvme16x.o SUBDIRS := $(SUBDIRS) arch/m68k/mvme16x @@ -91,6 +101,11 @@ CORE_FILES := $(CORE_FILES) arch/m68k/bvme6000/bvme6000.o SUBDIRS := $(SUBDIRS) arch/m68k/bvme6000 endif +ifdef CONFIG_SUN3X +CORE_FILES := $(CORE_FILES) arch/m68k/sun3x/sun3x.o +SUBDIRS := $(SUBDIRS) arch/m68k/sun3x +endif + ifdef CONFIG_M68040 CORE_FILES := $(CORE_FILES) arch/m68k/fpsp040/fpsp.o SUBDIRS := $(SUBDIRS) arch/m68k/fpsp040 diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c index 79ef5f9fd..6de1fd686 100644 --- a/arch/m68k/atari/atakeyb.c +++ b/arch/m68k/atari/atakeyb.c @@ -291,7 +291,7 @@ static void atakeyb_rep( unsigned long ignore ) atakeyb_rep_timer.prev = atakeyb_rep_timer.next = NULL; add_timer( &atakeyb_rep_timer ); - handle_scancode(rep_scancode); + handle_scancode(rep_scancode, 1); } atari_enable_irq( IRQ_MFP_ACIA ); @@ -448,7 +448,7 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp) add_timer( &atakeyb_rep_timer ); } - handle_scancode(break_flag | scancode); + handle_scancode(scancode, !break_flag); break; } break; diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c index 543b04c74..fc1b5627f 100644 --- a/arch/m68k/bvme6000/config.c +++ b/arch/m68k/bvme6000/config.c @@ -417,10 +417,10 @@ void bvme6000_init_console_port (struct console *co, int cflag) static void scc_delay (void) { int n; - char i; + volatile int trash; for (n = 0; n < 20; n++) - i = *(volatile char *)0; + trash = n; } static void scc_write (char ch) diff --git a/arch/m68k/config.in b/arch/m68k/config.in index a67227d60..a8dacc904 100644 --- a/arch/m68k/config.in +++ b/arch/m68k/config.in @@ -37,6 +37,7 @@ fi bool 'Apollo support' CONFIG_APOLLO bool 'VME (Motorola and BVM) support' CONFIG_VME if [ "$CONFIG_VME" = "y" ]; then + bool 'MVME147 support' CONFIG_MVME147 bool 'MVME162, 166 and 167 support' CONFIG_MVME16x bool 'BVME4000 and BVME6000 support' CONFIG_BVME6000 fi @@ -44,10 +45,13 @@ bool 'HP9000/300 support' CONFIG_HP300 if [ "$CONFIG_HP300" = "y" ]; then bool 'DIO bus support' CONFIG_DIO fi +bool 'Sun3x support' CONFIG_SUN3X + define_bool CONFIG_SUN3 n if [ "$CONFIG_PCI" = "y" ]; then bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC fi +bool 'Q40/Q60 support' CONFIG_Q40 comment 'Processor type' bool '68020 support' CONFIG_M68020 @@ -94,6 +98,29 @@ else fi fi bool '/proc/hardware support' CONFIG_PROC_HARDWARE + +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'Parallel port support (EXPERIMENTAL, disables old lp driver!)' CONFIG_PARPORT + if [ "$CONFIG_PARPORT" != "n" ]; then + if [ "$CONFIG_AMIGA" != "n" ]; then + dep_tristate ' Amiga builtin port' CONFIG_PARPORT_AMIGA $CONFIG_PARPORT + if [ "$CONFIG_ZORRO" != "n" ]; then + dep_tristate ' Multiface III parallel port' CONFIG_PARPORT_MFC3 $CONFIG_PARPORT + fi + fi + if [ "$CONFIG_Q40" != "n" ]; then + tristate ' Q40 Parallel port' CONFIG_PARPORT + if [ "$CONFIG_PARPORT" != "n" ]; then + define_bool CONFIG_PARPORT_PC y + fi + fi + fi + if [ "$CONFIG_ATARI" == "y" ]; then + dep_tristate ' Atari builtin port' CONFIG_PARPORT_ATARI $CONFIG_PARPORT + fi +fi + + endmenu source drivers/block/Config.in @@ -147,6 +174,7 @@ if [ "$CONFIG_ZORRO" = "y" ]; then bool 'A4091 SCSI support' CONFIG_A4091_SCSI bool 'WarpEngine SCSI support' CONFIG_WARPENGINE_SCSI bool 'Blizzard PowerUP 603e+ SCSI' CONFIG_BLZ603EPLUS_SCSI + dep_tristate 'BSC Oktagon SCSI support' CONFIG_OKTAGON_SCSI $CONFIG_SCSI bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI # bool 'GVP Turbo 040/060 SCSI support' CONFIG_GVP_TURBO_SCSI fi @@ -167,6 +195,10 @@ if [ "$CONFIG_MAC" = "y" ]; then fi #dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI +if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME147" = "y" ]; then + bool 'WD33C93 SCSI driver for MVME147' CONFIG_MVME147_SCSI +fi + if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then bool 'NCR53C710 SCSI driver for MVME16x' CONFIG_MVME16x_SCSI fi @@ -175,6 +207,10 @@ if [ "$CONFIG_VME" = "y" -a "$CONFIG_BVME6000" = "y" ]; then bool 'NCR53C710 SCSI driver for BVME6000' CONFIG_BVME6000_SCSI fi +if [ "$CONFIG_SUN3X" = "y" ]; then + bool 'ESP SCSI driver' CONFIG_SUN3X_ESP +fi + endmenu fi @@ -219,6 +255,9 @@ if [ "$CONFIG_MAC" = "y" ]; then # bool 'Macintosh (AV) onboard MACE ethernet' CONFIG_MACMACE bool 'Macintosh (Quadra) onboard SONIC ethernet' CONFIG_MACSONIC fi +if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME147" = "y" ]; then + tristate 'MVME147 (Lance) Ethernet support' CONFIG_MVME147_NET +fi if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then tristate 'MVME16x Ethernet support' CONFIG_MVME16x_NET fi @@ -232,9 +271,17 @@ if [ "$CONFIG_ATARI" = "y" ]; then tristate 'PAMsNet support' CONFIG_ATARI_PAMSNET fi fi +if [ "$CONFIG_SUN3X" = "y" ]; then + bool 'Sun3x Lance support' CONFIG_SUNLANCE +fi if [ "$CONFIG_HP300" = "y" ]; then bool 'HP on-board LANCE support' CONFIG_HPLANCE fi +if [ "$CONFIG_Q40" = "y" ]; then + if [ ! "$CONFIG_PARPORT" = "n" ]; then + dep_tristate 'PLIP (parallel port) support' CONFIG_PLIP $CONFIG_PARPORT + fi +fi fi endmenu @@ -243,6 +290,23 @@ fi mainmenu_option next_comment comment 'Character devices' +if [ "$CONFIG_Q40" = "y" ]; then + tristate 'Q40 Standard/generic serial support' CONFIG_SERIAL +fi + +if [ "$CONFIG_SERIAL" = "y" ]; then + bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE + bool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED +fi + +if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then + bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS + bool ' Support for sharing serial interrupts' CONFIG_SERIAL_SHARE_IRQ +# bool ' Autodetect IRQ - do not yet enable !!' CONFIG_SERIAL_DETECT_IRQ + bool ' Support special multiport boards' CONFIG_SERIAL_MULTIPORT + bool ' Support the Bell Technologies HUB6 card' CONFIG_HUB6 +fi + if [ "$CONFIG_VME" = "n" ]; then define_bool CONFIG_VT y if [ "$CONFIG_VT" = "y" ]; then @@ -254,10 +318,17 @@ if [ "$CONFIG_ATARI" = "y" ]; then define_bool CONFIG_NVRAM y fi -tristate 'Parallel printer support' CONFIG_M68K_PRINTER -if [ "$CONFIG_ZORRO" = "y" ]; then - dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_M68K_PRINTER -fi +if [ "$CONFIG_PARPORT" = "n" ]; then + tristate 'Parallel printer support' CONFIG_M68K_PRINTER + if [ "$CONFIG_ZORRO" = "y" ]; then + dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_M68K_PRINTER + fi +else + dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT + if [ "$CONFIG_PRINTER" != "n" ]; then + bool ' Support IEEE1284 status readback' CONFIG_PRINTER_READBACK + fi +fi if [ "$CONFIG_AMIGA" = "y" ]; then tristate 'Amiga mouse support' CONFIG_AMIGAMOUSE fi @@ -280,13 +351,17 @@ if [ "$CONFIG_ATARI" = "y" ]; then fi if [ "$CONFIG_AMIGA" = "y" ]; then tristate 'Amiga builtin serial support' CONFIG_AMIGA_BUILTIN_SERIAL - bool 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET + if [ "$CONFIG_AMIGA_PCMCIA" = "y" ]; then + tristate 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET_SERIAL + fi fi -if [ "$CONFIG_ZORRO" = "y" ]; then - tristate 'GVP IO-Extender support' CONFIG_GVPIOEXT - dep_tristate 'GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT - dep_tristate 'GVP IO-Extender PLIP support' CONFIG_GVPIOEXT_PLIP $CONFIG_GVPIOEXT - tristate 'Multiface Card III serial support' CONFIG_MULTIFACE_III_TTY +if [ "$CONFIG_PARPORT" = "n" ]; then + if [ "$CONFIG_ZORRO" = "y" ]; then + tristate 'GVP IO-Extender support' CONFIG_GVPIOEXT + dep_tristate 'GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT + dep_tristate 'GVP IO-Extender PLIP support' CONFIG_GVPIOEXT_PLIP $CONFIG_GVPIOEXT + tristate 'Multiface Card III serial support' CONFIG_MULTIFACE_III_TTY + fi fi if [ "$CONFIG_MAC" = "y" ]; then bool 'Mac SCC serial support' CONFIG_MAC_SCC @@ -294,18 +369,32 @@ fi if [ "$CONFIG_HP300" = "y" -a "$CONFIG_DIO" = "y" ]; then tristate 'HP DCA serial support' CONFIG_HPDCA fi +if [ "$CONFIG_SUN3X" = "y" ]; then + bool 'Sun3x builtin serial support' CONFIG_SUN3X_ZS + if [ "$CONFIG_SUN3X_ZS" = "y" ]; then + bool 'Sun keyboard support' CONFIG_SUN_KEYBOARD + bool 'Sun mouse support' CONFIG_SUN_MOUSE + define_bool CONFIG_SBUS y + define_bool CONFIG_SBUSCHAR y + define_bool CONFIG_SUN_SERIAL y + fi +fi if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" -o \ - "$CONFIG_MAC" = "y" -o "$CONFIG_HP300" = "y" ]; then + "$CONFIG_MAC" = "y" -o "$CONFIG_HP300" = "y" -o \ + "$CONFIG_SUN3X" = "y" ]; then if [ "$CONFIG_ATARI_MFPSER" = "y" -o "$CONFIG_ATARI_SCC" = "y" -o \ "$CONFIG_ATARI_MIDI" = "y" -o "$CONFIG_MAC_SCC" = "y" -o \ "$CONFIG_AMIGA_BUILTIN_SERIAL" = "y" -o \ "$CONFIG_GVPIOEXT" = "y" -o "$CONFIG_MULTIFACE_III_TTY" = "y" -o \ - "$CONFIG_HPDCA" = "y" ]; then + "$CONFIG_HPDCA" = "y" -o "$CONFIG_SUN3X_ZS" = "y" ]; then bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE fi fi if [ "$CONFIG_VME" = "y" ]; then define_bool CONFIG_SERIAL_CONSOLE y + if [ "$CONFIG_MVME147" = "y" ]; then + bool 'SCC support for MVME147 serial ports' CONFIG_MVME147_SCC + fi if [ "$CONFIG_MVME16x" = "y" ]; then bool 'CD2401 support for MVME166/7 serial ports' CONFIG_SERIAL167 bool 'SCC support for MVME162 serial ports' CONFIG_MVME162_SCC @@ -346,13 +435,13 @@ endmenu source fs/Config.in if [ "$CONFIG_VME" = "n" ]; then + mainmenu_option next_comment + comment 'Console drivers' if [ "$CONFIG_HP300" = "y" ]; then bool 'Frame buffer support' CONFIG_FB else define_bool CONFIG_FB y fi - mainmenu_option next_comment - comment 'Console drivers' source drivers/video/Config.in endmenu fi diff --git a/arch/m68k/defconfig b/arch/m68k/defconfig index ab9152f5d..109ce19fa 100644 --- a/arch/m68k/defconfig +++ b/arch/m68k/defconfig @@ -78,7 +78,6 @@ CONFIG_BLK_DEV_INITRD=y CONFIG_PACKET=y # CONFIG_NETLINK is not set # CONFIG_FIREWALL is not set -# CONFIG_NET_ALIAS is not set # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y diff --git a/arch/m68k/hp300/hil.c b/arch/m68k/hp300/hil.c index 3be0d488a..d7fe1867c 100644 --- a/arch/m68k/hp300/hil.c +++ b/arch/m68k/hp300/hil.c @@ -223,12 +223,13 @@ static void poll_finished(void) { case 0x40: { - unsigned char scode = (poll.data[1] >> 1) | ((poll.data[1] & 1)?0x80:0); + int down = (poll.data[1] & 1) == 0; + unsigned char scode = poll.data[1] >> 1; #if 0 - if (scode & 0x80) - printk("[%02x]", scode & 0x7f); + if (down) + printk("[%02x]", scode); #endif - handle_scancode(scode); + handle_scancode(scode, down); } break; } diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index e21e4b21c..61482c3a8 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S @@ -164,8 +164,17 @@ SYMBOL_NAME_LABEL(inthandler) movel %sp,%sp@- movel %d0,%sp@- | put vector # on stack +#if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD) + btstb #4,0xff000000 | Q40 floppy needs very special treatment ... + jbeq 1f + btstb #3,0xff000004 + jbeq 1f + jbsr SYMBOL_NAME(floppy_hardint) + jbra 3f +1: +#endif jbsr SYMBOL_NAME(process_int)| process the IRQ - addql #8,%sp | pop parameters off stack +3: addql #8,%sp | pop parameters off stack SYMBOL_NAME_LABEL(ret_from_interrupt) subql #1,SYMBOL_NAME(local_irq_count) @@ -295,6 +304,8 @@ SYMBOL_NAME_LABEL(resume) 2: fmovemx %fp0-%fp7,%a0@(TASK_TSS+TSS_FPREG) fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_TSS+TSS_FPCNTL) 3: + /* Return previous task in %d1 */ + movel %curptr,%d1 /* switch to new task (a1 contains new task) */ movel %a1,%curptr @@ -320,8 +331,15 @@ SYMBOL_NAME_LABEL(resume) movec %d0,%cacr /* switch the root pointer */ +#ifdef CPU_M68030_ONLY + .chip 68030 + pmovefd %a1@(TASK_TSS+TSS_CRP),%crp + .chip 68k + pflush #0,#4 +#else pmove %a1@(TASK_TSS+TSS_CRP),%crp #endif +#endif #if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060) jra 2f /* skip m68040 stuff */ diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S index 482c15f50..361b10cb6 100644 --- a/arch/m68k/kernel/head.S +++ b/arch/m68k/kernel/head.S @@ -23,6 +23,7 @@ ** 98/04/25 Phil Blundell: added HP300 support ** 1998/08/30 David Kilzer: Added support for fbcon_font_desc structures ** for linux-2.1.115 +** 9/02/11 Richard Zidlicky: added Q40 support (initial vesion 99/01/01) ** ** This file is subject to the terms and conditions of the GNU General Public ** License. See the file README.legal in the main directory of this archive @@ -303,6 +304,12 @@ .globl SYMBOL_NAME(availmem) .globl SYMBOL_NAME(m68k_pgtable_cachemode) .globl SYMBOL_NAME(m68k_supervisor_cachemode) +#ifdef CONFIG_MVME16x +.globl SYMBOL_NAME(mvme_bdid_ptr) +#endif +#ifdef CONFIG_Q40 +.globl SYMBOL_NAME(q40_mem_cptr) +#endif CPUTYPE_040 = 1 /* indicates an 040 */ CPUTYPE_060 = 2 /* indicates an 060 */ @@ -512,13 +519,15 @@ func_define putn,1 #endif .endm - #define is_not_amiga(lab) cmpl &MACH_AMIGA,%pc@(m68k_machtype); jne lab #define is_not_atari(lab) cmpl &MACH_ATARI,%pc@(m68k_machtype); jne lab #define is_not_mac(lab) cmpl &MACH_MAC,%pc@(m68k_machtype); jne lab +#define is_not_mvme147(lab) cmpl &MACH_MVME147,%pc@(m68k_machtype); jne lab #define is_not_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jne lab #define is_not_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jne lab #define is_not_hp300(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); jne lab +#define is_not_q40(lab) cmpl &MACH_Q40,%pc@(m68k_machtype); jne lab +#define is_not_sun3x(lab) cmpl &MACH_SUN3X,%pc@(m68k_machtype); jne lab #define is_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jne lab #define is_not_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jeq lab @@ -552,9 +561,11 @@ ENTRY(_stext) .long BOOTINFOV_MAGIC .long MACH_AMIGA, AMIGA_BOOTI_VERSION .long MACH_ATARI, ATARI_BOOTI_VERSION + .long MACH_MVME147, MVME147_BOOTI_VERSION .long MACH_MVME16x, MVME16x_BOOTI_VERSION .long MACH_BVME6000, BVME6000_BOOTI_VERSION .long MACH_MAC, MAC_BOOTI_VERSION + .long MACH_Q40, Q40_BOOTI_VERSION .long 0 1: jra SYMBOL_NAME(__start) @@ -859,7 +870,12 @@ L(mmu_init_amiga): /* * 040: Map the 16Meg range physical 0x0 upto logical 0x8000.0000 */ - mmu_map #0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S + mmu_map #0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S + /* + * Map the Zorro III I/O space with transparent translation + * for frame buffer memory etc. + */ + mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE_S jbra L(mmu_init_done) @@ -867,7 +883,8 @@ L(mmu_init_amiga): /* * 030: Map the 32Meg range physical 0x0 upto logical 0x8000.0000 */ - mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030 + mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030 + mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE030 jbra L(mmu_init_done) @@ -926,6 +943,25 @@ L(spata68040): L(mmu_init_not_atari): #endif +#ifdef CONFIG_Q40 + is_not_q40(L(notq40)) + /* + * add transparent mapping for 0xff00 0000 - 0xffff ffff + * non-cached serialized etc.. + * this includes master chip, DAC, RTC and ISA ports + * 0xfe000000-0xfeffffff is for screen and ROM + */ + + putc 'Q' + + mmu_map_tt #0,#0xfe000000,#0x01000000,#_PAGE_CACHE040W + mmu_map_tt #1,#0xff000000,#0x01000000,#_PAGE_NOCACHE_S + + jbra L(mmu_init_done) + +L(notq40): +#endif + #ifdef CONFIG_HP300 is_not_hp300(L(nothp300)) @@ -940,6 +976,24 @@ L(nothp300): #endif +#ifdef CONFIG_MVME147 + + is_not_mvme147(L(not147)) + + /* + * On MVME147 we have already created kernel page tables for + * 4MB of RAM at address 0, so now need to do a transparent + * mapping of the top of memory space. Make it 0.5GByte for now, + * so we can access on-board i/o areas. + */ + + mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE030 + + jbra L(mmu_init_done) + +L(not147): +#endif /* CONFIG_MVME147 */ + #ifdef CONFIG_MVME16x is_not_mvme16x(L(not16x)) @@ -965,7 +1019,7 @@ L(nothp300): * 0xffe00000->0xffe1ffff. */ - mmu_map_tt 1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S + mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S jbra L(mmu_init_done) @@ -985,7 +1039,7 @@ L(not16x): * clash with User code virtual address space. */ - mmu_map_tt 1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S + mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S jbra L(mmu_init_done) @@ -1052,13 +1106,23 @@ L(mmu_init_mac): mmu_map_eq #0x50000000,#0x02000000,%d3 mmu_map_eq #0x60000000,#0x00400000,%d3 mmu_map_eq #0x9c000000,#0x00400000,%d3 - mmu_map_tt 1,#0xf8000000,#0x08000000,%d3 + mmu_map_tt #1,#0xf8000000,#0x08000000,%d3 jbra L(mmu_init_done) L(mmu_init_not_mac): #endif +#ifdef CONFIG_SUN3X + is_not_sun3x(L(notsun3x)) + + /* setup tt1 for I/O */ + mmu_map_tt #1,#0x40000000,#0x40000000,#_PAGE_NOCACHE_S + +L(notsun3x): + jbra L(mmu_init_done) +#endif + L(mmu_init_done): putc 'G' @@ -1214,6 +1278,14 @@ L(mmu_fixup_done): 1: #endif +#ifdef CONFIG_SUN3X + is_not_sun3x(1f) + + /* enable copro */ + oriw #0x4000,0x61000000 +1: +#endif + /* * Fixup the addresses for the kernel pointer table and availmem. * Convert them from physical addresses to virtual addresses. @@ -1780,7 +1852,7 @@ func_start mmu_map_tt,%d0/%d1/%a0,4 /* Extract the highest bit set */ bfffo ARG3{#0,#32},%d1 - cmpw #8,%d0 + cmpw #8,%d1 jcc L(do_map) /* And get the mask @@ -2155,7 +2227,9 @@ func_start mmu_temp_map,%d0/%d1/%a0/%a1 /* Temporary allocate a page table and insert it into the ptr table */ movel %a1@,%d0 - addl #PTR_TABLE_SIZE*4,%a1@ + /* The 512 should be PAGE_TABLE_SIZE*4, but that violates the + alignment restriction for pointer tables on the '0[46]0. */ + addl #512,%a1@ orw #_PAGE_TABLE+_PAGE_ACCESSED,%d0 movel %d0,%a0@ dputs " (new)" @@ -2703,6 +2777,31 @@ func_start serial_init,%d0/%d1/%a0/%a1 L(serial_init_not_mac): #endif /* CONFIG_MAC */ +#ifdef CONFIG_Q40 + is_not_q40(2f) +/* debug output goes into SRAM, so we don't do it unless requested + - check for '%LX$' signature in SRAM */ + lea %pc@(SYMBOL_NAME(q40_mem_cptr)),%a1 + move.l #0xff020010,%a1@ /* must be inited - also used by debug=mem */ + move.l #0xff020000,%a1 + cmp.b #'%',%a1@ + bne 2f /*nodbg*/ + addq.w #4,%a1 + cmp.b #'L',%a1@ + bne 2f /*nodbg*/ + addq.w #4,%a1 + cmp.b #'X',%a1@ + bne 2f /*nodbg*/ + addq.w #4,%a1 + cmp.b #'$',%a1@ + bne 2f /*nodbg*/ + /* signature OK */ + lea %pc@(L(q40_do_debug)),%a1 + tas %a1@ +/*nodbg: q40_do_debug is 0 by default*/ +2: +#endif + L(serial_init_done): func_return serial_init @@ -2792,6 +2891,15 @@ func_start serial_putc,%d0/%d1/%a0/%a1 4: #endif /* CONFIG_ATARI */ +#ifdef CONFIG_MVME147 + is_not_mvme147(2f) +1: btst #2,M147_SCC_CTRL_A + jeq 1b + moveb %d0,M147_SCC_DATA_A + jbra L(serial_putc_done) +2: +#endif + #ifdef CONFIG_MVME16x is_not_mvme16x(2f) /* @@ -2805,7 +2913,7 @@ func_start serial_putc,%d0/%d1/%a0/%a1 moveml %sp@+,%d0-%d7/%a2-%a6 jbra L(serial_putc_done) 2: -#endif CONFIG_MVME162 | CONFIG_MVME167 +#endif CONFIG_MVME16x #ifdef CONFIG_BVME6000 is_not_bvme6000(2f) @@ -2819,6 +2927,18 @@ func_start serial_putc,%d0/%d1/%a0/%a1 2: #endif +#ifdef CONFIG_Q40 + is_not_q40(2f) + tst.l %pc@(L(q40_do_debug)) /* only debug if requested */ + beq 2f + lea %pc@(SYMBOL_NAME(q40_mem_cptr)),%a1 + move.l %a1@,%a0 + move.b %d0,%a0@ + addq.l #4,%a0 + move.l %a0,%a1@ +2: +#endif + L(serial_putc_done): func_return serial_putc @@ -3472,6 +3592,10 @@ L(kernel_pgdir_ptr): L(temp_mmap_mem): .long 0 +#if defined (CONFIG_MVME147) +M147_SCC_CTRL_A = 0xfffe3002 +M147_SCC_DATA_A = 0xfffe3003 +#endif #if defined (CONFIG_BVME6000) BVME_SCC_CTRL_A = 0xffb0000b @@ -3509,3 +3633,9 @@ SYMBOL_NAME_LABEL(m68k_supervisor_cachemode) SYMBOL_NAME_LABEL(mvme_bdid_ptr) .long 0 #endif +#if defined(CONFIG_Q40) +SYMBOL_NAME_LABEL(q40_mem_cptr) + .long 0 +L(q40_do_debug): + .long 0 +#endif diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index 20e39f17f..66fc41064 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -38,6 +38,10 @@ #include <asm/page.h> #include <asm/machdep.h> +#ifdef CONFIG_Q40 +#include <asm/q40ints.h> +#endif + /* table for system interrupt handlers */ static irq_handler_t irq_list[SYS_IRQS]; @@ -177,14 +181,24 @@ void sys_free_irq(unsigned int irq, void *dev_id) /* * Do we need these probe functions on the m68k? + * + * ... may be usefull with ISA devices */ unsigned long probe_irq_on (void) { +#ifdef CONFIG_Q40 + if (MACH_IS_Q40) + return q40_probe_irq_on(); +#endif return 0; } int probe_irq_off (unsigned long irqs) { +#ifdef CONFIG_Q40 + if (MACH_IS_Q40) + return q40_probe_irq_off(irqs); +#endif return 0; } diff --git a/arch/m68k/kernel/m68k_defs.h b/arch/m68k/kernel/m68k_defs.h index b32e6a1c9..4926a6dad 100644 --- a/arch/m68k/kernel/m68k_defs.h +++ b/arch/m68k/kernel/m68k_defs.h @@ -3,6 +3,47 @@ */ #define TS_MAGICKEY 0x5a5a5a5a -#define TS_TSS 482 -#define TS_ESP0 502 -#define TS_FPU 506 +#define TASK_STATE 0 +#define TASK_FLAGS 4 +#define TASK_SIGPENDING 8 +#define TASK_NEEDRESCHED 20 +#define TASK_TSS 470 +#define TASK_MM 622 +#define TSS_KSP 0 +#define TSS_USP 4 +#define TSS_SR 8 +#define TSS_FS 10 +#define TSS_CRP 12 +#define TSS_ESP0 20 +#define TSS_FPREG 24 +#define TSS_FPCNTL 120 +#define TSS_FPSTATE 132 +#define PT_D0 32 +#define PT_ORIG_D0 36 +#define PT_SR 44 +#define PT_VECTOR 50 +#define IRQ_HANDLER 0 +#define IRQ_DEVID 8 +#define IRQ_NEXT 16 +#define STAT_IRQ 120 +#define BIR_TAG 0 +#define BIR_SIZE 2 +#define BIR_DATA 4 +#define FBCON_FONT_DESC_IDX 0 +#define FBCON_FONT_DESC_NAME 4 +#define FBCON_FONT_DESC_WIDTH 8 +#define FBCON_FONT_DESC_HEIGHT 12 +#define FBCON_FONT_DESC_DATA 16 +#define FBCON_FONT_DESC_PREF 20 +#define CUSTOMBASE -2132807680 +#define C_INTENAR 28 +#define C_INTREQR 30 +#define C_INTENA 154 +#define C_INTREQ 156 +#define C_SERDATR 24 +#define C_SERDAT 48 +#define C_SERPER 50 +#define CIAABASE -2134908927 +#define CIABBASE -2134913024 +#define C_PRA 0 +#define ZTWOBASE -2147483648 diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c index 793ca6ec7..5aae5953c 100644 --- a/arch/m68k/kernel/m68k_ksyms.c +++ b/arch/m68k/kernel/m68k_ksyms.c @@ -18,6 +18,7 @@ #include <asm/checksum.h> #include <asm/hardirq.h> #include <asm/softirq.h> +#include <asm/m68kserial.h> asmlinkage long long __ashrdi3 (long long, int); extern char m68k_debug_device[]; @@ -54,6 +55,8 @@ EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(kernel_set_cachemode); EXPORT_SYMBOL(kernel_thread); +EXPORT_SYMBOL(register_serial); +EXPORT_SYMBOL(unregister_serial); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy); @@ -69,4 +72,5 @@ EXPORT_SYMBOL_NOVERS(memcmp); EXPORT_SYMBOL_NOVERS(__down_failed); EXPORT_SYMBOL_NOVERS(__down_failed_interruptible); +EXPORT_SYMBOL_NOVERS(__down_failed_trylock); EXPORT_SYMBOL_NOVERS(__up_wakeup); diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index c7c3f458e..97f3bd151 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -169,15 +169,7 @@ asmlinkage int m68k_fork(struct pt_regs *regs) asmlinkage int m68k_vfork(struct pt_regs *regs) { - int child; - struct semaphore sem = MUTEX_LOCKED; - - child = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs); - - if (child > 0) - down(&sem); - - return child; + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs); } asmlinkage int m68k_clone(struct pt_regs *regs) @@ -190,7 +182,7 @@ asmlinkage int m68k_clone(struct pt_regs *regs) newsp = regs->d2; if (!newsp) newsp = rdusp(); - return do_fork(clone_flags & ~CLONE_VFORK, newsp, regs); + return do_fork(clone_flags, newsp, regs); } int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 5aeb2534b..e9254cfa7 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c @@ -312,6 +312,7 @@ static int write_long(struct task_struct * tsk, unsigned long addr, asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; + unsigned long flags; int ret; lock_kernel(); @@ -343,21 +344,22 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) (current->uid != child->uid) || (current->gid != child->egid) || (current->gid != child->sgid) || + (!cap_issubset(child->cap_permitted, current->cap_permitted)) || (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) goto out; /* the same process cannot be attached many times */ if (child->flags & PF_PTRACED) goto out; child->flags |= PF_PTRACED; - if (child->p_pptr != current) { - unsigned long flags; - write_lock_irqsave(&tasklist_lock, flags); + write_lock_irqsave(&tasklist_lock, flags); + if (child->p_pptr != current) { REMOVE_LINKS(child); child->p_pptr = current; SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); } + write_unlock_irqrestore(&tasklist_lock, flags); + send_sig(SIGSTOP, child, 1); ret = 0; goto out; @@ -502,7 +504,6 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) } case PTRACE_DETACH: { /* detach a process that was attached. */ - unsigned long flags; long tmp; ret = -EIO; diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c index ade12c46d..39dcd9c15 100644 --- a/arch/m68k/kernel/setup.c +++ b/arch/m68k/kernel/setup.c @@ -77,10 +77,26 @@ int (*mach_hwclk) (int, struct hwclk_time*) = NULL; int (*mach_set_clock_mmss) (unsigned long) = NULL; void (*mach_reset)( void ); long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */ -#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) +#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) || defined(CONFIG_BLK_DEV_FD) void (*mach_floppy_setup) (char *, int *) __initdata = NULL; void (*mach_floppy_eject) (void) = NULL; #endif +struct serial_struct; +#ifdef CONFIG_SERIAL +long serial_rs_init(void); +int serial_register_serial(struct serial_struct *); +void serial_unregister_serial(int); +long ser_console_init(long, long ); +#endif +#if defined(CONFIG_USERIAL)||defined(CONFIG_BVME6000_SCC)||defined(CONFIG_MVME162_SCC)||defined(CONFIG_HPDCA)||defined(CONFIG_WHIPPET_SERIAL)||defined(CONFIG_MULTIFACE_III_TTY)||defined(CONFIG_GVPIOEXT)||defined(CONFIG_AMIGA_BUILTIN_SERIAL)||defined(CONFIG_MAC_SCC)||defined(CONFIG_ATARI_MIDI)||defined(CONFIG_ATARI_SCC)||defined(CONFIG_ATARI_MFPSER) +#define M68K_SERIAL +#endif +#ifdef M68K_SERIAL +long m68k_rs_init(void); +int m68k_register_serial(struct serial_struct *); +void m68k_unregister_serial(int); +long m68k_serial_console_init(long, long ); +#endif #ifdef CONFIG_HEARTBEAT void (*mach_heartbeat) (int) = NULL; #endif @@ -97,15 +113,19 @@ char *mach_sysrq_xlate = NULL; extern int amiga_parse_bootinfo(const struct bi_record *); extern int atari_parse_bootinfo(const struct bi_record *); extern int mac_parse_bootinfo(const struct bi_record *); +extern int q40_parse_bootinfo(const struct bi_record *); extern void config_amiga(void); extern void config_atari(void); extern void config_mac(void); extern void config_sun3(void); extern void config_apollo(void); +extern void config_mvme147(void); extern void config_mvme16x(void); extern void config_bvme6000(void); extern void config_hp300(void); +extern void config_q40(void); +extern void config_sun3x(void); #define MASK_256K 0xfffc0000 @@ -149,6 +169,8 @@ __initfunc(static void m68k_parse_bootinfo(const struct bi_record *record)) unknown = atari_parse_bootinfo(record); else if (MACH_IS_MAC) unknown = mac_parse_bootinfo(record); + else if (MACH_IS_Q40) + unknown = q40_parse_bootinfo(record); else unknown = 1; } @@ -258,6 +280,11 @@ __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p, config_apollo(); break; #endif +#ifdef CONFIG_MVME147 + case MACH_MVME147: + config_mvme147(); + break; +#endif #ifdef CONFIG_MVME16x case MACH_MVME16x: config_mvme16x(); @@ -273,6 +300,16 @@ __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p, config_hp300(); break; #endif +#ifdef CONFIG_Q40 + case MACH_Q40: + config_q40(); + break; +#endif +#ifdef CONFIG_SUN3X + case MACH_SUN3X: + config_sun3x(); + break; +#endif default: panic ("No configuration setup"); } @@ -384,7 +421,52 @@ int get_hardware_list(char *buffer) return(len); } -#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) +#if defined(CONFIG_SERIAL) || defined(M68K_SERIAL) +int rs_init(void) +{ +#ifdef CONFIG_SERIAL + if (MACH_IS_Q40) + return serial_rs_init(); +#endif +#ifdef M68K_SERIAL + return m68k_rs_init(); +#endif +} +int register_serial(struct serial_struct *p) +{ +#ifdef CONFIG_SERIAL + if (MACH_IS_Q40) + return serial_register_serial(p); +#endif +#ifdef M68K_SERIAL + return m68k_register_serial(p); +#endif +} +void unregister_serial(int i) +{ +#ifdef CONFIG_SERIAL + if (MACH_IS_Q40) + serial_unregister_serial(i); +#endif +#ifdef M68K_SERIAL + m68k_unregister_serial(i); +#endif +} +#ifdef CONFIG_SERIAL_CONSOLE +long serial_console_init(long kmem_start, long kmem_end) +{ +#ifdef CONFIG_SERIAL + if (MACH_IS_Q40) + return ser_console_init(kmem_start, kmem_end); +#endif +#if defined(M68K_SERIAL) && defined(CONFIG_SERIAL_CONSOLE) + return m68k_serial_console_init(kmem_start, kmem_end); +#endif +} +#endif +#endif + +#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) || defined(CONFIG_BLK_DEV_FD) __initfunc(void floppy_setup(char *str, int *ints)) { if (mach_floppy_setup) @@ -399,7 +481,7 @@ void floppy_eject(void) #endif /* for "kbd-reset" cmdline param */ -void __init kbd_reset_setup(char *str, int *ints) +__initfunc(void kbd_reset_setup(char *str, int *ints)) { } diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c index 107d0de7f..9b98fdb75 100644 --- a/arch/m68k/kernel/time.c +++ b/arch/m68k/kernel/time.c @@ -198,8 +198,7 @@ void do_settimeofday(struct timeval *tv) xtime = *tv; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; - time_state = TIME_ERROR; /* p. 24, (a) */ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; - sti(); + write_unlock_irq(&xtime_lock); } diff --git a/arch/m68k/lib/semaphore.S b/arch/m68k/lib/semaphore.S index 8e4141149..842f83f64 100644 --- a/arch/m68k/lib/semaphore.S +++ b/arch/m68k/lib/semaphore.S @@ -32,6 +32,16 @@ ENTRY(__down_failed_interruptible) movel (%sp)+,%a0 rts +ENTRY(__down_failed_trylock) + movel %a0,-(%sp) + movel %d1,-(%sp) + movel %a1,-(%sp) + jbsr SYMBOL_NAME(__down_trylock) + movel (%sp)+,%a1 + movel (%sp)+,%d1 + movel (%sp)+,%a0 + rts + ENTRY(__up_wakeup) moveml %a0/%d0/%d1,-(%sp) movel %a1,-(%sp) diff --git a/arch/m68k/mac/mackeyb.c b/arch/m68k/mac/mackeyb.c index 5a6ae7c75..a128a6314 100644 --- a/arch/m68k/mac/mackeyb.c +++ b/arch/m68k/mac/mackeyb.c @@ -60,7 +60,7 @@ static void input_keycode(int, int); extern struct kbd_struct kbd_table[]; extern void adb_bus_init(void); -extern void handle_scancode(unsigned char); +extern void handle_scancode(unsigned char, int); extern void put_queue(int); /* keyb */ @@ -387,7 +387,7 @@ input_keycode(int keycode, int repeat) */ switch (keycode) { case 0x39: - handle_scancode(keycode); /* down */ + handle_scancode(keycode, 1); /* down */ up_flag = 0x80; /* see below ... */ mark_bh(KEYBOARD_BH); break; @@ -397,7 +397,7 @@ input_keycode(int keycode, int repeat) } } - handle_scancode(keycode + up_flag); + handle_scancode(keycode, !up_flag); } static void diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c index 8e520702f..9a41dc279 100644 --- a/arch/m68k/mm/init.c +++ b/arch/m68k/mm/init.c @@ -123,7 +123,7 @@ void show_mem(void) unsigned long mm_cachebits = 0; #endif -static pte_t *__init kernel_page_table(unsigned long *memavailp) +__initfunc(static pte_t * kernel_page_table(unsigned long *memavailp)) { pte_t *ptablep; @@ -140,15 +140,19 @@ static pte_t *__init kernel_page_table(unsigned long *memavailp) static pmd_t *last_pgtable __initdata = NULL; -static pmd_t *__init kernel_ptr_table(unsigned long *memavailp) +__initfunc(static pmd_t * kernel_ptr_table(unsigned long *memavailp)) { if (!last_pgtable) { unsigned long pmd, last; int i; + /* Find the last ptr table that was used in head.S and + * reuse the remaining space in that page for further + * ptr tables. + */ last = (unsigned long)kernel_pg_dir; for (i = 0; i < PTRS_PER_PGD; i++) { - if (!pgd_val(kernel_pg_dir[i])) + if (!pgd_present(kernel_pg_dir[i])) continue; pmd = pgd_page(kernel_pg_dir[i]); if (pmd > last) @@ -175,8 +179,8 @@ static pmd_t *__init kernel_ptr_table(unsigned long *memavailp) return last_pgtable; } -static unsigned long __init -map_chunk (unsigned long addr, long size, unsigned long *memavailp) +__initfunc(static unsigned long +map_chunk (unsigned long addr, long size, unsigned long *memavailp)) { #define PTRTREESIZE (256*1024) #define ROOTTREESIZE (32*1024*1024) @@ -282,8 +286,8 @@ extern char __init_begin, __init_end; * paging_init() continues the virtual memory environment setup which * was begun by the code in arch/head.S. */ -unsigned long __init paging_init(unsigned long start_mem, - unsigned long end_mem) +__initfunc(unsigned long paging_init(unsigned long start_mem, + unsigned long end_mem)) { int chunk; unsigned long mem_avail = 0; @@ -392,7 +396,7 @@ unsigned long __init paging_init(unsigned long start_mem, return PAGE_ALIGN(free_area_init(start_mem, end_mem)); } -void __init mem_init(unsigned long start_mem, unsigned long end_mem) +__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem)) { int codepages = 0; int datapages = 0; @@ -443,7 +447,7 @@ void __init mem_init(unsigned long start_mem, unsigned long end_mem) /* insert pointer tables allocated so far into the tablelist */ init_pointer_table((unsigned long)kernel_pg_dir); for (i = 0; i < PTRS_PER_PGD; i++) { - if (pgd_val(kernel_pg_dir[i])) + if (pgd_present(kernel_pg_dir[i])) init_pointer_table(pgd_page(kernel_pg_dir[i])); } diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c index d2cd29011..3fefe4e03 100644 --- a/arch/m68k/mm/kmap.c +++ b/arch/m68k/mm/kmap.c @@ -116,6 +116,14 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) if (!size || size > physaddr + size) return NULL; +#ifdef CONFIG_AMIGA + if (MACH_IS_AMIGA) { + if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000) + && (cacheflag == IOMAP_NOCACHE_SER)) + return (void *)physaddr; + } +#endif + #ifdef DEBUG printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag); #endif @@ -174,7 +182,7 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) } } - while (size > 0) { + while ((long)size > 0) { #ifdef DEBUG if (!(virtaddr & (PTRTREESIZE-1))) printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr); @@ -187,7 +195,7 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) } if (CPU_IS_020_OR_030) { - pmd_dir->pmd[(virtaddr/PTRTREESIZE)&-16] = physaddr; + pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr; physaddr += PTRTREESIZE; virtaddr += PTRTREESIZE; size -= PTRTREESIZE; @@ -217,7 +225,14 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) */ void iounmap(void *addr) { +#ifdef CONFIG_AMIGA + if ((!MACH_IS_AMIGA) || + (((unsigned long)addr < 0x40000000) || + ((unsigned long)addr > 0x60000000))) + free_io_area(addr); +#else free_io_area(addr); +#endif } /* @@ -232,7 +247,7 @@ void __iounmap(void *addr, unsigned long size) pmd_t *pmd_dir; pte_t *pte_dir; - while (size > 0) { + while ((long)size > 0) { pgd_dir = pgd_offset_k(virtaddr); if (pgd_bad(*pgd_dir)) { printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir)); @@ -242,7 +257,7 @@ void __iounmap(void *addr, unsigned long size) pmd_dir = pmd_offset(pgd_dir, virtaddr); if (CPU_IS_020_OR_030) { - int pmd_off = (virtaddr/PTRTREESIZE) & -16; + int pmd_off = (virtaddr/PTRTREESIZE) & 15; if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) { pmd_dir->pmd[pmd_off] = 0; @@ -308,7 +323,7 @@ void kernel_set_cachemode(void *addr, unsigned long size, int cmode) } } - while (size > 0) { + while ((long)size > 0) { pgd_dir = pgd_offset_k(virtaddr); if (pgd_bad(*pgd_dir)) { printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir)); @@ -318,7 +333,7 @@ void kernel_set_cachemode(void *addr, unsigned long size, int cmode) pmd_dir = pmd_offset(pgd_dir, virtaddr); if (CPU_IS_020_OR_030) { - int pmd_off = (virtaddr/PTRTREESIZE) & -16; + int pmd_off = (virtaddr/PTRTREESIZE) & 15; if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) { pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] & diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c index a97578ec2..a6d496571 100644 --- a/arch/m68k/mm/memory.c +++ b/arch/m68k/mm/memory.c @@ -11,6 +11,7 @@ #include <linux/types.h> #include <linux/malloc.h> #include <linux/init.h> +#include <linux/pagemap.h> #include <asm/setup.h> #include <asm/segment.h> @@ -93,12 +94,11 @@ typedef struct page ptable_desc; static ptable_desc ptable_list = { &ptable_list, &ptable_list }; #define PD_MARKBITS(dp) (*(unsigned char *)&(dp)->offset) -#define PD_PAGE(dp) (PAGE_OFFSET + ((dp)->map_nr << PAGE_SHIFT)) #define PAGE_PD(page) ((ptable_desc *)&mem_map[MAP_NR(page)]) #define PTABLE_SIZE (PTRS_PER_PMD * sizeof(pmd_t)) -void __init init_pointer_table(unsigned long ptable) +__initfunc(void init_pointer_table(unsigned long ptable)) { ptable_desc *dp; unsigned long page = ptable & PAGE_MASK; @@ -166,7 +166,7 @@ pmd_t *get_pointer_table (void) (dp->next = last->next)->prev = dp; (dp->prev = last)->next = dp; } - return (pmd_t *) (PD_PAGE(dp) + off); + return (pmd_t *) (page_address(dp) + off); } int free_pointer_table (pmd_t *ptable) @@ -215,8 +215,8 @@ static unsigned long transp_transl_matches( unsigned long regval, /* function code match? */ base = (regval >> 4) & 7; mask = ~(regval & 7); - if ((SUPER_DATA & mask) != (base & mask)) - return( 0 ); + if (((SUPER_DATA ^ base) & mask) != 0) + return 0; } else { /* must not be user-only */ @@ -226,8 +226,8 @@ static unsigned long transp_transl_matches( unsigned long regval, /* address match? */ base = regval & 0xff000000; - mask = ~((regval << 8) & 0xff000000); - return( (vaddr & mask) == (base & mask) ); + mask = ~(regval << 8) & 0xff000000; + return ((vaddr ^ base) & mask) == 0; } #ifndef CONFIG_SINGLE_MEMORY_CHUNK diff --git a/arch/m68k/mvme147/147ints.c b/arch/m68k/mvme147/147ints.c new file mode 100644 index 000000000..3121ad94f --- /dev/null +++ b/arch/m68k/mvme147/147ints.c @@ -0,0 +1,142 @@ +/* + * arch/m68k/mvme147/147ints.c + * + * Copyright (C) 1997 Richard Hirst [richard@sleepie.demon.co.uk] + * + * based on amiints.c -- Amiga Linux interrupt handling code + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file README.legal in the main directory of this archive + * for more details. + * + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/errno.h> + +#include <asm/ptrace.h> +#include <asm/system.h> +#include <asm/irq.h> +#include <asm/traps.h> + +static void mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp); + +/* + * This should ideally be 4 elements only, for speed. + */ + +static struct { + void (*handler)(int, void *, struct pt_regs *); + unsigned long flags; + void *dev_id; + const char *devname; + unsigned count; +} irq_tab[256]; + +/* + * void mvme147_init_IRQ (void) + * + * Parameters: None + * + * Returns: Nothing + * + * This function is called during kernel startup to initialize + * the mvme147 IRQ handling routines. + */ + +void mvme147_init_IRQ (void) +{ + int i; + + for (i = 0; i < 256; i++) { + irq_tab[i].handler = mvme147_defhand; + irq_tab[i].flags = IRQ_FLG_STD; + irq_tab[i].dev_id = NULL; + irq_tab[i].devname = NULL; + irq_tab[i].count = 0; + } +} + +int mvme147_request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *devname, void *dev_id) +{ + if (irq > 255) { + printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname); + return -ENXIO; + } + if (!(irq_tab[irq].flags & IRQ_FLG_STD)) { + if (irq_tab[irq].flags & IRQ_FLG_LOCK) { + printk("%s: IRQ %d from %s is not replaceable\n", + __FUNCTION__, irq, irq_tab[irq].devname); + return -EBUSY; + } + if (flags & IRQ_FLG_REPLACE) { + printk("%s: %s can't replace IRQ %d from %s\n", + __FUNCTION__, devname, irq, irq_tab[irq].devname); + return -EBUSY; + } + } + irq_tab[irq].handler = handler; + irq_tab[irq].flags = flags; + irq_tab[irq].dev_id = dev_id; + irq_tab[irq].devname = devname; + return 0; +} + +void mvme147_free_irq(unsigned int irq, void *dev_id) +{ + if (irq > 255) { + printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); + return; + } + if (irq_tab[irq].dev_id != dev_id) + printk("%s: Removing probably wrong IRQ %d from %s\n", + __FUNCTION__, irq, irq_tab[irq].devname); + + irq_tab[irq].handler = mvme147_defhand; + irq_tab[irq].flags = IRQ_FLG_STD; + irq_tab[irq].dev_id = NULL; + irq_tab[irq].devname = NULL; +} + +void mvme147_process_int (unsigned long vec, struct pt_regs *fp) +{ + if (vec > 255) + printk ("mvme147_process_int: Illegal vector %ld\n", vec); + else + { + irq_tab[vec].count++; + irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp); + } +} + +int mvme147_get_irq_list (char *buf) +{ + int i, len = 0; + + for (i = 0; i < 256; i++) { + if (irq_tab[i].count) + len += sprintf (buf+len, "Vec 0x%02x: %8d %s\n", + i, irq_tab[i].count, + irq_tab[i].devname ? irq_tab[i].devname : "free"); + } + return len; +} + + +static void mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp) +{ + printk ("Unknown interrupt 0x%02x\n", irq); +} + +void mvme147_enable_irq (unsigned int irq) +{ +} + + +void mvme147_disable_irq (unsigned int irq) +{ +} + diff --git a/arch/m68k/mvme147/Makefile b/arch/m68k/mvme147/Makefile new file mode 100644 index 000000000..c0f064118 --- /dev/null +++ b/arch/m68k/mvme147/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for Linux arch/m68k/mvme147 source directory +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +O_TARGET := mvme147.o +O_OBJS := config.o 147ints.o + + +include $(TOPDIR)/Rules.make + diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c new file mode 100644 index 000000000..639d5f640 --- /dev/null +++ b/arch/m68k/mvme147/config.c @@ -0,0 +1,240 @@ +/* + * arch/m68k/mvme147/config.c + * + * Copyright (C) 1996 Dave Frascone [chaos@mindspring.com] + * Cloned from Richard Hirst [richard@sleepie.demon.co.uk] + * + * Based on: + * + * Copyright (C) 1993 Hamish Macdonald + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file README.legal in the main directory of this archive + * for more details. + */ + +#include <linux/config.h> +#include <stdarg.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/kd.h> +#include <linux/tty.h> +#include <linux/console.h> +#include <linux/linkage.h> +#include <linux/init.h> +#include <linux/major.h> + +#include <asm/system.h> +#include <asm/pgtable.h> +#include <asm/setup.h> +#include <asm/irq.h> +#include <asm/traps.h> +#include <asm/machdep.h> +#include <asm/mvme147hw.h> + + +extern void mvme147_process_int (int level, struct pt_regs *regs); +extern void mvme147_init_IRQ (void); +extern void mvme147_free_irq (unsigned int, void *); +extern int mvme147_get_irq_list (char *); +extern void mvme147_enable_irq (unsigned int); +extern void mvme147_disable_irq (unsigned int); +static void mvme147_get_model(char *model); +static int mvme147_get_hardware_list(char *buffer); +extern int mvme147_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); +extern void mvme147_sched_init(void (*handler)(int, void *, struct pt_regs *)); +extern int mvme147_keyb_init(void); +extern int mvme147_kbdrate (struct kbd_repeat *); +extern unsigned long mvme147_gettimeoffset (void); +extern void mvme147_gettod (int *year, int *mon, int *day, int *hour, + int *min, int *sec); +extern int mvme147_hwclk (int, struct hwclk_time *); +extern int mvme147_set_clock_mmss (unsigned long); +extern void mvme147_check_partition (struct gendisk *hd, unsigned int dev); +extern void mvme147_reset (void); +extern void mvme147_waitbut(void); + + +static int bcd2int (unsigned char b); + +/* Save tick handler routine pointer, will point to do_timer() in + * kernel/sched.c, called via mvme147_process_int() */ + +void (*tick_handler)(int, void *, struct pt_regs *); + + +int mvme147_kbdrate (struct kbd_repeat *k) +{ + return 0; +} + +void mvme147_reset() +{ + printk ("\r\n\nCalled mvme147_reset\r\n"); + m147_pcc->watchdog = 0x0a; /* Clear timer */ + m147_pcc->watchdog = 0xa5; /* Enable watchdog - 100ms to reset */ + while (1) + ; +} + +static void mvme147_get_model(char *model) +{ + sprintf(model, "Motorola MVME147"); +} + + +static int mvme147_get_hardware_list(char *buffer) +{ + *buffer = '\0'; + + return 0; +} + + +__initfunc(void config_mvme147(void)) +{ + mach_sched_init = mvme147_sched_init; + mach_keyb_init = mvme147_keyb_init; + mach_kbdrate = mvme147_kbdrate; + mach_init_IRQ = mvme147_init_IRQ; + mach_gettimeoffset = mvme147_gettimeoffset; + mach_gettod = mvme147_gettod; + mach_hwclk = mvme147_hwclk; + mach_set_clock_mmss = mvme147_set_clock_mmss; + mach_reset = mvme147_reset; + mach_free_irq = mvme147_free_irq; + mach_process_int = mvme147_process_int; + mach_get_irq_list = mvme147_get_irq_list; + mach_request_irq = mvme147_request_irq; + enable_irq = mvme147_enable_irq; + disable_irq = mvme147_disable_irq; + mach_get_model = mvme147_get_model; + mach_get_hardware_list = mvme147_get_hardware_list; +} + + +/* Using pcc tick timer 1 */ + +static void mvme147_timer_int (int irq, void *dev_id, struct pt_regs *fp) +{ + m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR; + m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1; + tick_handler(irq, dev_id, fp); +} + + +void mvme147_sched_init (void (*timer_routine)(int, void *, struct pt_regs *)) +{ + tick_handler = timer_routine; + request_irq (PCC_IRQ_TIMER1, mvme147_timer_int, + IRQ_FLG_REPLACE, "timer 1", NULL); + + /* Init the clock with a value */ + /* our clock goes off every 6.25us */ + m147_pcc->t1_preload = PCC_TIMER_PRELOAD; + m147_pcc->t1_cntrl = 0x0; /* clear timer */ + m147_pcc->t1_cntrl = 0x3; /* start timer */ + m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR; /* clear pending ints */ + m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1; +} + +/* This is always executed with interrupts disabled. */ +/* XXX There are race hazards in this code XXX */ +unsigned long mvme147_gettimeoffset (void) +{ + volatile unsigned short *cp = (volatile unsigned short *)0xfffe1012; + unsigned short n; + + n = *cp; + while (n != *cp) + n = *cp; + + n -= PCC_TIMER_PRELOAD; + return (unsigned long)n * 25 / 4; +} + +extern void mvme147_gettod (int *year, int *mon, int *day, int *hour, + int *min, int *sec) +{ + m147_rtc->ctrl = RTC_READ; + *year = bcd2int (m147_rtc->bcd_year); + *mon = bcd2int (m147_rtc->bcd_mth); + *day = bcd2int (m147_rtc->bcd_dom); + *hour = bcd2int (m147_rtc->bcd_hr); + *min = bcd2int (m147_rtc->bcd_min); + *sec = bcd2int (m147_rtc->bcd_sec); + m147_rtc->ctrl = 0; +} + +static int bcd2int (unsigned char b) +{ + return ((b>>4)*10 + (b&15)); +} + +int mvme147_hwclk(int op, struct hwclk_time *t) +{ + return 0; +} + +int mvme147_set_clock_mmss (unsigned long nowtime) +{ + return 0; +} + +int mvme147_keyb_init (void) +{ + return 0; +} + +/*------------------- Serial console stuff ------------------------*/ + +void m147_scc_write(struct console *co, const char *str, unsigned cnt); + + +void mvme147_init_console_port (struct console *co, int cflag) +{ + co->write = m147_scc_write; +} + + +static void scc_delay (void) +{ + int n; + volatile int trash; + + for (n = 0; n < 20; n++) + trash = n; +} + +static void scc_write (char ch) +{ + volatile char *p = (volatile char *)M147_SCC_A_ADDR; + + do { + scc_delay(); + } + while (!(*p & 4)); + scc_delay(); + *p = 8; + scc_delay(); + *p = ch; +} + + +void m147_scc_write (struct console *co, const char *str, unsigned count) +{ + unsigned long flags; + + save_flags(flags); + cli(); + + while (count--) + { + if (*str == '\n') + scc_write ('\r'); + scc_write (*str++); + } + restore_flags(flags); +} + diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c index 838c3bbac..db7eb3137 100644 --- a/arch/m68k/mvme16x/config.c +++ b/arch/m68k/mvme16x/config.c @@ -335,10 +335,10 @@ void mvme16x_init_console_port (struct console *co, int cflag) static void scc_delay (void) { int n; - char i; + volatile int trash; for (n = 0; n < 20; n++) - i = *(volatile char *)0; + trash = n; } static void scc_write (char ch) diff --git a/arch/m68k/q40/Makefile b/arch/m68k/q40/Makefile new file mode 100644 index 000000000..90858884f --- /dev/null +++ b/arch/m68k/q40/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for Linux arch/m68k/q40 source directory +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +O_TARGET := q40.o +O_OBJS := config.o q40ints.o + + +include $(TOPDIR)/Rules.make diff --git a/arch/m68k/q40/README b/arch/m68k/q40/README new file mode 100644 index 000000000..5433796cb --- /dev/null +++ b/arch/m68k/q40/README @@ -0,0 +1,121 @@ +Linux for the Q40 +================= + +You may try http://www.geocities.com/SiliconValley/Bay/2602/ for +some up to date information. Booter and other tools will be also +available from this place and ftp.uni-erlangen.de/linux/680x0/q40/ +and mirrors. + +Hints to documentation usually refer to the linux source tree in +/usr/src/linux unless URL given. + +It seems IRQ unmasking can't be safely done on a Q40. Autoprobing is +not yet implemented - do not try it! (See below) + +For a list of kernel commandline options read the documentation for the +particular device drivers. + +The floppy imposes a very high interrupt load on the CPU, approx 30K/s. +When something blocks interrupts (HD) it will loose some of them, so far +this is not known to have caused any data loss. On hihgly loaded systems +it can make the floppy very slow. Other Q40 OS' simply poll the floppy +for this reason - something that can't be done in Linux. +Only possible cure is getting a 82072 contoler with fifo instead of +the 8272A + +drivers used by the Q40, appart from the very obvious (console etc.): + drivers/char/q40_keyb.c # use PC keymaps for national keyboards + serial.c # normal PC driver - any speed + lp.c # printer driver + char/joystick/* # most of this should work + block/q40ide.c # startup for ide + ide* # see Documentation/ide.txt + floppy.c # normal PC driver, DMA emu in asm/floppy.h + # and arch/m68k/kernel/entry.S + # see drivers/block/README.fd + video/q40fb.c + misc/parport_pc.c + +Various other PC drivers can be enabled simply by adding them to +arch/m68k/config.in, especially 8 bit devices should be without any +problems. For cards using 16bit io/mem more care is required, like +checking byteorder issues, hacking memcpy_*_io etc. + + +Debugging +========= + +Upon startup the kernel will usually output "ABCQGHIJ" into the SRAM, +preceded by the booter signature. This is a trace just in case something +went wrong during earliest setup stages. +*Changed* to preserve SRAM contents by default, this is only done when +requested - SRAM must start with '%LX$' signature to do this. '-d' option +to 'lxx' loader enables this. + +SRAM can also be used as additional console device, use debug=mem. +This will save kernel startup msgs into SRAM, the screen will display +only the penguin - and shell prompt if it gets that far.. + +Serial console works and can also be used for debugging, provided serial +initialisation works. + +Most problems seem to be caused by fawlty or badly configured io-cards or +harddrives anyway..there are so many things that can go wrong here. +Make sure to configure the parallel port as SPP for first testing..the +Q40 may have trouble with parallel interrupts. + + +Q40 Hardware Description +======================== + +This is just an overview, see asm-m68k/* for details ask if you have any +questions. + +The Q40 consists of a 68040@40 MHz, 1MB video RAM, up to 32MB RAM, AT-style +keyboard interface, 1 Programmable LED, 2 8bit DACs and up to 1MB ROM, 1MB +shadow ROM. + +Most interfacing like floppy, hd, serial, parallel ports is done via ISA +slots. The ISA io and mem range is mapped (sparse&byteswapped!) into separate +regions of the memory. +The main interrupt register IIRQ_REG will indicate whether an IRQ was internal +or from some ISA devices, EIRQ_REG can distinguish up to 8 ISA IRQs. + +The Q40 custom chip is programmable to provide 2 periodic timers: + - 50 or 200 Hz - level 2, !!THIS CANT BE DISABLED!! + - 10 or 20 KHz - level 4 (and possibly 6 - hardware decoding..) + +Linux uses the 200 Hz interrupt for timer and beep by default. + + +Interrupts +========== + +q40 master chip handles only level triggered interrupts :-(( +further limitation is no disabling etc. Unless someone finds +some ingenious clue this means autoprobing will never work. +Parallel port interrupts cause most trouble.. + +IRQ sharing is not yet implemented. + + +Keyboard +======== + +q40 receives AT make/break codes from the keyboard, these are translated to +the PC scancodes x86 Linux uses. So by theory every national keyboard should +work just by loading the apropriate x86 keytable - see any national-HOWTO. + +Unfortunately the AT->PC translation isn't quite trivial and even worse, my +documentation of it is absolutely minimal - thus some exotic keys may not +behave exactly as expected. + +There is still hope that it can be fixed completely though. If you encounter +problems, email me idealy this: + - exact keypress/release sequence + - 'showkey -s' run on q40, non-X session + - 'showkey -s' run on a PC, non-X session + - AT codes as displayed by the q40 debuging ROM +btw if the showkey output from PC and Q40 doesn't differ then you have some +classic configuration problem - don't send me anything in this case + diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c new file mode 100644 index 000000000..e3c35c60c --- /dev/null +++ b/arch/m68k/q40/config.c @@ -0,0 +1,425 @@ +/* + * arch/m68k/q40/config.c + * + * originally based on: + * + * linux/bvme/config.c + * + * Copyright (C) 1993 Hamish Macdonald + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file README.legal in the main directory of this archive + * for more details. + */ + +#include <stdarg.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/kd.h> +#include <linux/tty.h> +#include <linux/console.h> +#include <linux/linkage.h> +#include <linux/init.h> +#include <linux/major.h> + +#include <asm/bootinfo.h> +#include <asm/system.h> +#include <asm/pgtable.h> +#include <asm/setup.h> +#include <asm/irq.h> +#include <asm/traps.h> +#include <asm/machdep.h> +#include <asm/q40_master.h> +#include <asm/keyboard.h> + +extern void fd_floppy_eject(void); +extern void fd_floppy_setup(char *str, int *ints); + +extern void q40_process_int (int level, struct pt_regs *regs); +extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */ +extern void q40_init_IRQ (void); +extern void q40_free_irq (unsigned int, void *); +extern int q40_get_irq_list (char *); +extern void q40_enable_irq (unsigned int); +extern void q40_disable_irq (unsigned int); +static void q40_get_model(char *model); +static int q40_get_hardware_list(char *buffer); +extern int q40_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); +extern void q40_sched_init(void (*handler)(int, void *, struct pt_regs *)); +extern int q40_keyb_init(void); +extern int q40_kbdrate (struct kbd_repeat *); +extern unsigned long q40_gettimeoffset (void); +extern void q40_gettod (int *year, int *mon, int *day, int *hour, + int *min, int *sec); +extern int q40_hwclk (int, struct hwclk_time *); +extern int q40_set_clock_mmss (unsigned long); +extern void q40_reset (void); +extern void q40_waitbut(void); +void q40_set_vectors (void); +extern void (*kd_mksound)(unsigned int, unsigned int); +void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/ ); + +extern char *saved_command_line; +extern char m68k_debug_device[]; +static void q40_mem_console_write(struct console *co, const char *b, + unsigned int count); + +static int ql_ticks=0; +static int sound_ticks=0; + +static unsigned char bcd2bin (unsigned char b); +static unsigned char bin2bcd (unsigned char b); + +static int q40_wait_key(struct console *co){return 0;} +static struct console q40_console_driver = { + "debug", + NULL, /* write */ + NULL, /* read */ + NULL, /* device */ + q40_wait_key, /* wait_key */ + NULL, /* unblank */ + NULL, /* setup */ + CON_PRINTBUFFER, + -1, + 0, + NULL +}; + + +/* Save tick handler routine pointer, will point to do_timer() in + * kernel/sched.c */ + +/* static void (*tick_handler)(int, void *, struct pt_regs *); */ + + +/* early debugging function:*/ +extern char *q40_mem_cptr; /*=(char *)0xff020000;*/ +static int _cpleft; + +static void q40_mem_console_write(struct console *co, const char *s, + unsigned int count) +{ + char *p=(char *)s; + + if (count<_cpleft) + while (count-- >0){ + *q40_mem_cptr=*p++; + q40_mem_cptr+=4; + _cpleft--; + } +} +#if 0 +void printq40(char *str) +{ + int l=strlen(str); + char *p=q40_mem_cptr; + + while (l-- >0 && _cpleft-- >0) + { + *p=*str++; + p+=4; + } + q40_mem_cptr=p; +} +#endif + +#if 0 +int q40_kbdrate (struct kbd_repeat *k) +{ + return 0; +} +#endif + +void q40_reset() +{ + + printk ("\n\n*******************************************\n" + "Called q40_reset : press the RESET button!! \n"); + printk( "*******************************************\n"); + + while(1) + ; +} + +static void q40_get_model(char *model) +{ + sprintf(model, "Q40"); +} + + +/* No hardware options on Q40? */ + +static int q40_get_hardware_list(char *buffer) +{ + *buffer = '\0'; + return 0; +} + + +__initfunc(void config_q40(void)) +{ + mach_sched_init = q40_sched_init; /* ok */ + /*mach_kbdrate = q40_kbdrate;*/ /* unneeded ?*/ + mach_keyb_init = q40_keyb_init; /* OK */ + mach_init_IRQ = q40_init_IRQ; + mach_gettimeoffset = q40_gettimeoffset; + mach_gettod = q40_gettod; + mach_hwclk = q40_hwclk; + mach_set_clock_mmss = q40_set_clock_mmss; +/* mach_mksound = q40_mksound; */ + mach_reset = q40_reset; /* use reset button instead !*/ + mach_free_irq = q40_free_irq; + mach_process_int = q40_process_int; + mach_get_irq_list = q40_get_irq_list; + mach_request_irq = q40_request_irq; + enable_irq = q40_enable_irq; + disable_irq = q40_disable_irq; + mach_default_handler = &q40_sys_default_handler; + mach_get_model = q40_get_model; /* no use..*/ + mach_get_hardware_list = q40_get_hardware_list; /* no use */ + kd_mksound = q40_mksound; + /*mach_kbd_leds = q40kbd_leds;*/ +#ifdef CONFIG_MAGIC_SYSRQ + mach_sysrq_key = 0x54; +#endif + conswitchp = &dummy_con; +#ifdef CONFIG_BLK_DEV_FD + mach_floppy_setup = fd_floppy_setup; + mach_floppy_eject = fd_floppy_eject; + /**/ +#endif + + mach_max_dma_address = 0; /* no DMA at all */ + + +/* userfull for early debuging stages writes kernel messages into SRAM */ + + if (!strncmp( m68k_debug_device,"mem",3 )) + { + /*printk("using NVRAM debug, q40_mem_cptr=%p\n",q40_mem_cptr);*/ + _cpleft=2000-((long)q40_mem_cptr-0xff020000)/4; + q40_console_driver.write = q40_mem_console_write; + register_console(&q40_console_driver); + } +} + + +int q40_parse_bootinfo(const struct bi_record *rec) +{ + return 1; /* unknown */ +} + +#define DAC_LEFT ((unsigned char *)0xff008000) +#define DAC_RIGHT ((unsigned char *)0xff008004) +void q40_mksound(unsigned int hz, unsigned int ticks) +{ + /* for now ignore hz, except that hz==0 switches off sound */ + /* simply alternate the ampl 0-255-0-.. at 200Hz */ + if (hz==0) + { + if (sound_ticks) + sound_ticks=1; /* atomic - no irq spinlock used */ + + *DAC_LEFT=0; + *DAC_RIGHT=0; + + return; + } + /* sound itself is done in q40_timer_int */ + if (sound_ticks == 0) sound_ticks=1000; /* pretty long beep */ + sound_ticks=ticks<<1; +} + +static void (*q40_timer_routine)(int, void *, struct pt_regs *); + +static void q40_timer_int (int irq, void *dev_id, struct pt_regs *fp) +{ +#if (HZ==10000) + master_outb(-1,SAMPLE_CLEAR_REG); +#else /* must be 50 or 100 */ + master_outb(-1,FRAME_CLEAR_REG); +#endif + +#if (HZ==100) + ql_ticks = ql_ticks ? 0 : 1; + if (sound_ticks) + { + unsigned char sval=(sound_ticks & 1) ? 0 : 255; + sound_ticks--; + *DAC_LEFT=sval; + *DAC_RIGHT=sval; + } + if (ql_ticks) return; +#endif + q40_timer_routine(irq, dev_id, fp); +} + + +void q40_sched_init (void (*timer_routine)(int, void *, struct pt_regs *)) +{ + int timer_irq; + + q40_timer_routine = timer_routine; + +#if (HZ==10000) + timer_irq=Q40_IRQ_TIMER; +#else + timer_irq=Q40_IRQ_FRAME; +#endif + + /*printk("registering sched/timer IRQ %d\n", timer_irq);*/ + + if (request_irq(timer_irq, q40_timer_int, 0, + "timer", q40_timer_int)) + panic ("Couldn't register timer int"); + +#if (HZ==10000) + master_outb(SAMPLE_LOW,SAMPLE_RATE_REG); + master_outb(-1,SAMPLE_CLEAR_REG); + master_outb(1,SAMPLE_ENABLE_REG); +#else + master_outb(-1,FRAME_CLEAR_REG); /* not necessary ? */ +#if (HZ==100) + master_outb( 1,FRAME_RATE_REG); +#endif +#endif +} + + +unsigned long q40_gettimeoffset (void) +{ +#if (HZ==100) + return 5000*(ql_ticks!=0); +#else + return 0; +#endif +} + +extern void q40_gettod (int *year, int *mon, int *day, int *hour, + int *min, int *sec) +{ + RTC_CTRL |= RTC_READ; + *year = bcd2bin (RTC_YEAR); + *mon = bcd2bin (RTC_MNTH)-1; + *day = bcd2bin (RTC_DATE); + *hour = bcd2bin (RTC_HOUR); + *min = bcd2bin (RTC_MINS); + *sec = bcd2bin (RTC_SECS); + RTC_CTRL &= ~(RTC_READ); + +} + +static unsigned char bcd2bin (unsigned char b) +{ + return ((b>>4)*10 + (b&15)); +} + +static unsigned char bin2bcd (unsigned char b) +{ + return (((b/10)*16) + (b%10)); +} + + +/* + * Looks like op is non-zero for setting the clock, and zero for + * reading the clock. + * + * struct hwclk_time { + * unsigned sec; 0..59 + * unsigned min; 0..59 + * unsigned hour; 0..23 + * unsigned day; 1..31 + * unsigned mon; 0..11 + * unsigned year; 00... + * int wday; 0..6, 0 is Sunday, -1 means unknown/don't set + * }; + */ + +int q40_hwclk(int op, struct hwclk_time *t) +{ + if (op) + { /* Write.... */ + RTC_CTRL |= RTC_WRITE; + + RTC_SECS = bin2bcd(t->sec); + RTC_MINS = bin2bcd(t->min); + RTC_HOUR = bin2bcd(t->hour); + RTC_DATE = bin2bcd(t->day); + RTC_MNTH = bin2bcd(t->mon + 1); + RTC_YEAR = bin2bcd(t->year%100); + if (t->wday >= 0) + RTC_DOW = bin2bcd(t->wday+1); + + RTC_CTRL &= ~(RTC_WRITE); + } + else + { /* Read.... */ + RTC_CTRL |= RTC_READ; + + t->year = bcd2bin (RTC_YEAR); + t->mon = bcd2bin (RTC_MNTH)-1; + t->day = bcd2bin (RTC_DATE); + t->hour = bcd2bin (RTC_HOUR); + t->min = bcd2bin (RTC_MINS); + t->sec = bcd2bin (RTC_SECS); + + RTC_CTRL &= ~(RTC_READ); + + if (t->year < 70) + t->year += 100; + t->wday = bcd2bin(RTC_DOW)-1; + + } + + return 0; +} + +/* + * Set the minutes and seconds from seconds value 'nowtime'. Fail if + * clock is out by > 30 minutes. Logic lifted from atari code. + * Algorithm is to wait for the 10ms register to change, and then to + * wait a short while, and then set it. + */ + +int q40_set_clock_mmss (unsigned long nowtime) +{ + int retval = 0; + short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; + + int rtc_minutes; + + + rtc_minutes = bcd2bin (RTC_MINS); + + if ((rtc_minutes < real_minutes + ? real_minutes - rtc_minutes + : rtc_minutes - real_minutes) < 30) + { + RTC_CTRL |= RTC_WRITE; + RTC_MINS = bin2bcd(real_minutes); + RTC_SECS = bin2bcd(real_seconds); + RTC_CTRL &= ~(RTC_WRITE); + } + else + retval = -1; + + + return retval; +} + +extern void q40kbd_init_hw(void); + +int q40_keyb_init (void) +{ + q40kbd_init_hw(); + return 0; +} + +#if 0 +/* dummy to cause */ +void q40_slow_io() +{ + return; +} +#endif diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c new file mode 100644 index 000000000..e9b5a5b1f --- /dev/null +++ b/arch/m68k/q40/q40ints.c @@ -0,0 +1,347 @@ +/* + * arch/m68k/q40/q40ints.c + * + * Copyright (C) 1999 Richard Zidlicky + * + * 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. + * + * losely based on bvme6000ints.c + * + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> + +#include <asm/ptrace.h> +#include <asm/system.h> +#include <asm/irq.h> +#include <asm/traps.h> + +#include <asm/q40_master.h> +#include <asm/q40ints.h> + +/* + * Q40 IRQs are defined as follows: + * 3,4,5,6,7,10,11,14,15 : ISA dev IRQs + * 16-31: reserved + * 32 : keyboard int + * 33 : frame int (50 Hz periodic timer) + * 34 : sample int (10/20 KHz periodic timer) + * +*/ + +extern int ints_inited; + + +void q40_irq2_handler (int, void *, struct pt_regs *fp); + + +extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */ + +static void q40_defhand (int irq, void *dev_id, struct pt_regs *fp); +static void sys_default_handler(int lev, void *dev_id, struct pt_regs *regs); + +/* + * This should ideally be 4 elements only, for speed. + */ + +#define DEVNAME_SIZE 24 + +static struct { + void (*handler)(int, void *, struct pt_regs *); + unsigned long flags; + void *dev_id; + char devname[DEVNAME_SIZE]; + unsigned count; +} irq_tab[Q40_IRQ_MAX+1]; + +/* + * void q40_init_IRQ (void) + * + * Parameters: None + * + * Returns: Nothing + * + * This function is called during kernel startup to initialize + * the q40 IRQ handling routines. + */ + +void q40_init_IRQ (void) +{ + int i; + + for (i = 0; i <= Q40_IRQ_MAX; i++) { + irq_tab[i].handler = q40_defhand; + irq_tab[i].flags = IRQ_FLG_STD; + irq_tab[i].dev_id = NULL; + irq_tab[i].devname[0] = 0; + irq_tab[i].count = 0; + } + + /* setup handler for ISA ints */ + sys_request_irq(IRQ2,q40_irq2_handler, IRQ_FLG_LOCK, "q40 ISA and master chip", NULL); + + /* now enable some ints.. */ + +#if 0 /* has been abandoned */ + master_outb(1,SER_ENABLE_REG); +#endif + master_outb(1,EXT_ENABLE_REG); + + /* would be spurious ints by now, q40kbd_init_hw() does that */ + master_outb(0,KEY_IRQ_ENABLE_REG); +} + +int q40_request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *devname, void *dev_id) +{ + /*printk("q40_request_irq %d, %s\n",irq,devname);*/ + + if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) { + printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname); + return -ENXIO; + } + + /* test for ISA ints not implemented by HW */ + if (irq<15) + { + switch (irq){ + case 1: case 2: case 8: case 9: + case 12: case 13: + printk("%s: ISA IRQ %d from %s not implemented by HW\n", __FUNCTION__, irq, devname); + return -ENXIO; + default: + } + } + + if (irq<Q40_IRQ_TIMER) + { + if (irq==11) { + printk("warning IRQ 10 and 11 not distinguishable\n"); + irq=10; + } + if (!(irq_tab[irq].flags & IRQ_FLG_STD)) + { + if (irq_tab[irq].flags & IRQ_FLG_LOCK) + { + printk("%s: IRQ %d from %s is not replaceable\n", + __FUNCTION__, irq, irq_tab[irq].devname); + return -EBUSY; + } + if (flags & IRQ_FLG_REPLACE) + { + printk("%s: %s can't replace IRQ %d from %s\n", + __FUNCTION__, devname, irq, irq_tab[irq].devname); + return -EBUSY; + } + } + /*printk("IRQ %d set to handler %p\n",irq,handler);*/ + irq_tab[irq].handler = handler; + irq_tab[irq].flags = flags; + irq_tab[irq].dev_id = dev_id; + strncpy(irq_tab[irq].devname,devname,DEVNAME_SIZE); + return 0; + } + else { + /* Q40_IRQ_TIMER :somewhat special actions required here ..*/ + sys_request_irq(4,handler,flags,devname,dev_id); + sys_request_irq(6,handler,flags,devname,dev_id); + return 0; + } +} + +void q40_free_irq(unsigned int irq, void *dev_id) +{ + if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) { + printk("%s: Incorrect IRQ %d, dev_id %x \n", __FUNCTION__, irq, (unsigned)dev_id); + return; + } + + /* test for ISA ints not implemented by HW */ + if (irq<15) { + switch (irq){ + case 1: case 2: case 8: case 9: + case 12: case 13: + printk("%s: ISA IRQ %d from %x illegal\n", __FUNCTION__, irq, (unsigned)dev_id); + return; + default: + } + } + + if (irq<Q40_IRQ_TIMER){ + if (irq==11) irq=10; + if (irq_tab[irq].dev_id != dev_id) + printk("%s: Removing probably wrong IRQ %d from %s\n", + __FUNCTION__, irq, irq_tab[irq].devname); + + irq_tab[irq].handler = q40_defhand; + irq_tab[irq].flags = IRQ_FLG_STD; + irq_tab[irq].dev_id = NULL; + /* irq_tab[irq].devname = NULL; */ + } else { /* == Q40_IRQ_TIMER */ + sys_free_irq(4,dev_id); + sys_free_irq(6,dev_id); + } +} + +#if 1 +void q40_process_int (int level, struct pt_regs *fp) +{ + printk("unexpected interrupt %x\n",level); +} +#endif + +/* + * tables to translate bits into IRQ numbers + * it is a good idea to order the entries by priority + * +*/ + +struct IRQ_TABLE{ unsigned mask; int irq ;}; + +static struct IRQ_TABLE iirqs[]={ + {IRQ_FRAME_MASK,Q40_IRQ_FRAME}, + {IRQ_KEYB_MASK,Q40_IRQ_KEYBOARD}, + {0,0}}; +static struct IRQ_TABLE eirqs[]={ + {IRQ3_MASK,3}, /* ser 1 */ + {IRQ4_MASK,4}, /* ser 2 */ + {IRQ14_MASK,14}, /* IDE 1 */ + {IRQ15_MASK,15}, /* IDE 2 */ + {IRQ6_MASK,6}, /* floppy */ + {IRQ7_MASK,7}, /* par */ + + {IRQ5_MASK,5}, + {IRQ10_MASK,10}, + + + + + {0,0}}; + +/* complaiun only this many times about spurious ints : */ +static int ccleirq=60; /* ISA dev IRQ's*/ +static int cclirq=60; /* internal */ + +/* FIX: add IRQ_INPROGRESS,mask,unmask,probing.... */ + +void q40_irq2_handler (int vec, void *devname, struct pt_regs *fp) +{ + /* got level 2 interrupt, dispatch to ISA or keyboard IRQs */ + + unsigned mir=master_inb(IIRQ_REG); + unsigned mer; + int irq,i; + + /* + * more than 1 bit might be set, must handle atmost 1 int source, + * - handle only those with explicitly set handler + */ + + if ((mir&IRQ_SER_MASK) || (mir&IRQ_EXT_MASK)) + { + + /* some ISA dev caused the int */ + + mer=master_inb(EIRQ_REG); + + for (i=0; eirqs[i].mask; i++) + { + if (mer&(eirqs[i].mask)) + { + irq=eirqs[i].irq; + irq_tab[irq].count++; + if (irq_tab[irq].handler == q40_defhand ) + continue; /* ignore uninited INTs :-( */ + + irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp); + return; + } + } + if (ccleirq>0) + printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--; + } + else + { + /* internal */ + + for (i=0; iirqs[i].mask; i++) + { + if (mir&(iirqs[i].mask)) + { + irq=iirqs[i].irq; + irq_tab[irq].count++; + if (irq_tab[irq].handler == q40_defhand ) + continue; /* ignore uninited INTs :-( */ + + irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp); + return; + } + } + if (cclirq>0) + printk("internal level 2 interrupt from unknown source ? IIRQ_REG=%x\n",mir),cclirq--; + } +} + +int q40_get_irq_list (char *buf) +{ + int i, len = 0; + + for (i = 0; i <= Q40_IRQ_MAX; i++) { + if (irq_tab[i].count) + len += sprintf (buf+len, "Vec 0x%02x: %8d %s%s\n", + i, irq_tab[i].count, + irq_tab[i].devname[0] ? irq_tab[i].devname : "?", + irq_tab[i].handler == q40_defhand ? + " (now unassigned)" : ""); + } + return len; +} + + +static void q40_defhand (int irq, void *dev_id, struct pt_regs *fp) +{ +#if 0 + printk ("Unknown q40 interrupt 0x%02x\n", irq); +#endif +} +static void sys_default_handler(int lev, void *dev_id, struct pt_regs *regs) +{ +#if 0 + if (ints_inited) +#endif + printk ("Uninitialised interrupt level %d\n", lev); +#if 0 + else + printk ("Interrupt before interrupt initialisation\n"); +#endif +} + + void (*q40_sys_default_handler[SYS_IRQS]) (int, void *, struct pt_regs *) = { + sys_default_handler,sys_default_handler,sys_default_handler,sys_default_handler, + sys_default_handler,sys_default_handler,sys_default_handler,sys_default_handler + }; + +void q40_enable_irq (unsigned int irq) +{ +} + + +void q40_disable_irq (unsigned int irq) +{ +} + +unsigned long q40_probe_irq_on (void) +{ + printk("sorry, irq probing not yet implemented - reconfigure the driver to avoid this\n"); + return 0; +} +int q40_probe_irq_off (unsigned long irqs) +{ + return -1; +} diff --git a/arch/m68k/sun3x/Makefile b/arch/m68k/sun3x/Makefile new file mode 100644 index 000000000..ba1f2bbd5 --- /dev/null +++ b/arch/m68k/sun3x/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for Linux arch/m68k/sun3x source directory +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +O_TARGET := sun3x.o +O_OBJS := config.o time.o dvma.o sbus.o +OX_OBJS := + +include $(TOPDIR)/Rules.make diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c new file mode 100644 index 000000000..5054cd888 --- /dev/null +++ b/arch/m68k/sun3x/config.c @@ -0,0 +1,128 @@ +/* + * Setup kernel for a Sun3x machine + * + * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + * + * based on code from Oliver Jowett <oliver@jowett.manawatu.gen.nz> + */ + +#include <linux/types.h> +#include <linux/mm.h> +#include <linux/console.h> +#include <linux/init.h> + +#include <asm/system.h> +#include <asm/machdep.h> +#include <asm/irq.h> +#include <asm/sun3x.h> + +#include "time.h" + +static volatile unsigned char *sun3x_intreg = (unsigned char *)SUN3X_INTREG; +extern int serial_console; + +void sun3x_halt(void) +{ + /* Disable interrupts */ + cli(); + + /* we can't drop back to PROM, so we loop here */ + for (;;); +} + +void sun3x_reboot(void) +{ + /* This never returns, don't bother saving things */ + cli(); + + /* no idea, whether this works */ + asm ("reset"); +} + +__initfunc(int sun3x_keyb_init(void)) +{ + return 0; +} + +int sun3x_kbdrate(struct kbd_repeat *r) +{ + return 0; +} + +void sun3x_kbd_leds(unsigned int i) +{ + +} + +static void sun3x_badint (int irq, void *dev_id, struct pt_regs *fp) +{ + printk ("received spurious interrupt %d\n",irq); + num_spurious += 1; +} + +void (*sun3x_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = { + sun3x_badint, sun3x_badint, sun3x_badint, sun3x_badint, + sun3x_badint, sun3x_badint, sun3x_badint, sun3x_badint +}; + +void sun3x_enable_irq(unsigned int irq) +{ + *sun3x_intreg |= (1 << irq); +} + +void sun3x_disable_irq(unsigned int irq) +{ + *sun3x_intreg &= ~(1 << irq); +} + +__initfunc(void sun3x_init_IRQ(void)) +{ + /* disable all interrupts initially */ + *sun3x_intreg = 1; /* master enable only */ +} + +int sun3x_get_irq_list(char *buf) +{ + return 0; +} + +/* + * Setup the sun3x configuration info + */ +__initfunc(void config_sun3x(void)) +{ + mach_get_irq_list = sun3x_get_irq_list; + mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */ + + mach_keyb_init = sun3x_keyb_init; + mach_kbdrate = sun3x_kbdrate; + mach_kbd_leds = sun3x_kbd_leds; + + mach_sched_init = sun3x_sched_init; + mach_init_IRQ = sun3x_init_IRQ; + enable_irq = sun3x_enable_irq; + disable_irq = sun3x_disable_irq; + mach_request_irq = sys_request_irq; + mach_free_irq = sys_free_irq; + mach_default_handler = &sun3x_default_handler; + mach_gettimeoffset = sun3x_gettimeoffset; + mach_reset = sun3x_reboot; + + mach_gettod = sun3x_gettod; + + switch (*(unsigned char *)SUN3X_EEPROM_CONS) { + case 0x10: + serial_console = 1; + conswitchp = NULL; + break; + case 0x11: + serial_console = 2; + conswitchp = NULL; + break; + default: + serial_console = 0; + conswitchp = &dummy_con; + break; + } + +} diff --git a/arch/m68k/sun3x/dvma.c b/arch/m68k/sun3x/dvma.c new file mode 100644 index 000000000..9ef3471a2 --- /dev/null +++ b/arch/m68k/sun3x/dvma.c @@ -0,0 +1,162 @@ +/* + * Virtual DMA allocation + * + * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/bitops.h> +#include <linux/mm.h> + +#include <asm/sun3x.h> +#include <asm/dvma.h> +#include <asm/io.h> +#include <asm/page.h> + +/* IOMMU support */ + +#define IOMMU_ENTRIES 2048 +#define IOMMU_ADDR_MASK 0x03ffe000 +#define IOMMU_CACHE_INHIBIT 0x00000040 +#define IOMMU_FULL_BLOCK 0x00000020 +#define IOMMU_MODIFIED 0x00000010 +#define IOMMU_USED 0x00000008 +#define IOMMU_WRITE_PROTECT 0x00000004 +#define IOMMU_DT_MASK 0x00000003 +#define IOMMU_DT_INVALID 0x00000000 +#define IOMMU_DT_VALID 0x00000001 +#define IOMMU_DT_BAD 0x00000002 + +#define DVMA_PAGE_SHIFT 13 +#define DVMA_PAGE_SIZE (1UL << DVMA_PAGE_SHIFT) +#define DVMA_PAGE_MASK (~(DVMA_PAGE_SIZE-1)) + + +static volatile unsigned long *iommu_pte = (unsigned long *)SUN3X_IOMMU; +static unsigned long iommu_use[IOMMU_ENTRIES]; +static unsigned long iommu_bitmap[IOMMU_ENTRIES/32]; + + +#define dvma_entry_paddr(index) (iommu_pte[index] & IOMMU_ADDR_MASK) +#define dvma_entry_vaddr(index,paddr) ((index << DVMA_PAGE_SHIFT) | \ + (paddr & (DVMA_PAGE_SIZE-1))) +#define dvma_entry_set(index,addr) (iommu_pte[index] = \ + (addr & IOMMU_ADDR_MASK) | \ + IOMMU_DT_VALID) +#define dvma_entry_clr(index) (iommu_pte[index] = IOMMU_DT_INVALID) +#define dvma_entry_use(index) (iommu_use[index]) +#define dvma_entry_inc(index) (iommu_use[index]++) +#define dvma_entry_dec(index) (iommu_use[index]--) +#define dvma_entry_hash(addr) ((addr >> DVMA_PAGE_SHIFT) ^ \ + ((addr & 0x03c00000) >> \ + (DVMA_PAGE_SHIFT+4))) +#define dvma_map iommu_bitmap +#define dvma_map_size (IOMMU_ENTRIES/2) +#define dvma_slow_offset (IOMMU_ENTRIES/2) +#define dvma_is_slow(addr) ((addr) & \ + (dvma_slow_offset << DVMA_PAGE_SHIFT)) + +static int fixed_dvma; + +void __init dvma_init(void) +{ + unsigned long tmp; + + if ((unsigned long)high_memory < (IOMMU_ENTRIES << DVMA_PAGE_SHIFT)) { + printk ("Sun3x fixed DVMA mapping\n"); + fixed_dvma = 1; + for (tmp = 0; tmp < (unsigned long)high_memory; tmp += DVMA_PAGE_SIZE) + dvma_entry_set (tmp >> DVMA_PAGE_SHIFT, virt_to_phys((void *)tmp)); + fixed_dvma = 1; + } else { + printk ("Sun3x variable DVMA mapping\n"); + for (tmp = 0; tmp < IOMMU_ENTRIES; tmp++) + dvma_entry_clr (tmp); + fixed_dvma = 0; + } +} + +unsigned long dvma_slow_alloc (unsigned long paddr, int npages) +{ + int scan, base; + + scan = 0; + for (;;) { + scan = find_next_zero_bit(dvma_map, dvma_map_size, scan); + if ((base = scan) + npages > dvma_map_size) { + printk ("dvma_slow_alloc failed for %d pages\n",npages); + return 0; + } + for (;;) { + if (scan >= base + npages) goto found; + if (test_bit(scan, dvma_map)) break; + scan++; + } + } + +found: + for (scan = base; scan < base+npages; scan++) { + dvma_entry_set(scan+dvma_slow_offset, paddr); + paddr += DVMA_PAGE_SIZE; + set_bit(scan, dvma_map); + } + return (dvma_entry_vaddr((base+dvma_slow_offset),paddr)); +} + +unsigned long dvma_alloc (unsigned long paddr, unsigned long size) +{ + int index; + int pages = ((paddr & ~DVMA_PAGE_MASK) + size + (DVMA_PAGE_SIZE-1)) >> + DVMA_PAGE_SHIFT; + + if (fixed_dvma) + return ((unsigned long)phys_to_virt (paddr)); + + if (pages > 1) /* multi page, allocate from slow pool */ + return dvma_slow_alloc (paddr, pages); + + index = dvma_entry_hash (paddr); + + if (dvma_entry_use(index)) { + if (dvma_entry_paddr(index) == (paddr & DVMA_PAGE_MASK)) { + dvma_entry_inc(index); + return dvma_entry_vaddr(index,paddr); + } + /* collision, allocate from slow pool */ + return dvma_slow_alloc (paddr, pages); + } + + dvma_entry_set(index,paddr); + dvma_entry_inc(index); + return dvma_entry_vaddr(index,paddr); +} + +void dvma_free (unsigned long dvma_addr, unsigned long size) +{ + int npages; + int index; + + if (fixed_dvma) + return; + + if (!dvma_is_slow(dvma_addr)) { + index = (dvma_addr >> DVMA_PAGE_SHIFT); + if (dvma_entry_use(index) == 0) { + printk ("dvma_free: %lx entry already free\n",dvma_addr); + return; + } + dvma_entry_dec(index); + if (dvma_entry_use(index) == 0) + dvma_entry_clr(index); + return; + } + + /* free in slow pool */ + npages = ((dvma_addr & ~DVMA_PAGE_MASK) + size + (DVMA_PAGE_SIZE-1)) >> + DVMA_PAGE_SHIFT; + for (index = (dvma_addr >> DVMA_PAGE_SHIFT); npages--; index++) { + dvma_entry_clr(index); + clear_bit (index,dvma_map); + } +} diff --git a/arch/m68k/sun3x/sbus.c b/arch/m68k/sun3x/sbus.c new file mode 100644 index 000000000..f1a89df65 --- /dev/null +++ b/arch/m68k/sun3x/sbus.c @@ -0,0 +1,44 @@ +/* + * SBus helper functions + * + * Sun3x don't have a sbus, but many of the used devices are also + * used on Sparc machines with sbus. To avoid having a lot of + * duplicate code, we provide necessary glue stuff to make using + * of the sbus driver code possible. + * + * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + */ + +#include <linux/types.h> +#include <linux/init.h> + +__initfunc(void sbus_init(void)) +{ + +} + +void *sparc_alloc_io (u32 address, void *virtual, int len, char *name, + u32 bus_type, int rdonly) +{ + return (void *)address; +} + +int prom_getintdefault(int node, char *property, int deflt) +{ + return deflt; +} + +int prom_getbool (int node, char *prop) +{ + return 1; +} + +void prom_printf(char *fmt, ...) +{ + +} + +void prom_halt (void) +{ + +} diff --git a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c new file mode 100644 index 000000000..39fa5f696 --- /dev/null +++ b/arch/m68k/sun3x/time.c @@ -0,0 +1,83 @@ +/* + * linux/arch/m68k/sun3x/time.c + * + * Sun3x-specific time handling + */ + +#include <linux/config.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/kernel_stat.h> +#include <linux/interrupt.h> + +#include <asm/irq.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/traps.h> +#include <asm/sun3x.h> + +#include "time.h" + +#define M_CONTROL 0xf8 +#define M_SEC 0xf9 +#define M_MIN 0xfa +#define M_HOUR 0xfb +#define M_DAY 0xfc +#define M_DATE 0xfd +#define M_MONTH 0xfe +#define M_YEAR 0xff + +#define C_WRITE 0x80 +#define C_READ 0x40 +#define C_SIGN 0x20 +#define C_CALIB 0x1f + +#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10) + +/* Read the Mostek */ +void sun3x_gettod (int *yearp, int *monp, int *dayp, + int *hourp, int *minp, int *secp) +{ + volatile unsigned char *eeprom = (unsigned char *)SUN3X_EEPROM; + + /* Stop updates */ + *(eeprom + M_CONTROL) |= C_READ; + + /* Read values */ + *yearp = BCD_TO_BIN(*(eeprom + M_YEAR)); + *monp = BCD_TO_BIN(*(eeprom + M_MONTH)); + *dayp = BCD_TO_BIN(*(eeprom + M_DATE)); + *hourp = BCD_TO_BIN(*(eeprom + M_HOUR)); + *minp = BCD_TO_BIN(*(eeprom + M_MIN)); + *secp = BCD_TO_BIN(*(eeprom + M_SEC)); + + /* Restart updates */ + *(eeprom + M_CONTROL) &= ~C_READ; +} + +/* Not much we can do here */ +unsigned long sun3x_gettimeoffset (void) +{ + return 0L; +} + +static void sun3x_timer_tick(int irq, void *dev_id, struct pt_regs *regs) +{ + void (*vector)(int, void *, struct pt_regs *) = dev_id; + + /* Clear the pending interrupt - pulse the enable line low */ + disable_irq(5); + enable_irq(5); + + vector(irq, NULL, regs); +} + +__initfunc(void sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *))) +{ + sys_request_irq(5, sun3x_timer_tick, IRQ_FLG_STD, "timer tick", vector); + + /* Pulse enable low to get the clock started */ + disable_irq(5); + enable_irq(5); +} diff --git a/arch/m68k/sun3x/time.h b/arch/m68k/sun3x/time.h new file mode 100644 index 000000000..873742d70 --- /dev/null +++ b/arch/m68k/sun3x/time.h @@ -0,0 +1,9 @@ +#ifndef SUN3X_TIME_H +#define SUN3X_TIME_H + +void sun3x_gettod (int *yearp, int *monp, int *dayp, + int *hourp, int *minp, int *secp); +unsigned long sun3x_gettimeoffset (void); +void sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *)); + +#endif |