From: Peter De Schrijver <p2@ace.ulyssis.student.kuleuven.ac.be>
Subject: L68K: apollo patches
To: linux-m68k@lists.linux-m68k.org
Date: Fri, 26 Sep 1997 19:28:59 +0200 (MET DST)
Sender: owner-linux-m68k@phil.uni-sb.de

Hi *,

Some patches for the apollo DN3500 :

diff -c -r -N ../linux-2.1.55/arch/m68k/Makefile linux-apollo-dev/arch/m68k/Makefile
*** ../linux-2.1.55/arch/m68k/Makefile	Thu Sep 25 22:37:52 1997
--- linux-apollo-dev/arch/m68k/Makefile	Wed Sep 17 01:40:52 1997
***************
*** 62,67 ****
--- 68,78 ----
  ifdef CONFIG_MAC
  CORE_FILES := $(CORE_FILES) arch/m68k/mac/mac.o
  SUBDIRS := $(SUBDIRS) arch/m68k/mac
+ endif
+ 
+ ifdef CONFIG_APOLLO
+ CORE_FILES := $(CORE_FILES) arch/m68k/apollo/apollo.o
+ SUBDIRS := $(SUBDIRS) arch/m68k/apollo
  endif
  
  ifdef CONFIG_M68040
diff -c -r -N ../linux-2.1.55/arch/m68k/apollo/Makefile linux-apollo-dev/arch/m68k/apollo/Makefile
*** ../linux-2.1.55/arch/m68k/apollo/Makefile	Thu Jan  1 01:00:00 1970
--- linux-apollo-dev/arch/m68k/apollo/Makefile	Sat Sep 20 00:22:12 1997
***************
*** 0 ****
--- 1,14 ----
+ #
+ # Makefile for Linux arch/m68k/amiga 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 := apollo.o
+ O_OBJS   := config.o dn_ints.o \
+ 
+ 
+ include $(TOPDIR)/Rules.make
diff -c -r -N ../linux-2.1.55/arch/m68k/apollo/config.c linux-apollo-dev/arch/m68k/apollo/config.c
*** ../linux-2.1.55/arch/m68k/apollo/config.c	Thu Jan  1 01:00:00 1970
--- linux-apollo-dev/arch/m68k/apollo/config.c	Thu Sep 25 17:26:27 1997
***************
*** 0 ****
--- 1,245 ----
+ #include <stdarg.h>
+ #include <linux/config.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 <asm/setup.h>
+ #include <asm/system.h>
+ #include <asm/pgtable.h>
+ #include <asm/apollohw.h>
+ #include <asm/irq.h>
+ #include <asm/machdep.h>
+ 
+ extern struct consw fb_con;
+ extern void dn_sched_init(void (*handler)(int,void *,struct pt_regs *));
+ extern int dn_keyb_init(void);
+ extern int dn_dummy_kbdrate(struct kbd_repeat *);
+ extern void dn_init_IRQ(void);
+ #if 0
+ extern void (*dn_default_handler[])(int,void *,struct pt_regs *);
+ #endif
+ extern int dn_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
+ extern void dn_free_irq(unsigned int irq, void *dev_id);
+ extern void dn_enable_irq(unsigned int);
+ extern void dn_disable_irq(unsigned int);
+ extern int dn_get_irq_list(char *);
+ extern unsigned long dn_gettimeoffset(void);
+ extern void dn_gettod(int *, int *, int *, int *, int *, int *);
+ extern int dn_dummy_hwclk(int, struct hwclk_time *);
+ extern int dn_dummy_set_clock_mmss(unsigned long);
+ extern void dn_mksound(unsigned int count, unsigned int ticks);
+ extern void dn_dummy_reset(void);
+ extern void dn_dummy_waitbut(void);
+ extern struct fb_info *dn_fb_init(long *);
+ extern void dn_dummy_debug_init(void);
+ extern void (*kd_mksound)(unsigned int, unsigned int);
+ extern void dn_dummy_video_setup(char *,int *);
+ extern void dn_process_int(int irq, struct pt_regs *fp);
+ 
+ static struct console dn_console_driver;
+ static void dn_debug_init(void);
+ static void dn_timer_int(int irq,void *, struct pt_regs *);
+ static void (*sched_timer_handler)(int, void *, struct pt_regs *)=NULL;
+ 
+ int dn_serial_console_wait_key(void) {
+ 
+ 	while(!(sio01.srb_csrb & 1))
+ 		barrier();
+ 	return sio01.rhrb_thrb;
+ }
+ 
+ void dn_serial_console_write (const char *str,unsigned int count)
+ {
+    while(count--) {
+ 	if (*str == '\n') { 
+     	sio01.rhrb_thrb = (unsigned char)'\r';
+        	while (!(sio01.srb_csrb & 0x4))
+                 ;
+  	}
+     sio01.rhrb_thrb = (unsigned char)*str++;
+     while (!(sio01.srb_csrb & 0x4))
+             ;
+   }	
+ }
+  
+ void dn_serial_print (const char *str)
+ {
+     while (*str) {
+         if (*str == '\n') {
+             sio01.rhrb_thrb = (unsigned char)'\r';
+             while (!(sio01.srb_csrb & 0x4))
+                 ;
+         }
+         sio01.rhrb_thrb = (unsigned char)*str++;
+         while (!(sio01.srb_csrb & 0x4))
+             ;
+     }
+ }
+ 
+ void config_apollo(void) {
+ 
+ 	dn_serial_print("Config apollo !\n");
+ #if 0
+ 	dn_debug_init();	
+ #endif
+ 	printk("Config apollo !\n");
+ 
+ 
+ 	mach_sched_init=dn_sched_init; /* */
+ 	mach_keyb_init=dn_keyb_init;
+ 	mach_kbdrate=dn_dummy_kbdrate;
+ 	mach_init_IRQ=dn_init_IRQ;
+ 	mach_default_handler=NULL;
+ 	mach_request_irq     = dn_request_irq;
+ 	mach_free_irq        = dn_free_irq;
+ 	enable_irq      = dn_enable_irq;
+ 	disable_irq     = dn_disable_irq;
+ 	mach_get_irq_list    = dn_get_irq_list;
+ 	mach_gettimeoffset   = dn_gettimeoffset;
+ 	mach_gettod	     = dn_gettod; /* */
+ 	mach_max_dma_address = 0xffffffff;
+ 	mach_hwclk           = dn_dummy_hwclk; /* */
+ 	mach_set_clock_mmss  = dn_dummy_set_clock_mmss; /* */
+ 	mach_process_int     = dn_process_int;
+ #ifdef CONFIG_BLK_DEV_FD
+ 	mach_floppy_init     = dn_dummy_floppy_init;
+ 	mach_floppy_setup    = dn_dummy_floppy_setup;
+ #endif
+ 	mach_reset	     = dn_dummy_reset;  /* */
+ 	conswitchp	     = &fb_con;
+ #if 0
+ 	mach_fb_init 	     = dn_fb_init; 
+ 	mach_video_setup     = dn_dummy_video_setup; 
+ #endif
+ 	kd_mksound	     = dn_mksound;
+ 
+ }		
+ 
+ void dn_timer_int(int irq, void *dev_id, struct pt_regs *fp) {
+ 
+ 	volatile unsigned char x;
+ 
+ 	sched_timer_handler(irq,dev_id,fp);
+ 	
+ 	x=*(volatile unsigned char *)(IO_BASE+0x10803);
+ 	x=*(volatile unsigned char *)(IO_BASE+0x10805);
+ 
+ }
+ 
+ void dn_sched_init(void (*timer_routine)(int, void *, struct pt_regs *)) {
+ 
+ 	dn_serial_print("dn sched_init\n");
+ 
+ #if 0
+ 	/* program timer 2 */
+ 	*(volatile unsigned char *)(IO_BASE+0x10803)=0x00;
+ 	*(volatile unsigned char *)(IO_BASE+0x10809)=0;
+ 	*(volatile unsigned char *)(IO_BASE+0x1080b)=50;
+ 
+ 	/* program timer 3 */
+ 	*(volatile unsigned char *)(IO_BASE+0x10801)=0x00;
+ 	*(volatile unsigned char *)(IO_BASE+0x1080c)=0;
+ 	*(volatile unsigned char *)(IO_BASE+0x1080f)=50;	
+ #endif
+ 	/* program timer 1 */       	
+ 	*(volatile unsigned char *)(IO_BASE+0x10803)=0x01;
+ 	*(volatile unsigned char *)(IO_BASE+0x10801)=0x40;
+ 	*(volatile unsigned char *)(IO_BASE+0x10805)=0x09;
+ 	*(volatile unsigned char *)(IO_BASE+0x10807)=0xc4;
+ 
+ 	/* enable IRQ of PIC B */
+ 	*(volatile unsigned char *)(IO_BASE+PICA+1)&=(~8);
+ 
+ 
+ 
+ 	printk("*(0x10803) %02x\n",*(volatile unsigned char *)(IO_BASE+0x10803));
+ 	printk("*(0x10803) %02x\n",*(volatile unsigned char *)(IO_BASE+0x10803));
+ 
+ 	sched_timer_handler=timer_routine;
+ 	request_irq(0,dn_timer_int,0,NULL,NULL);
+ 
+ 	
+ }
+ 
+ unsigned long dn_gettimeoffset(void) {
+ 
+ 	return 0xdeadbeef;
+ 
+ }
+ 
+ void dn_gettod(int *yearp, int *monp, int *dayp,
+ 	       int *hourp, int *minp, int *secp) {
+ 
+   *yearp=rtc->year;
+   *monp=rtc->month;
+   *dayp=rtc->day_of_month;
+   *hourp=rtc->hours;
+   *minp=rtc->minute;
+   *secp=rtc->second;
+ 
+ printk("gettod: %d %d %d %d %d %d\n",*yearp,*monp,*dayp,*hourp,*minp,*secp);
+ 
+ }
+ 
+ int dn_dummy_hwclk(int op, struct hwclk_time *t) {
+ 
+   dn_serial_print("hwclk !\n");
+ 
+   if(!op) { /* read */
+     t->sec=rtc->second;
+     t->min=rtc->minute;
+     t->hour=rtc->hours;
+     t->day=rtc->day_of_month;
+     t->wday=rtc->day_of_week;
+     t->mon=rtc->month;
+     t->year=rtc->year;
+   } else {
+     rtc->second=t->sec;
+     rtc->minute=t->min;
+     rtc->hours=t->hour;
+     rtc->day_of_month=t->day;
+     if(t->wday!=-1)
+       rtc->day_of_week=t->wday;
+     rtc->month=t->mon;
+     rtc->year=t->year;
+   }
+ 
+   dn_serial_print("hwclk end!\n");
+   return 0;
+ 
+ }
+ 
+ int dn_dummy_set_clock_mmss(unsigned long nowtime) {
+ 
+   printk("set_clock_mmss\n");
+ 
+   return 0;
+ 
+ }
+ 
+ void dn_dummy_reset(void) {
+ 
+   dn_serial_print("The end !\n");
+ 
+   for(;;);
+ 
+ }
+ 	
+ void dn_dummy_waitbut(void) {
+ 
+   dn_serial_print("waitbut\n");
+ 
+ }
+ 
+ #if 0
+ void dn_debug_init(void) {
+ 
+   dn_console_driver.write=dn_serial_console_write;
+   register_console(&dn_console_driver);
+ 
+ }
+ #endif
diff -c -r -N ../linux-2.1.55/arch/m68k/apollo/dn_debug.c linux-apollo-dev/arch/m68k/apollo/dn_debug.c
*** ../linux-2.1.55/arch/m68k/apollo/dn_debug.c	Thu Jan  1 01:00:00 1970
--- linux-apollo-dev/arch/m68k/apollo/dn_debug.c	Fri Sep 12 15:15:33 1997
***************
*** 0 ****
--- 1,23 ----
+ #include <stdarg.h>
+ 
+ #define DN_DEBUG_BUFFER_BASE 0x82800000
+ #define DN_DEBUG_BUFFER_SIZE 8*1024*1024
+ 
+ static char *current_dbg_ptr=DN_DEBUG_BUFFER_BASE;
+ 
+ int dn_deb_printf(const char *fmt, ...) {
+ 
+ 	va_list args;
+ 	int i;
+ 
+ 	if(current_dbg_ptr<(DN_DEBUG_BUFFER_BASE + DN_DEBUG_BUFFER_SIZE)) {
+ 		va_start(args,fmt);
+ 		i=vsprintf(current_dbg_ptr,fmt,args);
+ 		va_end(args);
+ 		current_dbg_ptr+=i;
+ 	
+ 		return i;
+ 	}
+ 	else 
+ 		return 0;
+ }
diff -c -r -N ../linux-2.1.55/arch/m68k/apollo/dn_ints.c linux-apollo-dev/arch/m68k/apollo/dn_ints.c
*** ../linux-2.1.55/arch/m68k/apollo/dn_ints.c	Thu Jan  1 01:00:00 1970
--- linux-apollo-dev/arch/m68k/apollo/dn_ints.c	Sun Sep 21 03:42:21 1997
***************
*** 0 ****
--- 1,166 ----
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+ #include <linux/kernel_stat.h>
+ 
+ #include <asm/system.h>
+ #include <asm/irq.h>
+ #include <asm/traps.h>
+ #include <asm/page.h>
+ #include <asm/machdep.h>
+ #include <asm/apollohw.h>
+ 
+ static irq_handler_t dn_irqs[16];
+ 
+ extern void write_keyb_cmd(u_short length, u_char *cmd);
+ static char BellOnCommand[] =  { 0xFF, 0x21, 0x81 },
+ 		    BellOffCommand[] = { 0xFF, 0x21, 0x82 };
+ 
+ void dn_process_int(int irq, struct pt_regs *fp) {
+ 
+ #if 0
+   unsigned char x;
+ #endif 
+ 
+ #if 0
+   printk("Aha DN interrupt ! : %d\n",irq);
+ #endif
+ 
+   if(dn_irqs[irq-160].handler) {
+     dn_irqs[irq-160].handler(irq,dn_irqs[irq-160].dev_id,fp);
+   }
+   else {
+     printk("spurious irq %d occured\n",irq);
+   }
+ 
+ #if 0  
+   printk("*(0x10803) %02x\n",*(volatile unsigned char *)(IO_BASE+0x10803));
+   x=*(volatile unsigned char *)(IO_BASE+0x10805);
+ #endif
+ 
+   *(volatile unsigned char *)(IO_BASE+0x11000)=0x20;
+   *(volatile unsigned char *)(IO_BASE+0x11100)=0x20;
+ 
+ }
+ 
+ void dn_init_IRQ(void) {
+ 
+   int i;
+ 
+   printk("Init IRQ\n");
+ 
+   for(i=0;i<16;i++) {
+     dn_irqs[i].handler=NULL;
+     dn_irqs[i].flags=IRQ_FLG_STD;
+     dn_irqs[i].dev_id=NULL;
+     dn_irqs[i].devname=NULL;
+   }
+   
+ }
+ 
+ int dn_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) {
+ 
+   printk("dn request IRQ\n");
+ 
+   if((irq<0) || (irq>15)) {
+     printk("Trying to request illegal IRQ\n");
+     return -ENXIO;
+   }
+ 
+   if(!dn_irqs[irq].handler) {
+     dn_irqs[irq].handler=handler;
+     dn_irqs[irq].flags=IRQ_FLG_STD;
+     dn_irqs[irq].dev_id=dev_id;
+     dn_irqs[irq].devname=devname;
+     if(irq<8)
+       *(volatile unsigned char *)(IO_BASE+PICA+1)&=~(1<<irq);
+     else
+       *(volatile unsigned char *)(IO_BASE+PICB+1)&=~(1<<(irq-8));
+     return 0;
+   }
+   else {
+     printk("Trying to request already assigned irq %d\n",irq);
+     return -ENXIO;
+   }
+ 
+ }
+ 
+ void dn_free_irq(unsigned int irq, void *dev_id) {
+ 
+   printk("dn free irq\n");
+ 
+   if((irq<0) || (irq>15)) {
+     printk("Trying to free illegal IRQ\n");
+     return ;
+   }
+ 
+   if(irq<8)
+     *(volatile unsigned char *)(IO_BASE+PICA+1)|=(1<<irq);
+   else
+     *(volatile unsigned char *)(IO_BASE+PICB+1)|=(1<<(irq-8));  
+ 
+   dn_irqs[irq].handler=NULL;
+   dn_irqs[irq].flags=IRQ_FLG_STD;
+   dn_irqs[irq].dev_id=NULL;
+   dn_irqs[irq].devname=NULL;
+ 
+   return ;
+ 
+ }
+ 
+ void dn_enable_irq(unsigned int irq) {
+ 
+   printk("dn enable irq\n");
+ 
+ }
+ 
+ void dn_disable_irq(unsigned int irq) {
+ 
+   printk("dn disable irq\n");
+ 
+ }
+ 
+ int dn_get_irq_list(char *buf) {
+ 
+   printk("dn get irq list\n");
+ 
+   return 0;
+ 
+ }
+ 
+ struct fb_info *dn_dummy_fb_init(long *mem_start) {
+ 
+   printk("fb init\n");
+ 
+   return NULL;
+ 
+ }
+ 
+ static void dn_nosound (unsigned long ignored) {
+ 
+ 	write_keyb_cmd(sizeof(BellOffCommand),BellOffCommand);
+ 
+ }
+ 
+ void dn_mksound( unsigned int count, unsigned int ticks ) {
+ 
+ 	static struct timer_list sound_timer = { NULL, NULL, 0, 0,
+        										 dn_nosound };
+ 
+ 	del_timer( &sound_timer );
+ 	if(count) {
+ 		write_keyb_cmd(sizeof(BellOnCommand),BellOnCommand);
+ 		if (ticks) {
+        		sound_timer.expires = jiffies + ticks;
+ 			add_timer( &sound_timer );
+ 		}
+ 	}
+ 	else
+ 		write_keyb_cmd(sizeof(BellOffCommand),BellOffCommand);
+ }
+ 
+ void dn_dummy_video_setup(char *options,int *ints) {
+ 
+   printk("no video yet\n");
+ 
+ }
diff -c -r -N ../linux-2.1.55/arch/m68k/config.in linux-apollo-dev/arch/m68k/config.in
*** ../linux-2.1.55/arch/m68k/config.in	Thu Sep 25 22:37:54 1997
--- linux-apollo-dev/arch/m68k/config.in	Thu Sep 25 23:59:55 1997
***************
*** 24,29 ****
--- 24,30 ----
  bool 'Amiga support' CONFIG_AMIGA
  bool 'Atari support' CONFIG_ATARI
  bool 'Macintosh support' CONFIG_MAC
+ bool 'Apollo support' CONFIG_APOLLO
  
  comment 'Processor type'
  bool '68020 support' CONFIG_M68020
***************
*** 205,210 ****
--- 206,214 ----
    tristate 'A2065 support' CONFIG_A2065
    tristate 'Hydra support' CONFIG_HYDRA
  fi
+ if [ "$CONFIG_APOLLO" = "y" ] ; then
+   tristate 'Apollo 3c505 support' CONFIG_APOLLO_ELPLUS
+ fi
  if [ "$CONFIG_ATARI" = "y" ]; then
    bool 'Atari Lance support' CONFIG_ATARILANCE
  if [ "$CONFIG_ATARI_ACSI" = "y" ]; then
***************
*** 265,270 ****
--- 269,278 ----
       "$CONFIG_GVPIOEXT" = "y" -o "$CONFIG_MULTIFACE_III_TTY" = "y" ]; then
    bool 'Serial console support' CONFIG_SERIAL_CONSOLE
  fi
+ if [ "$CONFIG_APOLLO" = "y" ]; then
+   bool 'Support for DN serial port (dummy)' CONFIG_SERIAL
+   bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE
+ fi 
  bool 'Support for user serial device modules' CONFIG_USERIAL
  bool 'Watchdog Timer Support'	CONFIG_WATCHDOG
  if [ "$CONFIG_WATCHDOG" != "n" ]; then
diff -c -r -N ../linux-2.1.55/arch/m68k/kernel/head.S linux-apollo-dev/arch/m68k/kernel/head.S
*** ../linux-2.1.55/arch/m68k/kernel/head.S	Thu Sep 25 22:35:54 1997
--- linux-apollo-dev/arch/m68k/kernel/head.S	Fri Sep 12 15:13:10 1997
***************
*** 433,438 ****
--- 433,450 ----
  /*
   * Do any machine specific page table initializations.
   */
+ 
+ #ifdef CONFIG_APOLLO
+ 
+         putc('O')
+ 
+         moveq   #_PAGE_NOCACHE030+_PAGE_PRESENT,%d0
+         movel   %d0,%a5@(0x40<<2)
+ 	movel	%d0,%a5@(0x41<<2)
+ 
+         jra     Lmapphys
+ 
+ #endif
  #ifdef CONFIG_AMIGA
  	is_not_amiga(Lnotami)
  
***************
*** 625,630 ****
--- 637,680 ----
  Lmapphys:
  	putc('J')
  
+ #ifdef CONFIG_APOLLO
+ 
+         putc('P')
+ 
+         movew   #PAGESIZE,%sp
+ 
+         /* fixup the Apollo IO base location before printing */
+         lea     %pc@(Liobase),%a0
+         movel   #0x80000000,%a0@
+ 
+         lea     2f:w,%a0
+         movel   %d5,%d0
+         andl    #0xff000000,%d0
+ 
+         orw     #TTR_ENABLE+TTR_CI+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d0
+         lea     %pc@(Lmmu),%a3
+         movel   %d0,%a3@
+         .long   0xf0130800      /* pmove %a3@,%tt0 */
+         /* no limit, 4byte descriptors */
+         movel   #0x80000002,%a3@
+         movel   %a5,%a3@(4)
+         .long   0xf0134800      /* pmove %a3@,%srp */
+         .long   0xf0134c00      /* pmove %a3@,%crp */
+         .long   0xf0002400      /* pflusha */
+         /*
+          * enable,super root enable,4096 byte pages,7 bit root index,
+          * 7 bit pointer index, 6 bit page table index.
+          */
+ 
+         movel   #0x82c07760,%a3@
+         .long   0xf0134000      /* pmove %a3@,%tc (enable the MMU) */
+         jmp     %a0@
+ 2:      clrl    %a3@
+         .long   0xf0130800      /* pmove %a3@,%tt0 */
+         jmp     LdoneMMUenable:w
+ 
+ #endif
+ 
  #ifdef CONFIG_AMIGA
  	is_not_amiga(Lmapphysnotamiga)
  
***************
*** 988,993 ****
--- 1038,1051 ----
  LSERIAL_DTR	= 7
  
  /*
+  * SIO1 support
+  */
+ 
+ LSRB0        = 0x10412
+ LTHRB0       = 0x10416
+ 
+ 
+ /*
   * Initialize serial port hardware for 9600/8/1
   * a0 thrashed
   * Amiga d0 trashed
***************
*** 1042,1053 ****
--- 1100,1124 ----
  9:
  	rts
  
+ #ifdef CONFIG_APOLLO
+ /* We count on the PROM initializing SIO1 */
+         rts
+ #endif
+ 
  /*
   * Output character in d7 on serial port.
   * d7 thrashed.
   */
  Lserial_putc:
  	moveml	%a0/%a1,%sp@-
+ #ifdef CONFIG_APOLLO
+         movl    %pc@(Liobase),%a1
+         moveb   %d7,%a1@(LTHRB0)
+ 1:      moveb   %a1@(LSRB0),%d7
+         andb    #0x4,%d7
+         jeq     1b
+         jra     9f
+ #endif
  #ifdef CONFIG_AMIGA
  	cmpil	#MACH_AMIGA,%d4
  	jne	2f
diff -c -r -N ../linux-2.1.55/arch/m68k/kernel/setup.c linux-apollo-dev/arch/m68k/kernel/setup.c
*** ../linux-2.1.55/arch/m68k/kernel/setup.c	Thu Sep 25 22:37:56 1997
--- linux-apollo-dev/arch/m68k/kernel/setup.c	Wed Sep 17 01:39:58 1997
***************
*** 154,167 ****
--- 154,172 ----
  	int i;
  	char *p, *q;
  
+ 	dn_serial_print("He setup_arch !\n");
+ 
  	/* The bootinfo is located right after the kernel bss */
  	m68k_parse_bootinfo((const struct bi_record *)&_end);
  
+ 	dn_serial_print("1\n");
  	if (CPU_IS_040)
  		m68k_is040or060 = 4;
  	else if (CPU_IS_060)
  		m68k_is040or060 = 6;
  
+ 	dn_serial_print("2\n");
+ 
  	base_trap_init();
  
  	/* clear the fpu if we have one */
***************
*** 170,181 ****
--- 175,188 ----
  		asm __volatile__ ("frestore %0" : : "m" (zero));
  	}
  
+ 	dn_serial_print("3\n");
  	memory_start = availmem;
  	memory_end = 0;
  
  	for (i = 0; i < m68k_num_memory; i++)
  		memory_end += m68k_memory[i].size & MASK_256K;
  
+ 	dn_serial_print("4\n");
  	init_task.mm->start_code = 0;
  	init_task.mm->end_code = (unsigned long) &_etext;
  	init_task.mm->end_data = (unsigned long) &_edata;
***************
*** 184,189 ****
--- 191,197 ----
  	*cmdline_p = m68k_command_line;
  	memcpy(saved_command_line, *cmdline_p, CL_SIZE);
  
+ 	dn_serial_print("5\n");
  	/* Parse the command line for arch-specific options.
  	 * For the m68k, this is currently only "debug=xxx" to enable printing
  	 * certain kernel messages to some machine-specific device.
***************
*** 208,213 ****
--- 216,222 ----
  	    }
  	}
  
+ 	dn_serial_print("6\n");
  	*memory_start_p = memory_start;
  	*memory_end_p = memory_end;
  
***************
*** 238,246 ****
--- 247,257 ----
  	    	break;
  #endif
  	    default:
+ 		dn_serial_print ("No configuration setup");
  		panic ("No configuration setup");
  	}
  
+ 	dn_serial_print("7\n");
  #ifdef CONFIG_BLK_DEV_INITRD
  	if (m68k_ramdisk.size) {
  		initrd_start = PTOV (m68k_ramdisk.addr);
diff -c -r -N ../linux-2.1.55/drivers/char/Makefile linux-apollo-dev/drivers/char/Makefile
*** ../linux-2.1.55/drivers/char/Makefile	Thu Sep 25 22:38:12 1997
--- linux-apollo-dev/drivers/char/Makefile	Sun Sep 21 10:41:21 1997
***************
*** 169,175 ****
--- 171,181 ----
  L_OBJS += keyboard.o defkeymap.o
  endif
  ifndef CONFIG_AMIGA
+ ifdef CONFIG_APOLLO
+ L_OBJS += dn_keyb.o
+ else
  L_OBJS += pc_keyb.o
+ endif
  else
  L_OBJS += amikeyb.o
  endif
***************
*** 472,477 ****
--- 478,484 ----
  endif
  endif
  
+ 
  ifeq ($(CONFIG_HFMODEM),y)
  ALL_SUB_DIRS += hfmodem
  SUB_DIRS += hfmodem
diff -c -r -N ../linux-2.1.55/drivers/char/dn_keyb.c linux-apollo-dev/drivers/char/dn_keyb.c
*** ../linux-2.1.55/drivers/char/dn_keyb.c	Thu Jan  1 01:00:00 1970
--- linux-apollo-dev/drivers/char/dn_keyb.c	Tue Sep 23 12:52:27 1997
***************
*** 0 ****
--- 1,612 ----
+ #include <linux/types.h>
+ #include <linux/sched.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/kernel.h>
+ #include <linux/module.h>
+ #include <linux/poll.h>
+ #include <linux/miscdevice.h>
+ 
+ #include <asm/setup.h>
+ #include <asm/irq.h>
+ #include <asm/apollohw.h>
+ #include <asm/uaccess.h>
+ 
+ 
+ extern void handle_scancode(unsigned char);
+ 
+ #define DNKEY_CAPS 0x7e
+ #define BREAK_FLAG 0x80
+ #define DNKEY_REPEAT_DELAY 50
+ #define DNKEY_CTRL 0x43
+ #define DNKEY_LSHIFT 0x5e
+ #define DNKEY_RSHIFT 0x6a
+ #define DNKEY_REPT 0x5d
+ #define DNKEY_REPEAT 0x7f
+ #define DNKEY_LALT 0x75
+ #define DNKEY_RALT 0x77
+ 
+ #define APOLLO_KEYB_CMD_ENTRIES 16
+ #define APOLLO_KBD_MODE_KEYB   0x01
+ #define APOLLO_KBD_MODE_MOUSE   0x02
+ #define APOLLO_KBD_MODE_CHANGE 0xff
+ 
+ #define MSE_UPDATE_ON() mouse_update_allowed=1
+ #define MSE_UPDATE_OFF() mouse_update_allowed=0
+ 
+ static u_char keyb_cmds[APOLLO_KEYB_CMD_ENTRIES];
+ static short keyb_cmd_read=0, keyb_cmd_write=0;
+ static int keyb_cmd_transmit=0;
+ 
+ static unsigned int kbd_mode=APOLLO_KBD_MODE_KEYB;
+ static short mouse_dx,mouse_dy,mouse_buttons;
+ static int mouse_ready=0,mouse_update_allowed=0,mouse_active=0;
+ static struct wait_queue *mouse_wait=NULL;
+ static struct fasync_struct *mouse_fasyncptr=NULL;
+ 
+ #if 0
+ static void debug_keyb_timer_handler(unsigned long ignored);
+ static u_char debug_buf1[4096],debug_buf2[4096],*debug_buf=&debug_buf1[0];
+ static u_char *shadow_buf=&debug_buf2[0];
+ static short debug_buf_count=0;
+ static int debug_buf_overrun=0,debug_timer_running=0,debug_buffer_updated=0;
+ static struct timer_list debug_keyb_timer = { NULL, NULL, 0, 0,
+ 											  debug_keyb_timer_handler };
+ #endif
+ 
+ static u_short dnplain_map[NR_KEYS] = {
+ /*         ins     del     del     F1      F2      F3      F4  
+            mark    line    char                                 */
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ /* F5      F6      F7      F8      F9      F0      Again   Read */
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ /* Edit    Exit    Hold    Copy    Paste   Grow            ESC  */
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf01b,
+ /* 1       2       3       4       5       6       7       8    */
+    0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037, 0xf038,
+ /* 9       0       -       =       `       Back            |<--
+                                            Space                */
+    0xf039, 0xf030, 0xf02d, 0xf03d, 0xf060, 0xf07f, 0xf200, 0xf200,
+ /* Shell   -->|                    Tab     q       w       e
+    Cmd                                                          */
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf009, 0xfb71, 0xfb77, 0xfb65,
+ /* r       t       y       u       i       o       p       [    */
+    0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, 0xfb6f, 0xfb70, 0xf05b,
+ /* ]               Del             7       8       9       +    */
+    0xf05d, 0xf200, 0xf200, 0xf200, 0xf307, 0xf308, 0xf300, 0xf30a,
+ /* [<--]   Up      [-->]   Ctrl                    a       s    */
+    0xf200, 0xf600, 0xf200, 0xf702, 0xf200, 0xf200, 0xfb61, 0xfb73,
+ /* d       f       g       h       j       k       l       ;    */
+    0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
+ /* '               Return  \               4       5       6    */
+    0xf027, 0xf200, 0xf201, 0xf05c, 0xf200, 0xf304, 0xf305, 0xf306,
+ /* -       <--     Next    -->             Rept    Shift        
+                    Window                                       */
+    0xf30b, 0xf601, 0xf200, 0xf602, 0xf200, 0xf200, 0xf700, 0xf200,
+ /* z       x       c       v       b       n       m       ,    */
+    0xfb7a, 0xfb78, 0xfb63, 0xfb76, 0xfb62, 0xfb6e, 0xfb6d, 0xf02c,
+ /* .       /       Shift           Pop             1       2    */
+    0xf02e, 0xf02f, 0xf700, 0xf200, 0xf200, 0xf200, 0xf301, 0xf302,
+ /* 3               PgUp    Down    PgDn    Alt     Space   Alt  */
+    0xf303, 0xf200, 0xf118, 0xf603, 0xf119, 0xf703, 0xf020, 0xf701,
+ /*         0               .       Enter                        */
+    0xf200, 0xf300, 0xf200, 0xf310, 0xf30e, 0xf200, 0xf700, 0xf200,
+ };
+ 
+ static u_short dnshift_map[NR_KEYS] = {
+ /*         ins     del     del     F1      F2      F3      F4
+            mark    line    char                                 */
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ /* F5      F6      F7      F8      F9      F0      Again   Read */
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ /* Save    Abort   Help    Cut     Undo    Grow            ESC  */
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf01b,
+ /* !       @       #       $       %       ^       &       *    */
+    0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e, 0xf026, 0xf02a,
+ /* (       )       _       +       ~       Back            |<--
+                                            Space                */
+    0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07e, 0xf07f, 0xf200, 0xf200,
+ /* Shell   -->|                    Tab     Q       W       E
+    Cmd                                                          */
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf009, 0xfb51, 0xfb57, 0xfb45,
+ /* R       T       Y       U       I       O       P       {    */
+    0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49, 0xfb4f, 0xfb50, 0xf07b,
+ /* }               Del             7       8       9       +    */
+    0xf07d, 0xf200, 0xf200, 0xf200, 0xf307, 0xf308, 0xf300, 0xf30a,
+ /* [<--]   Up      [-->]   Ctrl                    A       S    */
+    0xf200, 0xf600, 0xf200, 0xf702, 0xf200, 0xf200, 0xfb41, 0xfb53,
+ /* D       F       G       H       J       K       L       :    */
+    0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a,
+ /* "               Return  |               4       5       6    */
+    0xf022, 0xf200, 0xf201, 0xf07c, 0xf200, 0xf304, 0xf305, 0xf306,
+ /* -       <--     Next    -->             Rept    Shift        
+                    Window                                       */
+    0xf30b, 0xf601, 0xf200, 0xf602, 0xf200, 0xf200, 0xf700, 0xf200,
+ /* Z       X       C       V       B       N       M       <    */
+    0xfb5a, 0xfb58, 0xfb43, 0xfb56, 0xfb42, 0xfb4e, 0xfb4d, 0xf03c,
+ /* >       ?       Shift           Pop             1       2    */
+    0xf03e, 0xf03f, 0xf700, 0xf200, 0xf200, 0xf200, 0xf301, 0xf302,
+ /* 3               PgUp    Down    PgDn    Alt     Space   Alt  */
+    0xf303, 0xf200, 0xf118, 0xf603, 0xf119, 0xf703, 0xf020, 0xf701,
+ /*         0               .       Enter                        */
+    0xf200, 0xf300, 0xf200, 0xf310, 0xf30e, 0xf200, 0xf708, 0xf200,
+ };
+ 
+ static u_short dnctrl_map[NR_KEYS] = {
+ /*         ins     del     del     F1      F2      F3      F4
+            mark    line    char                                 */
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ /* F5      F6      F7      F8      F9      F0      Again   Read */
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ /* Save    Abort   Help    Cut     Undo    Grow            ESC  */
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf01b,
+ /* !       @       #       $       %       ^       &       *    */
+    0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f, 0xf07f,
+ /* (       )       _       +       ~       Back            |<--
+                                            Space                */
+    0xf200, 0xf200, 0xf01f, 0xf200, 0xf01c, 0xf200, 0xf200, 0xf200,
+ /* Shell   -->|                    Tab     Q       W       E
+    Cmd                                                          */
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf009, 0xf011, 0xf017, 0xf005,
+ /* R       T       Y       U       I       O       P       {    */
+    0xf012, 0xf014, 0xf019, 0xf015, 0xf009, 0xf00f, 0xf010, 0xf01b,
+ /* }               Del             7       8       9       +    */
+    0xf01d, 0xf200, 0xf200, 0xf200, 0xf307, 0xf308, 0xf300, 0xf30a,
+ /* [<--]   Up      [-->]   Ctrl                    A       S    */
+    0xf200, 0xf600, 0xf200, 0xf702, 0xf200, 0xf200, 0xfb01, 0xfb53,
+ /* D       F       G       H       J       K       L       :    */
+    0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
+ /* "               Return  |               4       5       6    */
+    0xf200, 0xf200, 0xf201, 0xf01c, 0xf200, 0xf304, 0xf305, 0xf306,
+ /* -       <--     Next    -->             Rept    Shift        
+                    Window                                       */
+    0xf30b, 0xf601, 0xf200, 0xf602, 0xf200, 0xf200, 0xf704, 0xf200,
+ /* Z       X       C       V       B       N       M       <    */
+    0xf01a, 0xf018, 0xf003, 0xf016, 0xf002, 0xf00e, 0xf01d, 0xf03c,
+ /* >       ?       Shift           Pop             1       2    */
+    0xf03e, 0xf03f, 0xf705, 0xf200, 0xf200, 0xf200, 0xf301, 0xf302,
+ /* 3               PgUp    Down    PgDn    Alt     Space   Alt  */
+    0xf303, 0xf200, 0xf118, 0xf603, 0xf119, 0xf703, 0xf020, 0xf701,
+ /*         0               .       Enter                        */
+    0xf200, 0xf300, 0xf200, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200,
+ };
+ 
+ static u_short dnalt_map[NR_KEYS] = {
+ /*         ins     del     del     F1      F2      F3      F4  
+            mark    line    char                                 */
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf500, 0xf501, 0xf502, 0xf503,
+ /* F5      F6      F7      F8      F9      F0      Again   Read */
+    0xf504, 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf200, 0xf200,
+ /* Edit    Exit    Hold    Copy    Paste   Grow            ESC  */
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf01b,
+ /* 1       2       3       4       5       6       7       8    */
+    0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836, 0xf837, 0xf838,
+ /* 9       0       -       =       `       Back            |<--
+                                            Space                */
+    0xf839, 0xf830, 0xf82d, 0xf83d, 0xf860, 0xf87f, 0xf200, 0xf200,
+ /* Shell   -->|                    Tab     q       w       e
+    Cmd                                                          */
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf809, 0xf871, 0xf877, 0xf865,
+ /* r       t       y       u       i       o       p       [    */
+    0xf872, 0xf874, 0xf879, 0xf875, 0xf869, 0xf86f, 0xf870, 0xf85b,
+ /* ]               Del             7       8       9       +    */
+    0xf05d, 0xf200, 0xf200, 0xf200, 0xf307, 0xf308, 0xf300, 0xf30a,
+ /* [<--]   Up      [-->]   Ctrl                    a       s    */
+    0xf200, 0xf600, 0xf200, 0xf702, 0xf200, 0xf200, 0xf861, 0xf873,
+ /* d       f       g       h       j       k       l       ;    */
+    0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf03b,
+ /* '               Return  \               4       5       6    */
+    0xf027, 0xf200, 0xf201, 0xf05c, 0xf200, 0xf304, 0xf305, 0xf306,
+ /* -       <--     Next    -->             Rept    Shift        
+                    Window                                       */
+    0xf30b, 0xf601, 0xf200, 0xf602, 0xf200, 0xf200, 0xf704, 0xf200,
+ /* z       x       c       v       b       n       m       ,    */
+    0xf87a, 0xf878, 0xf863, 0xf876, 0xf862, 0xf86e, 0xf86d, 0xf82c,
+ /* .       /       Shift           Pop             1       2    */
+    0xf82e, 0xf82f, 0xf705, 0xf200, 0xf200, 0xf200, 0xf301, 0xf302,
+ /* 3               PgUp    Down    PgDn    Alt     Space   Alt  */
+    0xf303, 0xf200, 0xf118, 0xf603, 0xf119, 0xf703, 0xf820, 0xf701,
+ /*         0               .       Enter                        */
+    0xf200, 0xf300, 0xf200, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200,
+ };
+ 
+ static u_short dnaltgr_map[NR_KEYS] = {
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
+ };
+ 
+ static u_short dnshift_ctrl_map[NR_KEYS] = {
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
+ };
+ 
+ static u_short dnctrl_alt_map[NR_KEYS] = {
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+    0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
+ };
+ 
+ #if 0
+ static void debug_keyb_timer_handler(unsigned long ignored) {
+ 
+ 	unsigned long flags;
+ 	u_char *swap;
+ 	short length,i;
+ 
+ 	if((jiffies-debug_buffer_updated) > 100) {
+ 		save_flags(flags);
+ 		cli();
+ 		length=debug_buf_count;		
+ 		swap=debug_buf;	
+ 		debug_buf=shadow_buf;
+ 		shadow_buf=swap;
+ 		debug_buf_count=0;
+ 		debug_timer_running=0;
+ 		restore_flags(flags);
+ 		for(i=1;length;length--,i++)	
+ 			printk("%02x%c",*(swap++), (i % 25) ? ' ' : '\n');
+ 		printk("\n");
+ 	}
+ 	else {
+ 		debug_keyb_timer.expires=jiffies+10;
+ 		add_timer(&debug_keyb_timer);
+ 	}
+ }
+ #endif
+ 
+ static unsigned int mouse_poll(struct file *file, poll_table * wait)
+ {
+         poll_wait(&mouse_wait, wait);
+         if (mouse_ready)
+                 return POLLIN | POLLRDNORM;
+         return 0;
+ }
+ 
+ static long write_mouse(struct inode * inode, struct file * file,
+                         const char * buffer, unsigned long count)
+ {
+         return -EINVAL;
+ }
+ 
+ static long read_mouse(struct inode * inode, struct file * file,
+                        char * buffer, unsigned long count) {
+ 
+ 	int dx,dy,r;
+ 	unsigned char buttons;
+ 
+ 	if (count < 3)
+ 		return -EINVAL;
+ 	if ((r = verify_area(VERIFY_WRITE, buffer, count)))
+    		return r;
+ 	if (!mouse_ready)
+ 		return -EAGAIN;	
+ 
+ 	MSE_UPDATE_OFF();
+ 	dx=mouse_dx;	
+ 	dy=mouse_dy;	
+ 	if (dx < -127)
+ 		dx = -127;
+ 	else
+ 	if (dx > 127)
+    		dx = 127;
+ 	if (dy < -127)
+    		dy = -127;
+ 	else
+ 	if (dy > 127)
+    		dy = 127;
+ 	buttons=(mouse_buttons & 1 ? 4 : 0) |
+ 			(mouse_buttons & 2 ? 1 : 0) |
+ 			(mouse_buttons & 4 ? 2 : 0);
+ 
+ 	mouse_dx-=dx;
+ 	mouse_dy-=dy;
+ 	MSE_UPDATE_ON();
+ 
+ 	put_user(buttons | 0x80, buffer);
+ 	put_user((char)dx, buffer + 1);
+ 	put_user((char)dy, buffer + 2);
+ 	for (r = 3; r < count; r++)
+   		put_user(0x00, buffer + r);
+ 
+ 	return r;
+ }
+ 
+ static int fasync_mouse(struct inode *inode, struct file *filp, int on)
+ {
+         int retval;
+ 
+         retval = fasync_helper(inode, filp, on, &mouse_fasyncptr);
+         if (retval < 0)
+                 return retval;
+         return 0;
+ }
+ 
+ 
+ static int release_mouse(struct inode * inode, struct file * file)
+ {
+         fasync_mouse(inode, file, 0);
+         if (--mouse_active)
+                 return 0;
+         MSE_UPDATE_OFF();
+         MOD_DEC_USE_COUNT;
+         return 0;
+ }
+ 
+ static int open_mouse(struct inode * inode, struct file * file)
+ {
+         if (mouse_active++)
+                 return 0;
+         /*
+          *  use VBL to poll mouse deltas
+          */
+ 
+         mouse_dx = 0;
+         mouse_dy = 0;
+         mouse_buttons = 0;
+         mouse_active = 1;
+         MOD_INC_USE_COUNT;
+         MSE_UPDATE_ON();
+         return 0;
+ }
+ 
+ static void dn_keyb_process_key_event(unsigned char scancode) {
+ 
+ 	static unsigned char lastscancode;
+ 	unsigned char prev_scancode=lastscancode;
+ 	static unsigned int lastkeypress;
+ 	
+ 	lastscancode=scancode;
+ 
+ 	/*  printk("scan: %02x, lastscan: %02X, prev_scancode: %02X\n",scancode,lastscancode,prev_scancode); */
+ 
+ 	if(prev_scancode==APOLLO_KBD_MODE_CHANGE) {
+ 		kbd_mode=scancode;
+ /*		printk("modechange: %d\n",scancode);*/
+ 	}
+ 	else if((scancode & (~BREAK_FLAG)) == DNKEY_CAPS) {
+     	/* printk("handle_scancode: %02x\n",DNKEY_CAPS); */
+ 		handle_scancode(DNKEY_CAPS);
+ 		/*    printk("handle_scancode: %02x\n",BREAK_FLAG | DNKEY_CAPS); */
+ 		handle_scancode(BREAK_FLAG | DNKEY_CAPS);
+ 	}
+ 	else if( (scancode == DNKEY_REPEAT) && (prev_scancode < 0x7e) &&
+    			!(prev_scancode==DNKEY_CTRL || prev_scancode==DNKEY_LSHIFT ||
+        	   	prev_scancode==DNKEY_RSHIFT || prev_scancode==DNKEY_REPT ||
+        	  	prev_scancode==DNKEY_LALT || prev_scancode==DNKEY_RALT)) {
+         		if(jiffies-lastkeypress > DNKEY_REPEAT_DELAY) {
+ 			/*    	printk("handle_scancode: %02x\n",prev_scancode); */
+            			handle_scancode(prev_scancode);
+ 			  	}
+ 	   			lastscancode=prev_scancode;
+   			}
+   	else {
+ 	/*    	printk("handle_scancode: %02x\n",scancode);  */
+    			handle_scancode(scancode);
+    			lastkeypress=jiffies;
+   	}
+ }
+ 
+ static void dn_keyb_process_mouse_event(unsigned char mouse_data) {
+ 
+ 	static short mouse_byte_count=0;
+ 	static u_char mouse_packet[3];
+ 	
+ 	mouse_packet[mouse_byte_count++]=mouse_data;
+ 
+ 	if(mouse_byte_count==3) {
+ 		if(mouse_packet[0]==APOLLO_KBD_MODE_CHANGE) {
+ 			kbd_mode=mouse_packet[1];
+ 			mouse_byte_count=0;
+ /*			printk("modechange: %d\n",mouse_packet[1]); */
+ 			if(kbd_mode==APOLLO_KBD_MODE_KEYB)
+ 				dn_keyb_process_key_event(mouse_packet[2]);
+ 		}				
+ 		if((mouse_packet[0] & 0x8f) == 0x80) {
+ 			if(mouse_update_allowed) {
+ 				mouse_ready=1;
+ 				mouse_buttons=(mouse_packet[0] >> 4) & 0x7;
+ 				mouse_dx+=mouse_packet[1] == 0xff ? 0 : (signed char)mouse_packet[1];
+ 				mouse_dy+=mouse_packet[2] == 0xff ? 0 : (signed char)mouse_packet[2];
+ 				wake_up_interruptible(&mouse_wait);
+ 				if (mouse_dx < -2048)
+               		mouse_dx = -2048;
+           		else
+           		if (mouse_dx >  2048)
+               		mouse_dx =  2048;
+           		if (mouse_dy < -2048)
+               		mouse_dy = -2048;
+           		else
+           		if (mouse_dy >  2048)
+               		mouse_dy =  2048;
+ 				if (mouse_fasyncptr)
+               		kill_fasync(mouse_fasyncptr, SIGIO);
+ 			}
+ 			mouse_byte_count=0;
+ /*			printk("mouse: %d, %d, %x\n",mouse_x,mouse_y,buttons); */
+ 		}
+ 	}
+ }
+ 
+ static void dn_keyb_int(int irq, void *dummy, struct pt_regs *fp) {
+ 
+ 	unsigned char data;
+   	unsigned long flags;
+   	int scn2681_ints;
+ 
+ 	do {
+ 		scn2681_ints=sio01.isr_imr & 3;
+ 		if(scn2681_ints & 2) {
+ 			data=sio01.rhra_thra;
+ #if 0
+ 			if(debug_buf_count<4096) {
+ 				debug_buf[debug_buf_count++]=data;
+ 				debug_buffer_updated=jiffies;	
+ 				if(!debug_timer_running) {
+ 					add_timer(&debug_keyb_timer);
+ 					debug_keyb_timer.expires=jiffies+10;
+ 					debug_timer_running=1;
+ 				}
+ 			}
+ 			else
+ 				debug_buf_overrun=1;
+ #endif
+ 			if(sio01.sra_csra & 0x10) {
+ 				printk("whaa overrun !\n");
+ 				continue;
+ 			}
+ 
+ 			if(kbd_mode==APOLLO_KBD_MODE_KEYB)
+ 				dn_keyb_process_key_event(data);
+ 			else
+ 				dn_keyb_process_mouse_event(data);
+ 		}
+ 	
+ 		if(scn2681_ints & 1) {
+ 			save_flags(flags);
+ 			cli();
+ 			if(keyb_cmd_write!=keyb_cmd_read) {
+ 				sio01.rhra_thra=keyb_cmds[keyb_cmd_read++];
+ 				if(keyb_cmd_read==APOLLO_KEYB_CMD_ENTRIES)
+ 					keyb_cmd_read=0;
+ 				keyb_cmd_transmit=1;
+ 			}
+ 			else {
+ 				keyb_cmd_transmit=0;
+ 				sio01.BRGtest_cra=9;
+ 			}
+ 			restore_flags(flags);
+ 		}
+ 	} while(scn2681_ints) ;
+ }
+ 
+ void write_keyb_cmd(u_short length, u_char *cmd) {
+ 
+   	unsigned long flags;
+ 
+ 	if((keyb_cmd_write==keyb_cmd_read) && keyb_cmd_transmit)
+ 		return;
+ 
+ 	save_flags(flags);
+ 	cli();
+ 	for(;length;length--) {
+ 		keyb_cmds[keyb_cmd_write++]=*(cmd++);
+ 		if(keyb_cmd_write==keyb_cmd_read)
+ 			return;
+ 		if(keyb_cmd_write==APOLLO_KEYB_CMD_ENTRIES)
+ 			keyb_cmd_write=0;
+ 	}
+ 	if(!keyb_cmd_transmit)  {
+  	   sio01.BRGtest_cra=5;
+ 	}
+ 	restore_flags(flags);
+ 
+ }
+ 
+ struct file_operations apollo_mouse_fops = {
+         NULL,           /* mouse_seek */
+         read_mouse,
+         write_mouse,
+         NULL,           /* mouse_readdir */
+         mouse_poll,     /* mouse_poll */
+         NULL,           /* mouse_ioctl */
+         NULL,           /* mouse_mmap */
+         open_mouse,
+         release_mouse,
+         NULL,
+         fasync_mouse,
+ };
+ 
+ static struct miscdevice apollo_mouse = {
+         APOLLO_MOUSE_MINOR, "apollomouse", &apollo_mouse_fops
+ };
+ 
+ int dn_keyb_init(void) {
+ 
+ /*  printk("dn_keyb_init\n"); */
+ 
+   key_maps[0]  = dnplain_map;
+   key_maps[1]  = dnshift_map;
+   key_maps[2]  = dnaltgr_map;
+   key_maps[4]  = dnctrl_map;
+   key_maps[5]  = dnshift_ctrl_map;
+   key_maps[8]  = dnalt_map;
+   key_maps[12] = dnctrl_alt_map;
+   memcpy(plain_map, dnplain_map, sizeof(plain_map));
+ 
+   mouse_dx=0; 
+   mouse_dy=0; 
+   mouse_buttons=0; 
+   mouse_wait=NULL;
+ 
+   misc_register(&apollo_mouse);
+ 
+   /* program UpDownMode */
+ 
+   while(!(sio01.sra_csra & 0x4));
+   sio01.rhra_thra=0xff;
+ 
+   while(!(sio01.sra_csra & 0x4));
+   sio01.rhra_thra=0x1;
+ 
+   request_irq(1, dn_keyb_int,0,NULL,NULL);
+   
+   /* enable receive int on DUART */
+   sio01.isr_imr=3;
+ 
+   return 0;
+ 
+ }
+ 
+ int dn_dummy_kbdrate(struct kbd_repeat *k) {
+ 
+   printk("dn_dummy_kbdrate\n");
+ 
+   return 0;
+ 
+ }
diff -c -r -N ../linux-2.1.55/drivers/char/fbmem.c linux-apollo-dev/drivers/char/fbmem.c
*** ../linux-2.1.55/drivers/char/fbmem.c	Thu Sep 25 22:38:13 1997
--- linux-apollo-dev/drivers/char/fbmem.c	Wed Sep 17 03:58:42 1997
***************
*** 53,58 ****
--- 53,60 ----
  extern unsigned long Mach64_fb_init(unsigned long mem_start);
  extern void Mach64_video_setup(char *options, int *ints);
  extern void resolver_video_setup(char *options, int *ints);
+ extern void dn_fb_init(unsigned long mem_start);
+ extern void dn_video_setup(char *options, int *ints);
  
  static struct {
  	const char *name;
***************
*** 81,86 ****
--- 83,91 ----
  	/* Not a real frame buffer device... */
  	{ "resolver", NULL, resolver_video_setup },
  #endif
+ #ifdef CONFIG_APOLLO
+ 	{ "apollo", dn_fb_init, dn_video_setup },
+ #endif
  };
  
  #define NUM_FB_DRIVERS	(sizeof(fb_drivers)/sizeof(*fb_drivers))
diff -c -r -N ../linux-2.1.55/drivers/net/3c505_pio_apollo.c linux-apollo-dev/drivers/net/3c505_pio_apollo.c
*** ../linux-2.1.55/drivers/net/3c505_pio_apollo.c	Thu Jan  1 01:00:00 1970
--- linux-apollo-dev/drivers/net/3c505_pio_apollo.c	Thu Sep 25 23:27:58 1997
***************
*** 0 ****
--- 1,1541 ----
+ /*
+  * Linux ethernet device driver for the 3Com Etherlink Plus (3C505)
+  * 	By Craig Southeren and Juha Laiho
+  *
+  * 3c505.c	This module implements an interface to the 3Com
+  *		Etherlink Plus (3c505) ethernet card. Linux device 
+  *		driver interface reverse engineered from the Linux 3C509
+  *		device drivers. Some 3C505 information gleaned from
+  *		the Crynwr packet driver. Still this driver would not
+  *		be here without 3C505 technical reference provided by
+  *		3Com.
+  *
+  * Version:	@(#)3c505.c	0.8.4	17-Dec-95
+  *
+  * Authors:	Linux 3c505 device driver by
+  *			Craig Southeren, <craigs@ineluki.apana.org.au>
+  *              Final debugging by
+  *			Andrew Tridgell, <tridge@nimbus.anu.edu.au>
+  *		Auto irq/address, tuning, cleanup and v1.1.4+ kernel mods by
+  *			Juha Laiho, <jlaiho@ichaos.nullnet.fi>
+  *              Linux 3C509 driver by
+  *             		Donald Becker, <becker@super.org>
+  *		Crynwr packet driver by
+  *			Krishnan Gopalan and Gregg Stefancik,
+  * 			   Clemson University Engineering Computer Operations.
+  *			Portions of the code have been adapted from the 3c505
+  *			   driver for NCSA Telnet by Bruce Orchard and later
+  *			   modified by Warren Van Houten and krus@diku.dk.
+  *              3C505 technical information provided by
+  *                      Terry Murphy, of 3Com Network Adapter Division
+  *		Linux 1.3.0 changes by
+  *			Alan Cox <Alan.Cox@linux.org>
+  *                     
+  */
+ 
+ #include <linux/module.h>
+ 
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+ #include <linux/string.h>
+ #include <linux/interrupt.h>
+ #include <linux/ptrace.h>
+ #include <linux/errno.h>
+ #include <linux/in.h>
+ #include <linux/malloc.h>
+ #include <linux/ioport.h>
+ #include <asm/bitops.h>
+ #include <asm/apollohw.h>
+ #include <asm/irq.h>
+ 
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+ #include <linux/skbuff.h>
+ 
+ #include "3c505_pio_apollo.h"
+ 
+ #define swapw(x)        ((((x)>>8)&0x00ffU)|(((x)<<8)&0xff00U))
+ #define swapd(x)        ((((x)>>24)&0xffU)|(((x)>>8) & 0xff00U) \
+ 			 |(((x)<<8)&0xff0000U)|(((x)<<24)&0xff000000U))
+ 
+ /*********************************************************
+  *
+  *  define debug messages here as common strings to reduce space
+  *
+  *********************************************************/
+ 
+ static const char * filename = __FILE__;
+ 
+ static const char * null_msg = "*** NULL at %s:%s (line %d) ***\n";
+ #define CHECK_NULL(p) \
+ 	if (!p) printk(null_msg, filename,__FUNCTION__,__LINE__)
+ 
+ static const char * timeout_msg = "*** timeout at %s:%s (line %d) ***\n";
+ #define TIMEOUT_MSG(lineno) \
+ 	printk(timeout_msg, filename,__FUNCTION__,(lineno))
+ 
+ static const char * invalid_pcb_msg =
+ 	"*** invalid pcb length %d at %s:%s (line %d) ***\n";
+ #define INVALID_PCB_MSG(len) \
+ 	printk(invalid_pcb_msg, (len),filename,__FUNCTION__,__LINE__)
+ 
+ static const char * search_msg = "%s: Looking for 3c505 adapter at address %#x...";
+ 
+ static const char * stilllooking_msg = "still looking...";
+ 
+ static const char * found_msg = "found.\n";
+ 
+ static const char * notfound_msg = "not found (reason = %d)\n";
+ 
+ static const char * couldnot_msg = "%s: 3c505 not found\n";
+ 
+ /*********************************************************
+  *
+  *  various other debug stuff
+  *
+  *********************************************************/
+ #define ELP_DEBUG 1
+ #define ELP_NEED_HARD_RESET 0
+ 
+ #ifdef ELP_DEBUG
+ static int elp_debug = ELP_DEBUG;
+ #else
+ static int elp_debug = 0;
+ #endif
+ 
+ /*
+  *  0 = no messages (well, some)
+  *  1 = messages when high level commands performed
+  *  2 = messages when low level commands performed
+  *  3 = messages when interrupts received
+  */
+ 
+ #define	ELP_VERSION	"0.8.4"
+ 
+ /*****************************************************************
+  *
+  * useful macros
+  *
+  *****************************************************************/
+ 
+ #ifndef	TRUE
+ #define	TRUE	1
+ #endif
+ 
+ #ifndef	FALSE
+ #define	FALSE	0
+ #endif
+ 
+ 
+ /*****************************************************************
+  *
+  * List of I/O-addresses we try to auto-sense
+  * Last element MUST BE 0!
+  *****************************************************************/
+ 
+ const int addr_list[]={IO_BASE + 0x58000,0}; 
+ 
+ /*****************************************************************
+  *
+  * Functions for I/O (note the inline !)
+  *
+  *****************************************************************/
+ 
+ static inline unsigned char
+ inb_status (unsigned int base_addr)
+ {
+ 	return inb(base_addr+PORT_STATUS);
+ }
+ 
+ static inline unsigned char
+ inb_control (unsigned int base_addr)
+ {
+ 	return inb(base_addr+PORT_CONTROL);
+ }
+ 
+ static inline int
+ inb_command (unsigned int base_addr)
+ {
+ 	return inb(base_addr+PORT_COMMAND);
+ }
+ 
+ static inline void
+ outb_control (unsigned char val, unsigned int base_addr)
+ {
+ 	outb(val, base_addr+PORT_CONTROL);
+ }
+ 
+ static inline void
+ outb_command (unsigned char val, unsigned int base_addr)
+ {
+ 	outb(val, base_addr+PORT_COMMAND);
+ }
+ 
+ static inline unsigned int
+ inw_data (unsigned int base_addr)
+ {
+ 	return inw(base_addr+PORT_DATA);
+ }
+ 
+ static inline void
+ outw_data (unsigned int val, unsigned int base_addr)
+ {
+ 	outw(val, base_addr+PORT_DATA);
+ }
+ 
+ 
+ /*****************************************************************
+  *
+  *  structure to hold context information for adapter
+  *
+  *****************************************************************/
+ 
+ typedef struct {
+ 	volatile short got[NUM_TRANSMIT_CMDS];	/* flags for command completion */
+ 	pcb_struct tx_pcb;	/* PCB for foreground sending */
+ 	pcb_struct rx_pcb;	/* PCB for foreground receiving */
+ 	pcb_struct itx_pcb;	/* PCB for background sending */
+ 	pcb_struct irx_pcb;	/* PCB for background receiving */
+ 	struct enet_statistics stats;
+ } elp_device;
+ 
+ static int reset_count=0;
+ 
+ /*****************************************************************
+  *
+  *  useful functions for accessing the adapter
+  *
+  *****************************************************************/
+ 
+ /*
+  * use this routine when accessing the ASF bits as they are
+  * changed asynchronously by the adapter
+  */
+ 
+ /* get adapter PCB status */
+ #define	GET_ASF(addr) \
+ 	(get_status(addr)&ASF_PCB_MASK)
+ 
+ static inline int
+ get_status (unsigned int base_addr)
+ {
+ 	int timeout = jiffies + 10;
+ 	register int stat1;
+ 	do {
+ 		stat1 = inb_status(base_addr);
+ 	} while (stat1 != inb_status(base_addr) && jiffies < timeout);
+ 	if (jiffies >= timeout)
+ 		TIMEOUT_MSG(__LINE__);
+ 	return stat1;
+ }
+ 
+ static inline void
+ set_hsf (unsigned int base_addr, int hsf)
+ {
+ 	cli();
+ 	outb_control((inb_control(base_addr)&~HSF_PCB_MASK)|hsf, base_addr);
+ 	sti(); 
+ }
+ 
+ #define WAIT_HCRE(addr,toval) wait_hcre((addr),(toval),__LINE__)
+ static inline int
+ wait_hcre (unsigned int base_addr, int toval, int lineno)
+ {
+ 	int timeout = jiffies + toval;
+ 	while (((inb_status(base_addr)&HCRE)==0) && (jiffies <= timeout))
+ 		;
+ 	if (jiffies >= timeout) {
+ 		TIMEOUT_MSG(lineno);
+ 		return FALSE;
+ 	}
+ 	return TRUE;
+ }
+ 
+ static inline int
+ wait_fast_hcre (unsigned int base_addr, int toval, int lineno)
+ {
+ 	int timeout = 0;
+ 	while (((inb_status(base_addr)&HCRE)==0) && (timeout++ < toval))
+ 		;
+ 	if (timeout >= toval) {
+ 		sti();
+ 		TIMEOUT_MSG(lineno);
+ 		return FALSE;
+ 	}
+ 	return TRUE;
+ }
+ 
+ static int start_receive (struct device *, pcb_struct *);
+ static void adapter_hard_reset (struct device *);
+ 
+ inline static void
+ adapter_reset (struct device * dev)
+ {
+ 	int timeout;
+ 	unsigned char orig_hcr=inb_control(dev->base_addr);
+ 
+ 	elp_device * adapter=dev->priv;
+ 
+ 	outb_control(0,dev->base_addr);
+ 
+ 	if (inb_status(dev->base_addr)&ACRF) {
+ 		do {
+ 			inb_command(dev->base_addr);
+ 			timeout=jiffies+2;
+ 			while ((jiffies<=timeout) && !(inb_status(dev->base_addr)&ACRF))
+ 				;
+ 		} while (inb_status(dev->base_addr)&ACRF);
+ 		set_hsf(dev->base_addr,HSF_PCB_NAK);
+ 	}
+ 
+ 	outb_control(inb_control(dev->base_addr)|ATTN|DIR,dev->base_addr);
+ 	timeout=jiffies+1;
+ 	while (jiffies<=timeout)
+ 		;
+ 	outb_control(inb_control(dev->base_addr)&~ATTN,dev->base_addr);
+ 	timeout=jiffies+1;
+ 	while (jiffies<=timeout)
+ 		;
+ 	outb_control(inb_control(dev->base_addr)|FLSH,dev->base_addr);
+ 	timeout=jiffies+1;
+ 	while (jiffies<=timeout)
+ 		;
+ 	outb_control(inb_control(dev->base_addr)&~FLSH,dev->base_addr);
+ 	timeout=jiffies+1;
+ 	while (jiffies<=timeout)
+ 		;
+ 
+ 	outb_control(orig_hcr, dev->base_addr);
+ 	if (!start_receive(dev, &adapter->tx_pcb))
+ 		printk("%s: start receive command failed \n", dev->name);
+ }
+ 
+ /*****************************************************************
+  *
+  * send_pcb
+  *   Send a PCB to the adapter. 
+  *
+  *	output byte to command reg  --<--+
+  *	wait until HCRE is non zero      |
+  *	loop until all bytes sent   -->--+
+  *	set HSF1 and HSF2 to 1
+  *	output pcb length
+  *	wait until ASF give ACK or NAK
+  *	set HSF1 and HSF2 to 0
+  *
+  *****************************************************************/
+ 
+ static int
+ send_pcb (struct device * dev, pcb_struct * pcb)
+ {
+ 	int i;
+ 	int timeout;
+ 	int cont;
+ 
+ 	/*
+ 	 * load each byte into the command register and
+ 	 * wait for the HCRE bit to indicate the adapter
+ 	 * had read the byte
+ 	 */
+ 	set_hsf(dev->base_addr,0); 
+ 	if ((cont = WAIT_HCRE(dev->base_addr,5))) {
+ 		cli();
+ 		if (pcb->command==CMD_TRANSMIT_PACKET)
+ 			outb_control(inb_control(dev->base_addr)&~DIR,dev->base_addr);
+ 		outb_command(pcb->command, dev->base_addr);
+ 		sti();
+ 		cont = WAIT_HCRE(dev->base_addr,5);
+ 	}
+ 
+ 	if (cont) {
+ 		outb_command(pcb->length, dev->base_addr);
+ 		cont = WAIT_HCRE(dev->base_addr,5);
+ 	}
+ 
+ 	cli();
+ 	for (i = 0; cont && (i < pcb->length); i++) {
+ 		outb_command(pcb->data.raw[i], dev->base_addr);
+ 		cont = wait_fast_hcre(dev->base_addr,20000,__LINE__);
+ 	} /* if wait_fast_hcre() failed, has already done sti() */
+ 
+ 	/* set the host status bits to indicate end of PCB */
+ 	/* send the total packet length as well */
+ 	/* wait for the adapter to indicate that it has read the PCB */
+ 	if (cont) {
+ 		set_hsf(dev->base_addr,HSF_PCB_END);
+ 		outb_command(2+pcb->length, dev->base_addr);
+ 		sti();
+ 		timeout = jiffies + 7;
+ 		while (jiffies < timeout) {
+ 			i = GET_ASF(dev->base_addr);
+ 			if ((i == ASF_PCB_ACK) || (i == ASF_PCB_NAK))
+ 				break;
+ 		}
+ 
+ 		if (i == ASF_PCB_ACK) {
+ 			reset_count=0;
+ 			return TRUE;
+ 		}
+ 		else if (i == ASF_PCB_NAK) {
+ 			printk("%s: PCB send was NAKed\n", dev->name);
+ 		} else {
+ 			printk("%s: timeout after sending PCB\n", dev->name);
+ 		}
+ 	} else {
+ 		sti();
+ 		printk("%s: timeout in middle of sending PCB\n", dev->name);
+ 	}
+ 
+ 	adapter_reset(dev);
+ 	return FALSE;
+ }
+ 
+ /*****************************************************************
+  *
+  * receive_pcb
+  *   Read a PCB to the adapter
+  *
+  *	wait for ACRF to be non-zero        ---<---+
+  *	input a byte                               |
+  *	if ASF1 and ASF2 were not both one         |
+  *		before byte was read, loop      --->---+
+  *	set HSF1 and HSF2 for ack
+  *
+  *****************************************************************/
+ 
+ static int
+ receive_pcb (struct device * dev, pcb_struct * pcb)
+ {
+ 	int i, j;
+ 	int total_length;
+ 	int stat;
+ 	int timeout;
+ 
+ 	CHECK_NULL(pcb);
+ 	CHECK_NULL(dev);
+ 
+ 	set_hsf(dev->base_addr,0);
+ 
+ 	/* get the command code */
+ 	do {
+ 	  timeout = jiffies + 2;
+ 	  while (((stat = get_status(dev->base_addr))&ACRF) == 0 && jiffies < timeout)
+ 		;
+ 	  if (jiffies >= timeout) {
+ 	    TIMEOUT_MSG(__LINE__);
+ 	    return FALSE;
+ 	  }
+ 	  
+ 	  pcb->command = inb_command(dev->base_addr);
+ 	} while((pcb->command < CMD_CONFIGURE_ADAPTER_RESPONSE) ||
+ 		(pcb->command > CMD_ADAPTER_INFO_RESPONSE));
+ 
+ 	/* read the data length */
+ 
+ 	do {
+ 	  timeout = jiffies + 3;
+ 	  while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && jiffies < timeout)
+ 		;
+ 	  if (jiffies >= timeout) {
+ 	    TIMEOUT_MSG(__LINE__);
+ 	    return FALSE;
+ 	  }
+ 	  pcb->length = inb_command(dev->base_addr);
+ 	} while(pcb->length==pcb->command);
+ 
+ 	if (pcb->length > MAX_PCB_DATA) {
+ 		INVALID_PCB_MSG(pcb->length);
+ 		adapter_reset(dev);
+ 		return FALSE;
+ 	}
+ 
+ 	/* read the data */
+ 	cli();
+ 	i = 0;
+ 	do {
+ 		j = 0;
+ 		while (((stat = get_status(dev->base_addr))&ACRF) == 0 && j++ < 20000)
+ 			;
+ 		pcb->data.raw[i++] = inb_command(dev->base_addr);
+ 		if (i > MAX_PCB_DATA)
+ 			INVALID_PCB_MSG(i);
+ 	} while ((stat & ASF_PCB_MASK) != ASF_PCB_END && j < 20000);
+ 	sti();
+ 	if (j >= 20000) {
+ 		TIMEOUT_MSG(__LINE__);
+ 		return FALSE;
+ 	}
+ 
+ 	/* woops, the last "data" byte was really the length! */
+ 	total_length = pcb->data.raw[--i];
+ 
+ 	/* safety check total length vs data length */
+ 	if (total_length != (pcb->length + 2)) {
+ 		if (elp_debug >= 2)
+ 			printk("%s: mangled PCB received\n", dev->name);
+ 		set_hsf(dev->base_addr,HSF_PCB_NAK);
+ 		return FALSE;
+ 	}
+ 
+ 	set_hsf(dev->base_addr,HSF_PCB_ACK);
+ 	reset_count=0;
+ 	return TRUE;
+ }
+ 
+ static void
+ adapter_hard_reset (struct device * dev)
+ {
+ 	int timeout;
+ 	long flags;
+ 
+ 	CHECK_NULL(dev);
+ 
+ 	save_flags(flags);
+ 	sti();
+ 
+ 	if (elp_debug > 0)
+ 		printk("%s: Resetting the adapter, please wait (approx 20 s)\n",
+ 			dev->name);
+ 	/*
+ 	 * take FLSH and ATTN high
+ 	 */
+ 	outb_control(ATTN|FLSH, dev->base_addr);
+ 
+ 	/*
+ 	 * wait for a little bit
+ 	 */
+ 	for (timeout = jiffies + 20; jiffies <= timeout; )
+ 		;
+ 
+ 	/*
+ 	 * now take them low
+ 	 */
+ 	outb_control(0, dev->base_addr);
+ 
+ 	/*
+ 	 * wait for a little bit
+ 	 */
+ 	for (timeout = jiffies + 20; jiffies <= timeout; )
+ 		;
+ 
+ 	/*
+ 	 * now hang around until the board gets it's act together
+ 	 */
+ 	for (timeout = jiffies + (100 * 15); jiffies <= timeout; ) 
+ 		if (GET_ASF(dev->base_addr) != ASF_PCB_END)
+ 			break;
+ 	restore_flags(flags);
+ }
+ 
+ /******************************************************
+  *
+  *  queue a receive command on the adapter so we will get an
+  *  interrupt when a packet is received.
+  *
+  ******************************************************/
+ 
+ static int
+ start_receive (struct device * dev, pcb_struct * tx_pcb)
+ {
+ 	CHECK_NULL(dev);
+ 	CHECK_NULL(tx_pcb);
+ 
+ 	if (elp_debug >= 3)
+ 		printk("%s: restarting receiver\n", dev->name);
+ 	tx_pcb->command = CMD_RECEIVE_PACKET;
+ 	tx_pcb->length = sizeof(struct Rcv_pkt);
+ 	tx_pcb->data.rcv_pkt.buf_seg
+ 		= tx_pcb->data.rcv_pkt.buf_ofs = 0; /* Unused */
+ 	tx_pcb->data.rcv_pkt.buf_len = swapw(1600);
+ 	tx_pcb->data.rcv_pkt.timeout = 0;	/* set timeout to zero */
+ 	return send_pcb(dev, tx_pcb); 
+ }
+ 
+ /******************************************************
+  *
+  * extract a packet from the adapter
+  * this routine is only called from within the interrupt
+  * service routine, so no cli/sti calls are needed
+  * note that the length is always assumed to be even
+  *
+  ******************************************************/
+ 
+ static void
+ receive_packet (struct device * dev, int len)
+ {
+ 	register int i;
+ 	unsigned short * ptr;
+ 	int timeout;
+ 	int rlen;
+ 	struct sk_buff *skb;
+ 	elp_device * adapter;
+ 
+ 	CHECK_NULL(dev);
+ 	adapter=dev->priv;
+ 
+ 	if (len <= 0 || ((len & ~1) != len))
+ 		if (elp_debug >= 3) {
+ 			sti();
+ 			printk("*** bad packet len %d at %s(%d)\n",len,filename,__LINE__);
+ 			cli();
+ 		}
+ 
+ 	rlen = (len+1) & ~1;
+ 
+ 	skb = dev_alloc_skb(rlen+2);
+ 
+ 	/*
+ 	 * make sure the data register is going the right way
+ 	 */
+ 
+ 	outb_control(inb_control(dev->base_addr)|DIR, dev->base_addr);
+ 
+ 	/*
+ 	 * if buffer could not be allocated, swallow it
+ 	 */
+ 	if (skb == NULL) {
+ 		for (i = 0; i < (rlen/2); i++) {
+ 			timeout = 0;
+ 			while ((inb_status(dev->base_addr)&HRDY) == 0 && timeout++ < 20000)
+ 				;
+ 			if (timeout >= 20000) {
+ 				sti();
+ 				TIMEOUT_MSG(__LINE__);
+ 				break;
+ 			}
+ 
+ 			inw_data(dev->base_addr);
+ 		}
+ 		adapter->stats.rx_dropped++;
+ 
+ 	} else {
+ 		skb_reserve(skb,2);	/* 16 byte alignment */
+ 		skb->dev = dev;
+ 
+ 		/*
+ 		 * now read the data from the adapter
+ 		 */
+ 		ptr = (unsigned short *)skb_put(skb,len);
+ 		for (i = 0; i < (rlen/2); i++) { 
+ 			timeout = 0;
+ 			while ((inb_status(dev->base_addr)&HRDY) == 0 && timeout++ < 20000) 
+ 				;
+ 			if (timeout >= 20000) {
+ 				sti();
+ 				printk("*** timeout at %s(%d) reading word %d of %d ***\n",
+ 					filename,__LINE__, i, rlen/2);	
+ 				kfree_skb(skb, FREE_WRITE);
+ 				return;
+ 			}
+ 
+ 			*ptr = inw_data(dev->base_addr); 
+ 			ptr++; 
+ 		}
+ 
+ 		sti();
+ 		skb->protocol=eth_type_trans(skb,dev);
+ 		netif_rx(skb);
+ 	}
+ 
+ 	outb_control(inb_control(dev->base_addr)&~DIR, dev->base_addr);
+ }
+ 
+ 
+ /******************************************************
+  *
+  * interrupt handler
+  *
+  ******************************************************/
+ 
+ static void
+ elp_interrupt (int irq, void *data, struct pt_regs *reg_ptr)
+ {
+ 	int len;
+ 	int dlen;
+ 	struct device *dev;
+ 	elp_device * adapter;
+ 	int timeout;
+ 
+ 	irq-=160;
+ 	if (irq < 0 || irq > 15) {
+ 		printk ("elp_interrupt(): illegal IRQ number found in interrupt routine (%i)\n", irq);
+ 		return;
+ 	}
+ 
+ 	dev = irq2dev_map[irq];
+ 
+ 	if (dev == NULL) {
+ 		printk ("elp_interrupt(): irq %d for unknown device.\n", irq);
+ 		return;
+ 	}
+ 
+ 	adapter = (elp_device *) dev->priv;
+ 
+ 	CHECK_NULL(adapter);
+ 
+ 	if (dev->interrupt)
+ 		if (elp_debug >= 2)
+ 			printk("%s: Re-entering the interrupt handler.\n", dev->name);
+ 	dev->interrupt = 1;
+ 
+ 	/*
+ 	 * allow interrupts (we need timers!)
+ 	 */
+ 	sti();
+ 
+ 	/*
+ 	 * receive a PCB from the adapter
+ 	 */
+ 	timeout = jiffies + 3;
+ 	while ((inb_status(dev->base_addr)&ACRF) != 0 && jiffies < timeout) {
+ 
+ 		if (receive_pcb(dev, &adapter->irx_pcb)) {
+ 
+ 			switch (adapter->irx_pcb.command) {
+ 
+ 				/*
+ 				 * received a packet - this must be handled fast
+ 				 */
+ 				case CMD_RECEIVE_PACKET_COMPLETE:
+ 					/* if the device isn't open, don't pass packets up the stack */
+ 					if (dev->start == 0)
+ 						break;
+ 					cli();
+ 					/* Set direction of adapter FIFO */
+ 					outb_control(inb_control(dev->base_addr)|DIR,
+ 					             dev->base_addr);
+ 					len = adapter->irx_pcb.data.rcv_resp.pkt_len;
+ 					len=swapw(len);
+ 
+ 					dlen = adapter->irx_pcb.data.rcv_resp.buf_len;
+ 					dlen=swapw(dlen);
+ 					if (adapter->irx_pcb.data.rcv_resp.timeout != 0) {
+ 						printk("%s: interrupt - packet not received correctly\n", dev->name);
+ 						sti();
+ 					} else {
+ 						if (elp_debug >= 3) {
+ 							sti();
+ 							printk("%s: interrupt - packet received of length %i (%i)\n", dev->name, len, dlen);
+ 							cli();
+ 						}
+ 						receive_packet(dev, dlen);
+ 						sti();
+ 						if (elp_debug >= 3)
+ 							printk("%s: packet received\n", dev->name);
+ 					}
+ 					if (dev->start && !start_receive(dev, &adapter->itx_pcb)) 
+ 						if (elp_debug >= 2)
+ 							printk("%s: interrupt - failed to send receive start PCB\n", dev->name);
+ 					if (elp_debug >= 3)
+ 					printk("%s: receive procedure complete\n", dev->name);
+ 
+ 					break;
+ 
+ 				/*
+ 				 * 82586 configured correctly
+ 				 */
+ 				case CMD_CONFIGURE_82586_RESPONSE:
+ 					adapter->got[CMD_CONFIGURE_82586] = 1;
+ 					printk("configure_82586_response: %02x\n",adapter->irx_pcb.data.configure );
+ 					if (elp_debug >= 3)
+ 						printk("%s: interrupt - configure response received\n", dev->name);
+ 					break;
+ 
+ 				/*
+ 				 * Adapter memory configuration
+ 				 */
+ 				case CMD_CONFIGURE_ADAPTER_RESPONSE:
+ 					adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 1;
+ 					if (elp_debug >= 3)
+ 						printk("%s: Adapter memory configuration %s.\n",dev->name,
+ 							adapter->irx_pcb.data.failed?"failed":"succeeded");
+ 					break;
+ 
+ 				/*
+ 				 * Multicast list loading
+ 				 */
+ 				case CMD_LOAD_MULTICAST_RESPONSE:
+ 					adapter->got[CMD_LOAD_MULTICAST_LIST] = 1;
+ 					if (elp_debug >= 3)
+ 						printk("%s: Multicast address list loading %s.\n",dev->name,
+ 							adapter->irx_pcb.data.failed?"failed":"succeeded");
+ 					break;
+ 
+ 				/*
+ 				 * Station address setting
+ 				 */
+ 				case CMD_SET_ADDRESS_RESPONSE:
+ 					adapter->got[CMD_SET_STATION_ADDRESS] = 1;
+ 					if (elp_debug >= 3)
+ 						printk("%s: Ethernet address setting %s.\n",dev->name,
+ 							adapter->irx_pcb.data.failed?"failed":"succeeded");
+ 					break;
+ 
+ 
+ 				/*
+ 				 * received board statistics
+ 				 */
+ 				case CMD_NETWORK_STATISTICS_RESPONSE:
+ 					adapter->stats.rx_packets += swapd(adapter->irx_pcb.data.netstat.tot_recv);
+ 					adapter->stats.tx_packets += swapd(adapter->irx_pcb.data.netstat.tot_xmit);
+ 					adapter->stats.rx_crc_errors += swapw(adapter->irx_pcb.data.netstat.err_CRC);
+ 					adapter->stats.rx_frame_errors += swapw(adapter->irx_pcb.data.netstat.err_align);
+ 					adapter->stats.rx_fifo_errors += swapw(adapter->irx_pcb.data.netstat.err_ovrrun);
+ 					adapter->got[CMD_NETWORK_STATISTICS] = 1;
+ 					if (elp_debug >= 3)
+ 						printk("%s: interrupt - statistics response received\n", dev->name);
+ 					break;
+ 
+ 				/*
+ 				 * sent a packet
+ 				 */
+ 				case CMD_TRANSMIT_PACKET_COMPLETE:
+ 					if (elp_debug >= 3) 
+ 					printk("%s: interrupt - packet sent\n", dev->name);
+ 					if (dev->start == 0)
+ 						break;
+ 					if (adapter->irx_pcb.data.xmit_resp.c_stat != 0)
+ 						if (elp_debug >= 2)
+ 							printk("%s: interrupt - error sending packet %4.4x\n",
+ 								dev->name, adapter->irx_pcb.data.xmit_resp.c_stat);
+ 					dev->tbusy = 0;
+ 					mark_bh(NET_BH);
+ 					break;
+ 
+ 				/*
+ 				 * some unknown PCB
+ 				 */
+ 				default:
+ 					printk("%s: unknown PCB received - %2.2x\n", dev->name, adapter->irx_pcb.command);
+ 					break;
+ 			}
+ 		} else {
+ 			printk("%s: failed to read PCB on interrupt\n", dev->name);
+ 			adapter_reset(dev);
+ 		}
+ 	}
+ 
+ 	/*
+ 	 * indicate no longer in interrupt routine
+ 	 */
+ 	dev->interrupt = 0;
+ }
+ 
+ 
+ /******************************************************
+  *
+  * open the board
+  *
+  ******************************************************/
+ 
+ static int
+ elp_open (struct device *dev)
+ {
+ 	elp_device * adapter;
+ 
+ 	CHECK_NULL(dev);
+ 
+ 	adapter = dev->priv;
+ 
+ 	if (elp_debug >= 3)  
+ 		printk("%s: request to open device\n", dev->name);
+ 
+ 	/*
+ 	 * make sure we actually found the device
+ 	 */
+ 	if (adapter == NULL) {
+ 		printk("%s: Opening a non-existent physical device\n", dev->name);
+ 		return -EAGAIN;
+ 	}
+ 
+ 	/*
+ 	 * disable interrupts on the board
+ 	 */
+ 	outb_control(0x00, dev->base_addr);
+ 
+ 	/*
+ 	 * clear any pending interrupts
+ 	 */
+ 	inb_command(dev->base_addr);
+ 	adapter_reset(dev);
+ 
+ 	/*
+ 	 * interrupt routine not entered
+ 	 */
+ 	dev->interrupt = 0;
+ 
+ 	/*
+ 	 *  transmitter not busy 
+ 	 */
+ 	dev->tbusy = 0;
+ 
+ 	/*
+ 	 * make sure we can find the device header given the interrupt number
+ 	 */
+ 	irq2dev_map[dev->irq] = dev;
+ 
+ 	/*
+ 	 * install our interrupt service routine
+ 	 */
+ 	if (request_irq(dev->irq, elp_interrupt, 0, "3c505",NULL)) {
+ 		irq2dev_map[dev->irq] = NULL;
+ 		return -EAGAIN;
+ 	}
+ 
+ 	/*
+ 	 * enable interrupts on the board
+ 	 */
+ 	outb_control(CMDE, dev->base_addr);
+ 
+ 	/*
+ 	 * device is now officially open!
+ 	 */
+ 	dev->start = 1;
+ 
+ 	/*
+ 	 * configure adapter memory: we need 10 multicast addresses, default==0
+ 	 */
+ 	if (elp_debug >= 3)
+ 		printk("%s: sending 3c505 memory configuration command\n", dev->name);
+ 	adapter->tx_pcb.command = CMD_CONFIGURE_ADAPTER_MEMORY;
+ 	adapter->tx_pcb.data.memconf.cmd_q = swapw(10);
+ 	adapter->tx_pcb.data.memconf.rcv_q = swapw(20);
+ 	adapter->tx_pcb.data.memconf.mcast = swapw(10);
+ 	adapter->tx_pcb.data.memconf.frame = swapw(20);
+ 	adapter->tx_pcb.data.memconf.rcv_b = swapw(20);
+ 	adapter->tx_pcb.data.memconf.progs = swapw(0);
+ 	adapter->tx_pcb.length = sizeof(struct Memconf);
+ 	adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 0;
+ 	if (!send_pcb(dev, &adapter->tx_pcb))
+ 		printk("%s: couldn't send memory configuration command\n", dev->name);
+ 	else {
+ 		int timeout = jiffies + TIMEOUT;
+ 		while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && jiffies < timeout)
+ 			;
+ 		if (jiffies >= timeout)
+ 			TIMEOUT_MSG(__LINE__);
+ 	}
+ 
+ 
+ 	/*
+ 	 * configure adapter to receive broadcast messages and wait for response
+ 	 */
+ 	if (elp_debug >= 3)
+ 		printk("%s: sending 82586 configure command\n", dev->name);
+ 	adapter->tx_pcb.command = CMD_CONFIGURE_82586;
+ 	adapter->tx_pcb.data.configure = swapw(NO_LOOPBACK | RECV_BROAD);
+ printk("adapter->tx_pcb.data.configure: %04x\n",adapter->tx_pcb.data.configure);
+ 	adapter->tx_pcb.length  = 2;
+ 	adapter->got[CMD_CONFIGURE_82586] = 0;
+ 	if (!send_pcb(dev, &adapter->tx_pcb))
+ 		printk("%s: couldn't send 82586 configure command\n", dev->name);
+ 	else {
+ 		int timeout = jiffies + TIMEOUT;
+ 		while (adapter->got[CMD_CONFIGURE_82586] == 0 && jiffies < timeout)
+ 			;
+ 		if (jiffies >= timeout)
+ 			TIMEOUT_MSG(__LINE__);
+ 	}
+ 
+ 	/*
+ 	 * queue receive commands to provide buffering
+ 	 */
+ 	if (!start_receive(dev, &adapter->tx_pcb))
+ 		printk("%s: start receive command failed \n", dev->name);
+ 	if (elp_debug >= 3)
+ 		printk("%s: start receive command sent\n", dev->name);
+ 
+ 	MOD_INC_USE_COUNT;
+ 
+ 	return 0;			/* Always succeed */
+ }
+ 
+ 
+ /******************************************************
+  *
+  * send a packet to the adapter
+  *
+  ******************************************************/
+ 
+ static int
+ send_packet (struct device * dev, unsigned char * ptr, int len)
+ {
+ 	int i;
+ 	int timeout = 0;
+ 	elp_device * adapter;
+ 
+ 	/*
+ 	 * make sure the length is even and no shorter than 60 bytes
+ 	 */
+ 	unsigned int nlen = (((len < 60) ? 60 : len) + 1) & (~1);
+ 
+ 	CHECK_NULL(dev);
+ 	CHECK_NULL(ptr);
+ 
+ 	adapter = dev->priv;
+ 
+ 	if (nlen < len)
+ 		printk("Warning, bad length nlen=%d len=%d %s(%d)\n",nlen,len,filename,__LINE__);
+ 
+ 	/*
+ 	 * send the adapter a transmit packet command. Ignore segment and offset
+ 	 * and make sure the length is even
+ 	 */
+ 	adapter->tx_pcb.command = CMD_TRANSMIT_PACKET;
+ 	adapter->tx_pcb.length = sizeof(struct Xmit_pkt);
+ 	adapter->tx_pcb.data.xmit_pkt.buf_ofs
+ 		= adapter->tx_pcb.data.xmit_pkt.buf_seg = 0; /* Unused */
+ 	adapter->tx_pcb.data.xmit_pkt.pkt_len = swapw(nlen);
+ 	if (!send_pcb(dev, &adapter->tx_pcb)) {
+ 		return FALSE;
+ 	}
+ 
+ 	/*
+ 	 * write data to the adapter
+ 	 */
+ 	cli();
+ 	for (i = 0; i < (nlen/2);i++) {
+ 		while (((inb_status(dev->base_addr)&HRDY) == 0)
+ 		       && (timeout++ < 20000))
+ 			;
+ 		if (timeout >= 20000) {
+ 			sti();
+ 			printk("%s: timeout at %s(%d) writing word %d of %d ***\n",
+ 				dev->name,filename,__LINE__, i, nlen/2);
+ 			return FALSE;
+ 		}
+ 
+ 		outw_data(*(short *)ptr, dev->base_addr);
+ 		ptr +=2;
+ 	}
+ 	sti();
+ 
+ 	return TRUE;
+ }
+ 
+ /******************************************************
+  *
+  * start the transmitter
+  *    return 0 if sent OK, else return 1
+  *
+  ******************************************************/
+ 
+ static int
+ elp_start_xmit (struct sk_buff *skb, struct device *dev)
+ {
+ 	CHECK_NULL(dev);
+ 
+ 	/*
+ 	 * not sure what this does, but the 3c509 driver does it, so...
+ 	 */
+ 	if (skb == NULL) {
+ 		dev_tint(dev);
+ 		return 0;
+ 	}
+ 
+ 	/*
+ 	 * if we ended up with a munged length, don't send it
+ 	 */
+ 	if (skb->len <= 0)
+ 		return 0;
+ 
+ 	if (elp_debug >= 3)
+ 		printk("%s: request to send packet of length %d\n", dev->name, (int)skb->len);
+ 
+ 	/*
+ 	 * if the transmitter is still busy, we have a transmit timeout...
+ 	 */
+ 	if (dev->tbusy) {
+ 		int tickssofar = jiffies - dev->trans_start;
+ 		int stat;
+ 		if (tickssofar < 50) /* was 500, AJT */
+ 			return 1;
+ 		printk("%s: transmit timed out, not resetting adapter\n", dev->name);
+ 		if (((stat=inb_status(dev->base_addr))&ACRF) != 0) 
+ 			printk("%s: hmmm...seemed to have missed an interrupt!\n", dev->name);
+ 		printk("%s: status %#02x\n", dev->name, stat);
+ 		dev->trans_start = jiffies;
+ 		dev->tbusy = 0;
+ 	}
+ 
+ 	/*
+ 	 * send the packet at skb->data for skb->len
+ 	 */
+ 	if (!send_packet(dev, skb->data, skb->len)) {
+ 		printk("%s: send packet PCB failed\n", dev->name);
+ 		return 1;
+ 	}
+ 
+ 	if (elp_debug >= 3)
+ 		printk("%s: packet of length %d sent\n", dev->name, (int)skb->len);
+ 
+ 
+ 	/*
+ 	 * start the transmit timeout
+ 	 */
+ 	dev->trans_start = jiffies;
+ 
+ 	/*
+ 	 * the transmitter is now busy
+ 	 */
+ 	dev->tbusy = 1;
+ 
+ 	/*
+ 	 * free the buffer
+ 	 */
+ 	dev_kfree_skb(skb, FREE_WRITE);
+ 
+ 	return 0;
+ }
+ 
+ /******************************************************
+  *
+  * return statistics on the board
+  *
+  ******************************************************/
+ 
+ static struct enet_statistics *
+ elp_get_stats (struct device *dev)
+ {
+ 	elp_device *adapter = (elp_device *) dev->priv;
+ 
+ 	if (elp_debug >= 3)
+ 		printk("%s: request for stats\n", dev->name);
+ 
+ 	/* If the device is closed, just return the latest stats we have,
+ 	   - we cannot ask from the adapter without interrupts */
+ 	if (!dev->start)
+ 		return &adapter->stats;
+ 
+ 	/* send a get statistics command to the board */
+ 	adapter->tx_pcb.command = CMD_NETWORK_STATISTICS;
+ 	adapter->tx_pcb.length  = 0;
+ 	adapter->got[CMD_NETWORK_STATISTICS] = 0;
+ 	if (!send_pcb(dev, &adapter->tx_pcb))
+ 		printk("%s: couldn't send get statistics command\n", dev->name);
+ 	else {
+ 		int timeout = jiffies + TIMEOUT;
+ 		while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && jiffies < timeout)
+ 			;
+ 		if (jiffies >= timeout) {
+ 			TIMEOUT_MSG(__LINE__);
+ 			return &adapter->stats;
+ 		}
+ 	}
+ 
+ 	/* statistics are now up to date */
+ 	return &adapter->stats;
+ }
+ 
+ /******************************************************
+  *
+  * close the board
+  *
+  ******************************************************/
+ 
+ static int
+ elp_close (struct device *dev)
+ {
+ 	elp_device * adapter;
+ 
+ 	CHECK_NULL(dev);
+ 	adapter = dev->priv;
+ 	CHECK_NULL(adapter);
+ 
+ 	if (elp_debug >= 3)
+ 		printk("%s: request to close device\n", dev->name);
+ 
+ 	/* Someone may request the device statistic information even when
+ 	 * the interface is closed. The following will update the statistics
+ 	 * structure in the driver, so we'll be able to give current statistics.
+ 	 */
+ 	(void) elp_get_stats(dev);
+ 
+ 	/*
+ 	 * disable interrupts on the board
+ 	 */
+ 	outb_control(0x00, dev->base_addr);
+ 
+ 	/*
+ 	 *  flag transmitter as busy (i.e. not available)
+ 	 */
+ 	dev->tbusy = 1;
+ 
+ 	/*
+ 	 *  indicate device is closed
+ 	 */
+ 	dev->start = 0;
+ 
+ 	/*
+ 	 * release the IRQ
+ 	 */
+ 	free_irq(dev->irq,NULL);
+ 
+ 	/*
+ 	 * and we no longer have to map irq to dev either
+ 	 */
+ 	irq2dev_map[dev->irq] = 0;
+ 
+ 	MOD_DEC_USE_COUNT;
+ 
+ 	return 0;
+ }
+ 
+ 
+ /************************************************************
+  *
+  * Set multicast list
+  * num_addrs==0: clear mc_list
+  * num_addrs==-1: set promiscuous mode
+  * num_addrs>0: set mc_list
+  *
+  ************************************************************/
+ 
+ static void
+ elp_set_mc_list (struct device *dev)
+ {
+ 	elp_device *adapter = (elp_device *) dev->priv;
+ 	struct dev_mc_list *dmi=dev->mc_list;
+ 	int i;
+ 
+ 	if (elp_debug >= 3)
+ 		printk("%s: request to set multicast list\n", dev->name);
+ 
+ 	if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI)))
+ 	{
+ 		/* send a "load multicast list" command to the board, max 10 addrs/cmd */
+ 		/* if num_addrs==0 the list will be cleared */
+ 		adapter->tx_pcb.command = CMD_LOAD_MULTICAST_LIST;
+ 		adapter->tx_pcb.length  = swapw(6*dev->mc_count);
+ 		for (i=0;i<dev->mc_count;i++)
+ 		{
+ 			memcpy(adapter->tx_pcb.data.multicast[i], dmi->dmi_addr,6);
+ 			dmi=dmi->next;
+ 		}
+ 		adapter->got[CMD_LOAD_MULTICAST_LIST] = 0;
+ 		if (!send_pcb(dev, &adapter->tx_pcb))
+ 			printk("%s: couldn't send set_multicast command\n", dev->name);
+ 		else {
+ 			int timeout = jiffies + TIMEOUT;
+ 			while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && jiffies < timeout)
+ 				;
+ 			if (jiffies >= timeout) {
+ 				TIMEOUT_MSG(__LINE__);
+ 			}
+ 		}
+ 		if (dev->mc_count)
+ 			adapter->tx_pcb.data.configure = swapw(NO_LOOPBACK | RECV_BROAD | RECV_MULTI);
+ 		else /* num_addrs == 0 */
+ 			adapter->tx_pcb.data.configure = swapw(NO_LOOPBACK | RECV_BROAD);
+ 	} 
+ 	else
+ 		adapter->tx_pcb.data.configure = swapw(NO_LOOPBACK | RECV_PROMISC);
+ 	/*
+ 	 * configure adapter to receive messages (as specified above)
+ 	 * and wait for response
+ 	 */
+ 	if (elp_debug >= 3)
+ 		printk("%s: sending 82586 configure command\n", dev->name);
+ 	adapter->tx_pcb.command = CMD_CONFIGURE_82586;
+ 	adapter->tx_pcb.length  = 2;
+ 	adapter->got[CMD_CONFIGURE_82586]  = 0;
+ 	if (!send_pcb(dev, &adapter->tx_pcb))
+ 		printk("%s: couldn't send 82586 configure command\n", dev->name);
+ 	else {
+ 		int timeout = jiffies + TIMEOUT;
+ 		while (adapter->got[CMD_CONFIGURE_82586] == 0 && jiffies < timeout)
+ 			;
+ 		if (jiffies >= timeout)
+ 			TIMEOUT_MSG(__LINE__);
+ 	}
+ }
+ 
+ /******************************************************
+  *
+  * initialise Etherlink Plus board
+  *
+  ******************************************************/
+ 
+ static void
+ elp_init (struct device *dev)
+ {
+ 	elp_device * adapter;
+ 
+ 	CHECK_NULL(dev);
+ 
+ 	/*
+ 	 * set ptrs to various functions
+ 	 */
+ 	dev->open = elp_open;	/* local */
+ 	dev->stop = elp_close;	/* local */
+ 	dev->get_stats = elp_get_stats;	/* local */
+ 	dev->hard_start_xmit = elp_start_xmit;	/* local */
+ 	dev->set_multicast_list = elp_set_mc_list;	/* local */
+ 
+ 	/* Setup the generic properties */
+ 	ether_setup(dev);
+ 
+ 	/*
+ 	 * setup ptr to adapter specific information
+ 	 */
+ 	adapter = (elp_device *)(dev->priv = kmalloc(sizeof(elp_device), GFP_KERNEL));
+ 	CHECK_NULL(adapter);
+ 	if (adapter == NULL)
+ 		return;
+ 	memset(&(adapter->stats), 0, sizeof(struct enet_statistics));
+ 
+ 	/*
+ 	 * memory information
+ 	 */
+ 	dev->mem_start = dev->mem_end = dev->rmem_end = dev->rmem_start = 0;
+ }
+ 
+ /************************************************************
+  *
+  * A couple of tests to see if there's 3C505 or not
+  * Called only by elp_autodetect
+  ************************************************************/
+ 
+ static int
+ elp_sense (struct device * dev)
+ {
+ 	int timeout;
+ 	int addr=dev->base_addr;
+ 	const char *name=dev->name;
+ 	long flags;
+ 	byte orig_HCR, orig_HSR;
+ 
+ #if 0
+ 	if (check_region(addr, 0xf)) 
+ 	  return -1;  
+ #endif
+ 
+ 	orig_HCR=inb_control(addr);
+ 	orig_HSR=inb_status(addr);
+ 
+ 	if (elp_debug > 0)
+ 		printk(search_msg, name, addr);
+ 
+ 	if (((orig_HCR==0xff) && (orig_HSR==0xff)) ||
+ 	    ((orig_HCR & DIR) != (orig_HSR & DIR))) {
+ 		if (elp_debug > 0)
+ 			printk(notfound_msg, 1);
+ 		return -1; /* It can't be 3c505 if HCR.DIR != HSR.DIR */
+ 	}
+ 
+ 	/* Enable interrupts - we need timers! */
+ 	save_flags(flags);
+ 	sti();
+ 
+ 	/* Wait for a while; the adapter may still be booting up */
+ 	if (elp_debug > 0)
+ 		printk(stilllooking_msg);
+ 	for (timeout = jiffies + (100 * 15); jiffies <= timeout; ) 
+ 		if (GET_ASF(addr) != ASF_PCB_END)
+ 			break;
+ 
+ 	if (orig_HCR & DIR) {
+ 		/* If HCR.DIR is up, we pull it down. HSR.DIR should follow. */
+ 		outb_control(orig_HCR & ~DIR,addr);
+ 		timeout = jiffies+30;
+ 		while (jiffies < timeout)
+ 			;
+ 		restore_flags(flags);
+ 		if (inb_status(addr) & DIR) {
+ 			outb_control(orig_HCR,addr);
+ 			if (elp_debug > 0)
+ 				printk(notfound_msg, 2);
+ 			return -1;
+ 		}
+ 	} else {
+ 		/* If HCR.DIR is down, we pull it up. HSR.DIR should follow. */
+ 		outb_control(orig_HCR | DIR,addr);
+ 		timeout = jiffies+300;
+ 		while (jiffies < timeout)
+ 			;
+ 		restore_flags(flags);
+ 		if (!(inb_status(addr) & DIR)) {
+ 			outb_control(orig_HCR,addr);
+ 			if (elp_debug > 0)
+ 				printk(notfound_msg, 3);
+ 			return -1;
+ 		}
+ 	}
+ 	/*
+ 	 * It certainly looks like a 3c505. If it has DMA enabled, it needs
+ 	 * a hard reset. Also, do a hard reset if selected at the compile time.
+ 	 */
+ 	if (elp_debug > 0)
+ 			printk(found_msg);
+ 
+ 	if (((orig_HCR==0x35) && (orig_HSR==0x5b)) || ELP_NEED_HARD_RESET)
+ 		adapter_hard_reset(dev);
+ 	return 0;
+ }
+ 
+ /*************************************************************
+  *
+  * Search through addr_list[] and try to find a 3C505
+  * Called only by eplus_probe
+  *************************************************************/
+ 
+ static int
+ elp_autodetect (struct device * dev)
+ {
+ 	int idx=0;
+ 
+ 	/* if base address set, then only check that address
+ 	otherwise, run through the table */
+ 	if (dev->base_addr != 0) { /* dev->base_addr == 0 ==> plain autodetect */
+ 		if (elp_sense(dev) == 0)
+ 			return dev->base_addr;
+ 	} else while ( (dev->base_addr=addr_list[idx++]) ) {
+ 		if (elp_sense(dev) == 0)
+ 			return dev->base_addr;
+ 	}
+ 
+ 	/* could not find an adapter */
+ 	if (elp_debug > 0)
+ 		printk(couldnot_msg, dev->name);
+ 
+ 	return 0; /* Because of this, the layer above will return -ENODEV */
+ }
+ 
+ /******************************************************
+  *
+  * probe for an Etherlink Plus board at the specified address
+  *
+  ******************************************************/
+ 
+ int
+ elplus_probe (struct device *dev)
+ {
+ 	elp_device adapter;
+ 	int i;
+ 
+ 	CHECK_NULL(dev);
+ 
+ 	/*
+ 	 *  setup adapter structure
+ 	 */
+ 
+ 	dev->base_addr = elp_autodetect(dev);
+ 	if ( !(dev->base_addr) )
+ 		return -ENODEV;
+ 
+ 	/*
+ 	 *  As we enter here from bootup, the adapter should have IRQs enabled,
+ 	 *  but we can as well enable them anyway.
+ 	 */
+ 	outb_control(inb_control(dev->base_addr) | CMDE, dev->base_addr);
+ #if 0
+ 	autoirq_setup(0);
+ #endif
+ 
+ 	/*
+ 	 * use ethernet address command to probe for board in polled mode
+ 	 * (this also makes us the IRQ that we need for automatic detection)
+ 	 */
+ 	adapter.tx_pcb.command = CMD_STATION_ADDRESS;
+ 	adapter.tx_pcb.length  = 0;
+ 	if (!send_pcb   (dev, &adapter.tx_pcb) ||
+ 	    !receive_pcb(dev, &adapter.rx_pcb) ||
+ 	    (adapter.rx_pcb.command != CMD_ADDRESS_RESPONSE) ||
+ 	    (adapter.rx_pcb.length != 6)) {
+ 		printk("%s: not responding to first PCB\n", dev->name);
+ 		return -ENODEV;
+ 	}
+ 
+ 	dev->irq=10;
+ 
+ #if 0
+ 	if (dev->irq) { /* Is there a preset IRQ? */
+ 		if (dev->irq != autoirq_report(0)) {
+ 			printk("%s: Detected IRQ doesn't match user-defined one.\n",dev->name);
+ 			return -ENODEV;
+ 		}
+ 		/* if dev->irq == autoirq_report(0), all is well */
+ 	} else /* No preset IRQ; just use what we can detect */
+ 		dev->irq=autoirq_report(0);
+ #endif
+ 	switch (dev->irq) { /* Legal, sane? */
+ 		case 0:
+ 			printk("%s: No IRQ reported by autoirq_report().\n",dev->name);
+ 			printk("%s: Check the jumpers of your 3c505 board.\n",dev->name);
+ 			return -ENODEV;
+ 		case 1:
+ 		case 6:
+ 		case 8:
+ 		case 13: 
+ 			printk("%s: Impossible IRQ %d reported by autoirq_report().\n",
+ 			       dev->name, dev->irq);
+ 			return -ENODEV;
+ 	}
+ 	/*
+ 	 *  Now we have the IRQ number so we can disable the interrupts from
+ 	 *  the board until the board is opened.
+ 	 */
+ 	outb_control(inb_control(dev->base_addr) & ~CMDE, dev->base_addr);
+ 
+ 	/*
+ 	 * copy ethernet address into structure
+ 	 */
+ 	for (i = 0; i < 6; i++) 
+ 		dev->dev_addr[i] = adapter.rx_pcb.data.eth_addr[i];
+ 
+ 	/*
+ 	 * print remainder of startup message
+ 	 */
+ 	printk("%s: 3c505 card found at I/O %#lx using IRQ%d"
+ 	       " has address %02x:%02x:%02x:%02x:%02x:%02x\n",
+ 	       dev->name, dev->base_addr, dev->irq,
+ 	       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ 	       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+ 
+ 	/*
+ 	 * and reserve the address region
+ 	 */
+ 	request_region(dev->base_addr, ELP_IO_EXTENT, "3c505");
+ 
+ 	/*
+ 	 * initialise the device
+ 	 */
+ 	elp_init(dev);
+ 	return 0;
+ }
+ 
+ #ifdef MODULE
+ static char devicename[9] = { 0, };
+ static struct device dev_3c505 = {
+ 	devicename, /* device name is inserted by linux/drivers/net/net_init.c */
+ 	0, 0, 0, 0,
+ 	0, 0,
+ 	0, 0, 0, NULL, elplus_probe };
+ 
+ int io = 0x300;
+ int irq = 0;
+ 
+ int init_module(void)
+ {
+ 	if (io == 0)
+ 		printk("3c505: You should not use auto-probing with insmod!\n");
+ 	dev_3c505.base_addr = io;
+ 	dev_3c505.irq       = irq;
+ 	if (register_netdev(&dev_3c505) != 0) {
+ 		printk("3c505: register_netdev() returned non-zero.\n");
+ 		return -EIO;
+ 	}
+ 	return 0;
+ }
+ 
+ void
+ cleanup_module(void)
+ {
+ 	unregister_netdev(&dev_3c505);
+ 	kfree(dev_3c505.priv);
+ 	dev_3c505.priv = NULL;
+ 
+ 	/* If we don't do this, we can't re-insmod it later. */
+ 	release_region(dev_3c505.base_addr, ELP_IO_EXTENT);
+ }
+ #endif /* MODULE */
diff -c -r -N ../linux-2.1.55/drivers/net/3c505_pio_apollo.h linux-apollo-dev/drivers/net/3c505_pio_apollo.h
*** ../linux-2.1.55/drivers/net/3c505_pio_apollo.h	Thu Jan  1 01:00:00 1970
--- linux-apollo-dev/drivers/net/3c505_pio_apollo.h	Mon Sep  1 19:26:35 1997
***************
*** 0 ****
--- 1,245 ----
+ /*****************************************************************
+  *
+  *  defines for 3Com Etherlink Plus adapter
+  *
+  *****************************************************************/
+ 
+ /*
+  * I/O register offsets
+  */
+ #define	PORT_COMMAND	0x00	/* read/write, 8-bit */
+ #define	PORT_STATUS	0x02	/* read only, 8-bit */
+ #define	PORT_AUXDMA	0x02	/* write only, 8-bit */
+ #define	PORT_DATA	0x04	/* read/write, 16-bit */
+ #define	PORT_CONTROL	0x06	/* read/write, 8-bit */
+ 
+ #define ELP_IO_EXTENT	0x10	/* size of used IO registers */
+ 
+ /*
+  * host control registers bits
+  */
+ #define	ATTN	0x80	/* attention */
+ #define	FLSH	0x40	/* flush data register */
+ #define DMAE	0x20	/* DMA enable */
+ #define DIR	0x10	/* direction */
+ #define	TCEN	0x08	/* terminal count interrupt enable */
+ #define	CMDE	0x04	/* command register interrupt enable */
+ #define	HSF2	0x02	/* host status flag 2 */
+ #define	HSF1	0x01	/* host status flag 1 */
+ 
+ /*
+  * combinations of HSF flags used for PCB transmission
+  */
+ #define	HSF_PCB_ACK	HSF1
+ #define	HSF_PCB_NAK	HSF2
+ #define	HSF_PCB_END	(HSF2|HSF1)
+ #define	HSF_PCB_MASK	(HSF2|HSF1)
+ 
+ /*
+  * host status register bits
+  */
+ #define	HRDY	0x80	/* data register ready */
+ #define	HCRE	0x40	/* command register empty */
+ #define	ACRF	0x20	/* adapter command register full */
+ /* #define DIR 	0x10	direction - same as in control register */
+ #define	DONE	0x08	/* DMA done */
+ #define	ASF3	0x04	/* adapter status flag 3 */
+ #define	ASF2	0x02	/* adapter status flag 2 */
+ #define	ASF1	0x01	/* adapter status flag 1 */
+ 
+ /*
+  * combinations of ASF flags used for PCB reception
+  */
+ #define	ASF_PCB_ACK	ASF1
+ #define	ASF_PCB_NAK	ASF2
+ #define	ASF_PCB_END	(ASF2|ASF1)
+ #define	ASF_PCB_MASK	(ASF2|ASF1)
+ 
+ /*
+  * host aux DMA register bits
+  */
+ #define	DMA_BRST	0x01	/* DMA burst */
+ 
+ /*
+  * maximum amount of data data allowed in a PCB
+  */
+ #define	MAX_PCB_DATA	62
+ 
+ /*****************************************************************
+  *
+  *  timeout value
+  *	this is a rough value used for loops to stop them from 
+  *	locking up the whole machine in the case of failure or
+  *	error conditions
+  *
+  *****************************************************************/
+ 
+ #define	TIMEOUT	300
+ 
+ /*****************************************************************
+  *
+  * PCB commands
+  *
+  *****************************************************************/
+ 
+ enum {
+   /*
+    * host PCB commands
+    */
+   CMD_CONFIGURE_ADAPTER_MEMORY	= 0x01,
+   CMD_CONFIGURE_82586		= 0x02,
+   CMD_STATION_ADDRESS		= 0x03,
+   CMD_DMA_DOWNLOAD		= 0x04,
+   CMD_DMA_UPLOAD		= 0x05,
+   CMD_PIO_DOWNLOAD		= 0x06,
+   CMD_PIO_UPLOAD		= 0x07,
+   CMD_RECEIVE_PACKET		= 0x08,
+   CMD_TRANSMIT_PACKET		= 0x09,
+   CMD_NETWORK_STATISTICS	= 0x0a,
+   CMD_LOAD_MULTICAST_LIST	= 0x0b,
+   CMD_CLEAR_PROGRAM		= 0x0c,
+   CMD_DOWNLOAD_PROGRAM		= 0x0d,
+   CMD_EXECUTE_PROGRAM		= 0x0e,
+   CMD_SELF_TEST			= 0x0f,
+   CMD_SET_STATION_ADDRESS	= 0x10,
+   CMD_ADAPTER_INFO		= 0x11,
+   NUM_TRANSMIT_CMDS,
+ 
+   /*
+    * adapter PCB commands
+    */
+   CMD_CONFIGURE_ADAPTER_RESPONSE	= 0x31,
+   CMD_CONFIGURE_82586_RESPONSE		= 0x32,
+   CMD_ADDRESS_RESPONSE			= 0x33,
+   CMD_DOWNLOAD_DATA_REQUEST		= 0x34,
+   CMD_UPLOAD_DATA_REQUEST		= 0x35,
+   CMD_RECEIVE_PACKET_COMPLETE		= 0x38,
+   CMD_TRANSMIT_PACKET_COMPLETE		= 0x39,
+   CMD_NETWORK_STATISTICS_RESPONSE	= 0x3a,
+   CMD_LOAD_MULTICAST_RESPONSE		= 0x3b,
+   CMD_CLEAR_PROGRAM_RESPONSE		= 0x3c,
+   CMD_DOWNLOAD_PROGRAM_RESPONSE		= 0x3d,
+   CMD_EXECUTE_RESPONSE			= 0x3e,
+   CMD_SELF_TEST_RESPONSE		= 0x3f,
+   CMD_SET_ADDRESS_RESPONSE		= 0x40,
+   CMD_ADAPTER_INFO_RESPONSE		= 0x41
+ };
+ 
+ /* Definitions for the PCB data structure */
+ 
+ /* Data units */
+ typedef unsigned char         byte;
+ typedef unsigned short int    word;
+ typedef unsigned long int     dword;
+ 
+ /* Data structures */
+ struct Memconf {
+ 	word	cmd_q,
+ 		rcv_q,
+ 		mcast,
+ 		frame,
+ 		rcv_b,
+ 		progs;
+ };
+ 
+ struct Rcv_pkt {
+ 	word	buf_ofs,
+ 		buf_seg,
+ 		buf_len,
+ 		timeout;
+ };
+ 
+ struct Xmit_pkt {
+ 	word	buf_ofs,
+ 		buf_seg,
+ 		pkt_len;
+ };
+ 
+ struct Rcv_resp {
+ 	word	buf_ofs,
+ 		buf_seg,
+ 		buf_len,
+ 		pkt_len,
+ 		timeout,
+ 		status;
+ 	dword	timetag;
+ };
+ 
+ struct Xmit_resp {
+ 	word	buf_ofs,
+ 		buf_seg,
+ 		c_stat,
+ 		status;
+ };
+ 
+ 
+ struct Netstat {
+ 	dword	tot_recv,
+ 		tot_xmit;
+ 	word	err_CRC,
+ 		err_align,
+ 		err_res,
+ 		err_ovrrun;
+ };
+ 
+ 
+ struct Selftest {
+ 	word	error;
+ 	union {
+ 		word ROM_cksum;
+ 		struct {
+ 			word ofs, seg;
+ 		} RAM;
+ 		word i82586;
+ 	} failure;
+ };
+ 
+ struct Info {
+ 	byte	minor_vers,
+ 		major_vers;
+ 	word	ROM_cksum,
+ 		RAM_sz,
+ 		free_ofs,
+ 		free_seg;
+ };
+ 
+ struct Memdump {
+        word size,
+             off,
+             seg;
+ };
+ 
+ /*
+ Primary Command Block. The most important data structure. All communication
+ between the host and the adapter is done with these. (Except for the actual
+ ethernet data, which has different packaging.)
+ */
+ typedef struct {
+ 	byte	command;
+ 	byte	length;
+ 	union	{
+ 		struct Memconf		memconf;
+ 		word			configure;
+ 		struct Rcv_pkt		rcv_pkt;
+ 		struct Xmit_pkt		xmit_pkt;
+ 		byte			multicast[10][6];
+ 		byte			eth_addr[6];
+ 		byte			failed;
+ 		struct Rcv_resp		rcv_resp;
+ 		struct Xmit_resp	xmit_resp;
+ 		struct Netstat		netstat;
+ 		struct Selftest		selftest;
+ 		struct Info		info;
+ 		struct Memdump    	memdump;
+ 		byte			raw[62];
+ 	} data;
+ } pcb_struct;
+ 
+ /* These defines for 'configure' */
+ #define RECV_STATION	0x00
+ #define RECV_BROAD	0x01
+ #define RECV_MULTI	0x02
+ #define RECV_PROMISC	0x04
+ #define NO_LOOPBACK	0x00
+ #define INT_LOOPBACK	0x08
+ #define EXT_LOOPBACK	0x10
diff -c -r -N ../linux-2.1.55/drivers/net/Makefile linux-apollo-dev/drivers/net/Makefile
*** ../linux-2.1.55/drivers/net/Makefile	Thu Sep 25 22:38:19 1997
--- linux-apollo-dev/drivers/net/Makefile	Thu Sep 25 16:21:33 1997
***************
*** 687,697 ****
    endif
  endif
  
! ifeq ($(CONFIG_ARIADNE),y)
! L_OBJS += ariadne.o
  else
!   ifeq ($(CONFIG_ARIADNE),m)
!   M_OBJS += ariadne.o
    endif
  endif
  
--- 687,697 ----
    endif
  endif
  
! ifeq ($(CONFIG_APOLLO_ELPLUS),y)
! L_OBJS += 3c505_pio_apollo.o
  else
!   ifeq ($(CONFIG_APOLLO_ELPLUS),m)
!   M_OBJS += 3c505_pio_apollo.o
    endif
  endif
  
diff -c -r -N ../linux-2.1.55/drivers/net/Space.c linux-apollo-dev/drivers/net/Space.c
*** ../linux-2.1.55/drivers/net/Space.c	Thu Sep 25 22:38:19 1997
--- linux-apollo-dev/drivers/net/Space.c	Thu Sep 25 16:58:35 1997
***************
*** 222,227 ****
--- 222,230 ----
  #ifdef CONFIG_ELPLUS		/* 3c505 */
  	&& elplus_probe(dev)
  #endif
+ #ifdef CONFIG_APOLLO_ELPLUS		/* 3c505 */
+ 	&& elplus_probe(dev)
+ #endif
  #ifdef CONFIG_DE600		/* D-Link DE-600 adapter */
  	&& de600_probe(dev)
  #endif
diff -c -r -N ../linux-2.1.55/drivers/video/Makefile linux-apollo-dev/drivers/video/Makefile
*** ../linux-2.1.55/drivers/video/Makefile	Thu Sep 25 22:38:35 1997
--- linux-apollo-dev/drivers/video/Makefile	Wed Sep 17 01:46:03 1997
***************
*** 26,31 ****
--- 26,35 ----
    LX_OBJS += fbcon.o fbcmap.o
  endif
  
+ ifeq ($(CONFIG_APOLLO),y)
+ L_OBJS += dn_fb.o
+ endif
+ 
  ifeq ($(CONFIG_FB_AMIGA),y)
  L_OBJS += amifb.o
  else
diff -c -r -N ../linux-2.1.55/drivers/video/dn_fb.c linux-apollo-dev/drivers/video/dn_fb.c
*** ../linux-2.1.55/drivers/video/dn_fb.c	Thu Jan  1 01:00:00 1970
--- linux-apollo-dev/drivers/video/dn_fb.c	Thu Sep 25 01:40:11 1997
***************
*** 0 ****
--- 1,390 ----
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/string.h>
+ #include <linux/mm.h>
+ #include <linux/tty.h>
+ #include <linux/malloc.h>
+ #include <linux/delay.h>
+ #include <linux/config.h>
+ #include <linux/interrupt.h>
+ #include <asm/setup.h>
+ #include <asm/segment.h>
+ #include <asm/system.h>
+ #include <asm/irq.h>
+ #include <asm/amigahw.h>
+ #include <asm/amigaints.h>
+ #include <asm/apollohw.h>
+ #include <linux/fb.h>
+ #include <linux/module.h>
+ 
+ /* apollo video HW definitions */
+ 
+ /*
+  * Control Registers.   IOBASE + $x
+  *
+  * Note: these are the Memory/IO BASE definitions for a mono card set to the
+  * alternate address
+  *
+  * Control 3A and 3B serve identical functions except that 3A
+  * deals with control 1 and 3b deals with Color LUT reg.
+  */
+ 
+ #define AP_IOBASE       0x5d80          /* Base address of 1 plane board. */
+ #define AP_STATUS       0x5d80          /* Status register.  Read */
+ #define AP_WRITE_ENABLE 0x5d80          /* Write Enable Register Write */
+ #define AP_DEVICE_ID    0x5d81          /* Device ID Register. Read */
+ #define AP_ROP_1        0x5d82          /* Raster Operation reg. Write Word */
+ #define AP_DIAG_MEM_REQ 0x5d84          /* Diagnostic Memory Request. Write Word */
+ #define AP_CONTROL_0    0x5d88          /* Control Register 0.  Read/Write */
+ #define AP_CONTROL_1    0x5d8a          /* Control Register 1.  Read/Write */
+ #define AP_CONTROL_3A   0x5d8e          /* Control Register 3a. Read/Write */
+ #define AP_CONTROL_2    0x5d8c          /* Control Register 2. Read/Write */
+ 
+ 
+ #define FRAME_BUFFER_START 0x0FA0000
+ #define FRAME_BUFFER_LEN 0x40000
+ 
+ /* CREG 0 */
+ #define VECTOR_MODE 0x40 /* 010x.xxxx */
+ #define DBLT_MODE   0x80 /* 100x.xxxx */
+ #define NORMAL_MODE 0xE0 /* 111x.xxxx */
+ #define SHIFT_BITS  0x1F /* xxx1.1111 */
+         /* other bits are Shift value */
+ 
+ /* CREG 1 */
+ #define AD_BLT      0x80 /* 1xxx.xxxx */
+ #define NORMAL      0x80 /* 1xxx.xxxx */   /* What is happening here ?? */
+ #define INVERSE     0x00 /* 0xxx.xxxx */   /* Clearing this reverses the screen */
+ #define PIX_BLT     0x00 /* 0xxx.xxxx */
+ 
+ #define AD_HIBIT        0x40 /* xIxx.xxxx */
+ 
+ #define ROP_EN          0x10 /* xxx1.xxxx */
+ #define DST_EQ_SRC      0x00 /* xxx0.xxxx */
+ #define nRESET_SYNC     0x08 /* xxxx.1xxx */
+ #define SYNC_ENAB       0x02 /* xxxx.xx1x */
+ 
+ #define BLANK_DISP      0x00 /* xxxx.xxx0 */
+ #define ENAB_DISP       0x01 /* xxxx.xxx1 */
+ 
+ #define NORM_CREG1      (nRESET_SYNC | SYNC_ENAB | ENAB_DISP) /* no reset sync */
+ 
+ /* CREG 2 */
+ 
+ /*
+  * Following 3 defines are common to 1, 4 and 8 plane.
+  */
+ 
+ #define S_DATA_1s   0x00 /* 00xx.xxxx */ /* set source to all 1's -- vector drawing */
+ #define S_DATA_PIX  0x40 /* 01xx.xxxx */ /* takes source from ls-bits and replicates over 16 bits */
+ #define S_DATA_PLN  0xC0 /* 11xx.xxxx */ /* normal, each data access =16-bits in
+  one plane of image mem */
+ 
+ /* CREG 3A/CREG 3B */
+ #       define RESET_CREG 0x80 /* 1000.0000 */
+ 
+ /* ROP REG  -  all one nibble */
+ /*      ********* NOTE : this is used r0,r1,r2,r3 *********** */
+ #define ROP(r2,r3,r0,r1) ( (U_SHORT)((r0)|((r1)<<4)|((r2)<<8)|((r3)<<12)) )
+ #define DEST_ZERO               0x0
+ #define SRC_AND_DEST    0x1
+ #define SRC_AND_nDEST   0x2
+ #define SRC                             0x3
+ #define nSRC_AND_DEST   0x4
+ #define DEST                    0x5
+ #define SRC_XOR_DEST    0x6
+ #define SRC_OR_DEST             0x7
+ #define SRC_NOR_DEST    0x8
+ #define SRC_XNOR_DEST   0x9
+ #define nDEST                   0xA
+ #define SRC_OR_nDEST    0xB
+ #define nSRC                    0xC
+ #define nSRC_OR_DEST    0xD
+ #define SRC_NAND_DEST   0xE
+ #define DEST_ONE                0xF
+ 
+ #define SWAP(A) ((A>>8) | ((A&0xff) <<8))
+ 
+ #if 0
+ #define outb(a,d) *(char *)(a)=(d)
+ #define outw(a,d) *(unsigned short *)a=d
+ #endif
+ 
+ 
+ void dn_video_setup(char *options, int *ints);
+ 
+ /* frame buffer operations */
+ 
+ static int dn_fb_open(int fbidx);
+ static int dn_fb_release(int fbidx);
+ static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con);
+ static int dn_fb_get_var(struct fb_var_screeninfo *var, int con);
+ static int dn_fb_set_var(struct fb_var_screeninfo *var, int isactive);
+ static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con);
+ static int dn_fb_set_cmap(struct fb_cmap *cmap,int kspc,int con);
+ static int dn_fb_pan_display(struct fb_var_screeninfo *var, int con);
+ static int dn_fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ 		       unsigned long arg, int con);
+ 
+ static int dnfbcon_switch(int con);
+ static int dnfbcon_updatevar(int con);
+ static void dnfbcon_blank(int blank);
+ 
+ static void dn_fb_set_disp(int con);
+ 
+ static struct display disp[MAX_NR_CONSOLES];
+ static struct fb_info fb_info;
+ static struct fb_ops dn_fb_ops = { 
+ 	dn_fb_open,dn_fb_release, dn_fb_get_fix, dn_fb_get_var, dn_fb_set_var,
+ 	dn_fb_get_cmap, dn_fb_set_cmap, dn_fb_pan_display, dn_fb_ioctl
+ };
+ 
+ static int currcon=0;
+ 
+ #define NUM_TOTAL_MODES 1
+ struct fb_var_screeninfo dn_fb_predefined[] = {
+ 
+ 	{ 0, },
+ 
+ };
+ 
+ static char dn_fb_name[]="Apollo ";
+ 
+ static int dn_fb_open(int fbidx)
+ {
+         /*
+          * Nothing, only a usage count for the moment
+          */
+ 
+         MOD_INC_USE_COUNT;
+         return(0);
+ }
+ 
+ static int dn_fb_release(int fbidx)
+ {
+         MOD_DEC_USE_COUNT;
+         return(0);
+ }
+ 
+ static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con) {
+ 
+ 	strcpy(fix->id,"Apollo Mono");
+ 	fix->smem_start=(char*)(FRAME_BUFFER_START+IO_BASE);
+ 	fix->smem_len=FRAME_BUFFER_LEN;
+ 	fix->type=FB_TYPE_PACKED_PIXELS;
+ 	fix->type_aux=0;
+ 	fix->visual=FB_VISUAL_MONO10;
+ 	fix->xpanstep=0;
+ 	fix->ypanstep=0;
+ 	fix->ywrapstep=0;
+         fix->line_length=256;
+ 
+ 	return 0;
+ 
+ }
+         
+ static int dn_fb_get_var(struct fb_var_screeninfo *var, int con) {
+ 		
+ 	var->xres=1280;
+ 	var->yres=1024;
+ 	var->xres_virtual=2048;
+ 	var->yres_virtual=1024;
+ 	var->xoffset=0;
+ 	var->yoffset=0;
+ 	var->bits_per_pixel=1;
+ 	var->grayscale=0;
+ 	var->nonstd=0;
+ 	var->activate=0;
+ 	var->height=-1;
+ 	var->width=-1;
+ 	var->pixclock=0;
+ 	var->left_margin=0;
+ 	var->right_margin=0;
+ 	var->hsync_len=0;
+ 	var->vsync_len=0;
+ 	var->sync=0;
+ 	var->vmode=FB_VMODE_NONINTERLACED;
+ 	var->accel=FB_ACCEL_NONE;
+ 
+ 	return 0;
+ 
+ }
+ 
+ static int dn_fb_set_var(struct fb_var_screeninfo *var, int isactive) {
+ 
+         printk("fb_set_var\n");
+ 	if(var->xres!=1280) 
+ 		return -EINVAL;
+ 	if(var->yres!=1024)
+ 		return -EINVAL;
+ 	if(var->xres_virtual!=2048)
+ 		return -EINVAL;
+ 	if(var->yres_virtual!=1024)
+ 		return -EINVAL;
+ 	if(var->xoffset!=0)
+ 		return -EINVAL;
+ 	if(var->yoffset!=0)
+ 		return -EINVAL;
+ 	if(var->bits_per_pixel!=1)
+ 		return -EINVAL;
+ 	if(var->grayscale!=0)
+ 		return -EINVAL;
+ 	if(var->nonstd!=0)
+ 		return -EINVAL;
+ 	if(var->activate!=0)
+ 		return -EINVAL;
+ 	if(var->pixclock!=0)
+ 		return -EINVAL;
+ 	if(var->left_margin!=0)
+ 		return -EINVAL;
+ 	if(var->right_margin!=0)
+ 		return -EINVAL;
+ 	if(var->hsync_len!=0)
+ 		return -EINVAL;
+ 	if(var->vsync_len!=0)
+ 		return -EINVAL;
+ 	if(var->sync!=0)
+ 		return -EINVAL;
+ 	if(var->vmode!=FB_VMODE_NONINTERLACED)
+ 		return -EINVAL;
+ 	if(var->accel!=FB_ACCEL_NONE)
+ 		return -EINVAL;
+ 
+ 	return 0;
+ 
+ }
+ 
+ static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con) {
+ 
+ 	printk("get cmap not supported\n");
+ 
+ 	return -EINVAL;
+ }
+ 
+ static int dn_fb_set_cmap(struct fb_cmap *cmap,int kspc,int con) {
+ 
+ 	printk("set cmap not supported\n");
+ 
+ 	return -EINVAL;
+ 
+ }
+ 
+ static int dn_fb_pan_display(struct fb_var_screeninfo *var, int con) {
+ 
+ 	printk("panning not supported\n");
+ 
+ 	return -EINVAL;
+ 
+ }
+ 
+ static int dn_fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ 		    unsigned long arg, int con) {
+ 
+ 	printk("no IOCTLs as of yet.\n");
+ 
+ 	return -EINVAL;
+ 
+ }
+ 
+ static void dn_fb_set_disp(int con) {
+ 
+   struct fb_fix_screeninfo fix;
+ 
+   dn_fb_get_fix(&fix,con);
+   if(con==-1) 
+     con=0;
+ 
+    disp[con].screen_base = (u_char *)fix.smem_start;
+ printk("screenbase: %p\n",fix.smem_start);
+    disp[con].visual = fix.visual;
+    disp[con].type = fix.type;
+    disp[con].type_aux = fix.type_aux;
+    disp[con].ypanstep = fix.ypanstep;
+    disp[con].ywrapstep = fix.ywrapstep;
+    disp[con].can_soft_blank = 1;
+    disp[con].inverse = 0;
+    disp[con].line_length = fix.line_length;
+ }
+   
+ unsigned long dn_fb_init(unsigned long mem_start) {
+ 
+ 	int err;
+        
+ printk("dn_fb_init\n");
+ 
+ 	fb_info.changevar=NULL;
+ 	strcpy(&fb_info.modename[0],dn_fb_name);
+ 	fb_info.fontname[0]=0;
+ 	fb_info.disp=disp;
+ 	fb_info.switch_con=&dnfbcon_switch;
+ 	fb_info.updatevar=&dnfbcon_updatevar;
+ 	fb_info.blank=&dnfbcon_blank;	
+ 	fb_info.node = -1;
+ 	fb_info.fbops = &dn_fb_ops;
+ 	fb_info.fbvar = dn_fb_predefined;
+ 	fb_info.fbvar_num = NUM_TOTAL_MODES;
+ 	
+ printk("dn_fb_init: register\n");
+ 	err=register_framebuffer(&fb_info);
+ 	if(err < 0) {
+ 		panic("unable to register apollo frame buffer\n");
+ 	}
+  
+ 	/* now we have registered we can safely setup the hardware */
+ 
+         outb(RESET_CREG, AP_CONTROL_3A);
+         outw(0x0, AP_WRITE_ENABLE);
+         outb(NORMAL_MODE,AP_CONTROL_0); 
+         outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1);
+         outb(S_DATA_PLN, AP_CONTROL_2);
+         outw(SWAP(0x3),AP_ROP_1);
+ 
+         printk("apollo frame buffer alive and kicking !\n");
+ 
+ 	
+         dn_fb_get_var(&disp[0].var,0);
+ 
+ 	dn_fb_set_disp(-1);
+ 
+ 	return mem_start;
+ 
+ }	
+ 
+ 	
+ static int dnfbcon_switch(int con) { 
+ 
+ 	currcon=con;
+ 	
+ 	return 0;
+ 
+ }
+ 
+ static int dnfbcon_updatevar(int con) {
+ 
+ 	return 0;
+ 
+ }
+ 
+ static void dnfbcon_blank(int blank) {
+ 
+ 	printk("dnfbcon_blank: %d\n",blank);
+ 	if(blank)  {
+         	outb(0, AP_CONTROL_3A);
+ 		outb((AD_BLT | DST_EQ_SRC | NORM_CREG1) & ~ENAB_DISP,
+ 		     AP_CONTROL_1);
+ 	}
+ 	else {
+ 	        outb(1, AP_CONTROL_3A);
+         	outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1);
+ 	}
+ 
+ 	return ;
+ 
+ }
+ 
+ void dn_video_setup(char *options, int *ints) {
+ 	
+ 	return;
+ 
+ }
+ 
diff -c -r -N ../linux-2.1.55/drivers/video/fbcon.c linux-apollo-dev/drivers/video/fbcon.c
*** ../linux-2.1.55/drivers/video/fbcon.c	Thu Sep 25 22:38:36 1997
--- linux-apollo-dev/drivers/video/fbcon.c	Wed Sep 17 13:31:23 1997
***************
*** 223,233 ****
--- 223,250 ----
  
  extern int num_registered_fb;
  
+ #ifdef CONFIG_APOLLO
+ static void cursor_timer_handler(unsigned long dev_addr);
+ 
+ static struct timer_list cursor_timer={NULL,NULL,0,0L,cursor_timer_handler};
+ 
+ static void cursor_timer_handler(unsigned long dev_addr) {
+ 
+       fbcon_vbl_handler(0,NULL,NULL);
+       cursor_timer.expires=jiffies+2;
+       cursor_timer.data=0;
+       cursor_timer.next=cursor_timer.next=NULL;
+       add_timer(&cursor_timer);
+ 
+ }
+ #endif
+ 
  static unsigned long fbcon_startup(unsigned long kmem_start,
  				   const char **display_desc)
  {
      int irqres = 1;
  
+ printk("fbcon_startup\n");
      /* Probe all frame buffer devices */
      kmem_start = probe_framebuffers(kmem_start);
  
***************
*** 290,295 ****
--- 307,322 ----
  			     "console/cursor", fbcon_vbl_handler);
      }
  #endif /* CONFIG_ATARI */
+ #ifdef CONFIG_APOLLO
+    if(MACH_IS_APOLLO) {
+       cursor_blink_rate = ATARI_CURSOR_BLINK_RATE;
+       cursor_timer.expires=jiffies+2;
+       cursor_timer.data=0;
+       cursor_timer.next=cursor_timer.prev=NULL;
+       add_timer(&cursor_timer);
+       irqres=0;
+    }
+ #endif /* CONFIG_APOLLO */
  
      if (irqres)
  	panic("fbcon_startup: Couldn't add vblank interrupt");
***************
*** 1102,1107 ****
--- 1129,1135 ----
  
      /* Then try an unaccelerated driver */
      dispsw = probe_list(drivers, disp);
+ 
  #ifdef CONFIG_KERNELD
      if (!dispsw) {
  	request_driver(disp, 0);
diff -c -r -N ../linux-2.1.55/include/asm-m68k/apollohw.h linux-apollo-dev/include/asm-m68k/apollohw.h
*** ../linux-2.1.55/include/asm-m68k/apollohw.h	Thu Jan  1 01:00:00 1970
--- linux-apollo-dev/include/asm-m68k/apollohw.h	Mon Jun 16 21:46:01 1997
***************
*** 0 ****
--- 1,71 ----
+ /* apollohw.h : some structures to access apollo HW */
+ 
+ #ifndef _ASMm68k_APOLLOHW_H_
+ #define _ASMm68k_APOLLOHW_H_
+ 
+ 
+ /* 
+    see scn2681 data sheet for more info. 
+    member names are read_write.
+ */
+ 
+ #define DECLARE_2681_FIELD(x) unsigned char x; unsigned char dummy##x
+ 
+ struct SCN2681 {
+ 
+ 	DECLARE_2681_FIELD(mra);
+ 	DECLARE_2681_FIELD(sra_csra);
+ 	DECLARE_2681_FIELD(BRGtest_cra);
+ 	DECLARE_2681_FIELD(rhra_thra);
+ 	DECLARE_2681_FIELD(ipcr_acr);
+ 	DECLARE_2681_FIELD(isr_imr);
+ 	DECLARE_2681_FIELD(ctu_ctur);
+ 	DECLARE_2681_FIELD(ctl_ctlr);
+ 	DECLARE_2681_FIELD(mrb);
+ 	DECLARE_2681_FIELD(srb_csrb);
+ 	DECLARE_2681_FIELD(tst_crb);
+ 	DECLARE_2681_FIELD(rhrb_thrb);
+ 	DECLARE_2681_FIELD(reserved);
+ 	DECLARE_2681_FIELD(ip_opcr);
+ 	DECLARE_2681_FIELD(startCnt_setOutBit);
+ 	DECLARE_2681_FIELD(stopCnt_resetOutBit);
+ 
+ };
+ 
+ #if 0
+ struct mc146818 {
+ 
+ 	unsigned int second1:4, second2:4, alarm_second1:4, alarm_second2:4,
+ 		     minute1:4, minute2:4, alarm_minute1:4, alarm_minute2:4;
+ 	unsigned int hours1:4, hours2:4, alarm_hours1:4, alarm_hours2:4,
+ 		     day_of_week1:4, day_of_week2:4, day_of_month1:4, day_of_month2:4;
+ 	unsigned int month1:4, month2:4, year1:4, year2:4, :16;
+ 
+ };
+ #endif
+ 
+ struct mc146818 {
+         unsigned char second, alarm_second;
+         unsigned char minute, alarm_minute;
+         unsigned char hours, alarm_hours;
+         unsigned char day_of_week, day_of_month;
+         unsigned char month, year;
+ };
+ 
+ #define IO_BASE 0x80000000
+ 
+ #define SIO01_PHYSADDR 0x10400
+ #define SIO23_PHYSADDR 0x10500
+ #define RTC_PHYSADDR 0x10900
+ #define PICA 0x11000
+ #define PICB 0x11100
+ #define sio01 ((*(volatile struct SCN2681 *)(IO_BASE + SIO01_PHYSADDR)))
+ #define sio23 ((*(volatile struct SCN2681 *)(IO_BASE + SIO01_PHYSADDR)))
+ #define rtc (((volatile struct mc146818 *)(IO_BASE + RTC_PHYSADDR)))
+ 
+ #define inb(addr) (*((volatile unsigned char *)(addr)))
+ #define outb(val,addr) (*((volatile unsigned char *)(addr)) = (val))
+ #define inw(addr) (*((volatile unsigned short *)(addr)))
+ #define outw(val,addr) (*((volatile unsigned short *)(addr)) = (val))
+ 
+ #endif
diff -c -r -N ../linux-2.1.55/include/asm-m68k/setup.h linux-apollo-dev/include/asm-m68k/setup.h
*** ../linux-2.1.55/include/asm-m68k/setup.h	Wed Jan 15 01:14:03 1997
--- linux-apollo-dev/include/asm-m68k/setup.h	Thu Sep 25 16:42:40 1997
***************
*** 45,51 ****
  
  #if !defined(CONFIG_AMIGA)
  #  define MACH_IS_AMIGA (0)
! #elif defined(CONFIG_ATARI) || defined(CONFIG_MAC)
  #  define MACH_IS_AMIGA (m68k_machtype == MACH_AMIGA)
  #else
  #  define MACH_AMIGA_ONLY
--- 45,51 ----
  
  #if !defined(CONFIG_AMIGA)
  #  define MACH_IS_AMIGA (0)
! #elif defined(CONFIG_ATARI) || defined(CONFIG_MAC) || defined(CONFIG_APOLLO)
  #  define MACH_IS_AMIGA (m68k_machtype == MACH_AMIGA)
  #else
  #  define MACH_AMIGA_ONLY
***************
*** 55,61 ****
  
  #if !defined(CONFIG_ATARI)
  #  define MACH_IS_ATARI (0)
! #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
  #  define MACH_IS_ATARI (m68k_machtype == MACH_ATARI)
  #else
  #  define MACH_ATARI_ONLY
--- 55,61 ----
  
  #if !defined(CONFIG_ATARI)
  #  define MACH_IS_ATARI (0)
! #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_APOLLO)
  #  define MACH_IS_ATARI (m68k_machtype == MACH_ATARI)
  #else
  #  define MACH_ATARI_ONLY
***************
*** 71,78 ****
  #  error Currently no Sun-3 support!
  #endif
  
! #if defined(CONFIG_APOLLO)
! #  error Currently no Apollo support!
  #endif
  
  #ifndef MACH_TYPE
--- 71,84 ----
  #  error Currently no Sun-3 support!
  #endif
  
! #if !defined (CONFIG_APOLLO)
! #  define MACH_IS_APOLLO (0)
! #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI)
! #  define MACH_IS_APOLLO (boot_info.machtype == MACH_APOLLO)
! #else
! #  define CONFIG_APOLLO_ONLY
! #  define MACH_IS_APOLLO (1)
! #  define MACH_TYPE (MACH_APOLLO)
  #endif
  
  #ifndef MACH_TYPE
diff -c -r -N ../linux-2.1.55/include/linux/miscdevice.h linux-apollo-dev/include/linux/miscdevice.h
*** ../linux-2.1.55/include/linux/miscdevice.h	Thu Sep 25 22:36:44 1997
--- linux-apollo-dev/include/linux/miscdevice.h	Mon Sep 22 17:32:00 1997
***************
*** 8,13 ****
--- 8,14 ----
  #define AMIGAMOUSE_MINOR 4
  #define ATARIMOUSE_MINOR 5
  #define SUN_MOUSE_MINOR 6
+ #define APOLLO_MOUSE_MINOR 7
  #define PC110PAD_MINOR 9
  #define RTC_MINOR 135
  #define SUN_OPENPROM_MINOR 139
