diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/Makefile LINUX_ALPHA_SDK/sources/linux/Makefile *** LINUX_ALPHA_SDK/sources/linux.0.1.0/Makefile Tue Jan 17 17:12:45 1995 --- LINUX_ALPHA_SDK/sources/linux/Makefile Thu Feb 9 19:45:38 1995 *************** *** 1,8 **** ! VERSION = 0.99 ! PATCHLEVEL = 14 ALPHA = ! all: Version linux linux.stripped .EXPORT_ALL_VARIABLES: --- 1,8 ---- ! VERSION = 0.1 ! PATCHLEVEL = 1 ALPHA = ! all: Version linux linux.stripped linux.gz .EXPORT_ALL_VARIABLES: *************** *** 213,218 **** --- 213,223 ---- cp linux linux.stripped $(STRIP) linux.stripped + linux.gz: linux.stripped + cp linux.stripped linux_gz + gzip -9 linux_gz + mv linux_gz.gz linux.gz + linkonly: $(LD) $(LDFLAGS) -T linux.ld -N alpha/head.o init/main.o \ tools/version.o \ *************** *** 278,284 **** clean: rm -f core `find . -name '*.[oas]' -print` rm -f core `find . -name 'core' -print` ! rm -f linux linuxboot linux.stripped rm -f alpha_boot/linuxboot rm -f drivers/sound/configure rm -f init/*.o tools/build tools/*.o --- 283,290 ---- clean: rm -f core `find . -name '*.[oas]' -print` rm -f core `find . -name 'core' -print` ! rm -f core `find . -name '*~' -print` ! rm -f linux linuxboot linux.stripped linux.gz rm -f alpha_boot/linuxboot rm -f drivers/sound/configure rm -f init/*.o tools/build tools/*.o diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha/asmutils.S LINUX_ALPHA_SDK/sources/linux/alpha/asmutils.S *** LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha/asmutils.S Wed Jan 11 16:06:01 1995 --- LINUX_ALPHA_SDK/sources/linux/alpha/asmutils.S Thu Feb 9 15:30:53 1995 *************** *** 283,288 **** --- 283,289 ---- ldq ra,0(sp) ldq a0,8(sp) ldq a1,16(sp) + lda sp,24(sp) ret zero,(ra) .end tbis *************** *** 303,310 **** --- 304,313 ---- lda t1,8(t1) # increment dest addr lda t2,-1(t2) # decrement count bne t2,1b # loop + lda a0,-2(zero) # -2 means "flush whole TB" call_pal PAL_tbi # Do it! + ldq a0,8(sp) ldq ra,0(sp) # Pop ra & a0 lda sp,16(sp) *************** *** 455,458 **** --- 458,489 ---- call_pal PAL_imb ret zero,(ra) .end imb + + + /* + * Routines to read and write the MCES register (used when clearing out the + * machine checks in progress flag. + */ + .globl rdmces + .ent rdmces + rdmces: + call_pal PAL_mfpr_mces + ret zero,(ra) + .end rdmces + + .globl wrmces + .ent wrmces + wrmces: + lda sp,-16(sp) + stq ra,0(sp) # Save ra & a0 + stq a0,8(sp) # (PAL smashes a0) + call_pal PAL_mtpr_mces # write mces + ldq a0,8(sp) # Restore a0 + ldq ra,0(sp) # restore ra + lda sp,16(sp) # restore sp + ret zero,(ra) + .end wrmces + + + diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha/cpu.c LINUX_ALPHA_SDK/sources/linux/alpha/cpu.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha/cpu.c Mon Jan 9 12:26:04 1995 --- LINUX_ALPHA_SDK/sources/linux/alpha/cpu.c Thu Feb 9 19:16:30 1995 *************** *** 8,17 **** --- 8,25 ---- #include #include /* for cli()/sti() */ + #include #include extern HWRPB *rpb; + extern int KEYBOARD_IRQ; /* in drivers/char/keyboard.c */ + + /* + * globals with platform-dependent values + */ + int high_page_byte; /* for DMA address settings */ + /* * these globals hold pointers to the appropriate low-level routines for * accessing bus I/O and MEMORY spaces on the current platform. they are *************** *** 40,46 **** --- 48,58 ---- */ U64 alpha_io_base; U64 alpha_mem_base; + #ifdef CONFIG_PCI + U64 alpha_cfg_base; + #endif U64 alpha_junk_base; + U64 alpha_system_type; /* "standard" platforms' entry points */ extern int inb_std (int port,U64 base); *************** *** 60,107 **** extern int jinb_jen (int port,U64 base); extern void joutb_jen (int v,int port,U64 base); ! extern void write_cpureg_jen(int v,U64 addr); ! extern int read_cpureg_jen(U64 addr); - #ifndef CALLBACK_KEYBOARD - /* - * external entry points for interrupt handlers - */ - extern void keyboard_interrupt(int); - #endif /* CALLBACK_KEYBOARD */ - - /* - * DEC processor types for Alpha systems. Found in HWRPB. - * These values are architected. - */ ! #define EV3_CPU 1 /* EV3 */ ! #define EV4_CPU 2 /* EV4 (21064) */ ! #define LCA4_CPU 4 /* LCA4 (21066/21068) */ ! #define EV5_CPU 5 /* EV5 (21164) */ ! #define EV45_CPU 6 /* EV4.5 (21064/xxx) */ ! ! /* ! * DEC system types for Alpha systems. Found in HWRPB. ! * These values are architected. ! */ ! ! #define ST_ADU 1 /* Alpha ADU systype */ ! #define ST_DEC_4000 2 /* Cobra systype */ ! #define ST_DEC_7000 3 /* Ruby systype */ ! #define ST_DEC_3000_500 4 /* Flamingo systype */ ! #define ST_DEC_2000_300 6 /* Jensen systype */ ! #define ST_DEC_3000_300 7 /* Pelican systype */ ! #define ST_DEC_2100_A500 9 /* Sable systype */ ! #define ST_DEC_AXPVME_64 10 /* AXPvme system type */ ! #define ST_DEC_AXPPCI_33 11 /* NoName system type */ ! #define ST_DEC_TLASER 12 /* Turbolaser systype */ ! #define ST_DEC_2100_A50 13 /* Avanti systype */ ! #define ST_DEC_MUSTANG 14 /* Mustang systype */ ! #define ST_DEC_ALCOR 15 /* Alcor systype */ ! #define ST_DEC_1000 17 /* Mikasa systype */ ! ! #define PASS1_LCA_TYPE 0x100000004ULL /* Pass 1 LCA chip detect */ /* * JENSEN I/O assignments --- 72,88 ---- extern int jinb_jen (int port,U64 base); extern void joutb_jen (int v,int port,U64 base); ! /* "hardware-less" platforms' entry points */ ! extern int inb_stub (int port,U64 base); ! extern int inw_stub (int port,U64 base); ! extern int inl_stub (int port,U64 base); ! extern void outb_stub (int v,int port,U64 base); ! extern void outw_stub (int v,int port,U64 base); ! extern void outl_stub (int v,int port,U64 base); ! extern void write_cpureg_long(int v,U64 addr); ! extern int read_cpureg_long(U64 addr); /* * JENSEN I/O assignments *************** *** 120,132 **** { RPB_PERCPU *percpu; int i; ! switch (rpb->rpb_systype) { case ST_DEC_2000_300: - printk("JENSEN cpu initialization\n"); - /* * init the JENSEN base address global values */ --- 101,126 ---- { RPB_PERCPU *percpu; int i; + unsigned long long proctype; ! /* ! * First, save the system type, then fetch processor type. ! */ ! alpha_system_type = rpb->rpb_systype; ! ! percpu = (RPB_PERCPU *) ((int)rpb + (int)rpb->rpb_percpu_slot_offset); ! proctype = percpu->rpb_proctype; ! ! /* NOTE: NO PRINTING VIA "PRINTK" BEFORE THE SECOND "SWITCH"!!!!!! */ ! ! /* ! * set-up the address constants used for IO and memory space ! * accesses first ! */ ! switch (alpha_system_type) { case ST_DEC_2000_300: /* * init the JENSEN base address global values */ *************** *** 147,206 **** alpha_jinb = jinb_jen; alpha_joutb = joutb_jen; ! /* ! * initialize the SCB vectors for the devices which ! * do NOT come through the PIC ! */ ! #ifndef CALLBACK_KEYBOARD ! intrsetvec(JENSEN_SCB_KEYBD, keyboard_interrupt, 0); ! #endif /* CALLBACK_KEYBOARD */ ! #ifdef NOT_YET ! intrsetvec(JENSEN_SCB_MOUSE, mouse_interrupt, 0); ! intrsetvec(JENSEN_SCB_COMMA, serial_interrupt, 0); ! intrsetvec(JENSEN_SCB_COMMB, serial_interrupt, 1); ! #endif /* NOT_YET */ /* ! * Enable the NMI interrupt */ ! outb(0x00, 0x70); ! /* ! * Set Special Mask Mode as an EOI precaution */ ! outb(0xc0, 0xa0); /*CTLR 2*/ ! outb(0xc0, 0x20); /*CTLR 1*/ /* ! * Enable Non Maskable Interrupt (NMI) masks */ ! outw(0x0000, 0x61); ! outw(0x0c00, 0x461); ! /* ! * Initialize PIC ELR to set all IRQ interrupts to Edge trigger, ! * This should be power-up default, but let's do it any way ! * and let EISA bus code set as needed */ ! outb(0x00, 0x4d1); ! outb(0x00, 0x4d0); ! /* ! * Initialize all PIC interrupts to be disabled just in case ! * They will be enabled through EISA bus support */ ! outb(0xff, 0xa1); /* CTRL2 */ ! outb(0xff, 0x21); /* CTRL1 */ /* * Intitalize HAE to zero */ ! #ifdef DEBUG ! printk("cpu_init: JENSEN HAE 0x%x\n", ! read_cpureg_jen(0xfffffc01d0000000ULL) & 0xff); ! #endif /* DEBUG */ ! write_cpureg_jen(0x00, 0xfffffc01d0000000ULL); /* * make sure that the VTI combo chip is set for PS/2 interface --- 141,255 ---- alpha_jinb = jinb_jen; alpha_joutb = joutb_jen; ! high_page_byte = 0; /* direct map from EISA to MEM */ ! break; ! case ST_ADU: ! /* No hardware to speak of on ADU or ISP, so stub ! * everything out... ! */ ! printk("cpu_init: CPU is ADU/ISP\n"); ! alpha_inb = inb_stub; ! alpha_inw = inw_stub; ! alpha_inl = inl_stub; ! alpha_outb = outb_stub; ! alpha_outw = outw_stub; ! alpha_outl = outl_stub; ! alpha_jinb = inb_stub; /* same as inb */ ! alpha_joutb = outb_stub; /* same as outb */ ! break; ! ! default: ! /* fall thru to default inits */ ! ! case ST_DEC_MUSTANG: /* LCA MUSTANG */ ! case ST_DEC_AXPPCI_33: /* LCA NONAME */ ! case ST_DEC_2100_A50: /* APECS AVANTI/MUSTANG */ ! case ST_DEC_1000: /* APECS MIKASA */ ! case ST_DEC_EB66: /* LCA EB66 */ ! case ST_DEC_EB64P: /* APECS EB64+ */ /* ! * init the non-JENSEN base address global variables */ ! alpha_mem_base = 0xfffffc0200000000ULL; ! #ifdef CONFIG_PCI ! alpha_cfg_base = 0xfffffc01e0000000ULL; ! #endif ! /* ! * determine if and which pass of LCA chip we have. */ ! if (proctype == PASS1_LCA_TYPE) { ! alpha_io_base = 0xfffffc0300000000ULL; ! alpha_junk_base = 0xfffffc0300000000ULL; ! } ! else { ! alpha_io_base = 0xfffffc01c0000000ULL; ! alpha_junk_base = 0xfffffc01c0000000ULL; ! } /* ! * assign the transfer vectors for access routines ! * to the set of "standard" entries */ ! alpha_inb = inb_std; ! alpha_inw = inw_std; ! alpha_inl = inl_std; ! alpha_outb = outb_std; ! alpha_outw = outw_std; ! alpha_outl = outl_std; ! alpha_jinb = inb_std; /* same as inb */ ! alpha_joutb = outb_std; /* same as outb */ ! /* ! * JAE: NOTE: this may be different for other platforms; ! * but this does work for EB66 at the moment */ ! high_page_byte = 0x40; /* map 4GB from PCI to MEM */ ! ! break; ! } ! ! ! #ifndef CONFIG_SCSI ! /* ! * make this call *BEFORE* doing and PIC or DMA inits, ! * as the console FW may undo that work... :-( ! */ ! rpb_early_init(); /* call before doing anything else!! */ ! /* see drivers/block/rpb.c for details */ ! #endif /* ! CONFIG_SCSI */ ! ! /* ! * now finish up the CPU-dependent stuff ! */ ! switch (alpha_system_type) { ! ! case ST_DEC_2000_300: ! ! printk("JENSEN cpu initialization\n"); ! ! /* init the PIC for the IRQs */ ! alpha_pic_init(); ! /* ! * initialize the SCB vectors for the devices which ! * do NOT come through the PIC */ ! /* set this so call to request_irq() will see SCB vec */ ! KEYBOARD_IRQ = JENSEN_SCB_KEYBD; ! ! #ifdef NOT_YET ! intrsetvec(JENSEN_SCB_MOUSE, mouse_interrupt, 0); ! intrsetvec(JENSEN_SCB_COMMA, serial_interrupt, 0); ! intrsetvec(JENSEN_SCB_COMMB, serial_interrupt, 1); ! #endif /* NOT_YET */ /* * Intitalize HAE to zero */ ! write_cpureg_long(0x00, 0xfffffc01d0000000ULL); /* * make sure that the VTI combo chip is set for PS/2 interface *************** *** 210,220 **** JOUTB(0x6a, 0x170); JOUTB(i, 0x171); break; default: printk("cpu_init: unrecognized cpu type %d\n", ! rpb->rpb_systype); printk("cpu_init: doing default init\n"); /* fall thru to default inits */ --- 259,281 ---- JOUTB(0x6a, 0x170); JOUTB(i, 0x171); + /* + * do DMA controller inits + */ + outb(0xff, DMA1_RESET_REG); + outb(0xff, DMA2_RESET_REG); + + outb(0x10, DMA1_CMD_REG); /* rotate, REQHI, ACKLO */ + outb(0x10, DMA2_CMD_REG); + + outb(0x0f, DMA1_MASK_ALL_REG); /* 0,1,2,3 */ + outb(0x0e, DMA2_MASK_ALL_REG); /* 5,6,7 */ + break; default: printk("cpu_init: unrecognized cpu type %d\n", ! alpha_system_type); printk("cpu_init: doing default init\n"); /* fall thru to default inits */ *************** *** 222,263 **** case ST_DEC_AXPPCI_33: /* LCA NONAME */ case ST_DEC_2100_A50: /* APECS AVANTI/MUSTANG */ case ST_DEC_1000: /* APECS MIKASA */ printk("non-JENSEN cpu initialization\n"); /* ! * init the non-JENSEN base address global variables ! */ ! alpha_mem_base = 0xfffffc0200000000ULL; ! ! /* ! * determine if and which pass of LCA chip we have. */ ! percpu = (RPB_PERCPU *) ! ((long)rpb + rpb->rpb_percpu_slot_offset); ! if (percpu->rpb_proctype == PASS1_LCA_TYPE) { ! printk("Pass 1 LCA cpu detected\n"); ! alpha_io_base = 0xfffffc0300000000ULL; ! alpha_junk_base = 0xfffffc0300000000ULL; ! } ! else { ! alpha_io_base = 0xfffffc01c0000000ULL; ! alpha_junk_base = 0xfffffc01c0000000ULL; } - /* - * assign the transfer vectors for access routines - * to the set of "standard" entries - */ - alpha_inb = inb_std; - alpha_inw = inw_std; - alpha_inl = inl_std; - alpha_outb = outb_std; - alpha_outw = outw_std; - alpha_outl = outl_std; - alpha_jinb = inb_std; /* same as inb */ - alpha_joutb = outb_std; /* same as outb */ break; } } --- 283,401 ---- case ST_DEC_AXPPCI_33: /* LCA NONAME */ case ST_DEC_2100_A50: /* APECS AVANTI/MUSTANG */ case ST_DEC_1000: /* APECS MIKASA */ + case ST_DEC_EB66: /* LCA EB66 */ + case ST_DEC_EB64P: /* APECS EB64+ */ printk("non-JENSEN cpu initialization\n"); + /* init the PIC for the IRQs */ + alpha_pic_init(); + + #if 0 + /* JAE: for now, leave DMA and bus "windows" as set by the EB console */ /* ! * do DMA controller inits */ ! outb(0xff, DMA1_RESET_REG); ! outb(0xff, DMA2_RESET_REG); ! ! outb(0x10, DMA1_CMD_REG); /* rotate, REQHI, ACKLO */ ! outb(0x10, DMA2_CMD_REG); ! ! outb(0x0f, DMA1_MASK_ALL_REG); /* 0,1,2,3 */ ! outb(0x0e, DMA2_MASK_ALL_REG); /* 5,6,7 */ ! ! if ((proctype & 0xff) == LCA4_CPU) { ! write_cpureg_long(0x200000000ULL, 0xfffffc0180000100ULL); ! write_cpureg_long(0x0fff00000ULL, 0xfffffc0180000140ULL); } + #endif /* 0 */ break; } } + + alpha_pic_init() + { + /* + * Enable the NMI interrupt + */ + outb(0x00, 0x70); + + /* + * Set Special Mask Mode as an EOI precaution + */ + outb(0xc0, 0xa0); /*CTLR 2*/ + outb(0xc0, 0x20); /*CTLR 1*/ + + /* + * Enable Non Maskable Interrupt (NMI) masks + */ + outw(0x0000, 0x61); + outw(0x0c00, 0x461); + + /* + * Initialize PIC ELR to set all IRQ interrupts to Edge trigger, + * This should be power-up default, but let's do it any way + * and let EISA bus code set as needed + */ + outb(0x00, 0x4d1); + outb(0x00, 0x4d0); + + /* + * Initialize all PIC interrupts to be disabled just in case. + * They will be enabled through EISA bus support. + */ + outb(0xff, 0xa1); /* CTRL2 */ + outb(0xff, 0x21); /* CTRL1 */ + } + + + /* JAE: this needs to be done *ACCURATELY* for a given platform... */ + + #define USEC_DELAY 0x1000 + + void udelay(unsigned long usecs) + { + volatile int i, j; + + for (i = j = 0; i < USEC_DELAY * usecs; i++) + j += i; + } + + /* + * Alpha versions of the Linux Internet number representation + * function declarations. + */ + + unsigned long int ntohl(unsigned long int x) + { + return (((x & 0x000000ff) << 24) | + ((x & 0x0000ff00) << 8) | + ((x & 0x00ff0000) >> 8) | + ((x & 0xff000000) >> 24)); + } + + unsigned short int ntohs(unsigned short int x) + { + return (((x & 0x00ff) << 8) | + ((x & 0xff00) >> 8)); + } + + /* JAE: note that the below are identical to the above, so OPTIMIZE! */ + + unsigned long int htonl(unsigned long int x) + { + return (((x & 0x000000ff) << 24) | + ((x & 0x0000ff00) << 8) | + ((x & 0x00ff0000) >> 8) | + ((x & 0xff000000) >> 24)); + } + + unsigned short int htons(unsigned short int x) + { + return (((x & 0x00ff) << 8) | + ((x & 0xff00) >> 8)); + } + diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha/io.S LINUX_ALPHA_SDK/sources/linux/alpha/io.S *** LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha/io.S Fri Dec 30 15:37:46 1994 --- LINUX_ALPHA_SDK/sources/linux/alpha/io.S Thu Feb 9 15:30:56 1995 *************** *** 370,393 **** .end joutb_jen /* ! * read_cpureg_jen - Read a CPU register on JENSEN */ ! .globl read_cpureg_jen ! .ent read_cpureg_jen ! read_cpureg_jen: ldl v0,0(a0) ret zero,(ra) ! .end read_cpureg_jen /* ! * write_cpureg_jen - Write a CPU register on JENSEN */ ! .globl write_cpureg_jen ! .ent write_cpureg_jen ! write_cpureg_jen: stl a0,0(a1) ret zero,(ra) ! .end write_cpureg_jen --- 370,429 ---- .end joutb_jen /* ! * read_cpureg_long - Read a CPU register */ ! .globl read_cpureg_long ! .ent read_cpureg_long ! read_cpureg_long: ldl v0,0(a0) ret zero,(ra) ! .end read_cpureg_long /* ! * write_cpureg_long - Write a CPU register */ ! .globl write_cpureg_long ! .ent write_cpureg_long ! write_cpureg_long: stl a0,0(a1) + mb ret zero,(ra) ! .end write_cpureg_long + /* + * read_cpureg_quad - Read a CPU register + */ + + .globl read_cpureg_quad + .ent read_cpureg_quad + read_cpureg_quad: + ldq v0,0(a0) + ret zero,(ra) + .end read_cpureg_quad + /* + * write_cpureg_quad - Write a CPU register + */ + .globl write_cpureg_quad + .ent write_cpureg_quad + write_cpureg_quad: + stq a0,0(a1) + mb + ret zero,(ra) + .end write_cpureg_quad + + + /* + * Stub versions of the in/out routines for ADU/ISP/whatnot... + */ + .globl inb_stub, inw_stub, inl_stub + .globl outb_stub, outw_stub, outl_stub + inb_stub: + inw_stub: + inl_stub: + outb_stub: + outw_stub: + outl_stub: + bis zero,zero,v0 # Return zero + ret zero,(ra); diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha/stubs.c LINUX_ALPHA_SDK/sources/linux/alpha/stubs.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha/stubs.c Fri Dec 30 15:39:19 1994 --- LINUX_ALPHA_SDK/sources/linux/alpha/stubs.c Wed Feb 8 13:47:34 1995 *************** *** 1,8 **** --- 1,13 ---- + #include + /* Stubs for routines that are referenced by features we're not using yet. * Most of these should go away... */ + #ifndef CONFIG_INET loopback_init() { printk("Alpha STUB: loopback_init\n"); } + + #endif diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha_boot/Makefile LINUX_ALPHA_SDK/sources/linux/alpha_boot/Makefile *** LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha_boot/Makefile Tue Dec 13 14:44:22 1994 --- LINUX_ALPHA_SDK/sources/linux/alpha_boot/Makefile Fri Jan 27 11:33:50 1995 *************** *** 1,6 **** INCLUDES = -nostdinc -I. -I$(SRCBASE)/include/linux ! DEFINES = -DCALL_PAL_BROKEN ! CFLAGS = -g -m32addr $(DEFINES) $(INCLUDES) CC = alpha-dec-linux-gcc AS = alpha-dec-linux-gcc ASFLAGS = $(DEFINES) $(INCLUDES) --- 1,7 ---- INCLUDES = -nostdinc -I. -I$(SRCBASE)/include/linux ! DEFINES = -DCALL_PAL_BROKEN \ ! -DBOOT_COMPRESSED #-DBOOT_VERBOSE ! CFLAGS = -g -O -Wall -m32addr $(DEFINES) $(INCLUDES) CC = alpha-dec-linux-gcc AS = alpha-dec-linux-gcc ASFLAGS = $(DEFINES) $(INCLUDES) *************** *** 8,14 **** LD = alpha-dec-linux-ld LDFLAGS = -N -T linuxboot.ld ! OBJS = linuxboot.o boot_main.o printf.o boot_e2lib.o LIBS = ../lib/lib.a --- 9,16 ---- LD = alpha-dec-linux-ld LDFLAGS = -N -T linuxboot.ld ! OBJS = linuxboot.o boot_main.o printf.o boot_e2lib.o \ ! compressed/misc.o compressed/inflate.o compressed/unzip.o LIBS = ../lib/lib.a diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha_boot/boot_main.c LINUX_ALPHA_SDK/sources/linux/alpha_boot/boot_main.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha_boot/boot_main.c Thu Jan 19 10:56:40 1995 --- LINUX_ALPHA_SDK/sources/linux/alpha_boot/boot_main.c Fri Jan 27 11:33:52 1995 *************** *** 24,49 **** char iobuf[IO_SIZE]; char cons_readbuf[IO_SIZE]; char device_name[512]; ! extern U64 dispatch_pv; extern int cons_getc(int unit); static char * getenv(char *varname); ! /* Main entry point for system primary bootstrap code */ boot_main() { MEMDESC * md; CRB * crb; int i; - int retval; unsigned int vaddr; unsigned int physaddr; - unsigned int ophysaddr; unsigned int firstpfn = 0; unsigned int lastpfn = 0; - unsigned int lastfree = 0; - unsigned int npages = 0; unsigned int l1pfn; unsigned int l2pfn; unsigned int l3cpfn; --- 24,237 ---- char iobuf[IO_SIZE]; char cons_readbuf[IO_SIZE]; char device_name[512]; + unsigned int lastfree = 0; + unsigned int npages = 0; + int bytes_left; + char *dest_addr; ! extern U64 dispatch_pv; ! ! static int text_pages; ! static unsigned long text_entry_point = 0; extern int cons_getc(int unit); static char * getenv(char *varname); ! ! /* ! * This callback is invoked after the first block has been ! * read/decompressed. It checks the file-header, sets up kernel-code ! * mapping, then copies the block sans object-file header to the ! * lowest kernel-code address. ! */ ! void ! boot_first_block (char *buf, int block_len) ! { ! FILEHDR *fh; ! AOUTHDR *ah; ! SCNHDR *sh; ! PTE *l3pte; ! int offset; ! int i; ! char *src_addr; ! int nbytes; ! int kernel_pages; ! ! fh = (FILEHDR *)buf; ! ah = (AOUTHDR *)(&buf[sizeof(FILEHDR)]); ! ! #ifdef BOOT_VERBOSE ! printf("filehdr @0x%x, fh->f_opthdr = 0x%x, aouthdr @0x%x\n", ! fh, fh->f_opthdr, ah); ! printf("filehdr fields:\n"); ! printf(" f_magic: 0x%x, f_nscns: 0x%x, f_timdat: 0x%x\n", ! fh->f_magic, fh->f_nscns, fh->f_timdat); ! printf(" f_symptr: 0x%x%08x, f_nsyms: 0x%x\n", ! (fh->f_symptr>>32)&0xffffffff, fh->f_symptr&0xffffffff, ! fh->f_nsyms); ! printf(" f_opthdr: 0x%x, f_flags: 0x%x\n", ! fh->f_opthdr, fh->f_flags); ! ! printf("aouthdr fields:\n"); ! printf(" magic: 0%o, vstamp: 0x%x, bldrev: 0x%x, padcell: 0x%x\n", ! ah->magic, ah->vstamp, ah->bldrev, ah->padcell); ! printf(" text_start: %x%08x, ", ! (ah->text_start>>32) & 0xffffffff, ah->text_start&0xffffffff); ! printf(" tsize: %x%08x\n", ! (ah->tsize>>32) & 0xffffffff, ah->tsize&0xffffffff); ! printf(" data_start: %x%08x, ", ! (ah->data_start>>32) & 0xffffffff, ah->data_start&0xffffffff); ! printf(" dsize: %x%08x\n", ! (ah->dsize>>32) & 0xffffffff, ah->dsize&0xffffffff); ! printf(" bss_start: %x%08x, ", ! (ah->bss_start>>32) & 0xffffffff, ah->bss_start&0xffffffff); ! printf(" bsize: %x%08x\n", ! (ah->bsize>>32) & 0xffffffff, ah->bsize&0xffffffff); ! printf(" entry: %x%08x\n", ! (ah->entry>>32) & 0xffffffff, ah->entry&0xffffffff); ! printf(" gprmask: 0x%x, fprmask: 0x%x, gp_value: 0x%x%08x\n", ! ah->gprmask, ah->fprmask, ! (ah->gp_value>>32)&0xffffffff, ah->gp_value&0xffffffff); ! #endif ! ! /* Do some sanity checks... */ ! if (fh->f_magic != ALPHAMAGIC) { ! printf("Bad filehdr magic number 0x%x should be 0x%x\n", ! fh->f_magic, ALPHAMAGIC); ! halt(); ! } ! if ((ah->magic != OMAGIC) && (ah->magic != ZMAGIC)) { ! printf("Bad aouthdr magic number 0x%x should be 0x%x\n", ! ah->magic, OMAGIC); ! halt(); ! } ! if (ah->text_start != KERNEL_START_VADDR) { ! printf("Kernel must start at virtual address 0x%x, not 0x%x\n", ! KERNEL_START_VADDR, ah->text_start); ! halt(); ! } ! ! text_entry_point = ah->entry; ! ! /* Generate page tables for the kernel. */ ! kernel_pages = ((ah->tsize + ah->dsize + ah->bsize + ALPHA_PAGE_SIZE - 1) ! >> ALPHA_PG_SHIFT); ! ! if (kernel_pages > npages) { ! printf("Not enough physical memory for kernel; need %d pages, have %d\n", ! kernel_pages, npages); ! halt(); ! } ! ! text_pages = (ah->tsize + ALPHA_PAGE_SIZE - 1) >> ALPHA_PG_SHIFT; ! ! #ifdef BOOT_VERBOSE ! printf("First block loaded; kernel uses %d page(s)\n", kernel_pages); ! printf(" Text: 0x%x - 0x%x\n", ah->text_start, ah->text_start + ah->tsize - 1); ! printf(" Data: 0x%x - 0x%x\n", ah->data_start, ah->data_start + ah->dsize - 1); ! printf(" BSS: 0x%x - 0x%x\n", ah->bss_start, ah->bss_start + ah->bsize - 1); ! #endif ! ! l3pte = (PTE *)(KCODE_L3PT_VADDR); ! ! /* ! * While it's true nobody should write pte's in pieces thereby ! * leaving them in an inconsistent state, we can do so here with ! * impunity because we know NOBODY is going to try and use these ! * pages until WE'RE good-and-ready! ! */ ! #ifdef BOOT_VERBOSE ! printf("Setting up kernel page tables and zeroing memory\n"); ! #endif ! ! lastfree -= kernel_pages; ! npages -= kernel_pages; ! ! for (i = 0; i < kernel_pages; i++, l3pte++) { ! PTE tmppte; ! ! tmppte.pg_quadword = (U64)0; ! tmppte.pg_prot = PG_KERNEL_RW; ! ! /* Set up data pages to fault on execute... */ ! if (i >= text_pages) { ! tmppte.pg_flt_on = PG_FOE; ! } ! ! tmppte.pg_pfnum = lastfree + i + 1; ! tmppte.pg_v = 1; ! *l3pte = tmppte; ! zeropage_phys(l3pte->pg_pfnum); ! } ! tbia(); ! #ifdef BOOT_VERBOSE ! printf("Kernel page tables set up\n"); ! #endif ! /* ! * Copy the remainder of this first page into kernel memory. Here ! * we take advantage of the fact that the first scnhdr is that of ! * the .text section, which is at the start of the text segment. ! * This is where we start our offsets... ! */ ! sh = (SCNHDR *)(&buf[sizeof(FILEHDR)+sizeof(AOUTHDR)]); ! offset = sh->s_scnptr; ! #ifdef BOOT_VERBOSE ! printf("Text segment offset @0x%x (%d)\n", offset, offset); ! #endif ! src_addr = &buf[offset]; ! dest_addr = (char *)(KERNEL_START_VADDR); ! nbytes = block_len - offset; ! if (nbytes < 0) { ! printf("Oops: block_len only %d, expected at least %d\n", ! block_len, offset); ! halt(); ! } /* if */ ! memcpy(dest_addr, src_addr, nbytes); ! ! bytes_left = ah->tsize + ah->dsize - nbytes; ! dest_addr += nbytes; ! } /* boot_first_block */ ! ! ! static void ! plain_kernel(int fd) ! { ! int blkno; ! ! printf("Reading first block\n"); ! ! blkno = 0; /* logical block number */ ! ext2_bread(fd, blkno++, iobuf); ! boot_first_block(iobuf, sizeof(iobuf)); ! ! printf("Reading in kernel...\n"); ! ! /* Read in the remaining bytes of the kernel... */ ! ! while (bytes_left > 0) { ! ext2_bread(fd, blkno, dest_addr); ! ! /* go to next block */ ! dest_addr += IO_SIZE; ! bytes_left -= IO_SIZE; ! ++blkno; ! } ! } /* plain_kernel */ ! ! ! /* ! * Main entry point for system primary bootstrap code. ! */ ! void boot_main() { MEMDESC * md; CRB * crb; int i; unsigned int vaddr; unsigned int physaddr; unsigned int firstpfn = 0; unsigned int lastpfn = 0; unsigned int l1pfn; unsigned int l2pfn; unsigned int l3cpfn; *************** *** 55,68 **** int offset; int channel; int fd; - FILEHDR *fh; - AOUTHDR *ah; - SCNHDR *sh; - int nbytes; - int bytes_left; - int kernel_pages; - int text_pages; - char *src_addr; char *ramdisk_addr; char *dest_addr; int ramdisk_pages; --- 243,248 ---- *************** *** 96,106 **** * check the bad-page bitmap or anything... (we *can* add this * later if we'd like....) */ ! for(i = 0; i < md->md_nclusters; i++) { printf("memdesc %d: start_pfn: %d, page count: %d\n", i, md->md_clusters[i].start_pfn, md->md_clusters[i].page_count); ! if(md->md_clusters[i].usage == (U64)0) { /* We can use this one! */ firstpfn = md->md_clusters[i].start_pfn; npages = md->md_clusters[i].page_count; --- 276,286 ---- * check the bad-page bitmap or anything... (we *can* add this * later if we'd like....) */ ! for (i = 0; i < md->md_nclusters; i++) { printf("memdesc %d: start_pfn: %d, page count: %d\n", i, md->md_clusters[i].start_pfn, md->md_clusters[i].page_count); ! if (md->md_clusters[i].usage == (U64)0) { /* We can use this one! */ firstpfn = md->md_clusters[i].start_pfn; npages = md->md_clusters[i].page_count; *************** *** 111,117 **** printf("%d Kbytes physical memory available starting at 0x%x\n", (npages * ALPHA_PAGE_SIZE)/1024, firstpfn * ALPHA_PAGE_SIZE); ! if(npages < 128) { printf("Insufficient physical memory... halting!\n"); halt(); } --- 291,297 ---- printf("%d Kbytes physical memory available starting at 0x%x\n", (npages * ALPHA_PAGE_SIZE)/1024, firstpfn * ALPHA_PAGE_SIZE); ! if (npages < 128) { printf("Insufficient physical memory... halting!\n"); halt(); } *************** *** 157,163 **** halt(); } ! if(rpb->rpb_paddr != phys_readlong(rpb->rpb_paddr)) { printf("KSEG broken; 0x%x != 0x%x\n", rpb->rpb_paddr, phys_readlong(rpb->rpb_paddr)); halt(); --- 337,343 ---- halt(); } ! if (rpb->rpb_paddr != phys_readlong(rpb->rpb_paddr)) { printf("KSEG broken; 0x%x != 0x%x\n", rpb->rpb_paddr, phys_readlong(rpb->rpb_paddr)); halt(); *************** *** 240,246 **** vaddr += ALPHA_PAGE_SIZE; physaddr += sizeof(PTE); ! for(i = 0; i < (KERNEL_INITIAL_STACKSIZE >> ALPHA_PG_SHIFT); i++) { pfn = lastfree--; npages--; pte.pg_v = 1; --- 420,426 ---- vaddr += ALPHA_PAGE_SIZE; physaddr += sizeof(PTE); ! for (i = 0; i < (KERNEL_INITIAL_STACKSIZE >> ALPHA_PG_SHIFT); i++) { pfn = lastfree--; npages--; pte.pg_v = 1; *************** *** 307,313 **** pfn = rpb->rpb_paddr >> ALPHA_PG_SHIFT; physaddr = (l3upfn << ALPHA_PG_SHIFT) + (L3PT_OFFSET(vaddr)); ! for(i = 0; i < ((rpb->rpb_size + ALPHA_PAGE_SIZE - 1) >> ALPHA_PG_SHIFT); i++) { pte.pg_v = 1; pte.pg_prot = PG_KERNEL_RW; pte.pg_pfnum = pfn; --- 487,493 ---- pfn = rpb->rpb_paddr >> ALPHA_PG_SHIFT; physaddr = (l3upfn << ALPHA_PG_SHIFT) + (L3PT_OFFSET(vaddr)); ! for (i = 0; i < ((rpb->rpb_size + ALPHA_PAGE_SIZE - 1) >> ALPHA_PG_SHIFT); i++) { pte.pg_v = 1; pte.pg_prot = PG_KERNEL_RW; pte.pg_pfnum = pfn; *************** *** 334,340 **** physaddr = (l2pfn << ALPHA_PG_SHIFT) + L2PT_OFFSET(HWRPB_CRB_VADDR); pte.pg_pfnum = lastfree+1; pte.pg_v = 1; pte.pg_prot = PG_KERNEL_RW; ! for(i = 0; i < num_crb_l2ptes; i++, pte.pg_pfnum++, physaddr += sizeof(PTE)) { phys_writequad(physaddr, &pte); zeropage_phys(pte.pg_pfnum); } --- 514,520 ---- physaddr = (l2pfn << ALPHA_PG_SHIFT) + L2PT_OFFSET(HWRPB_CRB_VADDR); pte.pg_pfnum = lastfree+1; pte.pg_v = 1; pte.pg_prot = PG_KERNEL_RW; ! for (i = 0; i < num_crb_l2ptes; i++, pte.pg_pfnum++, physaddr += sizeof(PTE)) { phys_writequad(physaddr, &pte); zeropage_phys(pte.pg_pfnum); } *************** *** 343,356 **** * new memory space... */ physaddr = (lastfree+1)<crb_v_p_map_entries; i++) { int j; /* Need to do a full 64-bit shift here; some paddrs may indeed be * in high memory (e.g. I/O blocks in sparse address space...) */ pte.pg_pfnum = crb->crb_page_map[i].map_paddr >> ALPHA_PG_SHIFT; ! for(j = 0; j < crb->crb_page_map[i].map_pgcount; j++, pte.pg_pfnum++, physaddr += sizeof(PTE)) { phys_writequad(physaddr, &pte); --- 523,536 ---- * new memory space... */ physaddr = (lastfree+1)<crb_v_p_map_entries; i++) { int j; /* Need to do a full 64-bit shift here; some paddrs may indeed be * in high memory (e.g. I/O blocks in sparse address space...) */ pte.pg_pfnum = crb->crb_page_map[i].map_paddr >> ALPHA_PG_SHIFT; ! for (j = 0; j < crb->crb_page_map[i].map_pgcount; j++, pte.pg_pfnum++, physaddr += sizeof(PTE)) { phys_writequad(physaddr, &pte); *************** *** 364,376 **** i = prom_fixup(HWRPB_CRB_VADDR, HWRPB_SYSTEM_VADDR); /* If it fails, we're hosed! */ ! if(i != 0) { halt(); } /* FIXUP succeeded. Update the CRB map entries. */ vaddr = HWRPB_CRB_VADDR; ! for(i = 0; i < crb->crb_v_p_map_entries; i++) { crb->crb_page_map[i].map_vaddr = vaddr; vaddr += (crb->crb_page_map[i].map_pgcount << ALPHA_PG_SHIFT); } --- 544,556 ---- i = prom_fixup(HWRPB_CRB_VADDR, HWRPB_SYSTEM_VADDR); /* If it fails, we're hosed! */ ! if (i != 0) { halt(); } /* FIXUP succeeded. Update the CRB map entries. */ vaddr = HWRPB_CRB_VADDR; ! for (i = 0; i < crb->crb_v_p_map_entries; i++) { crb->crb_page_map[i].map_vaddr = vaddr; vaddr += (crb->crb_page_map[i].map_pgcount << ALPHA_PG_SHIFT); } *************** *** 396,562 **** printf("If you can read this, then the HWRPB got remapped correctly\n"); - enval = getenv("BOOTDEF_DEV"); - if(enval == 0) { - printf("Cannot get BOOTDEF_DEV environment variable... halting!\n"); - halt(); - } - - strcpy(device_name, enval); - #ifdef BOOT_VERBOSE - printf("FYI - BOOTDEF_DEV = %s\n", device_name); - #endif - - /* Get the name of the boot device... environment ID = BOOT_DEV */ - enval = getenv("BOOT_DEV"); - if(enval == 0) { - printf("Cannot get BOOT_DEV environment variable... halting!\n"); - halt(); - } - - - strcpy(device_name, enval); - - enval = getenv("BOOT_OSFLAGS"); - if(enval == 0) { - strcpy(boot_flags, "A"); - } - else { - strcpy(boot_flags, enval); - } - - if(boot_flags[0] == 'Q' || boot_flags[0] == 'Z') { - os_name[0] = 0; - } - else { - strcpy(os_name, "/linux"); - } - - - /* Open a channel to the boot device. */ - - channel = ext2_init(device_name); - - /* Compute the root filesystem size for later... */ - ramdisk_pages = (ext2_fs_size() + (ALPHA_PAGE_SIZE-1)) / ALPHA_PAGE_SIZE; - - for(;;) { - if(os_name[0]) { - printf("Searching for %s on device %s\n", os_name, device_name); - - fd = ext2_open(os_name); - - if(fd >= 0) break; - printf("Cannot find %s on device %s\n", os_name, device_name); - } - printf("OS to boot: "); - cons_gets(os_name); - } - - printf("Reading first block\n"); - - ext2_bread(fd, 0, iobuf); - - fh = (FILEHDR *)iobuf; - ah = (AOUTHDR *)(&iobuf[sizeof(FILEHDR)]); - - #ifdef BOOT_VERBOSE - printf("filehdr @0x%x, fh->f_opthdr = 0x%x, aouthdr @0x%x\n", - fh, fh->f_opthdr, ah); - printf("filehdr fields:\n"); - printf(" f_magic: 0x%x, f_nscns: 0x%x, f_timdat: 0x%x\n", - fh->f_magic, fh->f_nscns, fh->f_timdat); - printf(" f_symptr: 0x%x%08x, f_nsyms: 0x%x\n", - (fh->f_symptr>>32)&0xffffffff, fh->f_symptr&0xffffffff, - fh->f_nsyms); - printf(" f_opthdr: 0x%x, f_flags: 0x%x\n", - fh->f_opthdr, fh->f_flags); - - printf("aouthdr fields:\n"); - printf(" magic: 0%o, vstamp: 0x%x, bldrev: 0x%x, padcell: 0x%x\n", - ah->magic, ah->vstamp, ah->bldrev, ah->padcell); - printf(" text_start: %x%08x, ", (ah->text_start>>32) & 0xffffffff, ah->text_start&0xffffffff); - printf(" tsize: %x%08x\n", (ah->tsize>>32) & 0xffffffff, ah->tsize&0xffffffff); - printf(" data_start: %x%08x, ", (ah->data_start>>32) & 0xffffffff, ah->data_start&0xffffffff); - printf(" dsize: %x%08x\n", (ah->dsize>>32) & 0xffffffff, ah->dsize&0xffffffff); - printf(" bss_start: %x%08x, ", (ah->bss_start>>32) & 0xffffffff, ah->bss_start&0xffffffff); - printf(" bsize: %x%08x\n", (ah->bsize>>32) & 0xffffffff, ah->bsize&0xffffffff); - printf(" entry: %x%08x\n", (ah->entry>>32) & 0xffffffff, ah->entry&0xffffffff); - printf(" gprmask: 0x%x, fprmask: 0x%x, gp_value: 0x%x%08x\n", - ah->gprmask, ah->fprmask, - (ah->gp_value>>32)&0xffffffff, ah->gp_value&0xffffffff); - #endif - - /* Do some sanity checks... */ - if(fh->f_magic != ALPHAMAGIC) { - printf("Bad filehdr magic number 0x%x should be 0x%x\n", - fh->f_magic, ALPHAMAGIC); - halt(); - } - if((ah->magic != OMAGIC) && (ah->magic != ZMAGIC)) { - printf("Bad aouthdr magic number 0x%x should be 0x%x\n", - ah->magic, OMAGIC); - halt(); - } - if(ah->text_start != KERNEL_START_VADDR) { - printf("Kernel must start at virtual address 0x%x, not 0x%x\n", - KERNEL_START_VADDR, ah->text_start); - halt(); - } - - /* Generate page tables for the kernel. */ - kernel_pages = (ah->tsize + ah->dsize + ah->bsize + ALPHA_PAGE_SIZE - 1) >> ALPHA_PG_SHIFT; - - if(kernel_pages > npages) { - printf("Not enough physical memory for kernel; need %d pages, have %d\n", kernel_pages, npages); - halt(); - } - - text_pages = (ah->tsize + ALPHA_PAGE_SIZE - 1) >> ALPHA_PG_SHIFT; - - #ifdef BOOT_VERBOSE - printf("First block loaded; kernel uses %d page(s)\n", kernel_pages); - printf(" Text: 0x%x - 0x%x\n", ah->text_start, ah->text_start + ah->tsize - 1); - printf(" Data: 0x%x - 0x%x\n", ah->data_start, ah->data_start + ah->dsize - 1); - printf(" BSS: 0x%x - 0x%x\n", ah->bss_start, ah->bss_start + ah->bsize - 1); - #endif - - l3pte = (PTE *)(KCODE_L3PT_VADDR); - - /* While it's true nobody should write pte's in pieces thereby - * leaving them in an inconsistent state, we can do so here - * with impunity because we know NOBODY is going to try and use - * these pages until WE'RE good-and-ready! - */ - #ifdef BOOT_VERBOSE - printf("Setting up kernel page tables and zeroing memory\n"); - #endif - - lastfree -= kernel_pages; - npages -= kernel_pages; - - for(i = 0; i < kernel_pages; i++, l3pte++) { - PTE tmppte; - - tmppte.pg_quadword = (U64)0; - tmppte.pg_prot = PG_KERNEL_RW; - - /* Set up data pages to fault on execute... */ - if(i >= text_pages) { - tmppte.pg_flt_on = PG_FOE; - } - - tmppte.pg_pfnum = lastfree + i + 1; - tmppte.pg_v = 1; - *l3pte = tmppte; - zeropage_phys(l3pte->pg_pfnum); - } - - tbia(); - #ifdef BOOT_VERBOSE - printf("Kernel page tables set up\n"); - #endif - /* Map in our mini-kseg... */ { int n_kseg_pages; --- 576,581 ---- *************** *** 567,573 **** /* Figure out how many pages we'll need for kseg page tables */ n_kseg_pages = (lastpfn+ptes_per_page-1)/ptes_per_page; printf("Setting up mini-KSEG map... %d pages req'd\n", n_kseg_pages); ! kseg_pfn = lastfree - n_kseg_pages; #ifdef BOOT_VERBOSE printf("kseg_pfn = 0x%x\n", kseg_pfn); #endif --- 586,592 ---- /* Figure out how many pages we'll need for kseg page tables */ n_kseg_pages = (lastpfn+ptes_per_page-1)/ptes_per_page; printf("Setting up mini-KSEG map... %d pages req'd\n", n_kseg_pages); ! kseg_pfn = lastfree - n_kseg_pages + 1; #ifdef BOOT_VERBOSE printf("kseg_pfn = 0x%x\n", kseg_pfn); #endif *************** *** 583,589 **** #ifdef BOOT_VERBOSE printf("Mapping %d pages into kseg\n", lastpfn); #endif ! for(pfn = 0, l3pte = (PTE*)(kseg_pfn<s_scnptr; #ifdef BOOT_VERBOSE ! printf("Text segment offset @0x%x (%d)\n", offset, offset); #endif - src_addr = &iobuf[offset]; - dest_addr = (char *)(KERNEL_START_VADDR); - nbytes = (2*BLOCK_SIZE) - offset; - memcpy(dest_addr, src_addr, nbytes); ! printf("Reading in kernel...\n"); ! /* Read in the remaining bytes of the kernel... */ ! bytes_left = ah->tsize + ah->dsize - nbytes; ! dest_addr += nbytes; ! i = 1; /* Logical block number (we read in 0 already) */ ! while(bytes_left > 0) { ! unsigned int scratch; ! ext2_bread(fd, i, dest_addr); ! /* Go to next block */ ! dest_addr += IO_SIZE; ! bytes_left -= IO_SIZE; ! i++; } ext2_close(fd); ext2_finish(); /* Re-set the kernel text page tables to be readonly... */ l3pte = (PTE *)(KCODE_L3PT_VADDR); ! for(i = 0; i < text_pages-1; i++, l3pte++) { l3pte->pg_prot = PG_KERNEL_READ; } #ifdef BOOT_VERBOSE printf("Marked pages from 0x%x through 0x%x as READONLY\n", ! KERNEL_START_VADDR, ! KERNEL_START_VADDR + (i << ALPHA_PG_SHIFT) - 1); #endif tbia(); --- 627,728 ---- #endif } + enval = getenv("BOOTDEF_DEV"); + if (enval == 0) { + printf("Cannot get BOOTDEF_DEV environment variable... halting!\n"); + halt(); + } ! strcpy(device_name, enval); #ifdef BOOT_VERBOSE ! printf("FYI - BOOTDEF_DEV = %s\n", device_name); #endif ! /* Get the name of the boot device... environment ID = BOOT_DEV */ ! enval = getenv("BOOT_DEV"); ! if (enval == 0) { ! printf("Cannot get BOOT_DEV environment variable... halting!\n"); ! halt(); ! } ! ! strcpy(device_name, enval); ! ! enval = getenv("BOOT_OSFLAGS"); ! if (enval == 0) { ! strcpy(boot_flags, "A"); ! } ! else { ! strcpy(boot_flags, enval); ! } ! ! if (boot_flags[0] == 'Q' || boot_flags[0] == 'Z') { ! os_name[0] = 0; ! } ! else { ! #ifdef BOOT_COMPRESSED ! strcpy(os_name, "/linux.gz"); ! #else ! strcpy(os_name, "/linux"); ! #endif ! } ! ! ! /* Open a channel to the boot device. */ ! ! channel = ext2_init(device_name); ! ! /* Compute the root filesystem size for later... */ ! ramdisk_pages = (ext2_fs_size() + (ALPHA_PAGE_SIZE-1)) / ALPHA_PAGE_SIZE; ! ! for (;;) { ! if (os_name[0]) { ! printf("Searching for %s on device %s\n", os_name, device_name); ! ! fd = ext2_open(os_name); ! ! if (fd >= 0) break; ! ! ! printf("Cannot find %s on device %s\n", os_name, device_name); ! } ! printf("OS to boot: "); ! cons_gets(os_name); } + + #ifdef BOOT_COMPRESSED + { + extern void decompress_kernel (int fd, unsigned long block_size); + int len = strlen(os_name); + + if (len > 3 + && os_name[len-3] == '.' + && os_name[len-2] == 'g' + && os_name[len-1] == 'z') + { + decompress_kernel(fd, IO_SIZE); + } else { + plain_kernel(fd); + } /* if */ + } + #else + plain_kernel(fd); + #endif /* BOOT_COMPRESSED */ + ext2_close(fd); ext2_finish(); /* Re-set the kernel text page tables to be readonly... */ l3pte = (PTE *)(KCODE_L3PT_VADDR); ! for (i = 0; i < text_pages - 1; i++, l3pte++) { l3pte->pg_prot = PG_KERNEL_READ; } #ifdef BOOT_VERBOSE printf("Marked pages from 0x%x through 0x%x as READONLY\n", ! KERNEL_START_VADDR, ! KERNEL_START_VADDR + (i << ALPHA_PG_SHIFT) - 1); #endif tbia(); *************** *** 659,680 **** imb(); #ifdef ROOT_IS_RAMDISK ! /* For now, copy the root filesystem into RAM so that we can * provide a RAMdisk image to the kernel. * * First, allocate memory for the RAMdisk. */ lastfree -= (ramdisk_pages+1); npages -= (ramdisk_pages+1); ! ramdisk_addr = dest_addr = (char *)KSEG_ADDRESS((lastfree+1)<entry); printf(" firstpfn = %d, lastfree = %d, lastpfn = %d\n", ! firstpfn, lastfree, lastpfn); ! jump_to_kernel(ah->entry, firstpfn, lastfree, lastpfn, ramdisk_addr, ! (ramdisk_pages * ALPHA_PAGE_SIZE)/1024, boot_flags[0]); printf("If you can read this, something went VERY wrong!\n"); halt(); - } --- 838,851 ---- #endif ! printf("Bootstrap complete; jumping to kernel @0x%x\n", text_entry_point); printf(" firstpfn = %d, lastfree = %d, lastpfn = %d\n", ! firstpfn, lastfree, lastpfn); ! jump_to_kernel(text_entry_point, firstpfn, lastfree, lastpfn, ! ramdisk_addr, ! (ramdisk_pages * ALPHA_PAGE_SIZE)/1024, boot_flags[0]); printf("If you can read this, something went VERY wrong!\n"); halt(); } *************** *** 794,800 **** pte_physaddr = ptbr << 13; /* Get the Level 1 PTE */ ! if(using_osf_palcode) { phys_readquad(pte_physaddr, &pte1); } else { --- 867,873 ---- pte_physaddr = ptbr << 13; /* Get the Level 1 PTE */ ! if (using_osf_palcode) { phys_readquad(pte_physaddr, &pte1); } else { *************** *** 803,809 **** /* Calculate physaddr for L2 pte */ pte_physaddr = (pte1.pg_pfnum << 13) + (L2PT_INDEX(vaddr) << 3); ! if(using_osf_palcode) { phys_readquad(pte_physaddr, &pte2); } else { --- 876,882 ---- /* Calculate physaddr for L2 pte */ pte_physaddr = (pte1.pg_pfnum << 13) + (L2PT_INDEX(vaddr) << 3); ! if (using_osf_palcode) { phys_readquad(pte_physaddr, &pte2); } else { *************** *** 812,818 **** /* Calculate physaddr for L3 pte */ pte_physaddr = (pte2.pg_pfnum << 13) + (L3PT_INDEX(vaddr) << 3); ! if(using_osf_palcode) { phys_readquad(pte_physaddr, &pte3); } else { --- 885,891 ---- /* Calculate physaddr for L3 pte */ pte_physaddr = (pte2.pg_pfnum << 13) + (L3PT_INDEX(vaddr) << 3); ! if (using_osf_palcode) { phys_readquad(pte_physaddr, &pte3); } else { *************** *** 830,836 **** U64 retval; retval = prom_dispatcher(0x10, device_name, strlen(device_name)); ! if(retval & 0x1000000000000000LL) { return(-1); } else { --- 903,909 ---- U64 retval; retval = prom_dispatcher(0x10, device_name, strlen(device_name)); ! if (retval & 0x1000000000000000LL) { return(-1); } else { *************** *** 848,854 **** int cons_read(int channel, char * addr, int count, int offset) { ! if( ((count & (BLOCK_SIZE-1)) == 0) && ((offset & (BLOCK_SIZE-1)) == 0) ) { /* I/O is aligned... this is easy! */ --- 921,927 ---- int cons_read(int channel, char * addr, int count, int offset) { ! if ( ((count & (BLOCK_SIZE-1)) == 0) && ((offset & (BLOCK_SIZE-1)) == 0) ) { /* I/O is aligned... this is easy! */ *************** *** 867,877 **** blockoffset = (offset % BLOCK_SIZE); lbn = offset / BLOCK_SIZE; ! while(bytesleft > 0) { ! if((blockoffset == 0) && (bytesleft >= BLOCK_SIZE)) { /* This portion of the I/O is aligned, so read it straight in */ retval = (int)prom_dispatcher(0x13, channel, BLOCK_SIZE, addr, lbn); ! if(retval < 0) { printf("Error reading from %s: 0x%x\n", device_name, retval); return(-1); } --- 940,950 ---- blockoffset = (offset % BLOCK_SIZE); lbn = offset / BLOCK_SIZE; ! while (bytesleft > 0) { ! if ((blockoffset == 0) && (bytesleft >= BLOCK_SIZE)) { /* This portion of the I/O is aligned, so read it straight in */ retval = (int)prom_dispatcher(0x13, channel, BLOCK_SIZE, addr, lbn); ! if (retval < 0) { printf("Error reading from %s: 0x%x\n", device_name, retval); return(-1); } *************** *** 889,895 **** */ retval = (int)prom_dispatcher(0x13, channel, BLOCK_SIZE, cons_readbuf, lbn); ! if(retval != BLOCK_SIZE) { printf("Boot device read error, lbn %d, retval 0x%x\n", lbn, retval); return(-1); --- 962,968 ---- */ retval = (int)prom_dispatcher(0x13, channel, BLOCK_SIZE, cons_readbuf, lbn); ! if (retval != BLOCK_SIZE) { printf("Boot device read error, lbn %d, retval 0x%x\n", lbn, retval); return(-1); *************** *** 899,905 **** printf("cons_read: dispatch returns %d\n", retval); #endif } ! if(bytesleft < (BLOCK_SIZE-blockoffset)) { iosize = bytesleft; } else { --- 972,978 ---- printf("cons_read: dispatch returns %d\n", retval); #endif } ! if (bytesleft < (BLOCK_SIZE-blockoffset)) { iosize = bytesleft; } else { *************** *** 918,923 **** --- 991,998 ---- } } + + int cons_puts(unit, buf) { int written; *************** *** 925,932 **** remaining = strlen(buf); ! if(console_enabled) { ! while(remaining > 0) { written = (int)prom_dispatcher(2, unit, buf, remaining); buf += written; remaining -= written; --- 1000,1007 ---- remaining = strlen(buf); ! if (console_enabled) { ! while (remaining > 0) { written = (int)prom_dispatcher(2, unit, buf, remaining); buf += written; remaining -= written; *************** *** 938,949 **** } cons_gets(char * buf) { int i; int retval; ! for(i = 0; ; i++) { retval = cons_getc(0); retval &= 0xff; switch(retval) { --- 1013,1025 ---- } + void cons_gets(char * buf) { int i; int retval; ! for (i = 0; ; i++) { retval = cons_getc(0); retval &= 0xff; switch(retval) { *************** *** 958,964 **** case 0x08: /* BS */ case 0x7f: /* Delete */ ! if(i > 0) { cons_puts("\b \b"); i--; } --- 1034,1040 ---- case 0x08: /* BS */ case 0x7f: /* Delete */ ! if (i > 0) { cons_puts("\b \b"); i--; } *************** *** 1002,1021 **** int envnum = -1; int nbytes; ! for(i = 0; environ_table[i]; i++) { ! if(strcmp(varname, environ_table[i]) == 0) { envnum = i; break; } } ! if(envnum == -1) { return((char *)0); } /* Call prom dispatcher to get the environment variable... */ nbytes = (int)prom_dispatcher(0x22, envnum, env_val, sizeof(env_val)); ! if(nbytes <= 0) { return((char *)0); } else { --- 1078,1097 ---- int envnum = -1; int nbytes; ! for (i = 0; environ_table[i]; i++) { ! if (strcmp(varname, environ_table[i]) == 0) { envnum = i; break; } } ! if (envnum == -1) { return((char *)0); } /* Call prom dispatcher to get the environment variable... */ nbytes = (int)prom_dispatcher(0x22, envnum, env_val, sizeof(env_val)); ! if (nbytes <= 0) { return((char *)0); } else { *************** *** 1023,1027 **** return(env_val); } } - - --- 1099,1101 ---- diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha_boot/compressed/gzip.h LINUX_ALPHA_SDK/sources/linux/alpha_boot/compressed/gzip.h *** LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha_boot/compressed/gzip.h Thu Feb 9 19:57:28 1995 --- LINUX_ALPHA_SDK/sources/linux/alpha_boot/compressed/gzip.h Fri Jan 27 11:32:54 1995 *************** *** 0 **** --- 1,96 ---- + /* gzip.h -- common declarations for all gzip modules + * Copyright (C) 1992-1993 Jean-loup Gailly. + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + */ + #ifndef GZIP_H + #define GZIP_H + + #include + + #define memzero(s, n) memset ((s), 0, (n)) + + /* Return codes from gzip */ + #define OK 0 + #define ERROR 1 + #define WARNING 2 + + /* Compression methods (see algorithm.doc) */ + #define STORED 0 + #define COMPRESSED 1 + #define PACKED 2 + /* + * methods 3 to 7 reserved + */ + #define DEFLATED 8 + + extern long bytes_out; /* # of uncompressed bytes */ + extern int method; /* compression method */ + + #define INBUFSIZ 0x8000 /* input buffer size */ + #define WSIZE 0x8000 /* window size--must be a power of two, and */ + /* at least 32K for zip's deflate method */ + + unsigned char *inbuf; /* input buffer */ + unsigned char *window; /* sliding window and suffix table (unlzw) */ + + extern unsigned insize; /* valid bytes in inbuf */ + extern unsigned inptr; /* index of next byte to be processed in inbuf */ + extern unsigned outcnt; /* bytes in output buffer */ + + #define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */ + #define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */ + #define PKZIP_MAGIC "PK\003\004" /* Magic header for pkzip files */ + #define PACK_MAGIC "\037\036" /* Magic header for packed files */ + + /* gzip flag byte */ + #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ + #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ + #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ + #define ORIG_NAME 0x08 /* bit 3 set: original file name present */ + #define COMMENT 0x10 /* bit 4 set: file comment present */ + #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ + #define RESERVED 0xC0 /* bit 6,7: reserved */ + + /* internal file attribute */ + #define UNKNOWN (-1) + #define BINARY 0 + #define ASCII 1 + + + #define MIN_MATCH 3 + #define MAX_MATCH 258 + /* The minimum and maximum match lengths */ + + #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) + /* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + + #define MAX_DIST (WSIZE-MIN_LOOKAHEAD) + /* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + #define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) + #define put_char(c) {window[outcnt++]=(unsigned char)(c); if (outcnt==WSIZE)\ + flush_window();} + + /* Macros for getting two-byte and four-byte header values */ + #define SH(p) ((unsigned short)(unsigned char)((p)[0]) | ((unsigned short)(unsigned char)((p)[1]) << 8)) + #define LG(p) ((unsigned long)(SH(p)) | ((unsigned long)(SH((p)+2)) << 16)) + + /* in unzip.c */ + extern void unzip (int in, int out); + + /* in misc.c: */ + extern unsigned long updcrc (unsigned char *s, unsigned n); + extern void clear_bufs (void); + extern int fill_inbuf (void); + extern void flush_window (void); + extern void error (char *m); + + /* in inflate.c */ + extern int inflate (void); + + #endif /* GZIP_H */ diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha_boot/compressed/inflate.c LINUX_ALPHA_SDK/sources/linux/alpha_boot/compressed/inflate.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha_boot/compressed/inflate.c Thu Feb 9 19:57:29 1995 --- LINUX_ALPHA_SDK/sources/linux/alpha_boot/compressed/inflate.c Fri Jan 27 11:32:56 1995 *************** *** 0 **** --- 1,831 ---- + #if 0 + #define DEBG(x) {register long sp asm("30"); \ + printf("%s (sp=%lx)\n", x, sp);} + #define DEBG1(x) {register long sp asm("30"); \ + printf(" %s (sp=%lx)\n", x, sp);} + #else + #define DEBG(x) + #define DEBG1(x) + #endif + + /* + * inflate.c -- Not copyrighted 1992 by Mark Adler + * version c10p1, 10 January 1993 + */ + + /* + * Adapted for booting Linux by Hannu Savolainen 1993 + * based on gzip-1.0.3 + */ + + #ifndef lint + static char rcsid[] = "$Id: inflate.c,v 1.1 1995/01/27 16:32:56 jestabro Exp $"; + #endif + + #include "gzip.h" + #define slide window + + #if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H) + # include + # include + #endif + + struct huft { + unsigned char e; /* number of extra bits or operation */ + unsigned char b; /* number of bits in this code or subcode */ + union { + unsigned short n; /* literal, length base, or distance base */ + struct huft *t; /* pointer to next level of table */ + } v; + }; + + + /* Function prototypes */ + int huft_build (unsigned *, unsigned, unsigned, unsigned short *, + unsigned short *, struct huft **, int *); + int huft_free (struct huft *); + int inflate_codes (struct huft *, struct huft *, int, int); + int inflate_stored (void); + int inflate_fixed (void); + int inflate_dynamic (void); + int inflate_block (int *); + int inflate (void); + + + #define wp outcnt + #define flush_output(w) (wp=(w),flush_window()) + + /* Tables for deflate from PKZIP's appnote.txt. */ + static unsigned border[] = { + /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + }; + + static unsigned short cplens[] = { + /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 + }; + + /* note: see note #13 above about the 258 in this list. */ + static unsigned short cplext[] = { + /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99 /* 99==invalid */ + }; + + static unsigned short cpdist[] = { + /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577 + }; + + static unsigned short cpdext[] = { + /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13 + }; + + + unsigned long bb; /* bit buffer */ + unsigned bk; /* bits in bit buffer */ + + unsigned short mask_bits[] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff + }; + + #define NEXTBYTE() (unsigned char)get_byte() + #define NEEDBITS(n) {while(k<(n)){b|=((unsigned long)NEXTBYTE())<>=(n);k-=(n);} + + int lbits = 9; /* bits in base literal/length lookup table */ + int dbits = 6; /* bits in base distance lookup table */ + + + /* + * If BMAX needs to be larger than 16, then h and x[] should be + * unsigned long. + */ + #define BMAX 16 /* maximum bit length of any code (16 for explode) */ + #define N_MAX 288 /* maximum number of codes in any set */ + + + unsigned hufts; /* track memory usage */ + + + /* + * Given a list of code lengths and a maximum table size, make a set + * of tables to decode that set of codes. Return zero on success, one + * if the given code set is incomplete (the tables are still built in + * this case), two if the input is invalid (all zero length codes or + * an oversubscribed set of lengths), and three if not enough + * memory. + */ + int + huft_build(b, n, s, d, e, t, m) + unsigned *b; /* code lengths in bits (all assumed <= BMAX) */ + unsigned n; /* number of codes (assumed <= N_MAX) */ + unsigned s; /* number of simple-valued codes (0..s-1) */ + unsigned short *d; /* list of base values for non-simple codes */ + unsigned short *e; /* list of extra bits for non-simple codes */ + struct huft **t; /* result: starting table */ + int *m; /* maximum lookup bits, returns actual */ + { + unsigned a; /* counter for codes of length k */ + unsigned c[BMAX+1]; /* bit length count table */ + unsigned f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register unsigned i; /* counter, current code */ + register unsigned j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + register unsigned *p; /* pointer into c[], b[], or v[] */ + register struct huft *q; /* points to current table */ + struct huft r; /* table entry for structure assignment */ + struct huft *u[BMAX]; /* table stack */ + unsigned v[N_MAX]; /* values in order of bit length */ + register int w; /* bits before this table == (l * h) */ + unsigned x[BMAX+1]; /* bit offsets, then code stack */ + unsigned *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + unsigned z; /* number of entries in current table */ + + DEBG("huft1 "); + + /* Generate counts for each bit length */ + memzero(c, sizeof(c)); + p = b; i = n; + do { + c[*p++]++; /* assume all entries <= BMAX */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (struct huft *)NULL; + *m = 0; + return 0; + } + + DEBG("huft2 "); + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((unsigned)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((unsigned)l > i) + l = i; + *m = l; + + DEBG("huft3 "); + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return 2; /* bad input: more codes than bits */ + if ((y -= c[i]) < 0) + return 2; + c[i] += y; + + DEBG("huft4 "); + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + DEBG("huft5 "); + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + + DEBG("h6 "); + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (struct huft *)NULL; /* just to keep compilers happy */ + q = (struct huft *)NULL; /* ditto */ + z = 0; /* ditto */ + DEBG("h6a "); + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + DEBG("h6b "); + a = c[k]; + while (a--) + { + DEBG("h6b1 "); + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { + DEBG1("1 "); + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = (z = g - w) > (unsigned)l ? l : z; /* upper limit on table size */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + DEBG1("2 "); + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + DEBG1("3 "); + z = 1 << j; /* table entries for j-bit table */ + + /* allocate and link in new table */ + q = (struct huft *)malloc((z + 1)*sizeof(struct huft)); + DEBG1("4 "); + hufts += z + 1; /* track memory usage */ + *t = q + 1; /* link to list for huft_free() */ + *(t = &(q->v.t)) = (struct huft *)NULL; + u[h] = ++q; /* table starts after link */ + + DEBG1("5 "); + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.b = (unsigned char)l; /* bits to dump before this table */ + r.e = (unsigned char)(16 + j); /* bits in this table */ + r.v.t = q; /* pointer to this table */ + j = i >> (w - l); /* (get around Turbo C bug) */ + u[h-1][j] = r; /* connect to last table */ + } + DEBG1("6 "); + } + DEBG("h6c "); + + /* set up table entry in r */ + r.b = (unsigned char)(k - w); + if (p >= v + n) + r.e = 99; /* out of values--invalid code */ + else if (*p < s) + { + r.e = (unsigned char)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ + r.v.n = *p++; /* simple code is just the value */ + } + else + { + r.e = (unsigned char)e[*p - s]; /* non-simple--look up in lists */ + r.v.n = d[*p++ - s]; + } + DEBG("h6d "); + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + while ((i & ((1 << w) - 1)) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + } + DEBG("h6e "); + } + DEBG("h6f "); + } + + DEBG("huft7 "); + + /* Return true (1) if we were given an incomplete table */ + return y != 0 && g != 1; + } + + + + int huft_free(t) + struct huft *t; /* table to free */ + /* Free the malloc'ed tables built by huft_build(), which makes a linked + list of the tables it made, with the links in a dummy first entry of + each table. */ + { + register struct huft *p, *q; + + + /* Go through linked list, freeing from the malloced (t[-1]) address. */ + p = t; + while (p != (struct huft *)NULL) + { + q = (--p)->v.t; + free(p); + p = q; + } + return 0; + } + + + int inflate_codes(tl, td, bl, bd) + struct huft *tl, *td; /* literal/length and distance decoder tables */ + int bl, bd; /* number of bits decoded by tl[] and td[] */ + /* inflate (decompress) the codes in a deflated (compressed) block. + Return an error code or zero if it all goes ok. */ + { + register unsigned e; /* table entry flag/number of extra bits */ + unsigned n, d; /* length and index for copy */ + unsigned w; /* current window position */ + struct huft *t; /* pointer to table entry */ + unsigned ml, md; /* masks for bl and bd bits */ + register unsigned long b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* make local copies of globals */ + b = bb; /* initialize bit buffer */ + k = bk; + w = wp; /* initialize window position */ + + /* inflate the coded data */ + ml = mask_bits[bl]; /* precompute masks for speed */ + md = mask_bits[bd]; + for (;;) /* do until end of block */ + { + NEEDBITS((unsigned)bl) + if ((e = (t = tl + ((unsigned)b & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + if (e == 16) /* then it's a literal */ + { + slide[w++] = (unsigned char)t->v.n; + if (w == WSIZE) + { + flush_output(w); + w = 0; + } + } + else /* it's an EOB or a length */ + { + /* exit if end of block */ + if (e == 15) + break; + + /* get length of block to copy */ + NEEDBITS(e) + n = t->v.n + ((unsigned)b & mask_bits[e]); + DUMPBITS(e); + + /* decode distance of block to copy */ + NEEDBITS((unsigned)bd) + if ((e = (t = td + ((unsigned)b & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + NEEDBITS(e) + d = w - t->v.n - ((unsigned)b & mask_bits[e]); + DUMPBITS(e) + + /* do the copy */ + do { + n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e); + #if !defined(NOMEMCPY) && !defined(DEBUG) + if (w - d >= e) /* (this test assumes unsigned comparison) */ + { + memcpy(slide + w, slide + d, e); + w += e; + d += e; + } + else /* do it slow to avoid memcpy() overlap */ + #endif /* !NOMEMCPY */ + do { + slide[w++] = slide[d++]; + } while (--e); + if (w == WSIZE) + { + flush_output(w); + w = 0; + } + } while (n); + } + } + + + /* restore the globals from the locals */ + wp = w; /* restore global window pointer */ + bb = b; /* restore global bit buffer */ + bk = k; + + /* done */ + return 0; + } + + + + int inflate_stored() + /* "decompress" an inflated type 0 (stored) block. */ + { + unsigned n; /* number of bytes in block */ + unsigned w; /* current window position */ + register unsigned long b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + DEBG(""); + return 0; + } + + + + int inflate_fixed() + /* decompress an inflated type 1 (fixed Huffman codes) block. We should + either replace this with a custom decoder, or at least precompute the + Huffman tables. */ + { + int i; /* temporary variable */ + struct huft *tl; /* literal/length code table */ + struct huft *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int bd; /* lookup bits for td */ + unsigned l[288]; /* length list for huft_build */ + + DEBG(" 1) + { + huft_free(tl); + + DEBG(">"); + return i; + } + + + /* decompress until an end-of-block code */ + if (inflate_codes(tl, td, bl, bd)) + return 1; + + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + return 0; + } + + + + int inflate_dynamic() + /* decompress an inflated type 2 (dynamic Huffman codes) block. */ + { + int i; /* temporary variables */ + unsigned j; + unsigned l; /* last length */ + unsigned m; /* mask for bit lengths table */ + unsigned n; /* number of lengths to get */ + struct huft *tl; /* literal/length code table */ + struct huft *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int bd; /* lookup bits for td */ + unsigned nb; /* number of bit length codes */ + unsigned nl; /* number of literal/length codes */ + unsigned nd; /* number of distance codes */ + #ifdef PKZIP_BUG_WORKAROUND + unsigned ll[288+32]; /* literal/length and distance code lengths */ + #else + unsigned ll[286+30]; /* literal/length and distance code lengths */ + #endif + register unsigned long b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + DEBG(" 288 || nd > 32) + #else + if (nl > 286 || nd > 30) + #endif + return 1; /* bad lengths */ + + DEBG("dyn1 "); + + /* read in bit-length-code lengths */ + for (j = 0; j < nb; j++) + { + NEEDBITS(3) + ll[border[j]] = (unsigned)b & 7; + DUMPBITS(3) + } + for (; j < 19; j++) + ll[border[j]] = 0; + + DEBG("dyn2 "); + + /* build decoding table for trees--single level, 7 bit lookup */ + bl = 7; + if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) + { + if (i == 1) + huft_free(tl); + return i; /* incomplete code set */ + } + + DEBG("dyn3 "); + + /* read in literal and distance code lengths */ + n = nl + nd; + m = mask_bits[bl]; + i = l = 0; + while ((unsigned)i < n) + { + NEEDBITS((unsigned)bl) + j = (td = tl + ((unsigned)b & m))->b; + DUMPBITS(j) + j = td->v.n; + if (j < 16) /* length of code in bits (0..15) */ + ll[i++] = l = j; /* save last length in l */ + else if (j == 16) /* repeat last length 3 to 6 times */ + { + NEEDBITS(2) + j = 3 + ((unsigned)b & 3); + DUMPBITS(2) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = l; + } + else if (j == 17) /* 3 to 10 zero length codes */ + { + NEEDBITS(3) + j = 3 + ((unsigned)b & 7); + DUMPBITS(3) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = 0; + l = 0; + } + else /* j == 18: 11 to 138 zero length codes */ + { + NEEDBITS(7) + j = 11 + ((unsigned)b & 0x7f); + DUMPBITS(7) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = 0; + l = 0; + } + } + + DEBG("dyn4 "); + + /* free decoding table for trees */ + huft_free(tl); + + DEBG("dyn5 "); + + /* restore the global bit buffer */ + bb = b; + bk = k; + + DEBG("dyn5a "); + + /* build the decoding tables for literal/length and distance codes */ + bl = lbits; + if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) + { + DEBG("dyn5b "); + if (i == 1) { + error(" incomplete literal tree\n"); + huft_free(tl); + } + return i; /* incomplete code set */ + } + DEBG("dyn5c "); + bd = dbits; + if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) + { + DEBG("dyn5d "); + if (i == 1) { + error(" incomplete distance tree\n"); + #ifdef PKZIP_BUG_WORKAROUND + i = 0; + } + #else + huft_free(td); + } + huft_free(tl); + return i; /* incomplete code set */ + #endif + } + + DEBG("dyn6 "); + + /* decompress until an end-of-block code */ + if (inflate_codes(tl, td, bl, bd)) + return 1; + + DEBG("dyn7 "); + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + + DEBG(">"); + return 0; + } + + + + int inflate_block(e) + int *e; /* last block flag */ + /* decompress an inflated block */ + { + unsigned t; /* block type */ + register unsigned long b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + DEBG(""); + + /* bad block type */ + return 2; + } + + + + int inflate() + /* decompress an inflated entry */ + { + int e; /* last block flag */ + int r; /* result code */ + unsigned h; /* maximum struct huft's malloc'ed */ + + + /* initialize window, bit buffer */ + wp = 0; + bk = 0; + bb = 0; + + + /* decompress until the last block */ + h = 0; + do { + hufts = 0; + if ((r = inflate_block(&e)) != 0) + return r; + if (hufts > h) + h = hufts; + } while (!e); + + /* Undo too much lookahead. The next read will be byte aligned so we + * can discard unused bits in the last meaningful byte. + */ + while (bk >= 8) { + bk -= 8; + inptr--; + } + + /* flush out slide */ + flush_output(wp); + + /* return success */ + return 0; + } diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha_boot/compressed/misc.c LINUX_ALPHA_SDK/sources/linux/alpha_boot/compressed/misc.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha_boot/compressed/misc.c Thu Feb 9 19:57:29 1995 --- LINUX_ALPHA_SDK/sources/linux/alpha_boot/compressed/misc.c Fri Jan 27 11:32:58 1995 *************** *** 0 **** --- 1,294 ---- + /* + * misc.c + * + * This is a collection of several routines from gzip-1.0.3 + * adapted for Linux. + * + * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 + * puts by Nick Holloway 1993 + * + * Adapted to Linux/Alpha boot by David Mosberger (davidm@cs.arizona.edu). + */ + #include "gzip.h" + #include + + /* + * Maximum kernel text size: + */ + #define MAX_KERNEL_SIZE (2*1024*1024) + + /* + * From boot_main.c: + */ + extern int bytes_left; + extern char *dest_addr; + extern unsigned int lastfree; + extern unsigned int _end[]; + + unsigned char *inbuf; + unsigned char *window; + unsigned outcnt; + unsigned insize; + unsigned inptr; + long bytes_out; + int method; + + static unsigned long crc_32_tab[256]; + static unsigned long free_mem_ptr; + static unsigned long phys_end; + static int input_fd = -1; + static int block_size = 0; + + + void + makecrc(void) + { + /* Not copyrighted 1990 Mark Adler */ + unsigned long c; /* crc shift register */ + unsigned long e; /* polynomial exclusive-or pattern */ + int i; /* counter for all possible eight bit values */ + int k; /* byte being shifted into crc apparatus */ + + /* terms of polynomial defining this crc (except x^32): */ + static int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* Make exclusive-or pattern from polynomial */ + e = 0; + for (i = 0; i < sizeof(p)/sizeof(int); i++) + e |= 1L << (31 - p[i]); + + crc_32_tab[0] = 0; + + for (i = 1; i < 256; i++) { + c = 0; + for (k = i | 256; k != 1; k >>= 1) { + c = c & 1 ? (c >> 1) ^ e : c >> 1; + if (k & 1) + c ^= e; + } + crc_32_tab[i] = c; + } + } + + + /* + * Run a set of bytes through the crc shift register. If s is a NULL + * pointer, then initialize the crc shift register contents instead. + * Return the current crc in either case. + * + * Input: + * S pointer to bytes to pump through. + * N number of bytes in S[]. + */ + unsigned long + updcrc(unsigned char *s, unsigned n) + { + register unsigned long c; + static unsigned long crc = + (unsigned long)0xffffffffL; /* shift register contents */ + + if (!s) { + c = 0xffffffffL; + } else { + c = crc; + while (n--) { + c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8); + } + } + crc = c; + return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ + } + + + void *malloc(int size) + { + free_mem_ptr = (free_mem_ptr - size) & ~(sizeof(long) - 1); + if ((unsigned long) free_mem_ptr <= phys_end) { + error("malloc: out of memory"); + } + return (void*) free_mem_ptr; + } + + + void free(void *where) + { + /* Don't care */ + } + + + /* + * Clear input and output buffers + */ + void + clear_bufs(void) + { + outcnt = 0; + insize = inptr = 0; + bytes_out = 0; + } + + + void + error(char *x) + { + printf("\n\n%s\n\n -- System stopped (press reset to halt).", x); + while(1); /* Halt */ + } + + + /* + * Check the magic number of the input file and update ofname if an + * original name was given and to_stdout is not set. + * Return the compression method, -1 for error, -2 for warning. + * Set inptr to the offset of the next byte to be processed. + * This function may be called repeatedly for an input file consisting + * of several contiguous gzip'ed members. + * IN assertions: there is at least one remaining compressed member. + * If the member is a zip file, it must be the only one. + */ + static int + get_method(void) + { + unsigned char flags; + char magic[2]; /* magic header */ + + magic[0] = get_byte(); + magic[1] = get_byte(); + + method = -1; /* unknown yet */ + /* assume multiple members in gzip file except for record oriented I/O */ + + if (memcmp(magic, GZIP_MAGIC, 2) == 0 + || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) { + + method = get_byte(); + flags = get_byte(); + if ((flags & ENCRYPTED) != 0) + error("Input is encrypted\n"); + if ((flags & CONTINUATION) != 0) + error("Multi part input\n"); + if ((flags & RESERVED) != 0) + error("Input has invalid flags\n"); + get_byte(); /* skip over timestamp */ + get_byte(); + get_byte(); + get_byte(); + + get_byte(); /* skip extra flags */ + get_byte(); /* skip OS type */ + + if ((flags & EXTRA_FIELD) != 0) { + unsigned len = get_byte(); + len |= get_byte() << 8; + while (len--) get_byte(); + } + + /* Get original file name if it was truncated */ + if ((flags & ORIG_NAME) != 0) { + /* skip name */ + while (get_byte() != 0) /* null */ ; + } /* if */ + + /* Discard file comment if any */ + if ((flags & COMMENT) != 0) { + while (get_byte() != 0) /* null */ ; + } + } else + error("unknown compression method"); + return method; + } + + + /* + * Fill the input buffer and return the first byte in it. This is called + * only when the buffer is empty and at least one byte is really needed. + */ + int + fill_inbuf(void) + { + static int block_number = 0; + int i; + + if (INBUFSIZ % block_size != 0) { + printf("INBUFSIZ (%d) is not multiple of block-size (%d)\n", + INBUFSIZ, block_size); + error("Bad block-size"); + } /* if */ + + for (i = 0; i < INBUFSIZ/block_size; ++i) { + ext2_bread(input_fd, block_number++, &inbuf[i * block_size]); + } /* for */ + insize = INBUFSIZ; + + inptr = 1; + return inbuf[0]; + } /* fill_inbuf */ + + + /* + * Write the output window window[0..outcnt-1] holding uncompressed + * data and update crc. + */ + void + flush_window(void) + { + if (!outcnt) { + return; + } /* if */ + + updcrc(window, outcnt); + bytes_out += outcnt; + + if (dest_addr) { + /* + * Simply copy adjacent to previous block: + */ + if (outcnt > bytes_left) { + outcnt = bytes_left; + } /* if */ + memcpy((char*)dest_addr, window, outcnt); + dest_addr += outcnt; + bytes_left -= outcnt; + } else { + boot_first_block(window, outcnt); + } /* if */ + } /* flush_window */ + + + /* + * We have to be careful with the memory-layout during decompression. + * The stack we're currently executing on lies somewhere between the + * end of this program (given by _end) and lastfree. However, as I + * understand it, there is no guarantee that the stack occupies the + * lowest page-frame following the page-frames occupied by this code. + * + * Thus, we are stuck allocating memory towards decreasing addresses, + * starting with lastfree. Unfortunately, to know the size of the + * kernel-code, we need to decompress the image and we have a circular + * dependency. To make the long story short: we put a limit on + * the maximum kernel size at MAX_KERNEL_SIZE and allocate dynamic + * memory starting at (lastfree << ALPHA_PG_SHIFT) - MAX_KERNEL_SIZE. + */ + void + decompress_kernel(int fd, unsigned long block_len) + { + input_fd = fd; + block_size = block_len; + dest_addr = 0; + phys_end = LINUX_KSEG_VADDR + virttophys((char*) _end); + free_mem_ptr = + LINUX_KSEG_VADDR + ((lastfree + 1) << ALPHA_PG_SHIFT) - MAX_KERNEL_SIZE; + + inbuf = (unsigned char*) malloc(INBUFSIZ); + window = (unsigned char*) malloc(WSIZE); + + clear_bufs(); + makecrc(); + + printf("Uncompressing Linux..."); + + method = get_method(); + unzip(0, 0); + + printf("done.\n"); + } diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha_boot/compressed/unzip.c LINUX_ALPHA_SDK/sources/linux/alpha_boot/compressed/unzip.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/alpha_boot/compressed/unzip.c Thu Feb 9 19:57:29 1995 --- LINUX_ALPHA_SDK/sources/linux/alpha_boot/compressed/unzip.c Fri Jan 27 11:32:59 1995 *************** *** 0 **** --- 1,135 ---- + /* unzip.c -- decompress files in gzip or pkzip format. + * Copyright (C) 1992-1993 Jean-loup Gailly + * + * Adapted for Linux booting by Hannu Savolainen 1993 + * + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + * + * The code in this file is derived from the file funzip.c written + * and put in the public domain by Mark Adler. + */ + + /* + * This version can extract files in gzip or pkzip format. For the + * latter, only the first entry is extracted, and it has to be either + * deflated or stored. + */ + + #ifndef lint + static char rcsid[] = "$Id: unzip.c,v 1.1 1995/01/27 16:32:59 jestabro Exp $"; + #endif + + #include "gzip.h" + + #include + + /* PKZIP header definitions */ + #define LOCSIG 0x04034b50L /* four-byte lead-in (lsb first) */ + #define LOCFLG 6 /* offset of bit flag */ + #define CRPFLG 1 /* bit for encrypted entry */ + #define EXTFLG 8 /* bit for extended local header */ + #define LOCHOW 8 /* offset of compression method */ + #define LOCTIM 10 /* file mod time (for decryption) */ + #define LOCCRC 14 /* offset of crc */ + #define LOCSIZ 18 /* offset of compressed size */ + #define LOCLEN 22 /* offset of uncompressed length */ + #define LOCFIL 26 /* offset of file name field length */ + #define LOCEXT 28 /* offset of extra field length */ + #define LOCHDR 30 /* size of local header, including sig */ + #define EXTHDR 16 /* size of extended local header, inc sig */ + + + /* Globals */ + + int pkzip = 0; /* set for a pkzip file */ + int extended = 0; /* set if extended local header */ + + /* + * Unzip in to out. This routine works on both gzip and pkzip files. + * + * IN assertions: the buffer inbuf contains already the beginning of + * the compressed data, from offsets inptr to insize-1 included. + * The magic header has already been checked. The output buffer is cleared. + */ + void unzip(in, out) + int in, out; /* input and output file descriptors */ + { + unsigned long orig_crc = 0; /* original crc */ + unsigned long orig_len = 0; /* original uncompressed length */ + int n; + unsigned char buf[EXTHDR]; /* extended local header */ + + /* ifd = in; + ofd = out; */ + + updcrc(NULL, 0); /* initialize crc */ + + if (pkzip && !extended) { /* crc and length at the end otherwise */ + orig_crc = LG(inbuf + LOCCRC); + orig_len = LG(inbuf + LOCLEN); + } + + /* Decompress */ + if (method == DEFLATED) { + + int res = inflate(); + + if (res == 3) { + error("out of memory"); + } else if (res != 0) { + error("invalid compressed format"); + } + + } else if (pkzip && method == STORED) { + register unsigned long n = LG(inbuf + LOCLEN); + + if (n != LG(inbuf + LOCSIZ)) { + error("length mismatch"); + } + while (n--) { + unsigned char c = get_byte(); + put_char(c); + } + } else { + error("internal error, invalid method"); + } + + /* Get the crc and original length */ + if (!pkzip) { + /* crc32 (see algorithm.doc) + * uncompressed input size modulo 2^32 + */ + for (n = 0; n < 8; n++) { + buf[n] = get_byte(); /* may cause an error if EOF */ + } + orig_crc = LG(buf); + orig_len = LG(buf+4); + + } else if (extended) { /* If extended header, check it */ + /* signature - 4bytes: 0x50 0x4b 0x07 0x08 + * CRC-32 value + * compressed size 4-bytes + * uncompressed size 4-bytes + */ + for (n = 0; n < EXTHDR; n++) { + buf[n] = get_byte(); /* may cause an error if EOF */ + } + orig_crc = LG(buf+4); + orig_len = LG(buf+12); + } + + /* Validate decompression */ + if (orig_crc != updcrc(buf, 0)) { + error("crc error"); + } + if (orig_len != bytes_out) { + error("length error"); + } + + /* Check if there are more entries in a pkzip file */ + if (pkzip && inptr + 4 < insize && LG(inbuf+inptr) == LOCSIG) { + error("zip file has more than one entry"); + } + extended = pkzip = 0; /* for next file */ + } diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/config.in LINUX_ALPHA_SDK/sources/linux/config.in *** LINUX_ALPHA_SDK/sources/linux.0.1.0/config.in Tue Dec 13 21:09:56 1994 --- LINUX_ALPHA_SDK/sources/linux/config.in Thu Feb 9 19:22:08 1995 *************** *** 12,17 **** --- 12,18 ---- bool 'Limit memory to low 16MB' CONFIG_MAX_16M n bool 'System V IPC' CONFIG_SYSVIPC y bool 'Use -m486 flag for 486-specific optimizations' CONFIG_M486 n + bool 'PCI support' CONFIG_PCI n * * Alpha-specific setup * *************** *** 42,57 **** * * SCSI low-level drivers * ! bool 'Adaptec AHA152X support' CONFIG_SCSI_AHA152X y ! bool 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 y bool 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 y ! bool 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN y ! bool 'Generic NCR5380 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 y ! bool 'PAS16 SCSI support' CONFIG_SCSI_PAS16 y ! bool 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE y ! bool 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 y ! bool 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR y ! bool '7000FASST SCSI support' CONFIG_SCSI_7000FASST y fi * * Network device support --- 43,58 ---- * * SCSI low-level drivers * ! bool 'Adaptec AHA152X support' CONFIG_SCSI_AHA152X n ! bool 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 n bool 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 y ! bool 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN n ! bool 'Generic NCR5380 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 n ! bool 'PAS16 SCSI support' CONFIG_SCSI_PAS16 n ! bool 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE n ! bool 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 n ! bool 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR n ! bool '7000FASST SCSI support' CONFIG_SCSI_7000FASST n fi * * Network device support *************** *** 63,77 **** : Skipping ethercard configuration options... : else ! bool 'SLIP (serial line) support' CONFIG_SLIP n if [ "$CONFIG_SLIP" = "y" ] ! bool ' CSLIP compressed headers' SL_COMPRESSED y # bool ' SLIP debugging on' SL_DUMP y fi #bool 'PPP (point-to-point) support' CONFIG_PPP n bool 'PLIP (parallel port) support' CONFIG_PLIP n bool 'NE2000/NE1000 support' CONFIG_NE2000 n ! bool 'WD80*3 support' CONFIG_WD80x3 y bool 'SMC Ultra support' CONFIG_ULTRA n bool '3c501 support' CONFIG_EL1 n bool '3c503 support' CONFIG_EL2 n --- 64,78 ---- : Skipping ethercard configuration options... : else ! bool 'SLIP (serial line) support' CONFIG_SLIP y if [ "$CONFIG_SLIP" = "y" ] ! bool ' CSLIP compressed headers' SL_COMPRESSED y # bool ' SLIP debugging on' SL_DUMP y fi #bool 'PPP (point-to-point) support' CONFIG_PPP n bool 'PLIP (parallel port) support' CONFIG_PLIP n bool 'NE2000/NE1000 support' CONFIG_NE2000 n ! bool 'WD80*3 support' CONFIG_WD80x3 n bool 'SMC Ultra support' CONFIG_ULTRA n bool '3c501 support' CONFIG_EL1 n bool '3c503 support' CONFIG_EL2 n *************** *** 83,89 **** bool 'AT1700 support' CONFIG_AT1700 n #bool 'Zenith Z-Note support' CONFIG_ZNET n #bool 'EtherExpress support' CONFIG_EEXPRESS n ! bool 'DEPCA support' CONFIG_DEPCA n #bool 'NI52** support' CONFIG_NI52 n #bool 'NI65** support' CONFIG_NI65 n #bool 'Ansel Communications EISA 3200 support' CONFIG_AC3200 n --- 84,90 ---- bool 'AT1700 support' CONFIG_AT1700 n #bool 'Zenith Z-Note support' CONFIG_ZNET n #bool 'EtherExpress support' CONFIG_EEXPRESS n ! bool 'DEPCA support' CONFIG_DEPCA y #bool 'NI52** support' CONFIG_NI52 n #bool 'NI65** support' CONFIG_NI65 n #bool 'Ansel Communications EISA 3200 support' CONFIG_AC3200 n diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/block/floppy.c LINUX_ALPHA_SDK/sources/linux/drivers/block/floppy.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/block/floppy.c Tue Dec 13 14:44:01 1994 --- LINUX_ALPHA_SDK/sources/linux/drivers/block/floppy.c Wed Feb 8 14:01:23 1995 *************** *** 1,3 **** --- 1,13 ---- + /* #define FDC_FIFO_UNTESTED /* JAE: AHA1742 floppy is 82077... ? */ + + /* + #define DEBUG_ENTRY + #define DEBUG_REDO + #define DEBUG_RW_INT + #define DEBUG_RESULT + #define DEBUG_DMA + */ + /* * linux/kernel/floppy.c * *************** *** 75,81 **** #include #include #include - #include #include #include --- 85,90 ---- *************** *** 265,272 **** --- 274,288 ---- * corrupted/lost. Alignment of these is enforced in boot/head.s. * Note that you must not change the sizes below without updating head.s. */ + #ifdef i386 extern char tmp_floppy_area[BLOCK_SIZE]; extern char floppy_track_buffer[512*2*MAX_BUFFER_SECTORS]; + #elif defined(__alpha) + /* JAE: these are declared and inited in init/main.c:start_kernel() */ + /* JAE: and they hold KSEG addresses, since data is moved in/out by CPU */ + extern char *tmp_floppy_area; + extern char *floppy_track_buffer; + #endif /* i386 | __alpha */ static void redo_fd_request(void); *************** *** 296,301 **** --- 312,321 ---- static void select_callback(unsigned long unused) { + #ifdef DEBUG_ENTRY + printk("select_callback() entry\n"); + #endif /* DEBUG_ENTRY */ + floppy_ready(); } *************** *** 303,308 **** --- 323,332 ---- { static struct timer_list select = { NULL, NULL, 0, 0, select_callback }; + #ifdef DEBUG_ENTRY + printk("floppy_select(0x%x) entry\n", nr); + #endif /* DEBUG_ENTRY */ + if (current_drive == (current_DOR & 3)) { floppy_ready(); return; *************** *** 319,324 **** --- 343,352 ---- static void motor_on_callback(unsigned long nr) { + #ifdef DEBUG_ENTRY + printk("motor_on_callback(0x%x) entry\n", nr); + #endif /* DEBUG_ENTRY */ + running |= 0x10 << nr; floppy_select(nr); } *************** *** 333,343 **** --- 361,387 ---- static void motor_off_callback(unsigned long nr) { unsigned char mask = ~(0x10 << nr); + #ifdef __alpha + int oldipl; + #endif /* __alpha */ + + #ifdef DEBUG_ENTRY + printk("motor_off_callback(0x%x) entry\n", nr); + #endif /* DEBUG_ENTRY */ + + #ifdef i386 cli(); + #elif defined(__alpha) + oldipl = ipl(IPLMAX); + #endif /* i386 | __alpha */ running &= mask; current_DOR &= mask; outb(current_DOR,FD_DOR); + #ifdef i386 sti(); + #elif defined(__alpha) + ipl(oldipl); + #endif /* i386 | __alpha */ } static struct timer_list motor_off_timer[4] = { *************** *** 351,356 **** --- 395,404 ---- { unsigned char mask = 0x10 << nr; + #ifdef DEBUG_ENTRY + printk("floppy_on(0x%x) entry\n", nr); + #endif /* DEBUG_ENTRY */ + del_timer(motor_off_timer + nr); if (mask & running) floppy_select(nr); *************** *** 367,372 **** --- 415,424 ---- static void floppy_off(unsigned int nr) { + #ifdef DEBUG_ENTRY + printk("floppy_off(0x%x) entry\n", nr); + #endif /* DEBUG_ENTRY */ + del_timer(motor_off_timer+nr); motor_off_timer[nr].expires = 3*HZ; add_timer(motor_off_timer+nr); *************** *** 374,379 **** --- 426,435 ---- void request_done(int uptodate) { + #ifdef DEBUG_ENTRY + printk("request_done() entry\n"); + #endif /* DEBUG_ENTRY */ + timer_active &= ~(1 << FLOPPY_TIMER); if (format_status != FORMAT_BUSY) end_request(uptodate); *************** *** 393,398 **** --- 449,458 ---- { unsigned int mask = 1 << (bh->b_dev & 0x03); + #ifdef DEBUG_ENTRY + printk("floppy_change() entry\n"); + #endif /* DEBUG_ENTRY */ + if (MAJOR(bh->b_dev) != MAJOR_NR) { printk("floppy_changed: not a floppy\n"); return 0; *************** *** 428,443 **** --- 488,515 ---- return 0; } + #ifdef i386 #define copy_buffer(from,to) \ __asm__("cld ; rep ; movsl" \ : \ :"c" (BLOCK_SIZE/4),"S" ((long)(from)),"D" ((long)(to)) \ :"cx","di","si") + #elif defined(__alpha) + #define copy_buffer(from,to) \ + memcpy(to, from, BLOCK_SIZE) + #endif /* i386 | __alpha */ static void setup_DMA(void) { unsigned long addr,count; unsigned char dma_code; + #ifdef __alpha + int oldipl; + #endif /* __alpha */ + + #ifdef DEBUG_ENTRY + printk("setup_DMA() entry\n"); + #endif /* DEBUG_ENTRY */ dma_code = DMA_WRITE; if (command == FD_READ) *************** *** 459,472 **** if (command == FD_WRITE) copy_buffer(CURRENT->buffer,tmp_floppy_area); } cli(); disable_dma(FLOPPY_DMA); clear_dma_ff(FLOPPY_DMA); ! set_dma_mode(FLOPPY_DMA, (command == FD_READ)? DMA_MODE_READ : DMA_MODE_WRITE); set_dma_addr(FLOPPY_DMA, addr); set_dma_count(FLOPPY_DMA, count); enable_dma(FLOPPY_DMA); sti(); } static void output_byte(char byte) --- 531,566 ---- if (command == FD_WRITE) copy_buffer(CURRENT->buffer,tmp_floppy_area); } + #ifdef i386 cli(); + #elif defined(__alpha) + oldipl = ipl(IPLMAX); + #endif /* i386 | __alpha */ disable_dma(FLOPPY_DMA); clear_dma_ff(FLOPPY_DMA); ! set_dma_mode(FLOPPY_DMA, ! (command == FD_READ) ? DMA_MODE_READ : DMA_MODE_WRITE); ! #ifdef i386 set_dma_addr(FLOPPY_DMA, addr); + #elif defined(__alpha) + #ifdef DEBUG_DMA + printk("setup_DMA: setting address 0x%x\n", virttophys(addr)); + #endif /* DEBUG_DMA */ + #if 1 + clear_dma_ff(FLOPPY_DMA); /* do we really need this? */ + #endif /* 0 */ + set_dma_addr(FLOPPY_DMA, virttophys(addr)); + #if 1 + clear_dma_ff(FLOPPY_DMA); /* do we really need this? */ + #endif /* 0 */ + #endif /* i386 | __alpha */ set_dma_count(FLOPPY_DMA, count); enable_dma(FLOPPY_DMA); + #ifdef i386 sti(); + #elif defined(__alpha) + ipl(oldipl); + #endif /* i386 | __alpha */ } static void output_byte(char byte) *************** *** 492,502 **** { int i = 0, counter, status; ! if (reset) return -1; for (counter = 0 ; counter < 10000 ; counter++) { status = inb_p(FD_STATUS)&(STATUS_DIR|STATUS_READY|STATUS_BUSY); if (status == STATUS_READY) { return i; } if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) { --- 586,606 ---- { int i = 0, counter, status; ! if (reset) { ! #ifdef DEBUG_RESULT ! printk("result() returning -1\n"); ! #endif /* DEBUG_RESULT */ return -1; + } for (counter = 0 ; counter < 10000 ; counter++) { status = inb_p(FD_STATUS)&(STATUS_DIR|STATUS_READY|STATUS_BUSY); if (status == STATUS_READY) { + #ifdef DEBUG_RESULT + int j; + printk("result() returning %d:", i); + for (j = 0; j < i; j++) printk(" 0x%02x", reply_buffer[j]); + printk("\n"); + #endif /* DEBUG_RESULT */ return i; } if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) { *************** *** 517,522 **** --- 621,630 ---- { int errors; + #ifdef DEBUG_ENTRY + printk("bad_flp_intr() entry\n"); + #endif /* DEBUG_ENTRY */ + current_track = NO_TRACK; if (format_status == FORMAT_BUSY) errors = ++format_errors; *************** *** 542,547 **** --- 650,659 ---- */ static inline void perpendicular_mode(unsigned char rate) { + #ifdef DEBUG_ENTRY + printk("perpendicular_mode() entry\n"); + #endif /* DEBUG_ENTRY */ + if (fdc_version == FDC_TYPE_82077) { output_byte(FD_PERPENDICULAR); if (rate & 0x40) { *************** *** 573,578 **** --- 685,694 ---- */ static void configure_fdc_mode(void) { + #ifdef DEBUG_ENTRY + printk("configure_fdc_mode() entry\n"); + #endif /* DEBUG_ENTRY */ + if (need_configure && (fdc_version == FDC_TYPE_82077)) { /* Enhanced version with FIFO & vertical recording. */ output_byte(FD_CONFIGURE); *************** *** 615,627 **** static void rw_interrupt(void) { char * buffer_area; ! int nr; char bad; nr = result(); /* check IC to find cause of interrupt */ switch ((ST0 & ST0_INTR)>>6) { case 1: /* error occured during command execution */ bad = 1; if (ST1 & ST1_WP) { printk(DEVICE_NAME ": Drive %d is write protected\n", current_drive); --- 731,750 ---- static void rw_interrupt(void) { char * buffer_area; ! int nr, i; char bad; + #ifdef DEBUG_ENTRY + printk("rw_interrupt() entry\n"); + #endif /* DEBUG_ENTRY */ + nr = result(); /* check IC to find cause of interrupt */ switch ((ST0 & ST0_INTR)>>6) { case 1: /* error occured during command execution */ + #ifdef DEBUG_RW_INT + printk("rw_interrupt: case 1: error\n"); + #endif /* DEBUG_RW_INT */ bad = 1; if (ST1 & ST1_WP) { printk(DEVICE_NAME ": Drive %d is write protected\n", current_drive); *************** *** 631,638 **** if (ftd_msg[ST0 & ST0_DS]) printk(DEVICE_NAME ": Over/Underrun - retrying\n"); /* could continue from where we stopped, but ... */ bad = 0; ! } else if (CURRENT_ERRORS > min_report_error_cnt[ST0 & ST0_DS]) { printk(DEVICE_NAME " %d: ", ST0 & ST0_DS); if (ST0 & ST0_ECE) { printk("Recalibrate failed!"); --- 754,766 ---- if (ftd_msg[ST0 & ST0_DS]) printk(DEVICE_NAME ": Over/Underrun - retrying\n"); /* could continue from where we stopped, but ... */ + #ifdef DEBUG_RW_INT + printk("rw_interrupt: case 1: ST1 & ST1_OR\n"); + #endif /* DEBUG_RW_INT */ bad = 0; ! } else ! if (CURRENT_ERRORS > min_report_error_cnt[ST0 & ST0_DS]) ! { printk(DEVICE_NAME " %d: ", ST0 & ST0_DS); if (ST0 & ST0_ECE) { printk("Recalibrate failed!"); *************** *** 660,665 **** --- 788,796 ---- } if (bad) bad_flp_intr(); + #ifdef DEBUG_RW_INT + printk("rw_interrupt: case 1: calling redo_fd_request()\n"); + #endif /* DEBUG_RW_INT */ redo_fd_request(); return; case 2: /* invalid command given */ *************** *** 672,683 **** --- 803,820 ---- redo_fd_request(); return; default: /* (0) Normal command termination */ + #ifdef DEBUG_RW_INT + printk("rw_interrupt: default: normal termination\n"); + #endif /* DEBUG_RW_INT */ break; } if (probing) { int drive = MINOR(CURRENT->dev); + #ifdef DEBUG_RW_INT + printk("rw_interrupt: probing...\n"); + #endif /* DEBUG_RW_INT */ if (ftd_msg[drive]) printk("Auto-detected floppy type %s in fd%d\n", floppy->name,drive); *************** *** 686,691 **** --- 823,831 ---- probing = 0; } if (read_track) { + #ifdef DEBUG_RW_INT + printk("rw_interrupt: read_track...\n"); + #endif /* DEBUG_RW_INT */ buffer_track = seek_track; buffer_drive = current_drive; buffer_area = floppy_track_buffer + *************** *** 694,699 **** --- 834,842 ---- } else if (command == FD_READ && (unsigned long)(CURRENT->buffer) >= LAST_DMA_ADDR) copy_buffer(tmp_floppy_area,CURRENT->buffer); + #ifdef DEBUG_RW_INT + printk("rw_interrupt: calling request_done(1) and redo...\n"); + #endif /* DEBUG_RW_INT */ request_done(1); redo_fd_request(); } *************** *** 707,712 **** --- 850,859 ---- */ inline void setup_rw_floppy(void) { + #ifdef DEBUG_ENTRY + printk("setup_rw_floppy() entry\n"); + #endif /* DEBUG_ENTRY */ + setup_DMA(); do_floppy = rw_interrupt; output_byte(command); *************** *** 744,749 **** --- 891,900 ---- */ static void seek_interrupt(void) { + #ifdef DEBUG_ENTRY + printk("seek_interrupt() entry\n"); + #endif /* DEBUG_ENTRY */ + /* sense drive status */ output_byte(FD_SENSEI); if (result() != 2 || (ST0 & 0xF8) != 0x20 || ST1 != seek_track) { *************** *** 765,770 **** --- 916,925 ---- */ static void transfer(void) { + #ifdef DEBUG_ENTRY + printk("transfer() entry\n"); + #endif /* DEBUG_ENTRY */ + read_track = (command == FD_READ) && (CURRENT_ERRORS < 4) && (floppy->sect <= MAX_BUFFER_SECTORS); *************** *** 798,803 **** --- 953,962 ---- static void recal_interrupt(void) { + #ifdef DEBUG_ENTRY + printk("recal_interrupt() entry\n"); + #endif /* DEBUG_ENTRY */ + output_byte(FD_SENSEI); current_track = NO_TRACK; if (result()!=2 || (ST0 & 0xE0) == 0x60) *************** *** 811,816 **** --- 970,979 ---- static void unexpected_floppy_interrupt(void) { + #ifdef DEBUG_ENTRY + printk("unexpected_floppy_interrupt() entry\n"); + #endif /* DEBUG_ENTRY */ + current_track = NO_TRACK; output_byte(FD_SENSEI); printk(DEVICE_NAME ": unexpected interrupt\n"); *************** *** 822,827 **** --- 985,994 ---- static void recalibrate_floppy(void) { + #ifdef DEBUG_ENTRY + printk("recalibrate_floppy() entry\n"); + #endif /* DEBUG_ENTRY */ + recalibrate = 0; current_track = 0; do_floppy = recal_interrupt; *************** *** 838,843 **** --- 1005,1014 ---- { short i; + #ifdef DEBUG_ENTRY + printk("reset_interrupt() entry\n"); + #endif /* DEBUG_ENTRY */ + for (i=0; i<4; i++) { output_byte(FD_SENSEI); (void) result(); *************** *** 866,871 **** --- 1037,1049 ---- static void reset_floppy(void) { int i; + #ifdef __alpha + int oldipl; + #endif /* __alpha */ + + #ifdef DEBUG_ENTRY + printk("reset_floppy() entry\n"); + #endif /* DEBUG_ENTRY */ do_floppy = reset_interrupt; reset = 0; *************** *** 876,902 **** --- 1054,1108 ---- need_configure = 1; if (!initial_reset_flag) printk("Reset-floppy called\n"); + #ifdef i386 cli(); + #elif defined(__alpha) + oldipl = ipl(IPLMAX); + #endif /* i386 | __alpha */ outb_p(current_DOR & ~0x04, FD_DOR); for (i=0 ; i<1000 ; i++) __asm__("nop"); outb(current_DOR, FD_DOR); + #ifdef i386 sti(); + #elif defined(__alpha) + ipl(oldipl); + #endif /* i386 | __alpha */ } static void floppy_shutdown(void) { + #ifdef __alpha + int oldipl; + #endif /* __alpha */ + + #ifdef DEBUG_ENTRY + printk("floppy_shutdown() entry\n"); + #endif /* DEBUG_ENTRY */ + + #ifdef i386 cli(); + #elif defined(__alpha) + oldipl = ipl(IPLMAX); + #endif /* i386 | __alpha */ do_floppy = NULL; request_done(0); recover = 1; reset_floppy(); + #ifdef i386 sti(); + #elif defined(__alpha) + ipl(oldipl); + #endif /* i386 | __alpha */ redo_fd_request(); } static void shake_done(void) { + #ifdef DEBUG_ENTRY + printk("shake_done() entry\n"); + #endif /* DEBUG_ENTRY */ + current_track = NO_TRACK; if (inb(FD_DIR) & 0x80) request_done(0); *************** *** 905,910 **** --- 1111,1120 ---- static int retry_recal(void (*proc)(void)) { + #ifdef DEBUG_ENTRY + printk("retry_recal() entry\n"); + #endif /* DEBUG_ENTRY */ + output_byte(FD_SENSEI); if (result() == 2 && (ST0 & 0x10) != 0x10) return 0; do_floppy = proc; *************** *** 915,925 **** --- 1125,1143 ---- static void shake_zero(void) { + #ifdef DEBUG_ENTRY + printk("shake_zero() entry\n"); + #endif /* DEBUG_ENTRY */ + if (!retry_recal(shake_zero)) shake_done(); } static void shake_one(void) { + #ifdef DEBUG_ENTRY + printk("shake_one() entry\n"); + #endif /* DEBUG_ENTRY */ + if (retry_recal(shake_one)) return; do_floppy = shake_done; output_byte(FD_SEEK); *************** *** 929,934 **** --- 1147,1156 ---- static void floppy_ready(void) { + #ifdef DEBUG_ENTRY + printk("floppy_ready() entry\n"); + #endif /* DEBUG_ENTRY */ + if (inb(FD_DIR) & 0x80) { changed_floppies |= 1<sect / 6; /* a ``cylinder'' is two tracks plus a little stepping time */ *************** *** 994,1002 **** char * buffer_area; int device; ! if (CURRENT && CURRENT->dev < 0) return; repeat: if (format_status == FORMAT_WAIT) format_status = FORMAT_BUSY; if (format_status != FORMAT_BUSY) { --- 1220,1242 ---- char * buffer_area; int device; ! #if defined(DEBUG_ENTRY) || defined(DEBUG_REDO) ! printk("redo_fd_request() entry\n"); ! #endif /* DEBUG_ENTRY */ ! ! if (CURRENT && CURRENT->dev < 0) { ! #ifdef DEBUG_REDO ! printk("redo_fd_request: CURRENT inapprop.\n"); ! #endif /* DEBUG_REDO */ ! return; ! } repeat: + + #ifdef DEBUG_REDO + printk("redo_fd_request: at 'repeat'\n"); + #endif /* DEBUG_REDO */ + if (format_status == FORMAT_WAIT) format_status = FORMAT_BUSY; if (format_status != FORMAT_BUSY) { *************** *** 1006,1011 **** --- 1246,1256 ---- fdc_busy = 0; wake_up(&fdc_wait); CLEAR_INTR; + + #ifdef DEBUG_REDO + printk("redo_fd_request: !CURRENT\n"); + #endif /* DEBUG_REDO */ + return; } if (MAJOR(CURRENT->dev) != MAJOR_NR) *************** *** 1026,1031 **** --- 1271,1279 ---- probing = 1; floppy = base_type[device & 3]; if (!floppy) { + #ifdef DEBUG_REDO + printk("redo_fd_request: calling request_done(0): !floppy\n"); + #endif /* DEBUG_REDO */ request_done(0); goto repeat; } *************** *** 1034,1045 **** --- 1282,1299 ---- } } if (format_status != FORMAT_BUSY) { + #ifdef DEBUG_REDO + printk("redo_fd_request: format_status != FORMAT_BUSY\n"); + #endif /* DEBUG_REDO */ if (current_drive != CURRENT_DEV) { current_track = NO_TRACK; current_drive = CURRENT_DEV; } block = CURRENT->sector; if (block+2 > floppy->size) { + #ifdef DEBUG_REDO + printk("redo_fd_request: calling request_done(0): block+2>floppy->size\n"); + #endif /* DEBUG_REDO */ request_done(0); goto repeat; } *************** *** 1058,1068 **** --- 1312,1328 ---- goto repeat; } } else { + #ifdef DEBUG_REDO + printk("redo_fd_request: format_status == FORMAT_BUSY\n"); + #endif /* DEBUG_REDO */ if (current_drive != (format_req.device & 3)) current_track = NO_TRACK; current_drive = format_req.device & 3; if (((unsigned) format_req.track) >= floppy->track || (format_req.head & 0xfffe) || probing) { + #ifdef DEBUG_REDO + printk("redo_fd_request: calling request_done(0): format_req...\n"); + #endif /* DEBUG_REDO */ request_done(0); goto repeat; } *************** *** 1073,1078 **** --- 1333,1341 ---- command = FD_FORMAT; setup_format_params(); } + #ifdef DEBUG_REDO + printk("redo_fd_request: setting timer_active\n"); + #endif /* DEBUG_REDO */ timer_table[FLOPPY_TIMER].expires = jiffies+10*HZ; timer_active |= 1 << FLOPPY_TIMER; if ((seek_track == buffer_track) && *************** *** 1081,1086 **** --- 1344,1352 ---- ((sector + head*floppy->sect)<<9); if (command == FD_READ) { copy_buffer(buffer_area,CURRENT->buffer); + #ifdef DEBUG_REDO + printk("redo_fd_request: calling request_done(1): FD_READ in buffer!\n"); + #endif /* DEBUG_REDO */ request_done(1); goto repeat; } else if (command == FD_WRITE) *************** *** 1091,1104 **** --- 1357,1389 ---- sector++; del_timer(motor_off_timer + current_drive); floppy_on(current_drive); + #ifdef DEBUG_REDO + printk("redo_fd_request: done.\n"); + #endif /* DEBUG_REDO */ } void do_fd_request(void) { + #ifdef __alpha + int oldipl; + #endif /* __alpha */ + + #ifdef DEBUG_ENTRY + printk("do_fd_request() entry\n"); + #endif /* DEBUG_ENTRY */ + + #ifdef i386 cli(); + #elif defined(__alpha) + oldipl = ipl(IPLMAX); + #endif /* i386 | __alpha */ while (fdc_busy) sleep_on(&fdc_wait); fdc_busy = 1; + #ifdef i386 sti(); + #elif defined(__alpha) + ipl(oldipl); + #endif /* i386 | __alpha */ redo_fd_request(); } *************** *** 1107,1112 **** --- 1392,1404 ---- { int i,drive,cnt,okay; struct floppy_struct *this_floppy; + #ifdef __alpha + int oldipl; + #endif /* __alpha */ + + #ifdef DEBUG_ENTRY + printk("fd_ioctl() entry: cmd 0x%x param 0x%x\n", cmd, param); + #endif /* DEBUG_ENTRY */ switch (cmd) { RO_IOCTLS(inode->i_rdev,param); *************** *** 1120,1128 **** --- 1412,1428 ---- case FDFMTEND: if (!suser()) return -EPERM; + #ifdef i386 cli(); + #elif defined(__alpha) + oldipl = ipl(IPLMAX); + #endif /* i386 | __alpha */ fake_change |= 1 << (drive & 3); + #ifdef i386 sti(); + #elif defined(__alpha) + ipl(oldipl); + #endif /* i386 | __alpha */ drive &= 3; cmd = FDCLRPRM; break; *************** *** 1142,1148 **** --- 1442,1452 ---- return -EPERM; if (fd_ref[drive & 3] != 1) return -EBUSY; + #ifdef i386 cli(); + #elif defined(__alpha) + oldipl = ipl(IPLMAX); + #endif /* i386 | __alpha */ while (format_status != FORMAT_NONE) sleep_on(&format_done); for (cnt = 0; cnt < sizeof(struct format_descr); cnt++) *************** *** 1162,1168 **** --- 1466,1476 ---- while (format_status != FORMAT_OKAY && format_status != FORMAT_ERROR) sleep_on(&format_done); + #ifdef i386 sti(); + #elif defined(__alpha) + ipl(oldipl); + #endif /* i386 | __alpha */ okay = format_status == FORMAT_OKAY; format_status = FORMAT_NONE; floppy_off(drive & 3); *************** *** 1171,1179 **** --- 1479,1495 ---- case FDFLUSH: if (!permission(inode, 2)) return -EPERM; + #ifdef i386 cli(); + #elif defined(__alpha) + oldipl = ipl(IPLMAX); + #endif /* i386 | __alpha */ fake_change |= 1 << (drive & 3); + #ifdef i386 sti(); + #elif defined(__alpha) + ipl(oldipl); + #endif /* i386 | __alpha */ check_disk_change(inode->i_rdev); return 0; } *************** *** 1197,1206 **** --- 1513,1530 ---- if (cmd == FDDEFPRM) keep_data[drive] = -1; else { + #ifdef i386 cli(); + #elif defined(__alpha) + oldipl = ipl(IPLMAX); + #endif /* i386 | __alpha */ while (fdc_busy) sleep_on(&fdc_wait); fdc_busy = 1; + #ifdef i386 sti(); + #elif defined(__alpha) + ipl(oldipl); + #endif /* i386 | __alpha */ outb_p((current_DOR & 0xfc) | drive | (0x10 << drive),FD_DOR); for (cnt = 0; cnt < 1000; cnt++) __asm__("nop"); *************** *** 1228,1242 **** return 0; } #define CMOS_READ(addr) ({ \ ! outb_p(addr,0x70); \ ! inb_p(0x71); \ ! }) static struct floppy_struct *find_base(int drive,int code) { struct floppy_struct *base; if (code > 0 && code < 5) { base = &floppy_types[(code-1)*2]; printk("fd%d is %s",drive,base->name); --- 1552,1576 ---- return 0; } + #ifdef i386 #define CMOS_READ(addr) ({ \ ! outb_p(addr,0x70); \ ! inb_p(0x71); \ ! }) ! #elif defined(__alpha) ! /* JAE: we don't got no stinkin' CMOS... :-) :-) */ ! /* JAE: so fake a 1.44M drive #0 *ALWAYS*... */ ! #define CMOS_READ(addr) ((addr == 0x10) ? 0x40 : 0x00) ! #endif /* i386 | __alpha */ static struct floppy_struct *find_base(int drive,int code) { struct floppy_struct *base; + #ifdef DEBUG_ENTRY + printk("find_base() entry\n"); + #endif /* DEBUG_ENTRY */ + if (code > 0 && code < 5) { base = &floppy_types[(code-1)*2]; printk("fd%d is %s",drive,base->name); *************** *** 1270,1275 **** --- 1604,1613 ---- int drive; int old_dev; + #ifdef DEBUG_ENTRY + printk("floppy_open() entry\n"); + #endif /* DEBUG_ENTRY */ + drive = inode->i_rdev & 3; old_dev = fd_device[drive]; if (fd_ref[drive]) *************** *** 1287,1292 **** --- 1625,1634 ---- static void floppy_release(struct inode * inode, struct file * filp) { + #ifdef DEBUG_ENTRY + printk("floppy_release() entry\n"); + #endif /* DEBUG_ENTRY */ + sync_dev(inode->i_rdev); if (!fd_ref[inode->i_rdev & 3]--) { printk("floppy_release with fd_ref == 0"); *************** *** 1328,1333 **** --- 1670,1679 ---- { void (*handler)(void) = DEVICE_INTR; + #ifdef DEBUG_ENTRY + printk("floppy_interrupt() entry\n"); + #endif /* DEBUG_ENTRY */ + DEVICE_INTR = NULL; if (!handler) handler = unexpected_floppy_interrupt; *************** *** 1347,1352 **** --- 1693,1702 ---- void floppy_init(void) { + #ifdef DEBUG_ENTRY + printk("floppy_init() entry\n"); + #endif /* DEBUG_ENTRY */ + outb(current_DOR,FD_DOR); if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) { printk("Unable to get major %d for floppy\n",MAJOR_NR); *************** *** 1358,1366 **** timer_active &= ~(1 << FLOPPY_TIMER); config_types(); if (irqaction(FLOPPY_IRQ,&floppy_sigaction)) ! printk("Unable to grab IRQ%d for the floppy driver\n", FLOPPY_IRQ); if (request_dma(FLOPPY_DMA)) ! printk("Unable to grab DMA%d for the floppy driver\n", FLOPPY_DMA); /* Try to determine the floppy controller type */ DEVICE_INTR = ignore_interrupt; /* don't ask ... */ output_byte(FD_VERSION); /* get FDC version code */ --- 1708,1718 ---- timer_active &= ~(1 << FLOPPY_TIMER); config_types(); if (irqaction(FLOPPY_IRQ,&floppy_sigaction)) ! printk("Unable to grab IRQ%d for the floppy driver\n", ! FLOPPY_IRQ); if (request_dma(FLOPPY_DMA)) ! printk("Unable to grab DMA%d for the floppy driver\n", ! FLOPPY_DMA); /* Try to determine the floppy controller type */ DEVICE_INTR = ignore_interrupt; /* don't ask ... */ output_byte(FD_VERSION); /* get FDC version code */ diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/block/ll_rw_blk.c LINUX_ALPHA_SDK/sources/linux/drivers/block/ll_rw_blk.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/block/ll_rw_blk.c Fri Dec 30 15:44:08 1994 --- LINUX_ALPHA_SDK/sources/linux/drivers/block/ll_rw_blk.c Wed Feb 8 14:08:10 1995 *************** *** 598,605 **** --- 598,612 ---- } #ifndef CONFIG_SCSI + /* #define FLOPPY_ROOT */ + #ifdef FLOPPY_ROOT + ROOT_DEV = 0x0200; + printk("blk_dev_init: setting ROOT_DEV to 0x%x; FLOPPY unit %d partition 0\n", + ROOT_DEV, (ROOT_DEV >> 4) & 7); + #else /* Initialize the RPB disk (same device as boot disk) */ (void)rpb_init(ramdisk_size); + #endif /* FLOPPY_ROOT */ #endif /* ! CONFIG_SCSI */ #endif /* i386 | __alpha */ return mem_start; diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/block/rpb.c LINUX_ALPHA_SDK/sources/linux/drivers/block/rpb.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/block/rpb.c Wed Jan 11 16:06:22 1995 --- LINUX_ALPHA_SDK/sources/linux/drivers/block/rpb.c Wed Feb 8 14:05:19 1995 *************** *** 21,26 **** --- 21,27 ---- #include #include #include + #include #define MAJOR_NR RPB_CONSOLE_MAJOR #include "blk.h" *************** *** 59,64 **** --- 60,68 ---- } oldipl = ipl(IPLMAX); + + save_irqs(); /* JAE: forced by firmware unreliability */ + if (CURRENT-> cmd == WRITE) { dispatch_result = cons_dispatch(0x14, channel, len, CURRENT->buffer, CURRENT->sector); *************** *** 71,79 **** panic("RPBDISK: unknown RPB disk command !\n"); } ipl(oldipl); ! if(dispatch_result & 0x1000000000000000LL) { /* Result has high bit set on error! */ printk("RPB: %s error, status = 0x%x\n", (CURRENT->cmd==READ)?"read":"write", --- 75,85 ---- panic("RPBDISK: unknown RPB disk command !\n"); } + restore_irqs(); /* JAE: forced by firmware unreliability */ + ipl(oldipl); ! if(dispatch_result & 0x8000000000000000LL) { /* Result has high bit set on error! */ printk("RPB: %s error, status = 0x%x\n", (CURRENT->cmd==READ)?"read":"write", *************** *** 121,131 **** } else { rpb_channels[minor] = (int)dispatch_result; ! printk("Opened RPB device %d on channel %d\n", unit, rpb_channels[minor]); } } ! /* Ascertains the boot device and opens up a channel to it. */ rpb_init(int ramdisk_size) { int i; --- 127,142 ---- } else { rpb_channels[minor] = (int)dispatch_result; ! printk("Opened RPB device %d on channel %d\n", ! unit, rpb_channels[minor]); } } ! /* ! * Registers the boot device, and performs setup to use callbacks for disk. ! * Assumes that rpb_early_init() has been called before, to open a channel. ! */ ! int rpb_init(int ramdisk_size) { int i; *************** *** 135,146 **** int oldipl; if (register_blkdev(RPB_CONSOLE_MAJOR,"rpb",&rpb_fops)) { ! printk("RPBDISK: Unable to get major %d.\n", RPB_CONSOLE_MAJOR); ! return 0; } printk("rpb_init: Initializing RPB callback disk driver\n"); blk_dev[RPB_CONSOLE_MAJOR].request_fn = DEVICE_REQUEST; /* Get the name of the boot device. Function code 0x22=GETENV, * environment ID 2 = BOOT_DEV */ --- 146,158 ---- int oldipl; if (register_blkdev(RPB_CONSOLE_MAJOR,"rpb",&rpb_fops)) { ! printk("RPBDISK: Unable to get major %d.\n", RPB_CONSOLE_MAJOR); ! return 0; } printk("rpb_init: Initializing RPB callback disk driver\n"); blk_dev[RPB_CONSOLE_MAJOR].request_fn = DEVICE_REQUEST; + #ifdef NOT_NOW /* Get the name of the boot device. Function code 0x22=GETENV, * environment ID 2 = BOOT_DEV */ *************** *** 179,184 **** --- 191,198 ---- ipl(oldipl); + #endif /* NOT_NOW */ + for(i=0;i<2;i++) rpb_blocksizes[i] = 512; blksize_size[MAJOR_NR] = rpb_blocksizes; *************** *** 191,196 **** --- 205,285 ---- } + /* + * rpb_early_init() is called *VERY* early in the boot sequence, + * to open a channel to the root device for callback access. + * + * NOTE (JAE): this is necessary as the SRM console "open" routine + * on (at least EB66) causes the keyboard to be reinitialized, as well. + * Since rpb_init() gets called *after* kbd_init(), it changes the + * keyboard setting out from under the native driver. :-( :-( + */ + int + rpb_early_init(int ramdisk_size) + { + int i; + U64 dispatch_result; + char device_name[128]; + int namelen; + int oldipl; + + #ifdef NOT_NOW + if (register_blkdev(RPB_CONSOLE_MAJOR,"rpb",&rpb_fops)) { + printk("RPBDISK: Unable to get major %d.\n", RPB_CONSOLE_MAJOR); + return 0; + } + printk("rpb_init: Initializing RPB callback disk driver\n"); + blk_dev[RPB_CONSOLE_MAJOR].request_fn = DEVICE_REQUEST; + #endif /* NOT_NOW */ + + /* Get the name of the boot device. Function code 0x22=GETENV, + * environment ID 2 = BOOT_DEV + */ + oldipl = ipl(IPLMAX); + dispatch_result = cons_dispatch(0x22, 2, + device_name, sizeof(device_name)); + if(dispatch_result & 0x1000000000000000LL) { + printk("rpb_init: Cannot get BOOT_DEV environment variable!\n"); + return; + } + /* dispatch_result is a byte count. Null-terminate the string */ + namelen = (int)dispatch_result; + device_name[namelen] = '\0'; + printk("RPBDISK: Boot device is %s\n", device_name); + /* open a channel to the device */ + dispatch_result = cons_dispatch(0x10, device_name, namelen); + + if(dispatch_result & 0x1100000000000000LL) { + printk("RPBDISK: Cannot open %s, error code 0x%x\n", + device_name, (int)(dispatch_result >> 32)); + } + else if(dispatch_result & 0x1000000000000000LL) { + printk("RPBDISK: Device %s does not exist\n", device_name); + } + else { + rpb_channels[BOOTDISK_MINOR] = (int)dispatch_result; + } + printk("RPBDISK %d initialized, channel = %d\n", + BOOTDISK_MINOR, rpb_channels[BOOTDISK_MINOR]); + + /* For LEAN: Open SCSI devices on the appropriate channels... */ + /* open_lean_dev(0, 0); */ + /* open_lean_dev(2, 2); */ + /* open_lean_dev(5, 5); */ + + ipl(oldipl); + + #ifdef NOT_NOW + for(i=0;i<2;i++) rpb_blocksizes[i] = 512; + blksize_size[MAJOR_NR] = rpb_blocksizes; + + /* If no RAMdisk, then use this one as root! */ + if(ramdisk_size == 0) { + ROOT_DEV = (RPB_CONSOLE_MAJOR << 8) | BOOTDISK_MINOR; + printk("Using console callback driver for root disk\n"); + } + #endif /* NOT_NOW */ + } #endif /* __alpha */ diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/char/console.c LINUX_ALPHA_SDK/sources/linux/drivers/char/console.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/char/console.c Fri Dec 30 15:45:23 1994 --- LINUX_ALPHA_SDK/sources/linux/drivers/char/console.c Wed Feb 8 14:10:26 1995 *************** *** 1547,1556 **** * type and sets everything accordingly. */ - #ifdef CALLBACK_VIDEO - void callback_console_print(); - #endif /* CALLBACK_VIDEO */ - long con_init(long kmem_start) { char *display_desc = "????"; --- 1547,1552 ---- *************** *** 1665,1672 **** printable = 1; register_console(console_print); #else /* ! CALLBACK_VIDEO */ ! printk("con_init: registering callback_console_print\n"); ! register_console(callback_console_print); #endif /* ! CALLBACK_VIDEO */ return kmem_start; --- 1661,1667 ---- printable = 1; register_console(console_print); #else /* ! CALLBACK_VIDEO */ ! printk("con_init: leaving console_print unregistered\n"); #endif /* ! CALLBACK_VIDEO */ return kmem_start; *************** *** 1740,1746 **** get_scrmem(fg_console); hide_cursor(); console_blanked = 1; ! MEMSETW((void *)video_mem_base, 0x0020, video_mem_term-video_mem_base); } void unblank_screen(void) --- 1735,1742 ---- get_scrmem(fg_console); hide_cursor(); console_blanked = 1; ! MEMSETW((void *)video_mem_base, 0x0020, ! (video_mem_term-video_mem_base)>>1); } void unblank_screen(void) *************** *** 2170,2179 **** extern U64 cons_dispatch(); #ifdef CALLBACK_VIDEO - void callback_console_print(const char * b) - { - cons_puts(0, b); - } void callback_con_write(struct tty_struct * tty) { --- 2166,2171 ---- *************** *** 2187,2193 **** } while (!tty->stopped && (c = get_tty_queue(&tty->write_q)) >= 0) { ! cons_puts_n(0, &c, 1); } if (LEFT(&tty->write_q) > WAKEUP_CHARS) --- 2179,2185 ---- } while (!tty->stopped && (c = get_tty_queue(&tty->write_q)) >= 0) { ! printk("%c",c); } if (LEFT(&tty->write_q) > WAKEUP_CHARS) *************** *** 2197,2219 **** int cons_puts(int unit, const char * s) { ! int oldipl; ! int remainder; ! int written; ! int total = 0; ! U64 retval; ! ! oldipl = ipl(IPLMAX); ! remainder = strlen(s); ! while(remainder > 0) { ! retval = cons_dispatch(2, unit, s, remainder); ! written = (int)(retval & 0xffffffffLL); ! total += written; ! s += written; ! remainder -= written; ! } ! ipl(oldipl); ! return(total); } int cons_puts_n(int unit, const char * s, int len) --- 2189,2195 ---- int cons_puts(int unit, const char * s) { ! return(cons_puts_n(unit, s, strlen(s))); } int cons_puts_n(int unit, const char * s, int len) *************** *** 2224,2229 **** --- 2200,2206 ---- oldipl = ipl(IPLMAX); remainder = len; + /* save_irqs(); /* JAE: forced by unreliable console FW... :-( */ while(remainder > 0) { retval = cons_dispatch(2, unit, s, remainder); written = (int)(retval & 0xffffffffLL); *************** *** 2231,2236 **** --- 2208,2214 ---- s += written; remainder -= written; } + /* restore_irqs(); /* JAE: forced by unreliable console FW... :-( */ ipl(oldipl); return(total); } diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/char/keyboard.c LINUX_ALPHA_SDK/sources/linux/drivers/char/keyboard.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/char/keyboard.c Mon Jan 9 12:22:16 1995 --- LINUX_ALPHA_SDK/sources/linux/drivers/char/keyboard.c Wed Feb 8 14:14:09 1995 *************** *** 11,19 **** * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993 */ ! /* #define DEBUG_SCANCODE */ ! #define KEYBOARD_IRQ 1 #include #include --- 11,23 ---- * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993 */ ! /* ! #define DEBUG_SCANCODE ! #define DEBUG_MODE ! */ ! int KEYBOARD_IRQ = 1; /* NOTE: may be changed by alpha/cpu.c:cpu_init() */ ! /* for platforms which are different (JENSEN) */ #include #include *************** *** 146,156 **** static inline void kb_wait(void) { ! int i; ! for (i=0; i<0x10000; i++) if ((JINB_P(0x64) & 0x02) == 0) break; } static inline void send_cmd(unsigned char c) --- 150,168 ---- static inline void kb_wait(void) { ! #ifdef i386 ! #define WAIT_TIMEOUT 0x10000 ! int j; ! #elif defined(__alpha) ! #define WAIT_TIMEOUT 0x10000 ! volatile int j; ! #endif ! for (j=0; j < WAIT_TIMEOUT; j++) if ((JINB_P(0x64) & 0x02) == 0) break; + if (j == WAIT_TIMEOUT) + printk("kb_wait: timed out\n"); } static inline void send_cmd(unsigned char c) *************** *** 159,164 **** --- 171,205 ---- JOUTB(c,0x64); } + #ifdef __alpha + int + read_kb_mode() + { + #if 0 + send_cmd(0x20); /* RDMODE */ + kb_wait(); + while (!(JINB(0x64) & 0x01)) continue; + return(JINB(0x60)); + #else + return(0x01); + #endif /* 0 */ + + } + + int + write_kb_mode(mode) + int mode; + { + send_cmd(0xae); /* enable */ + #if 1 + send_cmd(0x60); /* WRMODE */ + kb_wait(); + send_data(mode); + #endif /* 0 */ + return 0; + } + #endif /* __alpha */ + /* * Translation of escaped scancodes to keysyms. * This should be user-settable. *************** *** 213,223 **** }; - #ifdef __alpha - void keyboard_interrupt(int int_pt_regs) - #else /* __alpha */ static void keyboard_interrupt(int int_pt_regs) - #endif /* __alpha */ { unsigned char scancode; static unsigned int prev_scancode = 0; /* remember E0, E1 */ --- 254,260 ---- *************** *** 910,928 **** int i, j; extern unsigned long pg0[1024]; - #ifdef i386 sti(); - #elif defined(__alpha) - ipl(0); - #endif /* rebooting needs to touch the page at absolute addr 0 */ pg0[0] = 7; - #ifdef i386 *((unsigned short *)0x472) = 0x1234; - #elif defined(__alpha) - /* FIXME??????? */ - #endif for (;;) { for (i=0; i<100; i++) { --- 947,957 ---- *************** *** 931,939 **** /* nothing */; JOUTB(0xfe,0x64); /* pulse reset low */ } - #ifdef i386 __asm__("\tlidt _no_idt"); - #endif } } #endif /* i386 */ --- 960,966 ---- *************** *** 953,997 **** bh_base[KEYBOARD_BH].routine = kbd_bh; - #ifdef i386 request_irq(KEYBOARD_IRQ,keyboard_interrupt); ! #elif defined(__alpha) /* ! * read the initial MODE register constents (for debugging) */ send_cmd(0x20); /* RDMODE */ kb_wait(); i = JINB(0x60); ! #ifdef DEBUG printk("kbd_init: initial MODE 0x%x\n", i); ! #endif /* DEBUG */ send_cmd(0xAE); /* enable keyboard */ - send_data(0xFF); /* reset keyboard */ kb_wait(); ! send_data(0xF5); /* defaults disable */ kb_wait(); ! send_data(0xF4); /* enable */ kb_wait(); ! send_data(0xF0); /* select scancode */ kb_wait(); ! send_data(0x01); /* scancode set 1 */ ! /* * finally, enable the keyboard interrupt */ send_cmd(0x20); /* RDMODE */ kb_wait(); i = (JINB(0x60) | 0x01) & ~0x40; /* turn on kbd interrupt, off KCC */ ! #ifdef DEBUG printk("kbd_init: setting final MODE 0x%x\n", i); ! #endif /* DEBUG */ send_cmd(0x60); /* WRMODE */ send_data(i); ! #endif /* i386 */ mark_bh(KEYBOARD_BH); return kmem_start; } /* called after returning from RAW mode or when changing consoles - recompute k_down[] and shift_state from key_down[] */ --- 980,1081 ---- bh_base[KEYBOARD_BH].routine = kbd_bh; request_irq(KEYBOARD_IRQ,keyboard_interrupt); ! ! #if defined(__alpha) ! ! /* wait for idle keyboard */ ! while (JINB(0x64) & 0x01) { ! JINB(0x60); ! for (i = 0; i < 0x100000; i++) ! continue; ! } ! /* ! * read the initial MODE register contents (for debugging) */ send_cmd(0x20); /* RDMODE */ kb_wait(); + while (!(JINB(0x64) & 0x01)) continue; i = JINB(0x60); ! #ifdef DEBUG_MODE printk("kbd_init: initial MODE 0x%x\n", i); ! alpha_print_selectcode(); ! #endif /* DEBUG_MODE */ ! send_cmd(0x60); ! kb_wait(); ! #if 0 ! send_data(i | 1); /* enable keyboard interrupt */ ! #else /* 0 */ ! JOUTB(0x01, 0x60); /* enable only keyboard interrupt */ ! kb_wait(); ! #endif /* 0 */ ! ! #if 1 send_cmd(0xAE); /* enable keyboard */ kb_wait(); ! JOUTB(0xFF, 0x60); /* reset keyboard */ kb_wait(); ! while (!(JINB(0x64) & 0x01)) continue; JINB(0x60); /* ACK */ ! while (!(JINB(0x64) & 0x01)) continue; JINB(0x60); /* BAT */ ! JOUTB(0xF5, 0x60); /* defaults disable */ kb_wait(); ! while (!(JINB(0x64) & 0x01)) continue; JINB(0x60); /* ACK */ ! #endif /* 0 */ ! JOUTB(0xF0, 0x60); /* select scancode */ kb_wait(); ! while (!(JINB(0x64) & 0x01)) continue; JINB(0x60); /* ACK */ ! JOUTB(0x01, 0x60); /* scancode set 1 */ ! kb_wait(); ! while (!(JINB(0x64) & 0x01)) continue; JINB(0x60); /* ACK */ ! #if 1 ! JOUTB(0xF4, 0x60); /* enable */ ! kb_wait(); ! while (!(JINB(0x64) & 0x01)) continue; JINB(0x60); /* ACK */ ! #endif /* 0 */ ! /* * finally, enable the keyboard interrupt */ + kb_wait(); send_cmd(0x20); /* RDMODE */ kb_wait(); + while (!(JINB(0x64) & 0x01)) continue; i = (JINB(0x60) | 0x01) & ~0x40; /* turn on kbd interrupt, off KCC */ ! #ifdef DEBUG_MODE printk("kbd_init: setting final MODE 0x%x\n", i); ! alpha_print_selectcode(); ! #endif /* DEBUG_MODE */ send_cmd(0x60); /* WRMODE */ + kb_wait(); + #if 0 send_data(i); ! #else /* 0 */ ! JOUTB(0x01, 0x60); ! #endif /* 0 */ ! ! #endif /* __alpha */ mark_bh(KEYBOARD_BH); return kmem_start; } + + #ifdef __alpha + int + alpha_print_selectcode() + { + int code = -1; + + JOUTB(0xF0, 0x60); /* select scancode */ + kb_wait(); + while (!(JINB(0x64) & 0x01)) continue; JINB(0x60); /* ACK */ + JOUTB(0x00, 0x60); /* scancode set 0 forces read */ + kb_wait(); + while (!(JINB(0x64) & 0x01)) continue; JINB(0x60); /* ACK */ + while (!(JINB(0x64) & 0x01)) continue; code = JINB(0x60); /* code */ + printk("alpha_print_selectcode: selected code %d\n", code); + } + #endif /* __alpha */ /* called after returning from RAW mode or when changing consoles - recompute k_down[] and shift_state from key_down[] */ diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/net/depca.c LINUX_ALPHA_SDK/sources/linux/drivers/net/depca.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/net/depca.c Tue Dec 13 14:44:00 1994 --- LINUX_ALPHA_SDK/sources/linux/drivers/net/depca.c Wed Feb 8 14:17:58 1995 *************** *** 1,25 **** ! /* depca.c: A DIGITAL DEPCA ethernet driver for linux. Written 1994 by David C. Davies. - Copyright 1994 David C. Davies and United States Government as - represented by the Director, National Security Agency. This software - may be used and distributed according to the terms of the GNU Public - License, incorporated herein by reference. ! This driver is written for the Digital Equipment Corporation series ! of DEPCA ethernet cards: ! DE100 DEPCA ! DE200 DEPCA Turbo ! DE202 DEPCA Turbo (TP BNC) ! DE210 DEPCA ! The driver has been tested on DE100 and DE20x cards in a relatively busy ! network. ! The author may be reached as davies@wanton.enet.dec.com or ! Digital Equipment Corporation, 146 Main Street, Maynard MA 01754. ========================================================================= The driver was based on the 'lance.c' driver from Donald Becker which is --- 1,38 ---- ! /* depca.c: A DIGITAL DEPCA & EtherWORKS ethernet driver for linux. Written 1994 by David C. Davies. ! Copyright 1994 David C. Davies ! and ! United States Government ! (as represented by the Director, National Security Agency). ! ! This software may be used and distributed according to the terms of ! the GNU Public License, incorporated herein by reference. ! ! This driver is written for the Digital Equipment Corporation series ! of DEPCA and EtherWORKS ethernet cards: ! DEPCA (the original) ! DE100 ! DE101 ! DE200 Turbo ! DE201 Turbo ! DE202 Turbo (TP BNC) ! DE210 ! DE422 (EISA) ! ! The driver has been tested on DE100, DE200 and DE202 cards in a ! relatively busy network. The DE422 has been tested a little. ! ! This driver will NOT work for the DE203, DE204 and DE205 series of ! cards, since they have a new custom ASIC in place of the AMD LANCE ! chip. ! The author may be reached as davies@wanton.lkg.dec.com or ! Digital Equipment Corporation, 550 King Street, Littleton MA 01460. ========================================================================= The driver was based on the 'lance.c' driver from Donald Becker which is *************** *** 49,97 **** the filter bit positions correctly. Hash filtering is not yet implemented in the current driver set. ! The DE200 series boards have on-board 64kB RAM for use as a shared ! memory network buffer. Only the DE100 cards make use of a 2kB buffer ! mode which has not been implemented in this driver (only the 32kB and ! 64kB modes are supported). ! ! At the most only 2 DEPCA cards can be supported because there is only ! provision for two I/O base addresses on the cards (0x300 and 0x200). The ! base address is 'autoprobed' by looking for the self test PROM and ! detecting the card name. The shared memory base address is decoded by ! 'autoprobing' the Ethernet PROM address information. The second DEPCA is ! detected and information placed in the base_addr variable of the next ! device structure (which is created if necessary), thus enabling ! ethif_probe initialization for the device. ************************************************************************ ! NOTE: If you are using two DEPCAs, it is important that you assign the ! base memory addresses correctly. The driver autoprobes I/O 0x300 then ! 0x200. The base memory address for the first device must be less than ! that of the second so that the auto probe will correctly assign the I/O ! and memory addresses on the same card. I can't think of a way to do this unambiguously at the moment, since there is nothing on the cards to tie I/O and memory information together. ! I am unable to test 2 DEPCAs together for now, so this code is unchecked. All reports, good or bad, are welcome. ************************************************************************ ! The board IRQ setting must be at an unused IRQ which is auto-probed ! using Donald Becker's autoprobe routines. DE100 board IRQs are ! {2,3,4,5,7}, whereas the DE200 is at {5,9,10,11,15}. Note that IRQ2 is really IRQ9 in machines with 16 IRQ lines. No 16MB memory limitation should exist with this driver as DMA is not used and the common memory area is in low memory on the network card (my current system has 20MB and I've not had problems yet). ! The DE203, DE204 and DE205 cards may also work with this driver (I ! haven't tested them so I don't know). If you have one of these cards, ! place the name in the DEPCA_SIGNATURE string around line 160, recompile ! the kernel and reboot. Check if the card is recognised and works - mail ! me if so, so that I can add it into the list of supported cards! TO DO: ------ --- 62,147 ---- the filter bit positions correctly. Hash filtering is not yet implemented in the current driver set. ! The original DEPCA card requires that the ethernet ROM address counter ! be enabled to count and has an 8 bit NICSR. The ROM counter enabling is ! only done when a 0x08 is read as the first address octet (to minimise ! the chances of writing over some other hardware's I/O register). The ! NICSR accesses have been changed to byte accesses for all the cards ! supported by this driver, since there is only one useful bit in the MSB ! (remote boot timeout) and it is not used. Also, there is a maximum of ! only 48kB network RAM for this card. My thanks to Torbjorn Lindh for ! help debugging all this (and holding my feet to the fire until I got it ! right). ! ! The DE200 series boards have on-board 64kB RAM for use as a shared ! memory network buffer. Only the DE100 cards make use of a 2kB buffer ! mode which has not been implemented in this driver (only the 32kB and ! 64kB modes are supported [16kB/48kB for the original DEPCA]). ! ! At the most only 2 DEPCA cards can be supported on the ISA bus because ! there is only provision for two I/O base addresses on each card (0x300 ! and 0x200). The I/O address is detected by searching for a byte sequence ! in the Ethernet station address PROM at the expected I/O address for the ! Ethernet PROM. The shared memory base address is 'autoprobed' by ! looking for the self test PROM and detecting the card name. When a ! second DEPCA is detected, information is placed in the base_addr ! variable of the next device structure (which is created if necessary), ! thus enabling ethif_probe initialization for the device. More than 2 ! EISA cards can be supported, but care will be needed assigning the ! shared memory to ensure that each slot has the correct IRQ, I/O address ! and shared memory address assigned. ************************************************************************ ! NOTE: If you are using two ISA DEPCAs, it is important that you assign ! the base memory addresses correctly. The driver autoprobes I/O 0x300 ! then 0x200. The base memory address for the first device must be less ! than that of the second so that the auto probe will correctly assign the ! I/O and memory addresses on the same card. I can't think of a way to do this unambiguously at the moment, since there is nothing on the cards to tie I/O and memory information together. ! I am unable to test 2 cards together for now, so this code is unchecked. All reports, good or bad, are welcome. ************************************************************************ ! The board IRQ setting must be at an unused IRQ which is auto-probed ! using Donald Becker's autoprobe routines. DEPCA and DE100 board IRQs are ! {2,3,4,5,7}, whereas the DE200 is at {5,9,10,11,15}. Note that IRQ2 is really IRQ9 in machines with 16 IRQ lines. No 16MB memory limitation should exist with this driver as DMA is not used and the common memory area is in low memory on the network card (my current system has 20MB and I've not had problems yet). ! The ability to load this driver as a loadable module has been added. To ! utilise this ability, you have to do <8 things: ! ! 1) copy depca.c from the /linux/drivers/net directory to your favourite ! temporary directory. ! 2) edit the source code near line 1530 to reflect the I/O address and ! IRQ you're using. ! 3) compile depca.c, but include -DMODULE in the command line to ensure ! that the correct bits are compiled (see end of source code). ! 4) if you are wanting to add a new card, goto 5. Otherwise, recompile a ! kernel with the depca configuration turned off and reboot. ! 5) insmod depca.o ! 6) run the net startup bits for your eth?? interface manually ! (usually /etc/rc.inet[12] at boot time). ! 7) enjoy! ! ! Note that autoprobing is not allowed in loadable modules - the system is ! already up and running and you're messing with interrupts. Also, there ! is no way to check on the number of depcas installed at the moment. ! ! To unload a module, turn off the associated interface ! 'ifconfig eth?? down' then 'rmmod depca'. ! ! [Alan Cox: Changed to split off the module values as ints for insmod ! ! you can now do insmod depca.c irq=7 io=0x200 ] ! TO DO: ------ *************** *** 103,121 **** Version Date Description ! 0.1 25-jan-94 Initial writing ! 0.2 27-jan-94 Added LANCE TX buffer chaining ! 0.3 1-feb-94 Added multiple DEPCA support ! 0.31 4-feb-94 Added DE202 recognition ! 0.32 19-feb-94 Tidy up. Improve multi-DEPCA support. ========================================================================= */ ! static char *version = "depca.c:v0.32 2/19/94 davies@wanton.enet.dec.com\n"; #include - #include #include #include #include --- 153,187 ---- Version Date Description ! 0.1 25-jan-94 Initial writing. ! 0.2 27-jan-94 Added LANCE TX hardware buffer chaining. ! 0.3 1-feb-94 Added multiple DEPCA support. ! 0.31 4-feb-94 Added DE202 recognition. ! 0.32 19-feb-94 Tidy up. Improve multi-DEPCA support. ! 0.33 25-feb-94 Fix DEPCA ethernet ROM counter enable. ! Add jabber packet fix from murf@perftech.com ! and becker@super.org ! 0.34 7-mar-94 Fix DEPCA max network memory RAM & NICSR access. ! 0.35 8-mar-94 Added DE201 recognition. Tidied up. ! 0.351 30-apr-94 Added EISA support. Added DE422 recognition. ! 0.36 16-may-94 DE422 fix released. ! 0.37 22-jul-94 Added MODULE support ! 0.38 15-aug-94 Added DBR ROM switch in depca_close(). ! Multi DEPCA bug fix. ! 0.38axp 15-sep-94 Special version for Alpha AXP Linux V1.0 ! 0.381 12-dec-94 Added DE101 recognition, fix multicast bug ========================================================================= */ ! static char *version = "depca.c:v0.381 12/12/94 davies@wanton.lkg.dec.com\n"; ! ! #ifdef MODULE ! #include ! #include ! #endif /* MODULE */ #include #include #include #include *************** *** 128,149 **** #include #include #include "dev.h" #include "iow.h" #include "eth.h" #include "skbuff.h" #include "arp.h" #include "depca.h" #ifdef DEPCA_DEBUG ! int depca_debug = DEPCA_DEBUG; #else ! int depca_debug = 1; ! #endif ! ! #ifndef DEPCA_IRQ ! /*#define DEPCA_IRQ {5,9,10,11,15,0}*/ ! #define DEPCA_IRQ 5 #endif #ifndef PROBE_LENGTH --- 194,217 ---- #include #include + #ifdef LATEST_LINUX + #include + #include + #include + #else #include "dev.h" #include "iow.h" #include "eth.h" #include "skbuff.h" #include "arp.h" + #endif /* LATEST_LINUX */ + #include "depca.h" #ifdef DEPCA_DEBUG ! static int depca_debug = DEPCA_DEBUG; #else ! static int depca_debug = 6; /* JAE: maximize for now... :-) */ #endif #ifndef PROBE_LENGTH *************** *** 155,161 **** #endif #ifndef DEPCA_SIGNATURE ! #define DEPCA_SIGNATURE {"DEPCA","DE100","DE200","DE202","DE210",""} #define DEPCA_NAME_LENGTH 8 #endif --- 223,234 ---- #endif #ifndef DEPCA_SIGNATURE ! #define DEPCA_SIGNATURE {"DEPCA",\ ! "DE100","DE101",\ ! "DE200","DE201","DE202",\ ! "DE210",\ ! "DE422",\ ! ""} #define DEPCA_NAME_LENGTH 8 #endif *************** *** 177,182 **** --- 250,263 ---- #define MAX_NUM_DEPCAS 2 #endif + #ifndef DEPCA_EISA_IO_PORTS + #define DEPCA_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */ + #endif + + #ifndef MAX_EISA_SLOTS + #define MAX_EISA_SLOTS 8 + #endif + /* ** Set the number of Tx and Rx buffers. */ *************** *** 197,207 **** #endif /* CRC_POLYNOMIAL */ #endif /* HAVE_MULTICAST */ - #ifndef HAVE_ALLOC_SKB - #define alloc_skb(size, priority) (struct sk_buff *) kmalloc(size,priority) - #define kfree_skbmem(buff, size) kfree_s(buff,size) - #endif /* HAVE_ALLOC_SKB */ - /* ** The DEPCA Rx and Tx ring descriptors. */ --- 278,283 ---- *************** *** 217,224 **** short misc; /* Errors and TDR info */ }; ! struct depca_ring_info { ! }; /* ** The Lance initialization block, described in databook, in common memory. --- 293,300 ---- short misc; /* Errors and TDR info */ }; ! #define LA_MASK 0x0000ffff /* LANCE address mask for mapping network RAM ! to LANCE memory address space */ /* ** The Lance initialization block, described in databook, in common memory. *************** *** 232,250 **** }; struct depca_private { ! char devname[8]; /* Not used */ struct depca_rx_head *rx_ring; /* Pointer to start of RX descriptor ring */ struct depca_tx_head *tx_ring; /* Pointer to start of TX descriptor ring */ struct depca_init init_block;/* Initialization block */ long dma_buffs; /* Start address of Rx and Tx buffers. */ int cur_rx, cur_tx; /* The next free ring entry */ int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ int dma; struct enet_statistics stats; ! char old_depca; short ringSize; /* ring size based on available memory */ short rmask; /* modulus mask based on ring size */ long rlen; /* log2(ringSize) for the descriptors */ }; /* --- 308,347 ---- }; struct depca_private { ! #ifdef i386 ! char devname[8]; /* Device Product String */ struct depca_rx_head *rx_ring; /* Pointer to start of RX descriptor ring */ struct depca_tx_head *tx_ring; /* Pointer to start of TX descriptor ring */ struct depca_init init_block;/* Initialization block */ + long bus_offset; /* (E)ISA bus address offset vs LANCE */ long dma_buffs; /* Start address of Rx and Tx buffers. */ int cur_rx, cur_tx; /* The next free ring entry */ int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ int dma; struct enet_statistics stats; ! char depca_na; /* NICSR access width: 0=>byte, 1=>word */ short ringSize; /* ring size based on available memory */ short rmask; /* modulus mask based on ring size */ long rlen; /* log2(ringSize) for the descriptors */ + #elif defined(__alpha) + /* JAE: do more (alpha) natural alignment of some fields */ + /* JAE: also, add a field to hold the address of the init block on the board */ + char devname[8]; /* Device Product String */ + struct depca_rx_head *rx_ring; /* Pointer to start of RX descriptor ring */ + struct depca_tx_head *tx_ring; /* Pointer to start of TX descriptor ring */ + struct depca_init init_block;/* Initialization block */ + struct depca_init *init_block_addr;/* Initialization block address */ + long bus_offset; /* (E)ISA bus address offset vs LANCE */ + long dma_buffs; /* Start address of Rx and Tx buffers. */ + long rlen; /* log2(ringSize) for the descriptors */ + int cur_rx, cur_tx; /* The next free ring entry */ + int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ + int dma; + struct enet_statistics stats; + short ringSize; /* ring size based on available memory */ + short rmask; /* modulus mask based on ring size */ + char depca_na; /* NICSR access width: 0=>byte, 1=>word */ + #endif /* i386 | __alpha */ }; /* *************** *** 252,258 **** */ static int depca_open(struct device *dev); static int depca_start_xmit(struct sk_buff *skb, struct device *dev); ! static void depca_interrupt(int reg_ptr); static int depca_close(struct device *dev); static struct enet_statistics *depca_get_stats(struct device *dev); #ifdef HAVE_MULTICAST --- 349,355 ---- */ static int depca_open(struct device *dev); static int depca_start_xmit(struct sk_buff *skb, struct device *dev); ! static void depca_interrupt(int irq, struct pt_regs * regs); static int depca_close(struct device *dev); static struct enet_statistics *depca_get_stats(struct device *dev); #ifdef HAVE_MULTICAST *************** *** 275,281 **** static void SetMulticastFilter(int num_addrs, char *addrs, char *multicast_table); #endif ! static int num_depcas = 0, num_eth = 0;; /* ** Miscellaneous defines... --- 372,397 ---- static void SetMulticastFilter(int num_addrs, char *addrs, char *multicast_table); #endif ! #ifndef MODULE ! static struct device *isa_probe(struct device *dev); ! static struct device *eisa_probe(struct device *dev); ! static struct device *alloc_device(struct device *dev, int ioaddr); ! ! static int num_depcas = 0, num_eth = 0, autoprobed = 0; ! ! #else ! int init_module(void); ! void cleanup_module(void); ! ! #endif /* MODULE */ ! ! /* define some macros to make the code look cleaner when adding ALPHA stuff */ ! #ifdef i386 ! #elif defined(__alpha) ! void alpha_bus_memset(); ! void alpha_cpu_to_bus_memcpy(); ! void alpha_bus_to_cpu_memcpy(); ! #endif /* __alpha */ /* ** Miscellaneous defines... *************** *** 284,361 **** outw(CSR0, DEPCA_ADDR);\ outw(STOP, DEPCA_DATA) int depca_probe(struct device *dev) { ! int *port, ports[] = DEPCA_IO_PORTS; ! int base_addr = dev->base_addr; ! int status; ! struct device *eth0 = (struct device *) NULL; if (base_addr > 0x1ff) { /* Check a single specified location. */ ! status = depca_probe1(dev, base_addr); } else if (base_addr > 0) { /* Don't probe at all. */ ! status = -ENXIO; ! } else { /* First probe for the DEPCA test */ ! /* pattern in ROM */ ! ! for (status = -ENODEV, port = &ports[0]; ! *port && (num_depcas < MAX_NUM_DEPCAS); port++) { ! int ioaddr = *port; ! ! #ifdef HAVE_PORTRESERVE ! if (check_region(ioaddr, DEPCA_TOTAL_SIZE)) ! continue; ! #endif ! if (DevicePresent(DEPCA_PROM) == 0) { ! if (num_depcas > 0) { /* only gets here in autoprobe */ ! ! /* ! ** Check the device structures for an end of list or unused device ! */ ! while (dev->next != (struct device *)NULL) { ! if (dev->next->base_addr == 0xffe0) break; ! dev = dev->next; /* walk through eth device list */ ! num_eth++; /* increment eth device number */ ! } ! /* ! ** If no more device structures, malloc one up. If memory could ! ** not be allocated, print an error message. ! ** ! */ ! if (dev->next == (struct device *)NULL) { ! dev->next = (struct device *)kmalloc(sizeof(struct device) + 8, ! GFP_KERNEL); ! } else { ! printk("eth%d: Device not initialised, insufficient memory\n", ! num_eth); ! } - /* - ** If the memory was allocated, point to the new memory area - ** and initialize it (name, I/O address, next device (NULL) and - ** initialisation probe routine). - */ - if ((dev->next != (struct device *)NULL) && - (num_eth > 0) && (num_eth < 9999)) { - dev = dev->next; /* point to the new device */ - dev->name = (char *)(dev + sizeof(struct device)); - sprintf(dev->name,"eth%d", num_eth); /* New device name */ - dev->base_addr = ioaddr; /* assign the io address */ - dev->next = (struct device *)NULL; /* mark the end of list */ - dev->init = &depca_probe;/* initialisation routine */ - } - } else { - eth0 = dev; /* remember the first device */ - status = depca_probe1(dev, ioaddr); - } - num_depcas++; - num_eth++; - } - } - if (eth0) dev = eth0; /* restore the first device */ } if (status) dev->base_addr = base_addr; --- 400,438 ---- outw(CSR0, DEPCA_ADDR);\ outw(STOP, DEPCA_DATA) + int depca_probe(struct device *dev) { ! short base_addr = dev->base_addr; ! int status = -ENODEV; ! #ifndef MODULE ! struct device *eth0; ! #endif if (base_addr > 0x1ff) { /* Check a single specified location. */ ! if (DevicePresent(base_addr) == 0) { /* Is DEPCA really here? */ ! status = depca_probe1(dev, base_addr); ! } } else if (base_addr > 0) { /* Don't probe at all. */ ! status = -ENXIO; ! #ifdef MODULE ! } else { ! printk("Autoprobing is not supported when loading a module based driver.\n"); ! status = -EIO; ! #else ! } else if (!autoprobed) { /* First probe for the DEPCA test */ ! /* pattern in ROM */ ! eth0=isa_probe(dev); ! eth0=eisa_probe(eth0); ! if (dev->priv) status=0; ! autoprobed = 1; ! } else { ! status = -ENXIO; ! #endif /* MODULE */ } if (status) dev->base_addr = base_addr; *************** *** 369,386 **** struct depca_private *lp; int i,j, status=0; unsigned long mem_start, mem_base[] = DEPCA_RAM_BASE_ADDRESSES; ! char *name=(char *)NULL; ! int nicsr, offset; /* ! ** Stop the DEPCA. Enable the DBR ROM. Disable interrupts and remote boot */ STOP_DEPCA; ! nicsr = inw(DEPCA_NICSR); nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM); ! outw(nicsr, DEPCA_NICSR); if (inw(DEPCA_DATA) == STOP) { --- 446,463 ---- struct depca_private *lp; int i,j, status=0; unsigned long mem_start, mem_base[] = DEPCA_RAM_BASE_ADDRESSES; ! char *name = NULL; ! unsigned int nicsr, offset, netRAM; /* ! ** Stop the DEPCA. Enable the DBR ROM. Disable interrupts and remote boot. */ STOP_DEPCA; ! nicsr = inb(DEPCA_NICSR); nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM); ! outb(nicsr, DEPCA_NICSR); if (inw(DEPCA_DATA) == STOP) { *************** *** 391,413 **** ** shortens the search time a little for multiple DEPCAs. */ ! for (j = 0, i = 0; mem_base[i] && (j == 0);) { if (((mem_chkd >> i) & 0x01) == 0) { /* has the memory been checked? */ name = DepcaSignature(mem_base[i]);/* check for a DEPCA here */ mem_chkd |= (0x01 << i); /* mark location checked */ ! if (*name != (char)NULL) { /* one found? */ j = 1; /* set exit flag */ ! } else { ! i++; /* increment search index */ } } } ! if (*name != (char)NULL) { /* found a DEPCA device */ mem_start = mem_base[i]; dev->base_addr = ioaddr; ! printk("%s: DEPCA at %#3x is a %s, ", dev->name, ioaddr, name); /* There is a 32 byte station address PROM at DEPCA_PROM address. The first six bytes are the station address. They can be read --- 468,494 ---- ** shortens the search time a little for multiple DEPCAs. */ ! for (j = 0, i = 0; mem_base[i] && (j == 0);i++) { if (((mem_chkd >> i) & 0x01) == 0) { /* has the memory been checked? */ name = DepcaSignature(mem_base[i]);/* check for a DEPCA here */ mem_chkd |= (0x01 << i); /* mark location checked */ ! if (*name != '\0') { /* one found? */ j = 1; /* set exit flag */ ! --i; } } } ! if (*name != '\0') { /* found a DEPCA device */ mem_start = mem_base[i]; dev->base_addr = ioaddr; ! if ((ioaddr&0x0fff)==DEPCA_EISA_IO_PORTS) {/* EISA slot address */ ! printk("%s: %s at %#3x (EISA slot %d)", ! dev->name, name, ioaddr, ((ioaddr>>12)&0x0f)); ! } else { /* ISA port address */ ! printk("%s: %s at %#3x", dev->name, name, ioaddr); ! } /* There is a 32 byte station address PROM at DEPCA_PROM address. The first six bytes are the station address. They can be read *************** *** 418,430 **** read the ROM info. */ ! if (strstr(name,"DE100")!=(char *)NULL) { j = 1; } else { j = 0; } ! printk("ethernet address "); for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet address */ printk("%2.2x:", dev->dev_addr[i] = inb(DEPCA_PROM + j)); } --- 499,511 ---- read the ROM info. */ ! if (strstr(name,"DE100")!= NULL) { j = 1; } else { j = 0; } ! printk(", h/w address "); for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet address */ printk("%2.2x:", dev->dev_addr[i] = inb(DEPCA_PROM + j)); } *************** *** 435,475 **** } #ifdef HAVE_PORTRESERVE snarf_region(ioaddr, DEPCA_TOTAL_SIZE); #endif /* ! ** Determine the base address for the DEPCA RAM from the NI-CSR ! ** and make up a DEPCA-specific-data structure. */ if (nicsr & BUF) { ! offset = 0x8000; /* 32kbyte RAM */ nicsr &= ~BS; /* DEPCA RAM in top 32k */ ! printk(",\n with 32kB RAM"); } else { ! offset = 0x0000; /* 64kbyte RAM */ ! printk(",\n with 64kB RAM"); } ! mem_start += offset; ! printk(" starting at 0x%.5lx", mem_start); /* ! ** Enable the shadow RAM. */ ! nicsr |= SHE; ! outw(nicsr, DEPCA_NICSR); /* ** Calculate the ring size based on the available RAM ** found above. Allocate an equal number of buffers, each ! ** of size PKT_BUF_SZ (1544 bytes) to the Tx and Rx. Make sure ** that this ring size is <= RING_SIZE. The ring size must be ** a power of 2. */ ! j = ((0x10000 - offset) / PKT_BUF_SZ) >> 1; for (i=0;j>1;i++) { j >>= 1; } --- 516,587 ---- } #ifdef HAVE_PORTRESERVE + #ifdef LATEST_LINUX + request_region(ioaddr, DEPCA_TOTAL_SIZE,"depca"); + #else snarf_region(ioaddr, DEPCA_TOTAL_SIZE); + #endif /* LATEST_LINUX */ #endif + /* + ** Set up the maximum amount of network RAM(kB) + */ + if (strstr(name,"DEPCA")== NULL) { + netRAM=64; + } else { + netRAM=48; + } + /* ! ** Determine the base address for the DEPCA RAM from the NI-CSR ! ** and make up a DEPCA-specific-data structure. */ if (nicsr & BUF) { ! offset = 0x8000; /* 32kbyte RAM offset*/ nicsr &= ~BS; /* DEPCA RAM in top 32k */ ! printk(",\n has %dkB RAM", netRAM - 32); ! } else if ((nicsr & _128KB) && (netRAM!=48)) { ! offset = 0x0000; ! printk(",\n has 128kB RAM"); } else { ! offset = 0x0000; /* 64k/48k bytes RAM */ ! printk(",\n has %dkB RAM", netRAM); } ! mem_start += offset; /* (E)ISA start address */ ! printk(" at 0x%.5lx", mem_start); /* ! ** Enable the shadow RAM. */ ! if (strstr(name,"DEPCA") == NULL) { ! nicsr |= SHE; ! outb(nicsr, DEPCA_NICSR); ! } /* ** Calculate the ring size based on the available RAM ** found above. Allocate an equal number of buffers, each ! ** of size PKT_BUF_SZ (1544 bytes) to the Tx and Rx, allowing one ! ** descriptor entry (8 bytes) for each buffer. Make sure ** that this ring size is <= RING_SIZE. The ring size must be ** a power of 2. */ ! #ifdef i386 ! j = (((netRAM << 10) - offset - sizeof(struct depca_private)) / ! (PKT_BUF_SZ + 8)) >> 1; ! #elif defined(__alpha) ! /* JAE: Alpha version keeps the private structure in host memory, */ ! /* JAE: including a copy of the the init_block for the hardware, */ ! /* JAE: so all we need in the board memory is the init_block plus */ ! /* JAE: all the ring buffers and descriptors (all, he says... :-) */ ! ! j = (((netRAM << 10) - offset - sizeof(struct depca_init)) / ! (PKT_BUF_SZ + 8)) >> 1; ! #endif /* i386 | __alpha */ ! for (i=0;j>1;i++) { j >>= 1; } *************** *** 484,490 **** --- 596,606 ---- ** Set up memory information in the device structure. ** Align the descriptor rings on an 8 byte (quadword) boundary. ** + #ifdef i386 ** depca_private area + #elif defined(__alpha) + ** depca_init block + #endif ** rx ring descriptors ** tx ring descriptors ** rx buffers *************** *** 493,523 **** */ /* private area & initialise */ dev->priv = (void *)((mem_start + 0x07) & ~0x07); lp = (struct depca_private *)dev->priv; memset(dev->priv, 0, sizeof(struct depca_private)); /* Tx & Rx descriptors (aligned to a quadword boundary) */ mem_start = ((((unsigned long)dev->priv + sizeof(struct depca_private)) + (unsigned long)0x07) & (unsigned long)~0x07); lp->rx_ring = (struct depca_rx_head *)mem_start; mem_start += (sizeof(struct depca_rx_head) * j); lp->tx_ring = (struct depca_tx_head *)mem_start; mem_start += (sizeof(struct depca_tx_head) * j); ! lp->dma_buffs = mem_start & 0x00ffffff; mem_start += (PKT_BUF_SZ * j); /* (mem_start now points to the start of the Tx buffers) */ ! /* Initialise the data structures */ memset(lp->rx_ring, 0, sizeof(struct depca_rx_head)*j); memset(lp->tx_ring, 0, sizeof(struct depca_tx_head)*j); /* This should never happen. */ ! if ((int)(lp->rx_ring) & 0x07) { printk("\n **ERROR** DEPCA Rx and Tx descriptor rings not on a quadword boundary.\n"); return -ENXIO; } --- 609,661 ---- */ /* private area & initialise */ + #ifdef i386 dev->priv = (void *)((mem_start + 0x07) & ~0x07); + #elif defined(__alpha) + /* JAE: allocate kernel memory to hold the private structure */ + dev->priv = kmalloc(sizeof(struct depca_private), GFP_KERNEL); + #endif /* i386 | __alpha */ lp = (struct depca_private *)dev->priv; memset(dev->priv, 0, sizeof(struct depca_private)); + strcpy(lp->devname,name); /* Tx & Rx descriptors (aligned to a quadword boundary) */ + #ifdef i386 mem_start = ((((unsigned long)dev->priv + sizeof(struct depca_private)) + (unsigned long)0x07) & (unsigned long)~0x07); + #elif defined(__alpha) + /* JAE: calculate local ptr to init_block in board memory */ + lp->init_block_addr = (struct depca_init *)((mem_start + 0x07) & ~0x07); + mem_start = ((((unsigned long)lp->init_block_addr + + sizeof(struct depca_init)) + + (unsigned long)0x07) & (unsigned long)~0x07); + #endif /* i386 | __alpha */ lp->rx_ring = (struct depca_rx_head *)mem_start; mem_start += (sizeof(struct depca_rx_head) * j); lp->tx_ring = (struct depca_tx_head *)mem_start; mem_start += (sizeof(struct depca_tx_head) * j); ! lp->bus_offset = mem_start & 0x00ff0000; ! mem_start &= LA_MASK; /* LANCE re-mapped start address */ ! ! lp->dma_buffs = mem_start; mem_start += (PKT_BUF_SZ * j); /* (mem_start now points to the start of the Tx buffers) */ ! /* Initialise the data structures wrt CPU */ ! #ifdef i386 memset(lp->rx_ring, 0, sizeof(struct depca_rx_head)*j); memset(lp->tx_ring, 0, sizeof(struct depca_tx_head)*j); + #elif defined(__alpha) + alpha_bus_memset(lp->rx_ring, 0, sizeof(struct depca_rx_head)*j); + alpha_bus_memset(lp->tx_ring, 0, sizeof(struct depca_tx_head)*j); + #endif /* i386 | __alpha */ /* This should never happen. */ ! if ((long)(lp->rx_ring) & 0x07) { printk("\n **ERROR** DEPCA Rx and Tx descriptor rings not on a quadword boundary.\n"); return -ENXIO; } *************** *** 552,565 **** ** Enable DEPCA board interrupts for autoprobing */ nicsr = ((nicsr & ~IM)|IEN); ! outw(nicsr, DEPCA_NICSR); /* The DMA channel may be passed in on this parameter. */ dev->dma = 0; ! /* To auto-IRQ we enable the initialization-done and DMA err, interrupts. For now we will always get a DMA error. */ if (dev->irq < 2) { autoirq_setup(0); /* Trigger an initialization just for the interrupt. */ --- 690,704 ---- ** Enable DEPCA board interrupts for autoprobing */ nicsr = ((nicsr & ~IM)|IEN); ! outb(nicsr, DEPCA_NICSR); /* The DMA channel may be passed in on this parameter. */ dev->dma = 0; ! /* To auto-IRQ we enable the initialization-done and DMA err, interrupts. For now we will always get a DMA error. */ if (dev->irq < 2) { + #ifndef MODULE autoirq_setup(0); /* Trigger an initialization just for the interrupt. */ *************** *** 567,579 **** dev->irq = autoirq_report(1); if (dev->irq) { ! printk(" and probed IRQ%d.\n", dev->irq); } else { ! printk(". Failed to detect IRQ line.\n"); status = -EAGAIN; } } else { ! printk(". Assigned IRQ%d.\n", dev->irq); } } else { status = -ENXIO; --- 706,719 ---- dev->irq = autoirq_report(1); if (dev->irq) { ! printk(" and uses IRQ%d.\n", dev->irq); } else { ! printk(" and failed to detect IRQ line.\n"); status = -EAGAIN; } + #endif /* MODULE */ } else { ! printk(" and assigned IRQ%d.\n", dev->irq); } } else { status = -ENXIO; *************** *** 595,600 **** --- 735,743 ---- dev->mem_start = 0; /* Fill in the generic field of the device structure. */ + #ifdef LATEST_LINUX + ether_setup(dev); + #else for (i = 0; i < DEV_NUMBUFFS; i++) { dev->buffs[i] = NULL; } *************** *** 621,626 **** --- 764,770 ---- dev->pa_brdaddr = 0; dev->pa_mask = 0; dev->pa_alen = sizeof(unsigned long); + #endif /* LATEST_LINUX */ } } else { status = -ENXIO; *************** *** 636,642 **** --- 780,790 ---- struct depca_private *lp = (struct depca_private *)dev->priv; int i,nicsr,ioaddr = dev->base_addr; + #ifdef LATEST_LINUX + if (request_irq(dev->irq, &depca_interrupt, 0, "depca")) { + #else if (request_irq(dev->irq, &depca_interrupt)) { + #endif /* LATEST_LINUX */ printk("depca_open(): Requested IRQ%d is busy\n",dev->irq); return -EAGAIN; } *************** *** 647,653 **** ** Stop the DEPCA & get the board status information. */ STOP_DEPCA; ! nicsr = inw(DEPCA_NICSR); /* ** Re-initialize the DEPCA... --- 795,809 ---- ** Stop the DEPCA & get the board status information. */ STOP_DEPCA; ! nicsr = inb(DEPCA_NICSR); ! ! /* ! ** Make sure the shadow RAM is enabled ! */ ! if (strstr(lp->devname,"DEPCA") == NULL) { ! nicsr |= SHE; ! outb(nicsr, DEPCA_NICSR); ! } /* ** Re-initialize the DEPCA... *************** *** 665,675 **** --- 821,839 ---- (long)&lp->tx_ring[i].base); } printk("Buffer addresses:\n"); + #ifdef i386 for (i=0;iringSize;i++){ printk("\t0x%8.8lx 0x%8.8lx\n",(long)lp->rx_ring[i].base, (long)lp->tx_ring[i].base); } printk("Initialisation block at 0x%8.8lx\n",(long)&lp->init_block); + #elif defined(__alpha) + for (i=0;iringSize;i++){ + printk("\t0x%8.8lx 0x%8.8lx\n",MINL(&lp->rx_ring[i].base), + MINL(&lp->tx_ring[i].base)); + } + printk("Initialisation block at 0x%8.8lx\n",(long)lp->init_block_addr); + #endif /* i386 | __alpha */ printk("\tmode: 0x%4.4x\n",lp->init_block.mode); printk("\tphysical address: "); for (i=0;i<6;i++){ *************** *** 695,704 **** } /* ! ** Enable DEPCA board interrupts */ ! nicsr = ((nicsr & ~IM & ~LED)|SHE|IEN); ! outw(nicsr, DEPCA_NICSR); outw(CSR0,DEPCA_ADDR); dev->tbusy = 0; --- 859,868 ---- } /* ! ** Enable DEPCA board interrupts and turn off LED */ ! nicsr = ((nicsr & ~IM & ~LED)|IEN); ! outb(nicsr, DEPCA_NICSR); outw(CSR0,DEPCA_ADDR); dev->tbusy = 0; *************** *** 709,717 **** if (depca_debug > 1){ printk("CSR0: 0x%4.4x\n",inw(DEPCA_DATA)); ! printk("nicsr: 0x%4.4x\n",inw(DEPCA_NICSR)); } return 0; /* Always succeed */ } --- 873,885 ---- if (depca_debug > 1){ printk("CSR0: 0x%4.4x\n",inw(DEPCA_DATA)); ! printk("nicsr: 0x%02x\n",inb(DEPCA_NICSR)); } + #ifdef MODULE + MOD_INC_USE_COUNT; + #endif + return 0; /* Always succeed */ } *************** *** 728,737 **** --- 896,912 ---- /* Initialize the base addresses and length of each buffer in the ring */ for (i = 0; i < lp->ringSize; i++) { + #ifdef i386 lp->rx_ring[i].base = (lp->dma_buffs + i*PKT_BUF_SZ) | R_OWN; lp->rx_ring[i].buf_length = -PKT_BUF_SZ; lp->tx_ring[i].base = (lp->dma_buffs + (i+lp->ringSize) * PKT_BUF_SZ) & (unsigned long)(0x00ffffff); + #elif defined(__alpha) + MOUTL(((lp->dma_buffs + i*PKT_BUF_SZ) | R_OWN), &lp->rx_ring[i].base); + MOUTW(-PKT_BUF_SZ, &lp->rx_ring[i].buf_length); + MOUTL(((lp->dma_buffs + (i+lp->ringSize) * PKT_BUF_SZ) & + (unsigned long)(0x00ffffff)), &lp->tx_ring[i].base); + #endif /* i386 | __alpha */ } /* Set up the initialization block */ *************** *** 741,750 **** for (i = 0; i < 4; i++) { lp->init_block.filter[i] = 0x0000; } ! lp->init_block.rx_ring = (unsigned long)lp->rx_ring | lp->rlen; ! lp->init_block.tx_ring = (unsigned long)lp->tx_ring | lp->rlen; lp->init_block.mode = 0x0000; /* Enable the Tx and Rx */ } /* --- 916,931 ---- for (i = 0; i < 4; i++) { lp->init_block.filter[i] = 0x0000; } ! lp->init_block.rx_ring = ((unsigned long)lp->rx_ring & LA_MASK) | lp->rlen; ! lp->init_block.tx_ring = ((unsigned long)lp->tx_ring & LA_MASK) | lp->rlen; lp->init_block.mode = 0x0000; /* Enable the Tx and Rx */ + + #ifdef __alpha + /* JAE: now copy the shadow init_block to the real one... */ + alpha_cpu_to_bus_memcpy(lp->init_block_addr, &lp->init_block, + sizeof(struct depca_init)); + #endif /* __alpha */ } /* *************** *** 760,772 **** /* Transmitter timeout, serious problems. */ if (dev->tbusy) { int tickssofar = jiffies - dev->trans_start; ! if (tickssofar < 5) { status = -1; } else { ! STOP_DEPCA; ! printk("%s: transmit timed out, status %4.4x, resetting.\n", dev->name, inw(DEPCA_DATA)); depca_init_ring(dev); LoadCSRs(dev); InitRestartDepca(dev); --- 941,953 ---- /* Transmitter timeout, serious problems. */ if (dev->tbusy) { int tickssofar = jiffies - dev->trans_start; ! if (tickssofar < 10) { status = -1; } else { ! printk("%s: transmit timed out, status %04x, resetting.\n", dev->name, inw(DEPCA_DATA)); + STOP_DEPCA; depca_init_ring(dev); LoadCSRs(dev); InitRestartDepca(dev); *************** *** 781,794 **** return 0; } - /* Fill in the ethernet header. */ - if (!skb->arp && dev->rebuild_header(skb->data, dev)) { - skb->dev = dev; - arp_queue (skb); - return 0; - } - skb->arp=1; - if (skb->len <= 0) { return 0; } --- 962,967 ---- *************** *** 817,826 **** char *p = (char *) skb->data; entry &= lp->rmask; /* Ring around buffer number. */ ! buf = (unsigned char *)(lp->tx_ring[entry].base & 0x00ffffff); /* Wait for a full ring to free up */ while (lp->tx_ring[entry].base < 0); /* ** Caution: the write order is important here... don't set up the --- 990,1008 ---- char *p = (char *) skb->data; entry &= lp->rmask; /* Ring around buffer number. */ ! #ifdef i386 ! buf = (unsigned char *)((lp->tx_ring[entry].base+lp->bus_offset) & ! 0x00ffffff); /* Wait for a full ring to free up */ while (lp->tx_ring[entry].base < 0); + #elif defined(__alpha) + buf = (unsigned char *)((MINL(&lp->tx_ring[entry].base)+lp->bus_offset) & + 0x00ffffff); + + /* Wait for a full ring to free up */ + while (MINL(&lp->tx_ring[entry].base) < 0); + #endif /* i386 | __alpha */ /* ** Caution: the write order is important here... don't set up the *************** *** 829,834 **** --- 1011,1017 ---- len = ((skbL > PKT_SZ) ? PKT_SZ : skbL); /* skb too long */ if (len < ETH_ZLEN) len = ETH_ZLEN; /* len too short */ skbL -= len; + #ifdef i386 lp->tx_ring[entry].length = -len; /* Clears various error flags */ *************** *** 840,845 **** --- 1023,1045 ---- /* Hand over buffer ownership to the LANCE */ if (skbL <= 0) lp->tx_ring[entry].base |= (T_ENP); lp->tx_ring[entry].base |= (T_OWN|T_STP); + #elif defined(__alpha) + MOUTW(-len, &lp->tx_ring[entry].length); + + /* Clears various error flags */ + MOUTW(0x0000, &lp->tx_ring[entry].misc); + + /* copy the data from the socket buffer to the net memory */ + alpha_cpu_to_bus_memcpy((unsigned char *)(buf), skb->data, len); + + /* Hand over buffer ownership to the LANCE */ + if (skbL <= 0) + MOUTL(MINL(&lp->tx_ring[entry].base) | (T_ENP), + &lp->tx_ring[entry].base); + MOUTL(MINL(&lp->tx_ring[entry].base) | (T_OWN|T_STP), + &lp->tx_ring[entry].base); + + #endif /* i386 | __alpha */ /* Trigger an immediate send demand. */ outw(CSR0, DEPCA_ADDR); *************** *** 852,872 **** /* Get new buffer pointer */ entry = lp->cur_tx++; entry &= lp->rmask; /* Ring around buffer number. */ ! buf = (unsigned char *)(lp->tx_ring[entry].base & 0x00ffffff); ! /* Wait for a full ring to free up */ while (lp->tx_ring[entry].base < 0); dev->tbusy=0; /* Copy ethernet header to the new buffer */ memcpy((unsigned char *)buf, skb->data, PKT_HDR_LEN); ! /* Determine length of data buffer */ len = ((skbL > DAT_SZ) ? DAT_SZ : skbL); /* skbL too long */ if (len < ETH_ZLEN) len = ETH_ZLEN; /* len too short */ skbL -= len; lp->tx_ring[entry].length = -len; - /* Clears various error flags */ lp->tx_ring[entry].misc = 0x0000; --- 1052,1083 ---- /* Get new buffer pointer */ entry = lp->cur_tx++; entry &= lp->rmask; /* Ring around buffer number. */ ! #ifdef i386 ! buf = (unsigned char *)((lp->tx_ring[entry].base+lp->bus_offset) & ! 0x00ffffff); /* Wait for a full ring to free up */ while (lp->tx_ring[entry].base < 0); + #elif defined(__alpha) + buf = (unsigned char *) + ((MINL(&lp->tx_ring[entry].base)+lp->bus_offset) & 0x00ffffff); + /* Wait for a full ring to free up */ + while (MINL(&lp->tx_ring[entry].base) < 0); + #endif /* i386 | __alpha */ + dev->tbusy=0; /* Copy ethernet header to the new buffer */ + #ifdef i386 memcpy((unsigned char *)buf, skb->data, PKT_HDR_LEN); ! #elif defined(__alpha) ! alpha_cpu_to_bus_memcpy((unsigned char *)buf, skb->data, PKT_HDR_LEN); ! #endif /* i386 | __alpha */ /* Determine length of data buffer */ len = ((skbL > DAT_SZ) ? DAT_SZ : skbL); /* skbL too long */ if (len < ETH_ZLEN) len = ETH_ZLEN; /* len too short */ skbL -= len; + #ifdef i386 lp->tx_ring[entry].length = -len; /* Clears various error flags */ lp->tx_ring[entry].misc = 0x0000; *************** *** 876,890 **** /* Hand over buffer ownership to the LANCE */ if (skbL <= 0) lp->tx_ring[entry].base |= T_ENP; lp->tx_ring[entry].base |= T_OWN; } if (depca_debug > 4) { unsigned char *pkt = ! (unsigned char *)(lp->tx_ring[entry].base & 0x00ffffff); printk("%s: tx ring[%d], %#lx, sk_buf %#lx len %d.\n", dev->name, entry, (unsigned long) &lp->tx_ring[entry], lp->tx_ring[entry].base, -lp->tx_ring[entry].length); printk("%s: Tx %2.2x %2.2x %2.2x ... %2.2x %2.2x %2.2x %2.2x...%2.2x len %2.2x %2.2x %2.2x %2.2x.\n", dev->name, pkt[0], pkt[1], pkt[2], pkt[5], pkt[6], pkt[7], pkt[8], pkt[11], pkt[12], pkt[13], --- 1087,1132 ---- /* Hand over buffer ownership to the LANCE */ if (skbL <= 0) lp->tx_ring[entry].base |= T_ENP; lp->tx_ring[entry].base |= T_OWN; + #elif defined(__alpha) + MOUTW(-len, &lp->tx_ring[entry].length); + /* Clears various error flags */ + MOUTW(0x0000, &lp->tx_ring[entry].misc); + + /* copy the data from the socket buffer to the net memory */ + alpha_cpu_to_bus_memcpy((unsigned char *)(buf + PKT_HDR_LEN), + (unsigned char *)p, len); + + /* Hand over buffer ownership to the LANCE */ + if (skbL <= 0) + MOUTL(MINL(&lp->tx_ring[entry].base) | T_ENP, + &lp->tx_ring[entry].base); + MOUTL(MINL(&lp->tx_ring[entry].base) | T_OWN, + &lp->tx_ring[entry].base); + #endif /* i386 | __alpha */ } if (depca_debug > 4) { unsigned char *pkt = ! #ifdef i386 ! (unsigned char *)((lp->tx_ring[entry].base+lp->bus_offset) & ! 0x00ffffff); ! #elif defined(__alpha) ! (unsigned char *) ! ((MINL(&lp->tx_ring[entry].base)+lp->bus_offset) & ! 0x00ffffff); ! #endif /* i386 | __alpha */ + #ifdef i386 printk("%s: tx ring[%d], %#lx, sk_buf %#lx len %d.\n", dev->name, entry, (unsigned long) &lp->tx_ring[entry], lp->tx_ring[entry].base, -lp->tx_ring[entry].length); + #elif defined(__alpha) + printk("%s: tx ring[%d], %#lx, sk_buf %#lx len %d.\n", + dev->name, entry, (unsigned long) &lp->tx_ring[entry], + MINL(&lp->tx_ring[entry].base), + -MINW(&lp->tx_ring[entry].length)); + #endif /* i386 | __alpha */ + printk("%s: Tx %2.2x %2.2x %2.2x ... %2.2x %2.2x %2.2x %2.2x...%2.2x len %2.2x %2.2x %2.2x %2.2x.\n", dev->name, pkt[0], pkt[1], pkt[2], pkt[5], pkt[6], pkt[7], pkt[8], pkt[11], pkt[12], pkt[13], *************** *** 892,904 **** --- 1134,1154 ---- } /* Check if the TX ring is full or not - 'tbusy' cleared if not full. */ + #ifdef i386 if (lp->tx_ring[(entry+1) & lp->rmask].base >= 0) { + #elif defined(__alpha) + if (MINL(&lp->tx_ring[(entry+1) & lp->rmask].base) >= 0) { + #endif /* i386 | __alpha */ dev->tbusy=0; } + #ifdef LATEST_LINUX + dev_kfree_skb (skb, FREE_WRITE); + #else if (skb->free) { kfree_skb (skb, FREE_WRITE); } + #endif /* LATEST_LINUX */ } return 0; *************** *** 908,969 **** ** The DEPCA interrupt handler. */ static void ! depca_interrupt(int reg_ptr) { - int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2); struct device *dev = (struct device *)(irq2dev_map[irq]); struct depca_private *lp; int csr0, ioaddr, nicsr; if (dev == NULL) { printk ("depca_interrupt(): irq %d for unknown device.\n", irq); - return; } else { lp = (struct depca_private *)dev->priv; ioaddr = dev->base_addr; - } ! if (dev->interrupt) printk("%s: Re-entering the interrupt handler.\n", dev->name); ! dev->interrupt = MASK_INTERRUPTS; ! /* mask the DEPCA board interrupts and turn on the LED */ ! nicsr = inw(DEPCA_NICSR); ! nicsr |= (IM|LED); ! outw(nicsr, DEPCA_NICSR); ! outw(CSR0, DEPCA_ADDR); ! csr0 = inw(DEPCA_DATA); ! /* Acknowledge all of the current interrupt sources ASAP. */ ! outw(csr0 & ~(INEA|TDMD|STOP|STRT|INIT), DEPCA_DATA); ! if (depca_debug > 5) printk("%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", dev->name, csr0, inw(DEPCA_DATA)); ! if (csr0 & RINT) /* Rx interrupt (packet arrived) */ depca_rx(dev); ! if (csr0 & TINT) /* Tx interrupt (packet sent) */ depca_tx(dev); ! /* Clear the interrupts we've handled. */ ! outw(CSR0, DEPCA_ADDR); ! outw(BABL|CERR|MISS|MERR|RINT|TINT|IDON|INEA, DEPCA_DATA); ! if (depca_debug > 4) { ! printk("%s: exiting interrupt, csr%d=%#4.4x.\n", ! dev->name, inw(DEPCA_ADDR), ! inw(DEPCA_DATA)); ! } ! /* Unmask the DEPCA board interrupts and turn off the LED */ ! nicsr = (nicsr & ~IM & ~LED); ! outw(nicsr, DEPCA_NICSR); - dev->interrupt = UNMASK_INTERRUPTS; return; } --- 1158,1217 ---- ** The DEPCA interrupt handler. */ static void ! depca_interrupt(int irq, struct pt_regs * regs) { struct device *dev = (struct device *)(irq2dev_map[irq]); struct depca_private *lp; int csr0, ioaddr, nicsr; if (dev == NULL) { printk ("depca_interrupt(): irq %d for unknown device.\n", irq); } else { lp = (struct depca_private *)dev->priv; ioaddr = dev->base_addr; ! if (dev->interrupt) printk("%s: Re-entering the interrupt handler.\n", dev->name); ! dev->interrupt = MASK_INTERRUPTS; ! /* mask the DEPCA board interrupts and turn on the LED */ ! nicsr = inb(DEPCA_NICSR); ! nicsr |= (IM|LED); ! outb(nicsr, DEPCA_NICSR); ! outw(CSR0, DEPCA_ADDR); ! csr0 = inw(DEPCA_DATA); ! /* Acknowledge all of the current interrupt sources ASAP. */ ! outw(csr0 & ~(INEA|TDMD|STOP|STRT|INIT), DEPCA_DATA); ! if (depca_debug > 5) printk("%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", dev->name, csr0, inw(DEPCA_DATA)); ! if (csr0 & RINT) /* Rx interrupt (packet arrived) */ depca_rx(dev); ! if (csr0 & TINT) /* Tx interrupt (packet sent) */ depca_tx(dev); ! /* Clear the interrupts we've handled. */ ! outw(CSR0, DEPCA_ADDR); ! outw(BABL|CERR|MISS|MERR|RINT|TINT|IDON|INEA, DEPCA_DATA); ! if (depca_debug > 4) { ! printk("%s: exiting interrupt, csr%d=%#4.4x.\n", ! dev->name, inw(DEPCA_ADDR), ! inw(DEPCA_DATA)); ! } ! /* Unmask the DEPCA board interrupts and turn off the LED */ ! nicsr = (nicsr & ~IM & ~LED); ! outb(nicsr, DEPCA_NICSR); ! dev->interrupt = UNMASK_INTERRUPTS; ! } return; } *************** *** 974,1025 **** int entry = lp->cur_rx & lp->rmask; /* If we own the next entry, it's a new packet. Send it up. */ for (; lp->rx_ring[entry].base >= 0; entry = (++lp->cur_rx) & lp->rmask) { int status = lp->rx_ring[entry].base >> 16 ; ! if (status & R_ERR) { /* There was an error. */ ! lp->stats.rx_errors++; /* Update the error stats. */ if (status & R_FRAM) lp->stats.rx_frame_errors++; if (status & R_OFLO) lp->stats.rx_over_errors++; if (status & R_CRC) lp->stats.rx_crc_errors++; if (status & R_BUFF) lp->stats.rx_fifo_errors++; } else { /* Malloc up new buffer, compatible with net-2e. */ short pkt_len = lp->rx_ring[entry].msg_length; ! int sksize = sizeof(struct sk_buff) + pkt_len; struct sk_buff *skb; ! skb = alloc_skb(sksize, GFP_ATOMIC); if (skb == NULL) { printk("%s: Memory squeeze, deferring packet.\n", dev->name); lp->stats.rx_dropped++; /* Really, deferred. */ break; } - skb->mem_len = sksize; - skb->mem_addr = skb; skb->len = pkt_len; skb->dev = dev; memcpy(skb->data, ! (unsigned char *)(lp->rx_ring[entry].base & 0x00ffffff), pkt_len); /* ** Notify the upper protocol layers that there is another ** packet to handle */ - #ifdef HAVE_NETIF_RX netif_rx(skb); - #else - skb->lock = 0; - if (dev_rint((unsigned char*)skb, pkt_len, IN_SKBUFF, dev) != 0) { - kfree_skbmem(skb, sksize); - lp->stats.rx_dropped++; - break; - } - #endif lp->stats.rx_packets++; } /* turn over ownership of the current entry back to the LANCE */ lp->rx_ring[entry].base |= R_OWN; } /* --- 1222,1323 ---- int entry = lp->cur_rx & lp->rmask; /* If we own the next entry, it's a new packet. Send it up. */ + #ifdef i386 for (; lp->rx_ring[entry].base >= 0; entry = (++lp->cur_rx) & lp->rmask) { int status = lp->rx_ring[entry].base >> 16 ; + #elif defined(__alpha) + for (; MINL(&lp->rx_ring[entry].base) >= 0; + entry = (++lp->cur_rx) & lp->rmask) + { + int status = MINL(&lp->rx_ring[entry].base) >> 16 ; + #endif /* i386 | __alpha */ + int chained; + + /* + ** There is a tricky error noted by John Murphy, + ** to Russ Nelson: even with full-sized buffers, it's possible for a + ** jabber packet to use two buffers, with only the last one correctly + ** noting the error. + */ ! /* Check for a chaining buffer */ ! chained = 0; ! if (status == R_STP) { ! chained = 1; ! ! /* ! ** Wait for next buffer to complete to check for errors. This ! ** is slow but infrequent and allows for correct hardware buffer ! ** chaining (whilst defeating the chaining's purpose). ! */ ! #ifdef i386 ! while ((status=(lp->rx_ring[(entry+1)&lp->rmask].base >> 16)) < 0); ! #elif defined(__alpha) ! while ((status= ! (MINL(&lp->rx_ring[(entry+1)&lp->rmask].base) >> 16)) < 0); ! #endif /* i386 | __alpha */ ! ! /* NB: 'status' now comes from the buffer following 'entry'. */ ! } ! ! if (status & R_ERR) { /* There was an error. */ ! lp->stats.rx_errors++; /* Update the error stats. */ if (status & R_FRAM) lp->stats.rx_frame_errors++; if (status & R_OFLO) lp->stats.rx_over_errors++; if (status & R_CRC) lp->stats.rx_crc_errors++; if (status & R_BUFF) lp->stats.rx_fifo_errors++; } else { /* Malloc up new buffer, compatible with net-2e. */ + #ifdef i386 short pkt_len = lp->rx_ring[entry].msg_length; ! #elif defined(__alpha) ! short pkt_len = MINW(&lp->rx_ring[entry].msg_length); ! #endif /* i386 | __alpha */ struct sk_buff *skb; ! skb = alloc_skb(pkt_len, GFP_ATOMIC); if (skb == NULL) { printk("%s: Memory squeeze, deferring packet.\n", dev->name); lp->stats.rx_dropped++; /* Really, deferred. */ break; } skb->len = pkt_len; skb->dev = dev; + #ifdef i386 memcpy(skb->data, ! (unsigned char *)((lp->rx_ring[entry].base+lp->bus_offset) & ! 0x00ffffff), pkt_len); + #elif defined(__alpha) + alpha_bus_to_cpu_memcpy(skb->data, + (unsigned char *) + ((MINL(&lp->rx_ring[entry].base)+lp->bus_offset) & + 0x00ffffff), + pkt_len); + #endif /* i386 | __alpha */ /* ** Notify the upper protocol layers that there is another ** packet to handle */ netif_rx(skb); lp->stats.rx_packets++; } /* turn over ownership of the current entry back to the LANCE */ + #ifdef i386 lp->rx_ring[entry].base |= R_OWN; + #elif defined(__alpha) + MOUTL(MINL(&lp->rx_ring[entry].base) | R_OWN, + &lp->rx_ring[entry].base); + #endif /* i386 | __alpha */ + if (chained && (status & R_ERR)) { /* next entry also bad */ + entry = (++lp->cur_rx) & lp->rmask; + #ifdef i386 + lp->rx_ring[entry].base |= R_OWN; + #elif defined(__alpha) + MOUTL(MINL(&lp->rx_ring[entry].base) | R_OWN, + &lp->rx_ring[entry].base); + #endif /* i386 | __alpha */ + } } /* *************** *** 1047,1063 **** ** While the dirty entry is not the current one AND ** the LANCE doesn't own it... */ ! for (; dirty_tx!=(lp->cur_tx & lp->rmask) && lp->tx_ring[dirty_tx].base>0; ! dirty_tx = ++lp->dirty_tx & lp->rmask) { unsigned long *tmdp = (unsigned long *)(&lp->tx_ring[dirty_tx]); int status = lp->tx_ring[dirty_tx].base >> 16; if (status < 0) { /* Packet not yet sent! */ printk("interrupt for packet not yet sent!\n"); break; } if (status & T_ERR) { /* There was an major error, log it. */ int err_status = lp->tx_ring[dirty_tx].misc; lp->stats.tx_errors++; if (err_status & TMD3_RTRY) lp->stats.tx_aborted_errors++; --- 1345,1375 ---- ** While the dirty entry is not the current one AND ** the LANCE doesn't own it... */ ! for (; dirty_tx != (lp->cur_tx & lp->rmask) && ! #ifdef i386 ! lp->tx_ring[dirty_tx].base > 0; ! #elif defined(__alpha) ! MINL(&lp->tx_ring[dirty_tx].base) > 0; ! #endif /* i386 | __alpha */ ! dirty_tx = ++lp->dirty_tx & lp->rmask) ! { unsigned long *tmdp = (unsigned long *)(&lp->tx_ring[dirty_tx]); + #ifdef i386 int status = lp->tx_ring[dirty_tx].base >> 16; + #elif defined(__alpha) + int status = MINL(&lp->tx_ring[dirty_tx].base) >> 16; + #endif /* i386 | __alpha */ if (status < 0) { /* Packet not yet sent! */ printk("interrupt for packet not yet sent!\n"); break; } if (status & T_ERR) { /* There was an major error, log it. */ + #ifdef i386 int err_status = lp->tx_ring[dirty_tx].misc; + #elif defined(__alpha) + int err_status = MINW(&lp->tx_ring[dirty_tx].misc); + #endif /* i386 | __alpha */ lp->stats.tx_errors++; if (err_status & TMD3_RTRY) lp->stats.tx_aborted_errors++; *************** *** 1072,1080 **** --- 1384,1398 ---- } if (depca_debug > 5) + #ifdef i386 printk("%s: Tx done entry %d, %4.4lx %4.4lx %4.4lx %4.4lx.\n", dev->name, dirty_tx, tmdp[0], tmdp[1], tmdp[2], tmdp[3]); + #elif defined(__alpha) + printk("%s: Tx done entry %d, %4.4lx %4.4lx %4.4lx %4.4lx.\n", + dev->name, dirty_tx, + MINL(&tmdp[0]), MINL(&tmdp[1]), MINL(&tmdp[2]), MINL(&tmdp[3])); + #endif /* i386 | __alpha */ } /*mark_bh(INET_BH);*/ return 0; *************** *** 1083,1111 **** static int depca_close(struct device *dev) { ! int ioaddr = dev->base_addr; ! dev->start = 0; ! dev->tbusy = 1; ! outw(CSR0, DEPCA_ADDR); ! if (depca_debug > 1) { ! printk("%s: Shutting down ethercard, status was %2.2x.\n", ! dev->name, inw(DEPCA_DATA)); ! } ! /* ! ** We stop the DEPCA here -- it occasionally polls ! ** memory if we don't. ! */ ! outw(STOP, DEPCA_DATA); ! free_irq(dev->irq); ! irq2dev_map[dev->irq] = 0; ! return 0; } static void LoadCSRs(struct device *dev) --- 1401,1443 ---- static int depca_close(struct device *dev) { ! struct depca_private *lp = (struct depca_private *)dev->priv; ! int nicsr, ioaddr = dev->base_addr; ! dev->start = 0; ! dev->tbusy = 1; ! outw(CSR0, DEPCA_ADDR); ! if (depca_debug > 1) { ! printk("%s: Shutting down ethercard, status was %2.2x.\n", ! dev->name, inw(DEPCA_DATA)); ! } ! /* ! ** We stop the DEPCA here -- it occasionally polls ! ** memory if we don't. ! */ ! outw(STOP, DEPCA_DATA); ! ! /* ! ** Give back the ROM in case the user wants to go to DOS ! */ ! if (strstr(lp->devname,"DEPCA") == NULL) { ! nicsr = inb(DEPCA_NICSR); ! nicsr &= ~SHE; ! outb(nicsr, DEPCA_NICSR); ! } ! free_irq(dev->irq); ! irq2dev_map[dev->irq] = 0; ! #ifdef MODULE ! MOD_DEC_USE_COUNT; ! #endif ! ! return 0; } static void LoadCSRs(struct device *dev) *************** *** 1114,1122 **** int ioaddr = dev->base_addr; outw(CSR1, DEPCA_ADDR); /* initialisation block address LSW */ ! outw((unsigned short)(unsigned long)&lp->init_block, DEPCA_DATA); outw(CSR2, DEPCA_ADDR); /* initialisation block address MSW */ ! outw((unsigned short)((unsigned long)&lp->init_block >> 16), DEPCA_DATA); outw(CSR3, DEPCA_ADDR); /* ALE control */ outw(ACON, DEPCA_DATA); outw(CSR0, DEPCA_ADDR); /* point back to CSR0 */ --- 1446,1468 ---- int ioaddr = dev->base_addr; outw(CSR1, DEPCA_ADDR); /* initialisation block address LSW */ ! #ifdef i386 ! outw((unsigned short)((unsigned long)(&lp->init_block) & LA_MASK), ! DEPCA_DATA); ! #elif defined(__alpha) ! outw((unsigned short)((unsigned long)(lp->init_block_addr) & LA_MASK), ! DEPCA_DATA); ! #endif /* i386 | __alpha */ ! outw(CSR2, DEPCA_ADDR); /* initialisation block address MSW */ ! #ifdef i386 ! outw((unsigned short)(((unsigned long)(&lp->init_block) & LA_MASK) >> 16), ! DEPCA_DATA); ! #elif defined(__alpha) ! outw((unsigned short)(((unsigned long)(lp->init_block_addr) & LA_MASK) >> 16), ! DEPCA_DATA); ! #endif /* i386 | __alpha */ ! outw(CSR3, DEPCA_ADDR); /* ALE control */ outw(ACON, DEPCA_DATA); outw(CSR0, DEPCA_ADDR); /* point back to CSR0 */ *************** *** 1138,1150 **** --- 1484,1506 ---- /* clear IDON by writing a "1", enable interrupts and start lance */ outw(IDON | INEA | STRT, DEPCA_DATA); if (depca_debug > 2) { + #ifdef i386 printk("%s: DEPCA open after %d ticks, init block %#lx csr0 %4.4x.\n", dev->name, i, (long) &lp->init_block, inw(DEPCA_DATA)); + #elif defined(__alpha) + printk("%s: DEPCA open after %d ticks, init block %#lx csr0 %4.4x.\n", + dev->name, i, (long) lp->init_block_addr, inw(DEPCA_DATA)); + #endif /* i386 | __alpha */ } } else { status = -1; + #ifdef i386 printk("%s: DEPCA unopened after %d ticks, init block %#lx csr0 %4.4x.\n", dev->name, i, (long) &lp->init_block, inw(DEPCA_DATA)); + #elif defined(__alpha) + printk("%s: DEPCA unopened after %d ticks, init block %#lx csr0 %4.4x.\n", + dev->name, i, (long) lp->init_block_addr, inw(DEPCA_DATA)); + #endif /* i386 | __alpha */ } return status; *************** *** 1168,1202 **** ** num_addrs > 0 Multicast mode, receive normal and MC packets, and do ** best-effort filtering. */ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs) { short ioaddr = dev->base_addr; struct depca_private *lp = (struct depca_private *)dev->priv; ! /* We take the simple way out and always enable promiscuous mode. */ ! STOP_DEPCA; /* Temporarily stop the depca. */ ! ! lp->init_block.mode = PROM; /* Set promiscuous mode */ ! if (num_addrs >= 0) { ! short multicast_table[4]; ! int i; ! ! SetMulticastFilter(num_addrs, (char *)addrs, (char *)multicast_table); ! /* We don't use the multicast table, but rely on upper-layer filtering. */ ! memset(multicast_table, (num_addrs==0) ? 0 : -1, sizeof(multicast_table)); ! for (i = 0; i < 4; i++) { ! lp->init_block.filter[i] = multicast_table[i]; ! } ! lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */ ! } else { ! lp->init_block.mode |= PROM; /* Set promiscuous mode */ } - - outw(CSR0, DEPCA_ADDR); - outw(IDON|INEA|STRT, DEPCA_DATA); /* Resume normal operation. */ } /* --- 1524,1557 ---- ** num_addrs > 0 Multicast mode, receive normal and MC packets, and do ** best-effort filtering. */ + #define hash_filter lp->init_block.filter + static void set_multicast_list(struct device *dev, int num_addrs, void *addrs) { short ioaddr = dev->base_addr; struct depca_private *lp = (struct depca_private *)dev->priv; ! if (irq2dev_map[dev->irq] != NULL) { ! STOP_DEPCA; /* Temporarily stop the depca. */ ! depca_init_ring(dev); /* Initialize the descriptor rings */ ! ! if (num_addrs >= 0) { ! SetMulticastFilter(num_addrs, (char *)addrs, (char *)hash_filter); ! lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */ ! } else { ! lp->init_block.mode |= PROM; /* Set promiscuous mode */ ! } ! #ifdef __alpha ! /* JAE: now copy the shadow init_block to the real one... */ ! alpha_cpu_to_bus_memcpy(lp->init_block_addr, &lp->init_block, ! sizeof(struct depca_init)); ! #endif /* __alpha */ ! LoadCSRs(dev); /* Reload CSR3 */ ! InitRestartDepca(dev); /* Resume normal operation. */ } } /* *************** *** 1241,1246 **** --- 1596,1702 ---- #endif /* HAVE_MULTICAST */ + #ifndef MODULE + /* + ** ISA bus I/O device probe + */ + static struct device *isa_probe(struct device *dev) + { + int *port, ports[] = DEPCA_IO_PORTS; + int status; + + for (status = -ENODEV, port = &ports[0]; + *port && (num_depcas < MAX_NUM_DEPCAS); port++) { + int ioaddr = *port; + + if (DevicePresent(ioaddr) == 0) { + if (num_depcas > 0) { /* only gets here in autoprobe */ + dev = alloc_device(dev, ioaddr); + } else { + if ((status = depca_probe1(dev, ioaddr)) == 0) { + num_depcas++; + } + } + num_eth++; + } + } + return dev; + } + + /* + ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually + ** the motherboard. + */ + static struct device *eisa_probe(struct device *dev) + { + int i, ioaddr = DEPCA_EISA_IO_PORTS; + int status; + + ioaddr+=0x1000; /* get the first slot address */ + for (status = -ENODEV, i=1; i 0) { /* only gets here in autoprobe */ + dev = alloc_device(dev, ioaddr); + } else { + if ((status = depca_probe1(dev, ioaddr)) == 0) { + num_depcas++; + } + } + num_eth++; + } + } + return dev; + } + + /* + ** Allocate the device by pointing to the next available space in the + ** device structure. Should one not be available, it is created. + */ + static struct device *alloc_device(struct device *dev, int ioaddr) + { + /* + ** Check the device structures for an end of list or unused device + */ + while (dev->next != NULL) { + if (dev->next->base_addr == 0xffe0) break; + dev = dev->next; /* walk through eth device list */ + num_eth++; /* increment eth device number */ + } + + /* + ** If no more device structures, malloc one up. If memory could + ** not be allocated, print an error message. + */ + if (dev->next == NULL) { + dev->next = (struct device *)kmalloc(sizeof(struct device) + 8, + GFP_KERNEL); + if (dev->next == NULL) { + printk("eth%d: Device not initialised, insufficient memory\n", + num_eth); + } + } + + /* + ** If the memory was allocated, point to the new memory area + ** and initialize it (name, I/O address, next device (NULL) and + ** initialisation probe routine). + */ + if ((dev->next != NULL) && + (num_eth > 0) && (num_eth < 9999)) { + dev = dev->next; /* point to the new device */ + dev->name = (char *)(dev + 1); + sprintf(dev->name,"eth%d", num_eth);/* New device name */ + dev->base_addr = ioaddr; /* assign the io address */ + dev->next = NULL; /* mark the end of list */ + dev->init = &depca_probe; /* initialisation routine */ + num_depcas++; + } + + return dev; + } + #endif /* MODULE */ + /* ** Look for a particular board name in the on-board Remote Diagnostics ** and Boot (RDB) ROM. This will also give us a clue to the network RAM *************** *** 1254,1265 **** char tmpstr[17]; for (i=0;i<16;i++) { /* copy the first 16 bytes of ROM to */ tmpstr[i] = *(unsigned char *)(mem_addr+0xc000+i); /* a temporary string */ } ! tmpstr[i]=(char)NULL; strcpy(thisName,""); ! for (i=0;*signatures[i]!=(char)NULL && *thisName==(char)NULL;i++) { for (j=0,k=0;j<16 && k=0) { devSig[i]<<=4; if((devSig[i+1]=asc2hex(devSig[i+1]))>=0){ --- 1751,1780 ---- static short fp=1,sigLength=0; static char devSig[] = PROBE_SEQUENCE; char data; ! int i, j, nicsr, status = 0; static char asc2hex(char value); + /* + ** Initialize the counter on a DEPCA card. Two reads to ensure DEPCA ethernet + ** address counter is a) cleared and b) the correct data read. + */ + data = inb(DEPCA_PROM); /* clear counter */ + data = inb(DEPCA_PROM); /* read data */ + + /* + ** Enable counter + */ + if (data == 0x08) { + nicsr = inb(DEPCA_NICSR); + nicsr |= AAC; + outb(nicsr, DEPCA_NICSR); + } + /* ** Convert the ascii signature to a hex equivalent & pack in place */ if (fp) { /* only do this once!... */ ! for (i=0,j=0;devSig[i] != '\0' && !status;i+=2,j++) { if ((devSig[i]=asc2hex(devSig[i]))>=0) { devSig[i]<<=4; if((devSig[i+1]=asc2hex(devSig[i+1]))>=0){ *************** *** 1311,1324 **** /* ** Search the Ethernet address ROM for the signature. Since the ROM address ** counter can start at an arbitrary point, the search must include the entire ! ** probe sequence length plus the length of the (signature - 1). ** Stop the search IMMEDIATELY after the signature is found so that the ** PROM address counter is correctly positioned at the start of the ** ethernet address for later read out. */ if (!status) { for (i=0,j=0;j 0; count--, dst++) + MOUTB((unsigned char)val, dst); + } + /* JAE: this routine knows that the source is CPU memory */ + /* JAE: this routine knows that the destination is BUS memory */ + void + alpha_cpu_to_bus_memcpy(dst, src, count) + unsigned long dst, src; + int count; + { + for (; count > 0; count--, dst++, src++) + MOUTB(*(unsigned char *)src, dst); + } + + /* JAE: this routine knows that the source is BUS memory */ + /* JAE: this routine knows that the destination is CPU memory */ + void + alpha_bus_to_cpu_memcpy(dst, src, count) + unsigned long dst, src; + int count; + { + for (; count > 0; count--, dst++, src++) + *(unsigned char *)dst = MINB(src); + } + #endif /* __alpha */ diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/net/depca.h LINUX_ALPHA_SDK/sources/linux/drivers/net/depca.h *** LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/net/depca.h Tue Dec 13 14:44:00 1994 --- LINUX_ALPHA_SDK/sources/linux/drivers/net/depca.h Wed Feb 8 14:16:07 1995 *************** *** 14,20 **** --- 14,22 ---- #define DEPCA_RBI ioaddr+0x02 /* RAM buffer index (2k buffer mode) */ #define DEPCA_DATA ioaddr+0x04 /* LANCE registers' data port */ #define DEPCA_ADDR ioaddr+0x06 /* LANCE registers' address port */ + #define DEPCA_HBASE ioaddr+0x08 /* EISA high memory base address reg. */ #define DEPCA_PROM ioaddr+0x0c /* Ethernet address ROM data port */ + #define DEPCA_CNFG ioaddr+0x0c /* EISA Configuration port */ #define DEPCA_RBSA ioaddr+0x0e /* RAM buffer starting address (2k buff.) */ /* *************** *** 34,40 **** #define BS 0x0040 /* Bank Select */ #define BUF 0x0020 /* BUFfer size (1->32k, 0->64k) */ #define RBE 0x0010 /* Remote Boot Enable (1->net boot) */ ! #define AAC 0x0008 /* for DEPCA family compatability */ #define IM 0x0004 /* Interrupt Mask (1->mask) */ #define IEN 0x0002 /* Interrupt tristate ENable (1->enable) */ #define LED 0x0001 /* LED control */ --- 36,43 ---- #define BS 0x0040 /* Bank Select */ #define BUF 0x0020 /* BUFfer size (1->32k, 0->64k) */ #define RBE 0x0010 /* Remote Boot Enable (1->net boot) */ ! #define AAC 0x0008 /* Address ROM Address Counter (1->enable) */ ! #define _128KB 0x0008 /* 128kB Network RAM (1->enable) */ #define IM 0x0004 /* Interrupt Mask (1->mask) */ #define IEN 0x0002 /* Interrupt tristate ENable (1->enable) */ #define LED 0x0001 /* LED control */ *************** *** 119,124 **** --- 122,141 ---- #define TMD3_LCAR 0x0800 /* Loss of CARrier */ #define TMD3_RTRY 0x0400 /* ReTRY error */ + /* + ** EISA configuration Register (CNFG) bit definitions + */ + + #define TIMEOUT 0x0100 /* 0:2.5 mins, 1: 30 secs */ + #define REMOTE 0x0080 /* Remote Boot Enable -> 1 */ + #define IRQ11 0x0040 /* Enable -> 1 */ + #define IRQ10 0x0020 /* Enable -> 1 */ + #define IRQ9 0x0010 /* Enable -> 1 */ + #define IRQ5 0x0008 /* Enable -> 1 */ + #define BUFF 0x0004 /* 0: 64kB or 128kB, 1: 32kB */ + #define PADR16 0x0002 /* RAM on 64kB boundary */ + #define PADR17 0x0001 /* RAM on 128kB boundary */ + /* ** Miscellaneous */ *************** *** 126,128 **** --- 143,148 ---- #define MASK_INTERRUPTS 1 #define UNMASK_INTERRUPTS 0 + #define EISA_EN 0x0001 /* Enable EISA bus buffers */ + #define DEPCA_EISA_ID ioaddr+0x80 /* ID long word for EISA card */ + #define DEPCA_EISA_CTRL ioaddr+0x84 /* Control word for EISA card */ diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/scsi/aha1740.c LINUX_ALPHA_SDK/sources/linux/drivers/scsi/aha1740.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/scsi/aha1740.c Fri Dec 30 15:54:16 1994 --- LINUX_ALPHA_SDK/sources/linux/drivers/scsi/aha1740.c Wed Feb 8 14:24:23 1995 *************** *** 1,4 **** ! /* $Id: aha1740.c,v 1.2 1994/12/30 20:54:16 jestabro Exp $ * 1993/03/31 * linux/kernel/aha1740.c * --- 1,4 ---- ! /* $Id: aha1740.c,v 1.3 1995/02/08 19:24:23 jestabro Exp $ * 1993/03/31 * linux/kernel/aha1740.c * *************** *** 51,58 **** #define DEBERR(x) #endif /* ! static const char RCSid[] = "$Header: /amt/LINUX/LINUX_SDK/RCS/linux/drivers/scsi/aha1740.c,v 1.2 1994/12/30 20:54:16 jestabro Exp $"; */ static unsigned int slot, base; --- 51,63 ---- #define DEBERR(x) #endif + /* JAE: temporarily, make it possible to wire IRQ level to what ECU indicates */ /* ! #define HARDWIRED_IRQ 11 ! */ ! ! /* ! static const char RCSid[] = "$Header: /amt/LINUX/LINUX_SDK/RCS/linux/drivers/scsi/aha1740.c,v 1.3 1995/02/08 19:24:23 jestabro Exp $"; */ static unsigned int slot, base; *************** *** 202,209 **** case G2INTST_CCBRETRY: case G2INTST_CCBERROR: case G2INTST_CCBGOOD: ! ecbptr = (struct ecb *) ( ((ulong) inb(MBOXIN0)) + ! ((ulong) inb(MBOXIN1) <<8) + ((ulong) inb(MBOXIN2) <<16) + ((ulong) inb(MBOXIN3) <<24) ); DEB(printk("aha1740_intr_handle: ecbptr 0x%x\n", --- 207,214 ---- case G2INTST_CCBRETRY: case G2INTST_CCBERROR: case G2INTST_CCBGOOD: ! ecbptr = (struct ecb *) ( ((ulong) inb(MBOXIN0) ) + ! ((ulong) inb(MBOXIN1) << 8) + ((ulong) inb(MBOXIN2) <<16) + ((ulong) inb(MBOXIN3) <<24) ); DEB(printk("aha1740_intr_handle: ecbptr 0x%x\n", *************** *** 215,223 **** * for it... */ ecbptr = ecb + ! (((long)ecbptr - (long)virttophys(ecb)) / sizeof(struct ecb)); DEB(printk("aha1740_intr_handle: ALPHA ecbptr 0x%x\n", (unsigned long)ecbptr)); #endif /* __alpha */ outb(G2CNTRL_HRDY,G2CNTRL); /* Host Ready -> Mailbox in complete */ --- 220,232 ---- * for it... */ ecbptr = ecb + ! (((long)ecbptr - (long)virttophys(ecb)) / sizeof(struct ecb)); ! DEB(printk("aha1740_intr_handle: ALPHA ecbptr 0x%x\n", (unsigned long)ecbptr)); + + if (ecbptr < ecb || ecbptr > &ecb[AHA1740_ECBS-1]) + panic("aha1740_intr_handle: ECB ptr out of range"); #endif /* __alpha */ outb(G2CNTRL_HRDY,G2CNTRL); /* Host Ready -> Mailbox in complete */ *************** *** 259,269 **** } number_serviced++; }; - - #ifdef NOT_NOW - /* in case the INTPEND bit is NOT set (???), reset the interrupt */ - outb(G2CNTRL_IRST,G2CNTRL); /* interrupt reset */ - #endif /* __alpha */ } int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) --- 268,273 ---- *************** *** 467,472 **** --- 471,477 ---- (long) &ecb[ecbno], adrs); #endif #endif + outb((char) (adrs&0xff), MBOXOUT0); /* out, note this set */ outb((char) ((adrs>>8)&0xff), MBOXOUT1); /* of outb's must be */ outb((char) ((adrs>>16)&0xff), MBOXOUT2); /* atomic */ *************** *** 521,530 **** { static int intab[] = { 9,10,11,12,0,14,15,0 }; ! #ifdef i386 irq_level = intab [ inb(INTDEF)&0x7 ]; - #elif defined(__alpha) - irq_level = 11; /* JAE: for now, hardwire to what ECU wanted... */ #endif } --- 526,535 ---- { static int intab[] = { 9,10,11,12,0,14,15,0 }; ! #ifdef HARDWIRED_IRQ ! irq_level = HARDWIRED_IRQ; /* JAE: hardwire to what ECU usually wants */ ! #else irq_level = intab [ inb(INTDEF)&0x7 ]; #endif } diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/scsi/scsi.c LINUX_ALPHA_SDK/sources/linux/drivers/scsi/scsi.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/scsi/scsi.c Fri Dec 30 16:04:12 1994 --- LINUX_ALPHA_SDK/sources/linux/drivers/scsi/scsi.c Wed Feb 8 14:24:21 1995 *************** *** 25,34 **** #include "hosts.h" #include "constants.h" ! /* #define DEBUG */ /* ! static const char RCSid[] = "$Header: /amt/LINUX/LINUX_SDK/RCS/linux/drivers/scsi/scsi.c,v 1.2 1994/12/30 21:04:12 jestabro Exp $"; */ /* Command groups 3 and 4 are reserved and should never be used. */ --- 25,39 ---- #include "hosts.h" #include "constants.h" ! /* ! #define DEBUG ! #define DEBUG_BIGGER_TIMEOUT ! #define DEBUG_CMD ! #define DEBUG_INIT ! */ /* ! static const char RCSid[] = "$Header: /amt/LINUX/LINUX_SDK/RCS/linux/drivers/scsi/scsi.c,v 1.3 1995/02/08 19:24:21 jestabro Exp $"; */ /* Command groups 3 and 4 are reserved and should never be used. */ *************** *** 99,111 **** * respectively. */ ! #ifdef DEBUG #define SCSI_TIMEOUT 500 #else #define SCSI_TIMEOUT 100 #endif ! #ifdef DEBUG #define SENSE_TIMEOUT SCSI_TIMEOUT #define ABORT_TIMEOUT SCSI_TIMEOUT #define RESET_TIMEOUT SCSI_TIMEOUT --- 104,116 ---- * respectively. */ ! #if defined(DEBUG) || defined(DEBUG_BIGGER_TIMEOUT) #define SCSI_TIMEOUT 500 #else #define SCSI_TIMEOUT 100 #endif ! #if defined(DEBUG) || defined(DEBUG_BIGGER_TIMEOUT) #define SENSE_TIMEOUT SCSI_TIMEOUT #define ABORT_TIMEOUT SCSI_TIMEOUT #define RESET_TIMEOUT SCSI_TIMEOUT *************** *** 200,210 **** struct Scsi_Host * shpnt; Scsi_Cmnd SCmd; - #ifdef DEBUG_TIMEOUT - #define DEBUG_TIMEOUT_COUNT 1000000 - volatile int i; - #endif /* DEBUG_TIMEOUT */ - ++in_scan; lun = 0; --- 205,210 ---- *************** *** 264,279 **** scsi_result, 256, scan_scsis_done, SCSI_TIMEOUT + 400, 5); - #ifdef DEBUG_TIMEOUT - i = DEBUG_TIMEOUT_COUNT; - while (SCmd.request.dev != 0xfffe && i--); - #else while (SCmd.request.dev != 0xfffe); - #endif /* DEBUG_TIMEOUT */ #if defined(DEBUG) || defined(DEBUG_INIT) ! printk("scsi: scan SCSIS id %d lun %d\n", dev, lun); ! printk("scsi: return code %08x\n", SCmd.result); #endif --- 264,274 ---- scsi_result, 256, scan_scsis_done, SCSI_TIMEOUT + 400, 5); while (SCmd.request.dev != 0xfffe); #if defined(DEBUG) || defined(DEBUG_INIT) ! printk("scan_scsis: id %d lun %d retcode %08x\n", ! dev, lun, SCmd.result); #endif *************** *** 291,297 **** }; #if defined (DEBUG) || defined(DEBUG_INIT) ! printk("scsi: performing INQUIRY\n"); #endif /* --- 286,292 ---- }; #if defined (DEBUG) || defined(DEBUG_INIT) ! printk("scan_scsis: performing INQUIRY\n"); #endif /* *************** *** 312,331 **** scsi_result, 256, scan_scsis_done, SCSI_TIMEOUT, 3); - #ifdef DEBUG_TIMEOUT - i = DEBUG_TIMEOUT_COUNT; - while (SCmd.request.dev != 0xfffe && i--); - #else while (SCmd.request.dev != 0xfffe); - #endif /* DEBUG_TIMEOUT */ the_result = SCmd.result; #if defined(DEBUG) || defined(DEBUG_INIT) if (!the_result) ! printk("scsi: INQUIRY successful\n"); else ! printk("scsi: INQUIRY failed with code %08x\n"); #endif if(the_result) break; --- 307,321 ---- scsi_result, 256, scan_scsis_done, SCSI_TIMEOUT, 3); while (SCmd.request.dev != 0xfffe); the_result = SCmd.result; #if defined(DEBUG) || defined(DEBUG_INIT) if (!the_result) ! printk("scan_scsis: INQUIRY successful\n"); else ! printk("scan_scsis: INQUIRY failed with code %08x\n"); #endif if(the_result) break; *************** *** 365,371 **** default : #if 0 #ifdef DEBUG ! printk("scsi: unknown type %d\n", type); print_inquiry(scsi_result); #endif #endif --- 355,361 ---- default : #if 0 #ifdef DEBUG ! printk("scan_scsis: unknown type %d\n", type); print_inquiry(scsi_result); #endif #endif *************** *** 472,483 **** scsi_result, 0x2a, scan_scsis_done, SCSI_TIMEOUT, 3); - #ifdef DEBUG_TIMEOUT - i = DEBUG_TIMEOUT_COUNT; - while (SCmd.request.dev != 0xfffe && i--); - #else while (SCmd.request.dev != 0xfffe); - #endif /* DEBUG_TIMEOUT */ }; ++NR_SCSI_DEVICES; --- 462,468 ---- *************** *** 880,892 **** int oldipl; #endif /* __alpha */ ! #ifdef DEBUG { int i; int target = SCpnt->target; printk ("scsi_do_cmd (host = %d, target = %d, buffer =%08x, " "bufflen = %d, done = %08x, timeout = %d, retries = %d)\n" ! "command : " , host->host_no, target, buffer, bufflen, done, timeout, retries); for (i = 0; i < 10; ++i) printk ("%02x ", ((unsigned char *) cmnd)[i]); printk("\n"); --- 865,878 ---- int oldipl; #endif /* __alpha */ ! #if defined(DEBUG) || defined(DEBUG_CMD) { int i; int target = SCpnt->target; printk ("scsi_do_cmd (host = %d, target = %d, buffer =%08x, " "bufflen = %d, done = %08x, timeout = %d, retries = %d)\n" ! "command : " , host->host_no, target, buffer, bufflen, done, ! timeout, retries); for (i = 0; i < 10; ++i) printk ("%02x ", ((unsigned char *) cmnd)[i]); printk("\n"); *************** *** 902,908 **** /* We must prevent reentrancy to the lowlevel host driver. This prevents it - we enter a loop until the host we want to talk to is not busy. ! Race conditions are prevented, as interrupts are disabled inbetween the time we check for the host being not busy, and the time we mark it busy ourselves. */ --- 888,894 ---- /* We must prevent reentrancy to the lowlevel host driver. This prevents it - we enter a loop until the host we want to talk to is not busy. ! Race conditions are prevented, as interrupts are disabled between the time we check for the host being not busy, and the time we mark it busy ourselves. */ *************** *** 923,928 **** --- 909,918 ---- ipl(oldipl); #endif + #if defined(DEBUG) || defined(DEBUG_CMD) + printk("scsi_do_cmd: before call to SCSI_SLEEP\n"); + #endif /* DEBUG_CMD */ + SCSI_SLEEP(&host->host_wait, (host->host_busy >= host->hostt->can_queue)); } else { *************** *** 970,982 **** SCpnt->internal_timeout = 0; ! #ifdef DEBUG printk("scsi_do_cmd: before call to internal_cmnd\n"); #endif /* DEBUG */ internal_cmnd (SCpnt); ! #ifdef DEBUG printk ("Leaving scsi_do_cmd()\n"); #endif } --- 960,972 ---- SCpnt->internal_timeout = 0; ! #if defined(DEBUG) || defined(DEBUG_CMD) printk("scsi_do_cmd: before call to internal_cmnd\n"); #endif /* DEBUG */ internal_cmnd (SCpnt); ! #if defined(DEBUG) || defined(DEBUG_CMD) printk ("Leaving scsi_do_cmd()\n"); #endif } *************** *** 1117,1123 **** --- 1107,1116 ---- /* Failed to obtain sense information */ { SCpnt->flags &= ~WAS_SENSE; + #ifdef SAY_WHAT SCpnt->internal_timeout &= ~SENSE_TIMEOUT; + #endif /* SAY_WHAT */ + if (!(SCpnt->flags & WAS_RESET)) { *************** *** 1145,1151 **** #endif SCpnt->flags &= ~WAS_SENSE; ! SCpnt->internal_timeout &= ~SENSE_TIMEOUT; switch (checked = check_sense(SCpnt)) { --- 1138,1148 ---- #endif SCpnt->flags &= ~WAS_SENSE; ! #ifdef SAY_WHAT ! SCpnt->internal_timeout &= ! ~SENSE_TIMEOUT; ! #endif /* SAY_WHAT */ ! switch (checked = check_sense(SCpnt)) { *************** *** 1368,1376 **** if (status == FINISHED) { ! #ifdef DEBUG ! printk("Calling done function - at address %08x\n", SCpnt->done); ! #endif host->host_busy--; /* Indicate that we are free */ wake_up(&host->host_wait); SCpnt->result = result | ((exit & 0xff) << 24); --- 1365,1374 ---- if (status == FINISHED) { ! #ifdef DEBUG ! printk("Calling done function - at address %08x\n", ! SCpnt->done); ! #endif host->host_busy--; /* Indicate that we are free */ wake_up(&host->host_wait); SCpnt->result = result | ((exit & 0xff) << 24); *************** *** 1473,1479 **** #endif /* __alpha */ #ifdef DEBUG ! printk("Danger Will Robinson! - SCSI bus for host %d is being reset.\n",host->host_no); #endif while (1) { #ifdef i386 --- 1471,1478 ---- #endif /* __alpha */ #ifdef DEBUG ! printk("Danger Will Robinson! - SCSI bus for host %d is being reset.\n", ! host->host_no); #endif while (1) { #ifdef i386 *************** *** 1746,1752 **** dma_free_sectors -= nbits; #ifdef DEBUG ! printk("SMalloc: %d %x ",len, dma_malloc_buffer + (i << 13) + (j << 9)); #endif return (void *) ((unsigned long) dma_malloc_buffer + (i << 13) + (j << 9)); }; --- 1745,1752 ---- dma_free_sectors -= nbits; #ifdef DEBUG ! printk("SMalloc: %d %x\n", len, ! dma_malloc_buffer + (i << 13) + (j << 9)); #endif return (void *) ((unsigned long) dma_malloc_buffer + (i << 13) + (j << 9)); }; *************** *** 1937,1944 **** memory_start = sg_init(memory_start, memory_end); /* init scsi generic */ #ifdef __alpha ! ROOT_DEV = 0x0820; ! printk("scsi_dev_init: setting ROOT_DEV to 0x0820; ie SCSI unit 2 part 0\n"); #endif /* __alpha */ return memory_start; --- 1937,1952 ---- memory_start = sg_init(memory_start, memory_end); /* init scsi generic */ #ifdef __alpha ! #define SCSI_ROOT ! #ifdef SCSI_ROOT ! ROOT_DEV = 0x0810; ! printk("scsi_dev_init: setting ROOT_DEV to 0x%x; SCSI unit %d partition 0\n", ! ROOT_DEV, (ROOT_DEV >> 4) & 7); ! #else ! ROOT_DEV = 0x0200; ! printk("scsi_dev_init: setting ROOT_DEV to 0x%x; FLOPPY unit %d partition 0\n", ! ROOT_DEV, (ROOT_DEV >> 4) & 7); ! #endif /* SCSI_ROOT */ #endif /* __alpha */ return memory_start; diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/scsi/sg.c LINUX_ALPHA_SDK/sources/linux/drivers/scsi/sg.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/scsi/sg.c Tue Dec 13 14:44:15 1994 --- LINUX_ALPHA_SDK/sources/linux/drivers/scsi/sg.c Wed Feb 8 14:24:24 1995 *************** *** 307,313 **** --- 307,317 ---- #endif #ifdef SG_BIG_BUFF + #ifdef i386 big_buff= (char *) mem_start; + #elif defined(__alpha) + big_buff= (char *) KSEG_ADDRESS(mem_start); + #endif /* i386 | __alpha */ mem_start+=SG_BIG_BUFF; #endif return mem_start; *************** *** 315,321 **** --- 319,329 ---- unsigned long sg_init1(unsigned long mem_start, unsigned long mem_end) { + #ifdef i386 scsi_generics = (struct scsi_generic *) mem_start; + #elif defined(__alpha) + scsi_generics = (struct scsi_generic *) KSEG_ADDRESS(mem_start); + #endif /* i386 | __alpha */ mem_start += MAX_SG * sizeof(struct scsi_generic); return mem_start; }; diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/scsi/st.c LINUX_ALPHA_SDK/sources/linux/drivers/scsi/st.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/scsi/st.c Fri Dec 30 16:43:30 1994 --- LINUX_ALPHA_SDK/sources/linux/drivers/scsi/st.c Wed Feb 8 14:24:25 1995 *************** *** 1472,1477 **** --- 1472,1478 ---- st_nbr_buffers = 1; else st_nbr_buffers = 2; + for (i=0; i < st_nbr_buffers; i++) { #ifdef i386 st_buffers[i] = (ST_buffer *) mem_start; *************** *** 1481,1487 **** --- 1482,1494 ---- #ifdef DEBUG printk("st: Buffer address: %p\n", st_buffers[i]); #endif + #ifdef i386 mem_start += sizeof(ST_buffer) - 1 + ST_BUFFER_BLOCKS * ST_BLOCK_SIZE; + #elif defined(__alpha) + mem_start += sizeof(ST_buffer); + st_buffers[i]->b_data = KSEG_ADDRESS(mem_start); + mem_start += ST_BUFFER_BLOCKS * ST_BLOCK_SIZE; + #endif /* i386 || __alpha */ #ifdef i386 st_buffers[i]->mt_status = (struct mtget *) mem_start; #elif defined(__alpha) diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/scsi/st.h LINUX_ALPHA_SDK/sources/linux/drivers/scsi/st.h *** LINUX_ALPHA_SDK/sources/linux.0.1.0/drivers/scsi/st.h Tue Dec 13 14:44:13 1994 --- LINUX_ALPHA_SDK/sources/linux/drivers/scsi/st.h Wed Feb 8 14:24:27 1995 *************** *** 2,8 **** #ifndef _ST_H #define _ST_H /* ! $Header: /amt/LINUX/LINUX_SDK/RCS/linux/drivers/scsi/st.h,v 1.1.1.1 1994/12/13 19:44:13 jestabro Exp $ */ #ifndef _SCSI_H --- 2,8 ---- #ifndef _ST_H #define _ST_H /* ! $Header: /amt/LINUX/LINUX_SDK/RCS/linux/drivers/scsi/st.h,v 1.2 1995/02/08 19:24:27 jestabro Exp $ */ #ifndef _SCSI_H *************** *** 19,25 **** --- 19,29 ---- int writing; int last_result; int last_result_fatal; + #ifdef i386 unsigned char b_data[1]; + #elif defined(__alpha) + unsigned char * b_data; + #endif /* i386 || __alpha */ } ST_buffer; typedef struct { diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/fs/msdos/fat.c LINUX_ALPHA_SDK/sources/linux/fs/msdos/fat.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/fs/msdos/fat.c Tue Dec 13 14:43:07 1994 --- LINUX_ALPHA_SDK/sources/linux/fs/msdos/fat.c Wed Feb 8 14:36:22 1995 *************** *** 47,53 **** } if (MSDOS_SB(sb)->fat_bits == 16) { p_first = p_last = NULL; /* GCC needs that stuff */ ! next = CF_LE_W(((unsigned short *) data)[(first & (SECTOR_SIZE-1)) >> 1]); if (next >= 0xfff7) next = -1; } --- 47,53 ---- } if (MSDOS_SB(sb)->fat_bits == 16) { p_first = p_last = NULL; /* GCC needs that stuff */ ! next = CF_LE_W(&((unsigned short *) data)[(first & (SECTOR_SIZE-1)) >> 1]); if (next >= 0xfff7) next = -1; } diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/fs/msdos/inode.c LINUX_ALPHA_SDK/sources/linux/fs/msdos/inode.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/fs/msdos/inode.c Tue Dec 13 14:43:07 1994 --- LINUX_ALPHA_SDK/sources/linux/fs/msdos/inode.c Wed Feb 8 14:36:19 1995 *************** *** 189,211 **** #define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0) /* don't divide by zero */ ! logical_sector_size = CF_LE_W(*(unsigned short *) &b->sector_size); sector_mult = logical_sector_size >> SECTOR_BITS; MSDOS_SB(s)->cluster_size = b->cluster_size*sector_mult; MSDOS_SB(s)->fats = b->fats; ! MSDOS_SB(s)->fat_start = CF_LE_W(b->reserved)*sector_mult; ! MSDOS_SB(s)->fat_length = CF_LE_W(b->fat_length)*sector_mult; ! MSDOS_SB(s)->dir_start = (CF_LE_W(b->reserved)+b->fats*CF_LE_W( ! b->fat_length))*sector_mult; ! MSDOS_SB(s)->dir_entries = CF_LE_W(*((unsigned short *) &b->dir_entries ! )); MSDOS_SB(s)->data_start = MSDOS_SB(s)->dir_start+ROUND_TO_MULTIPLE(( MSDOS_SB(s)->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS, sector_mult); ! data_sectors = (CF_LE_W(*((unsigned short *) &b->sectors)) ? ! CF_LE_W(*((unsigned short *) &b->sectors)) : ! CF_LE_L(b->total_sect))*sector_mult-MSDOS_SB(s)->data_start; error = !b->cluster_size || !sector_mult; if (!error) { MSDOS_SB(s)->clusters = b->cluster_size ? data_sectors/ b->cluster_size/sector_mult : 0; --- 189,211 ---- #define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0) /* don't divide by zero */ ! logical_sector_size = CF_LE_W(&b->sector_size[0]); sector_mult = logical_sector_size >> SECTOR_BITS; MSDOS_SB(s)->cluster_size = b->cluster_size*sector_mult; MSDOS_SB(s)->fats = b->fats; ! MSDOS_SB(s)->fat_start = CF_LE_W(&b->reserved)*sector_mult; ! MSDOS_SB(s)->fat_length = CF_LE_W(&b->fat_length)*sector_mult; ! MSDOS_SB(s)->dir_start = (CF_LE_W(&b->reserved)+b->fats* ! CF_LE_W(&b->fat_length))*sector_mult; ! MSDOS_SB(s)->dir_entries = CF_LE_W(&b->dir_entries[0]); MSDOS_SB(s)->data_start = MSDOS_SB(s)->dir_start+ROUND_TO_MULTIPLE(( MSDOS_SB(s)->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS, sector_mult); ! data_sectors = (CF_LE_W(&b->sectors[0])) ? ! CF_LE_W(&b->sectors[0]) : ! CF_LE_L(&b->total_sect)*sector_mult-MSDOS_SB(s)->data_start; error = !b->cluster_size || !sector_mult; + if (!error) { MSDOS_SB(s)->clusters = b->cluster_size ? data_sectors/ b->cluster_size/sector_mult : 0; *************** *** 227,234 **** "se=%d,ts=%ld,ls=%d]\n",b->media,MSDOS_SB(s)->cluster_size, MSDOS_SB(s)->fats,MSDOS_SB(s)->fat_start,MSDOS_SB(s)-> fat_length,MSDOS_SB(s)->dir_start,MSDOS_SB(s)->dir_entries, ! MSDOS_SB(s)->data_start,CF_LE_W(*(unsigned short *) &b-> ! sectors),b->total_sect,logical_sector_size); } if (error) { if (!silent) --- 227,234 ---- "se=%d,ts=%ld,ls=%d]\n",b->media,MSDOS_SB(s)->cluster_size, MSDOS_SB(s)->fats,MSDOS_SB(s)->fat_start,MSDOS_SB(s)-> fat_length,MSDOS_SB(s)->dir_start,MSDOS_SB(s)->dir_entries, ! MSDOS_SB(s)->data_start,CF_LE_W(&b->sectors[0]), ! CF_LE_L(&b->total_sect),logical_sector_size); } if (error) { if (!silent) *************** *** 342,348 **** inode->i_mode = MSDOS_MKMODE(raw_entry->attr,S_IRWXUGO & ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IFDIR; inode->i_op = &msdos_dir_inode_operations; ! MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start); inode->i_nlink = msdos_subdirs(inode); /* includes .., compensating for "self" */ #ifdef DEBUG --- 342,348 ---- inode->i_mode = MSDOS_MKMODE(raw_entry->attr,S_IRWXUGO & ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IFDIR; inode->i_op = &msdos_dir_inode_operations; ! MSDOS_I(inode)->i_start = CF_LE_W(&raw_entry->start); inode->i_nlink = msdos_subdirs(inode); /* includes .., compensating for "self" */ #ifdef DEBUG *************** *** 352,358 **** } #endif inode->i_size = 0; ! if ((nr = CF_LE_W(raw_entry->start)) != 0) while (nr != -1) { inode->i_size += SECTOR_SIZE*MSDOS_SB(inode-> i_sb)->cluster_size; --- 352,358 ---- } #endif inode->i_size = 0; ! if ((nr = CF_LE_W(&raw_entry->start)) != 0) while (nr != -1) { inode->i_size += SECTOR_SIZE*MSDOS_SB(inode-> i_sb)->cluster_size; *************** *** 370,378 **** inode->i_op = MSDOS_CAN_BMAP(MSDOS_SB(inode->i_sb)) ? &msdos_file_inode_operations : &msdos_file_inode_operations_no_bmap; ! MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start); inode->i_nlink = 1; ! inode->i_size = CF_LE_L(raw_entry->size); } MSDOS_I(inode)->i_binary = is_binary(MSDOS_SB(inode->i_sb)->conversion, raw_entry->ext); --- 370,378 ---- inode->i_op = MSDOS_CAN_BMAP(MSDOS_SB(inode->i_sb)) ? &msdos_file_inode_operations : &msdos_file_inode_operations_no_bmap; ! MSDOS_I(inode)->i_start = CF_LE_W(&raw_entry->start); inode->i_nlink = 1; ! inode->i_size = CF_LE_L(&raw_entry->size); } MSDOS_I(inode)->i_binary = is_binary(MSDOS_SB(inode->i_sb)->conversion, raw_entry->ext); *************** *** 382,388 **** inode->i_blocks = (inode->i_size+inode->i_blksize-1)/ inode->i_blksize*MSDOS_SB(inode->i_sb)->cluster_size; inode->i_mtime = inode->i_atime = inode->i_ctime = ! date_dos2unix(CF_LE_W(raw_entry->time),CF_LE_W(raw_entry->date)); brelse(bh); } --- 382,388 ---- inode->i_blocks = (inode->i_size+inode->i_blksize-1)/ inode->i_blksize*MSDOS_SB(inode->i_sb)->cluster_size; inode->i_mtime = inode->i_atime = inode->i_ctime = ! date_dos2unix(CF_LE_W(&raw_entry->time),CF_LE_W(&raw_entry->date)); brelse(bh); } diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/fs/msdos/misc.c LINUX_ALPHA_SDK/sources/linux/fs/msdos/misc.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/fs/msdos/misc.c Tue Dec 13 14:43:07 1994 --- LINUX_ALPHA_SDK/sources/linux/fs/msdos/misc.c Wed Feb 8 14:36:20 1995 *************** *** 321,327 **** !(data[entry].attr & ATTR_VOLUME); #define RSS_START /* search for start cluster */ \ ! done = !IS_FREE(data[entry].name) && CF_LE_W(data[entry].start) == *number; #define RSS_FREE /* search for free entry */ \ { \ --- 321,327 ---- !(data[entry].attr & ATTR_VOLUME); #define RSS_START /* search for start cluster */ \ ! done = !IS_FREE(data[entry].name) && CF_LE_W(&data[entry].start) == *number; #define RSS_FREE /* search for free entry */ \ { \ *************** *** 364,370 **** } if (done) { if (ino) *ino = sector*MSDOS_DPS+entry; ! start = CF_LE_W(data[entry].start); if (!res_bh) brelse(bh); else { *res_bh = bh; --- 364,370 ---- } if (done) { if (ino) *ino = sector*MSDOS_DPS+entry; ! start = CF_LE_W(&data[entry].start); if (!res_bh) brelse(bh); else { *res_bh = bh; diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/include/asm/dma.h LINUX_ALPHA_SDK/sources/linux/include/asm/dma.h *** LINUX_ALPHA_SDK/sources/linux.0.1.0/include/asm/dma.h Fri Dec 30 16:50:06 1994 --- LINUX_ALPHA_SDK/sources/linux/include/asm/dma.h Wed Feb 8 14:40:14 1995 *************** *** 1,4 **** ! /* $Id: dma.h,v 1.2 1994/12/30 21:50:06 jestabro Exp $ * linux/include/asm/dma.h: Defines for using and allocating dma channels. * Written by Hennus Bergman, 1992. * High DMA channel support & info by Hannu Savolainen --- 1,4 ---- ! /* $Id: dma.h,v 1.3 1995/02/08 19:40:14 jestabro Exp $ * linux/include/asm/dma.h: Defines for using and allocating dma channels. * Written by Hennus Bergman, 1992. * High DMA channel support & info by Hannu Savolainen *************** *** 80,85 **** --- 80,88 ---- #define DMA1_RESET_REG 0x0D /* Master Clear (w) */ #define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */ #define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */ + #ifdef __alpha + #define DMA1_EXTMODE_REG 0x40b + #endif /* __alpha */ #define DMA2_CMD_REG 0xD0 /* command register (w) */ #define DMA2_STAT_REG 0xD0 /* status register (r) */ *************** *** 91,96 **** --- 94,102 ---- #define DMA2_RESET_REG 0xDA /* Master Clear (w) */ #define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */ #define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */ + #ifdef __alpha + #define DMA2_EXTMODE_REG 0x4d6 + #endif /* __alpha */ #define DMA_ADDR_0 0x00 /* DMA address registers */ #define DMA_ADDR_1 0x02 *************** *** 157,166 **** /* set mode (above) for a specific DMA channel */ static __inline__ void set_dma_mode(unsigned int dmanr, char mode) { ! if (dmanr<=3) outb(mode | dmanr, DMA1_MODE_REG); ! else outb(mode | (dmanr&3), DMA2_MODE_REG); } /* Set only the page register bits of the transfer address. --- 163,179 ---- /* set mode (above) for a specific DMA channel */ static __inline__ void set_dma_mode(unsigned int dmanr, char mode) { ! if (dmanr<=3) { outb(mode | dmanr, DMA1_MODE_REG); ! #ifdef __alpha ! outb(dmanr, DMA1_EXTMODE_REG); ! #endif /* __alpha */ ! } else { outb(mode | (dmanr&3), DMA2_MODE_REG); + #ifdef __alpha + outb(dmanr&3, DMA2_EXTMODE_REG); + #endif /* __alpha */ + } } /* Set only the page register bits of the transfer address. *************** *** 168,196 **** * the lower 16 bits of the DMA current address register, but a 64k boundary * may have been crossed. */ ! static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) { switch(dmanr) { case 0: outb(pagenr, DMA_PAGE_0); break; case 1: outb(pagenr, DMA_PAGE_1); break; case 2: outb(pagenr, DMA_PAGE_2); break; case 3: outb(pagenr, DMA_PAGE_3); break; case 5: outb(pagenr & 0xfe, DMA_PAGE_5); break; case 6: outb(pagenr & 0xfe, DMA_PAGE_6); break; case 7: outb(pagenr & 0xfe, DMA_PAGE_7); break; } } --- 181,236 ---- * the lower 16 bits of the DMA current address register, but a 64k boundary * may have been crossed. */ ! ! #ifdef __alpha ! /* JAE: the high byte differs between Alpha platforms... :-( */ ! extern int high_page_byte; ! #endif /* __alpha */ ! ! static __inline__ void set_dma_page(unsigned int dmanr, unsigned int pagenr) { switch(dmanr) { case 0: outb(pagenr, DMA_PAGE_0); + #ifdef __alpha + outb((pagenr>>8)|high_page_byte, 0x400 + DMA_PAGE_0); + #endif /* __alpha */ break; case 1: outb(pagenr, DMA_PAGE_1); + #ifdef __alpha + outb((pagenr>>8)|high_page_byte, 0x400 + DMA_PAGE_1); + #endif /* __alpha */ break; case 2: outb(pagenr, DMA_PAGE_2); + #ifdef __alpha + outb((pagenr>>8)|high_page_byte, 0x400 + DMA_PAGE_2); + #endif /* __alpha */ break; case 3: outb(pagenr, DMA_PAGE_3); + #ifdef __alpha + outb((pagenr>>8)|high_page_byte, 0x400 + DMA_PAGE_3); + #endif /* __alpha */ break; case 5: outb(pagenr & 0xfe, DMA_PAGE_5); + #ifdef __alpha + outb((pagenr>>8)|high_page_byte, 0x400 + DMA_PAGE_5); + #endif /* __alpha */ break; case 6: outb(pagenr & 0xfe, DMA_PAGE_6); + #ifdef __alpha + outb((pagenr>>8)|high_page_byte, 0x400 + DMA_PAGE_6); + #endif /* __alpha */ break; case 7: outb(pagenr & 0xfe, DMA_PAGE_7); + #ifdef __alpha + outb((pagenr>>8)|high_page_byte, 0x400 + DMA_PAGE_7); + #endif /* __alpha */ break; } } *************** *** 201,207 **** */ static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a) { - set_dma_page(dmanr, a>>16); if (dmanr <= 3) { outb( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); outb( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); --- 241,246 ---- *************** *** 209,214 **** --- 248,254 ---- outb( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); outb( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); } + set_dma_page(dmanr, a>>16); } *************** *** 226,234 **** --- 266,286 ---- if (dmanr <= 3) { outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); + #ifdef __alpha + #if 0 + /* JAE" only needed for JENSEN? */ + outb( (count>>16) & 0xff,((dmanr&3)<<1) + 1 + IO_DMA1_BASE+0x400 ); + #endif + #endif /* __alpha */ } else { outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + #ifdef __alpha + #if 0 + /* JAE" only needed for JENSEN? */ + outb( (count>>17) & 0xff,((dmanr&3)<<2) + 2 + IO_DMA2_BASE+0x400 ); + #endif + #endif /* __alpha */ } } diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/include/linux/alpha/alpha.h LINUX_ALPHA_SDK/sources/linux/include/linux/alpha/alpha.h *** LINUX_ALPHA_SDK/sources/linux.0.1.0/include/linux/alpha/alpha.h Fri Dec 30 16:54:10 1994 --- LINUX_ALPHA_SDK/sources/linux/include/linux/alpha/alpha.h Thu Feb 9 15:31:20 1995 *************** *** 62,67 **** --- 62,102 ---- U64 rpb_txrdy_mask; /* TXRDY bitmask */ } HWRPB; + /* + * DEC processor types for Alpha systems. Found in HWRPB. + * These values are architected. + */ + + #define EV3_CPU 1 /* EV3 */ + #define EV4_CPU 2 /* EV4 (21064) */ + #define LCA4_CPU 4 /* LCA4 (21066/21068) */ + #define EV5_CPU 5 /* EV5 (21164) */ + #define EV45_CPU 6 /* EV4.5 (21064/xxx) */ + + /* + * DEC system types for Alpha systems. Found in HWRPB. + * These values are architected. + */ + + #define ST_ADU 1 /* Alpha ADU systype */ + #define ST_DEC_4000 2 /* Cobra systype */ + #define ST_DEC_7000 3 /* Ruby systype */ + #define ST_DEC_3000_500 4 /* Flamingo systype */ + #define ST_DEC_2000_300 6 /* Jensen systype */ + #define ST_DEC_3000_300 7 /* Pelican systype */ + #define ST_DEC_2100_A500 9 /* Sable systype */ + #define ST_DEC_AXPVME_64 10 /* AXPvme system type */ + #define ST_DEC_AXPPCI_33 11 /* NoName system type */ + #define ST_DEC_TLASER 12 /* Turbolaser systype */ + #define ST_DEC_2100_A50 13 /* Avanti systype */ + #define ST_DEC_MUSTANG 14 /* Mustang systype */ + #define ST_DEC_ALCOR 15 /* Alcor systype */ + #define ST_DEC_1000 17 /* Mikasa systype */ + #define ST_DEC_EB66 19 /* EB66 systype */ + #define ST_DEC_EB64P 20 /* EB64+ systype */ + + #define PASS1_LCA_TYPE 0x100000004ULL /* Pass 1 LCA chip detect */ + /* Console callback routine block. This is found by adding the offset * in HWRPB.rpb_ccb_offset to the address of HWRPB itself. diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/include/linux/alpha/pal.h LINUX_ALPHA_SDK/sources/linux/include/linux/alpha/pal.h *** LINUX_ALPHA_SDK/sources/linux.0.1.0/include/linux/alpha/pal.h Tue Dec 13 14:43:29 1994 --- LINUX_ALPHA_SDK/sources/linux/include/linux/alpha/pal.h Tue Jan 24 05:06:28 1995 *************** *** 88,92 **** --- 88,93 ---- #define PAL_jtopal 46 /* 0x2e */ #define PAL_wrvptptr 45 /* 0x2d */ #define PAL_wrfen 43 /* 0x2b */ + #define PAL_mfpr_mces 16 /* 0x10 */ #define PAL_mtpr_mces 17 /* 0x11 */ diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/include/linux/alpha/pci.h LINUX_ALPHA_SDK/sources/linux/include/linux/alpha/pci.h *** LINUX_ALPHA_SDK/sources/linux.0.1.0/include/linux/alpha/pci.h Thu Feb 9 19:57:32 1995 --- LINUX_ALPHA_SDK/sources/linux/include/linux/alpha/pci.h Mon Jan 23 05:00:26 1995 *************** *** 0 **** --- 1,110 ---- + /* + * Alpha PCI specific definitions added by Dave Rusling (david.rusling@reo.mts.dec.com) + * + */ + #ifdef CONFIG_PCI + /* + * Define the PCI device data structure. + */ + typedef struct PCIDevice { + struct PCIBus *parent; /* parent bus */ + struct PCIDevice *next; /* in device chain */ + struct PCIDevice *sibling; /* for this bus */ + unsigned int slot; + unsigned short vendor; + unsigned short device; + unsigned int class; + + unsigned int PCI_IO_Reg; + unsigned int PCI_IO_Base; + unsigned int PCI_IO_Size; + unsigned int PCI_Mem_Reg; + unsigned int PCI_Mem_Base; + unsigned int PCI_Mem_Size; + + unsigned char irq; + + void (*print)(struct PCIDevice *device); + struct { + unsigned int IO : 1; + unsigned int MEM : 1; + unsigned int bridge : 1; + unsigned int allocated : 1; + } flags; + } PCIDevice_t; + + typedef struct PCIBus { + struct PCIBus *parent; + struct PCIBus *next; + struct PCIDevice *bridge; + struct PCIDevice *devices; + struct PCIBus *children; + + unsigned int PCI_IO_Reg; + unsigned int PCI_IO_Base; + unsigned int PCI_IO_Size; + unsigned int PCI_Mem_Reg; + unsigned int PCI_Mem_Base; + unsigned int PCI_Mem_Size; + + unsigned char number; + unsigned char primary; + unsigned char secondary; + unsigned char subordinate; + } PCIBus_t; + + + /* + * Define some macros for getting at fields in the + * PCIDevice_t and PCIBus_t typedefs. + */ + #define _PCI_IO_Base(device) (device)->PCI_IO_Base + #define _PCI_IO_Size(device) (device)->PCI_IO_Size + #define _PCI_Mem_Base(device) (device)->PCI_Mem_Base + #define _PCI_Mem_Size(device) (device)->PCI_Mem_Size + #define _PCI_Slot(device) (device)->slot + #define _PCI_Print(device) (device)->print + #define _PCI_Class(device) (device)->class + #define _PCI_Bus(device) (device)->parent->number + + /* + * Declare some maximums. + */ + #define PCI_MAX_DEVICES 21 /* bits 31:11 of type 0 */ + #define PCI_21050_MAX_DEVICES 16 /* bits 14:11 of type 1 */ + #define PCI_MAX_BRIDGES 4 + + /* + * The PCI configuration registers. + */ + #define PCI_CFG_REG_VENDOR_DEVICE 0x0 + #define PCI_CFG_REG_STATUS_COMMAND 0x4 + /* LONG */ + #define PCI_CFG_REG_REVISION_ID 0x8 + /* BYTE */ + #define PCI_CFG_REG_CLASS_CODE 0x9 + #define PCI_CFG_REG_LATENCY_TIMER 0xD + /* BYTE */ + #define PCI_CFG_REG_BAR0 0x10 + /* Long */ + #define PCI_CFG_REG_BRIDGE_PRIMARY 0x18 + #define PCI_CFG_REG_BRIDGE_SECONDARY 0x19 + #define PCI_CFG_REG_BRIDGE_SUBORDINATE 0x1a + + #define PCI_CFG_REG_EROM_BASE 0x30 + #define PCI_CFG_REG_IRQ 0x3c + + /* + * PCI Vendors and devices. + */ + #define DIGITAL 0x1011 + #define DECCHIP_21040 0x0002 + + #define PCI_BRIDGE_CLASS 0x060400 + + /* + * Where do we start allocating addresses from in PCI I/O space? + */ + #define PCI_IO_BASE 0xB000 + + #endif diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/include/linux/bios32.h LINUX_ALPHA_SDK/sources/linux/include/linux/bios32.h *** LINUX_ALPHA_SDK/sources/linux.0.1.0/include/linux/bios32.h Thu Feb 9 19:57:32 1995 --- LINUX_ALPHA_SDK/sources/linux/include/linux/bios32.h Mon Jan 23 04:59:10 1995 *************** *** 0 **** --- 1,45 ---- + /* + * BIOS32, PCI BIOS functions and defines + * Copyright 1994, Drew Eckhardt + * + * For more information, please consult + * + * PCI BIOS Specification Revision + * PCI Local Bus Specification + * PCI System Design Guide + * + * PCI Special Interest Group + * M/S HF3-15A + * 5200 N.E. Elam Young Parkway + * Hillsboro, Oregon 97124-6497 + * +1 (503) 696-2000 + * +1 (800) 433-5177 + * + * Manuals are $25 each or $50 for all three, plus $7 shipping + * within the United States, $35 abroad. + */ + + #ifndef BIOS32_H + #define BIOS32_H + + unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end); + + extern int pcibios_find_class (unsigned long class_code, unsigned short index, + unsigned char *bus, unsigned char *device_fn); + extern int pcibios_find_device (unsigned short vendor, unsigned short device_id, + unsigned short index, unsigned char *bus, unsigned char *device_fn); + extern int pcibios_read_config_byte (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned char *value); + extern int pcibios_read_config_word (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned short *value); + extern int pcibios_read_config_dword (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned long *value); + extern int pcibios_present (void); + extern int pcibios_write_config_byte (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned char value); + extern int pcibios_write_config_word (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned short value); + extern pcibios_write_config_dword (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned long value); + + #endif /* ndef BIOS32_H */ diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/include/linux/msdos_fs.h LINUX_ALPHA_SDK/sources/linux/include/linux/msdos_fs.h *** LINUX_ALPHA_SDK/sources/linux.0.1.0/include/linux/msdos_fs.h Tue Dec 13 14:43:23 1994 --- LINUX_ALPHA_SDK/sources/linux/include/linux/msdos_fs.h Wed Feb 8 14:37:14 1995 *************** *** 56,65 **** * endian, c: W = word (16 bits), L = longword (32 bits) */ ! #define CF_LE_W(v) (v) ! #define CF_LE_L(v) (v) #define CT_LE_W(v) (v) #define CT_LE_L(v) (v) struct msdos_boot_sector { --- 56,77 ---- * endian, c: W = word (16 bits), L = longword (32 bits) */ ! #ifdef i386 ! #define CF_LE_W(v) (*(unsigned short *)v) ! #define CF_LE_L(v) (*(unsigned long *)v) #define CT_LE_W(v) (v) #define CT_LE_L(v) (v) + #elif defined(__alpha) + /* JAE: must define for unaligned fetch, even though we are little-endian */ + #define CF_LE_W(v) \ + ((((unsigned char *)(v))[1]*256)+((unsigned char *)(v))[0]) + #define CF_LE_L(v) \ + (((((unsigned char *)(v))[3]<<24)+((unsigned char *)(v))[2]<<16) + \ + ((((unsigned char *)(v))[1]<<8)+((unsigned char *)(v))[0])) + /* JAE: leave these as-are for now... */ + #define CT_LE_W(v) (v) + #define CT_LE_L(v) (v) + #endif /* i386 | __alpha */ struct msdos_boot_sector { diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/include/linux/pci.h LINUX_ALPHA_SDK/sources/linux/include/linux/pci.h *** LINUX_ALPHA_SDK/sources/linux.0.1.0/include/linux/pci.h Thu Feb 9 19:57:32 1995 --- LINUX_ALPHA_SDK/sources/linux/include/linux/pci.h Mon Jan 23 05:01:26 1995 *************** *** 0 **** --- 1,172 ---- + /* + * Alpha PCI pseudo-BIOS added by Dave Rusling (david.rusling@reo.mts.dec.com) + * + * PCI defines and function prototypes + * Copyright 1994, Drew Eckhardt + * + * For more information, please consult + * + * PCI BIOS Specification Revision + * PCI Local Bus Specification + * PCI System Design Guide + * + * PCI Special Interest Group + * M/S HF3-15A + * 5200 N.E. Elam Young Parkway + * Hillsboro, Oregon 97124-6497 + * +1 (503) 696-2000 + * +1 (800) 433-5177 + * + * Manuals are $25 each or $50 for all three, plus $7 shipping + * within the United States, $35 abroad. + */ + + #ifndef PCI_H + #define PCI_H + + #ifdef __alpha + #include "alpha/pci.h" + #else + + + /* Configuration method #1 */ + #define PCI_CONFIG1_ADDRESS_REG 0xcf8 + #define PCI_CONFIG1_ENABLE 0x80000000 + #define PCI_CONFIG1_TUPPLE (bus, device, function, register) \ + (PCI_CONFIG1_ENABLE | ((bus) << 16) & 0xff0000 | \ + ((device) << 11) & 0xf800 | ((function) << 8) & 0x700 | \ + ((register) << 2) & 0xfc) + #define PCI_CONFIG1_DATA_REG 0xcfc + + /* Configuration method #2, deprecated */ + #define PCI_CONFIG2_ENABLE_REG 0xcf8 + #define PCI_CONFIG2_ENABLE 0xf0 + #define PCI_CONFIG2_TUPPLE (function) \ + (PCI_CONFIG2_ENABLE | ((function) << 1) & 0xe) + #define PCI_CONFIG2_FORWARD_REG 0xcfa + + /* + * Under PCI, each device has 256 bytes of configuration address space, + * of which the first 64 bytes is standardized as follows : + */ + + #define PCI_VENDOR_ID 0x00 /* 16 bits */ + #define PCI_DEVICE_ID 0x02 /* 16 bits */ + #define PCI_COMMAND 0x04 /* 16 bits */ + #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ + #define PCI_COMMAND_MEMORY 0x2 /* Enable response in I/O space */ + #define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */ + #define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */ + #define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */ + #define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */ + #define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */ + #define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */ + #define PCI_COMMAND_SERR 0x100 /* Enable SERR */ + #define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */ + + #define PCI_STATUS 0x06 /* 16 bits */ + #define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */ + #define PCI_STATUS_PARITY 0x100 /* Detected parity error */ + #define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */ + #define PCI_STATUS_DEVSEL_FAST 0x000 + #define PCI_STATUS_DEVSEL_MEDIUM 0x200 + #define PCI_STATUS_DEVESEL_SLOW 0x400 + #define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */ + #define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */ + #define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */ + #define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */ + #define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */ + + #define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8 + revision */ + #define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */ + #define PCI_LATENCY_TIMER 0x0d /* 8 bits */ + #define PCI_HEADER_TYPE 0x0e /* 8 bits */ + #define PCI_BIST 0x0f /* 8 bits */ + #define PCI_BIST_CODE_MASK 0x0f /* Return result */ + #define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */ + #define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */ + + /* + * Base addresses specify locations in memory or I/O space. + * Decoded size can be determined by writing a value of + * 0xffffffff to the register, and reading it back. Only + * 1 bits are decoded. + */ + + #define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */ + #define PCI_BASE_ADDRESS_1 0x14 /* 32 bits */ + #define PCI_BASE_ADDRESS_2 0x18 /* 32 bits */ + #define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */ + #define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */ + #define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */ + #define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */ + #define PCI_BASE_ADDRESS_SPACE_IO 0x01 + #define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00 + #define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06 + #define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */ + #define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M */ + #define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */ + #define PCI_BASE_ADDRESS_MEM_MASK ~7 + #define PCI_BASE_ADDRESS_IO_MASK ~3 + /* bit 1 is reserved if address_space = 1 */ + + /* 0x28-0x2f are reserved */ + #define PCI_ROM_ADDRESS 0x30 /* 32 bits */ + #define PCI_ROM_ADDRESS_ENABLE 0x01 /* Write 1 to enable ROM, + bits 31..11 are address, + 10..2 are reserved */ + /* 0x34-0x3b are reserved */ + #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ + #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ + #define PCI_MIN_GNT 0x3e /* 8 bits */ + #define PCI_MAX_LAT 0x3f /* 8 bits */ + + #define PCI_VENDOR_ID_NCR 0x1000 + #define PCI_DEVICE_ID_NCR_53C810 0x0001 + #define PCI_DEVICE_ID_NCR_53C815 0x0004 + #define PCI_DEVICE_ID_NCR_53C820 0x0002 + #define PCI_DEVICE_ID_NCR_53C825 0x0003 + + #define PCI_VENDOR_ID_ADAPTEC 0x9004 + #define PCI_DEVICE_ID_ADAPTEC_2940 0x7178 + + #endif + + /* + * PCI BIOS calls are common to x86 architectures and to Alpha. + */ + + extern int pcibios_present (void); + + #define PCIBIOS_SUCCESSFUL 0x00 + #define PCIBIOS_FUNC_NOT_SUPPORTED 0x81 + #define PCIBIOS_BAD_VENDOR_ID 0x83 + #define PCIBIOS_DEVICE_NOT_FOUND 0x86 + #define PCIBIOS_BAD_REGISTER_NUMBER 0x87 + + /* + * The PCIBIOS calls all bit-field the device_function variable such that + * the bit fielding matches that of the bl register used in the actual + * calls. + */ + + extern int pcibios_find_class (unsigned long class_code, unsigned short index, + unsigned char *bus, unsigned char *device_fn); + extern int pcibios_find_device (unsigned short vendor, unsigned short device_id, + unsigned short index, unsigned char *bus, unsigned char *device_fn); + extern int pcibios_read_config_byte (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned char *value); + extern int pcibios_read_config_word (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned short *value); + extern int pcibios_read_config_dword (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned long *value); + extern char *pcibios_strerror (int error); + extern int pcibios_write_config_byte (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned char value); + extern int pcibios_write_config_word (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned short value); + extern pcibios_write_config_dword (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned long value); + + #endif /* ndef PCI_H */ diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/init/main.c LINUX_ALPHA_SDK/sources/linux/init/main.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/init/main.c Wed Dec 28 18:30:01 1994 --- LINUX_ALPHA_SDK/sources/linux/init/main.c Thu Feb 9 15:31:49 1995 *************** *** 39,45 **** extern struct task_struct init_task; extern L2PTES init_l2ptes; int debugging_kernel = 0; ! #endif /* * we need this inline - forking from kernel space will result --- 39,53 ---- extern struct task_struct init_task; extern L2PTES init_l2ptes; int debugging_kernel = 0; ! extern U64 alpha_system_type; ! #ifdef CONFIG_FLOPPY ! /* JAE: gotta define some buffer pointers for the floppy driver */ ! /* JAE: I think these were originally set-up in head.s for the PC */ ! /* JAE: For now, we declare and init them here for drivers/block/floppy.c */ ! char * tmp_floppy_area; ! char * floppy_track_buffer; ! #endif /* CONFIG_FLOPPY */ ! #endif /* __alpha */ /* * we need this inline - forking from kernel space will result *************** *** 405,411 **** * zero at startup... */ ! cons_puts(0, "Linux/Alpha kernel startup\r\n"); memset(&init_task, 0, sizeof(init_task)); init_task.counter = 15; --- 413,421 ---- * zero at startup... */ ! cpu_init(); /* JAE: MUST BE FIRST!!! OTW printk will panic... */ ! ! printk("Linux/Alpha kernel startup\n"); memset(&init_task, 0, sizeof(init_task)); init_task.counter = 15; *************** *** 431,439 **** for(i = 0; i < USER_L2PT_NENTRIES; i++) { init_task.pcb.pcb_l2ptes->entries[i] = l2pt[i]; } ! cons_puts(0, "init_task initialized\r\n"); ! cpu_init(); ! cons_puts(0, "cpu_init initialized\r\n"); #endif /* __alpha */ --- 441,447 ---- for(i = 0; i < USER_L2PT_NENTRIES; i++) { init_task.pcb.pcb_l2ptes->entries[i] = l2pt[i]; } ! printk("init_task initialized\n"); #endif /* __alpha */ *************** *** 454,460 **** ramdisk_size = ramdisk_kb; #endif /* __alpha */ ! cons_puts(0, "copying options\r\n"); copy_options(command_line,COMMAND_LINE); #ifdef i386 --- 462,468 ---- ramdisk_size = ramdisk_kb; #endif /* __alpha */ ! printk("copying options\n"); copy_options(command_line,COMMAND_LINE); #ifdef i386 *************** *** 479,487 **** #elif defined(__alpha) memory_start = firstpfn * ALPHA_PAGE_SIZE; low_memory_start = 0; #endif /* __alpha */ ! cons_puts(0, "Calling paging_init()\r\n"); memory_start = paging_init(memory_start,memory_end); #ifdef i386 --- 487,506 ---- #elif defined(__alpha) memory_start = firstpfn * ALPHA_PAGE_SIZE; low_memory_start = 0; + #ifdef CONFIG_FLOPPY + /* JAE: gotta alloc some physical memory for floppy buffers */ + /* JAE: MAX_BUFFER_SECTORS actually defined in drivers/block/floppy.c */ + #define MAX_BUFFER_SECTORS 18 + tmp_floppy_area = (char *) KSEG_ADDRESS(memory_start); + memory_start += BLOCK_SIZE; + floppy_track_buffer = KSEG_ADDRESS(memory_start); + memory_start += 512*2*MAX_BUFFER_SECTORS; + printk("tmp_floppy_area 0x%x floppy_track_buffer 0x%x\n", + (unsigned long)tmp_floppy_area, (unsigned long)floppy_track_buffer); + #endif /* CONFIG_FLOPPY */ #endif /* __alpha */ ! printk("Calling paging_init()\n"); memory_start = paging_init(memory_start,memory_end); #ifdef i386 *************** *** 492,524 **** EISA_bus = 1; #endif /* i386 */ ! cons_puts(0, "Calling trap_init()\r\n"); trap_init(); ! cons_puts(0, "Calling init_IRQ()\r\n"); init_IRQ(); ! cons_puts(0, "Calling sched_init()\r\n"); sched_init(); ! cons_puts(0, "Calling parse_options()\r\n"); parse_options(command_line); #ifdef __alpha - memory_start = gdb_init(memory_start, memory_end); if(boot_flag == 'D' || boot_flag == 'Z') { debugging_kernel = 1; ! cons_puts(0, "Entering debugger...\r\n"); enter_debugger(); } #endif #ifdef CONFIG_PROFILE prof_buffer = (unsigned long *) memory_start; prof_len = (unsigned long) &end; prof_len >>= 2; memory_start += prof_len * sizeof(unsigned long); #endif ! cons_puts(0, "Calling kmalloc_init()\r\n"); memory_start = kmalloc_init(memory_start,memory_end); ! cons_puts(0, "Calling chr_dev_init()\r\n"); memory_start = chr_dev_init(memory_start,memory_end); ! cons_puts(0, "Calling blk_dev_init()\r\n"); #ifdef i386 memory_start = blk_dev_init(memory_start,memory_end); #elif defined(__alpha) --- 511,561 ---- EISA_bus = 1; #endif /* i386 */ ! printk("Calling trap_init()\n"); trap_init(); ! #ifdef __alpha ! if(alpha_system_type != ST_ADU) { /* Can't do this on ISP */ ! #endif ! printk("Calling init_IRQ()\n"); init_IRQ(); ! #ifdef __alpha ! } ! #endif ! printk("Calling sched_init()\n"); sched_init(); ! printk("Calling parse_options()\n"); parse_options(command_line); #ifdef __alpha if(boot_flag == 'D' || boot_flag == 'Z') { + memory_start = gdb_init(memory_start, memory_end); debugging_kernel = 1; ! printk("Entering debugger...\n"); enter_debugger(); } #endif + #ifdef CONFIG_PROFILE prof_buffer = (unsigned long *) memory_start; prof_len = (unsigned long) &end; prof_len >>= 2; memory_start += prof_len * sizeof(unsigned long); #endif ! printk("Calling kmalloc_init()\n"); memory_start = kmalloc_init(memory_start,memory_end); ! ! #ifdef __alpha ! #ifdef CONFIG_PCI ! /* ! * PCI Configuration (if wanted) must go before any PCI devices are ! * initialized. ! */ ! printk("Calling bios32_init()\n"); ! memory_start = bios32_init(memory_start, memory_end); ! #endif ! #endif ! printk("Calling chr_dev_init()\n"); memory_start = chr_dev_init(memory_start,memory_end); ! printk("Calling blk_dev_init()\n"); #ifdef i386 memory_start = blk_dev_init(memory_start,memory_end); #elif defined(__alpha) *************** *** 530,581 **** sti(); calibrate_delay(); #elif defined(__alpha) ! cons_puts(0, "Dropping IPL....\r\n"); ipl(0); #endif /* i386 */ #ifdef CONFIG_INET ! cons_puts(0, "Calling net_dev_init()\r\n"); memory_start = net_dev_init(memory_start,memory_end); #endif #ifdef CONFIG_SCSI ! cons_puts(0, "Calling scsi_dev_init()\r\n"); memory_start = scsi_dev_init(memory_start,memory_end); #endif ! cons_puts(0, "Calling inode_init()\r\n"); memory_start = inode_init(memory_start,memory_end); ! cons_puts(0, "Calling file_table_init()\r\n"); memory_start = file_table_init(memory_start,memory_end); #ifdef i386 mem_init(low_memory_start,memory_start,memory_end); #elif defined(__alpha) ! cons_puts(0, "Calling mem_init()\r\n"); mem_init(low_memory_start,memory_start,memory_end,lastpfn*PAGE_SIZE); #endif ! cons_puts(0, "Calling buffer_init()\r\n"); buffer_init(); ! cons_puts(0, "Calling time_init()\r\n"); time_init(); #ifdef CONFIG_FLOPPY ! cons_puts(0, "Calling floppy_init()\r\n"); floppy_init(); #endif ! cons_puts(0, "Calling sock_init()\r\n"); sock_init(); #ifdef CONFIG_SYSVIPC ! cons_puts(0, "Calling ipc_init()\r\n"); ipc_init(); #endif #ifdef i386 sti(); #elif defined(__alpha) ! cons_puts(0, "Dropping ipl...\r\n"); ipl(0); #endif /* __alpha */ --- 567,618 ---- sti(); calibrate_delay(); #elif defined(__alpha) ! printk("Dropping IPL....\n"); ipl(0); #endif /* i386 */ #ifdef CONFIG_INET ! printk("Calling net_dev_init()\n"); memory_start = net_dev_init(memory_start,memory_end); #endif #ifdef CONFIG_SCSI ! printk("Calling scsi_dev_init()\n"); memory_start = scsi_dev_init(memory_start,memory_end); #endif ! printk("Calling inode_init()\n"); memory_start = inode_init(memory_start,memory_end); ! printk("Calling file_table_init()\n"); memory_start = file_table_init(memory_start,memory_end); #ifdef i386 mem_init(low_memory_start,memory_start,memory_end); #elif defined(__alpha) ! printk("Calling mem_init()\n"); mem_init(low_memory_start,memory_start,memory_end,lastpfn*PAGE_SIZE); #endif ! printk("Calling buffer_init()\n"); buffer_init(); ! printk("Calling time_init()\n"); time_init(); #ifdef CONFIG_FLOPPY ! printk("Calling floppy_init()\n"); floppy_init(); #endif ! printk("Calling sock_init()\n"); sock_init(); #ifdef CONFIG_SYSVIPC ! printk("Calling ipc_init()\n"); ipc_init(); #endif #ifdef i386 sti(); #elif defined(__alpha) ! printk("Dropping ipl...\n"); ipl(0); #endif /* __alpha */ *************** *** 616,622 **** #endif /* i386 */ ! cons_puts(0, "Setting system name\r\n"); #ifdef i386 system_utsname.machine[1] = '0' + x86; --- 653,659 ---- #endif /* i386 */ ! printk("Setting system name\n"); #ifdef i386 system_utsname.machine[1] = '0' + x86; diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/Makefile LINUX_ALPHA_SDK/sources/linux/kernel/Makefile *** LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/Makefile Tue Dec 13 21:10:46 1994 --- LINUX_ALPHA_SDK/sources/linux/kernel/Makefile Tue Jan 24 05:02:28 1995 *************** *** 19,25 **** OBJS = sched.o sys_call.o traps.o irq.o dma.o fork.o \ panic.o printk.o vsprintf.o sys.o module.o ksyms.o exit.o \ signal.o mktime.o ptrace.o ioport.o itimer.o \ ! info.o ldt.o time.o gdb.o all: kernel.o --- 19,25 ---- OBJS = sched.o sys_call.o traps.o irq.o dma.o fork.o \ panic.o printk.o vsprintf.o sys.o module.o ksyms.o exit.o \ signal.o mktime.o ptrace.o ioport.o itimer.o \ ! info.o ldt.o time.o gdb.o bios32.o all: kernel.o diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/bios32.c LINUX_ALPHA_SDK/sources/linux/kernel/bios32.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/bios32.c Thu Feb 9 19:57:35 1995 --- LINUX_ALPHA_SDK/sources/linux/kernel/bios32.c Tue Jan 24 04:59:09 1995 *************** *** 0 **** --- 1,8 ---- + #ifdef i386 + #include "bios386.c" + #elif defined(__alpha) + #include "bios_alpha.c" + #else + #error Unsupported architecture + #endif + diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/bios386.c LINUX_ALPHA_SDK/sources/linux/kernel/bios386.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/bios386.c Thu Feb 9 19:57:35 1995 --- LINUX_ALPHA_SDK/sources/linux/kernel/bios386.c Tue Jan 24 05:00:30 1995 *************** *** 0 **** --- 1,466 ---- + /* + * bios32.c - BIOS32, PCI BIOS functions. + * + * Sponsored by + * iX Multiuser Multitasking Magazine + * Hannover, Germany + * hm@ix.de + * + * Copyright 1993, 1994 Drew Eckhardt + * Visionary Computing + * (Unix and Linux consulting and custom programming) + * Drew@Colorado.EDU + * +1 (303) 786-7975 + * + * For more information, please consult + * + * PCI BIOS Specification Revision + * PCI Local Bus Specification + * PCI System Design Guide + * + * PCI Special Interest Group + * M/S HF3-15A + * 5200 N.E. Elam Young Parkway + * Hillsboro, Oregon 97124-6497 + * +1 (503) 696-2000 + * +1 (800) 433-5177 + * + * Manuals are $25 each or $50 for all three, plus $7 shipping + * within the United States, $35 abroad. + * + * + * CHANGELOG : + * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION + * Revision 2.0 present on 's ASUS mainboard. + */ + + #include + #include + #include + #include + + #include + + #define PCIBIOS_PCI_FUNCTION_ID 0xb1XX + #define PCIBIOS_PCI_BIOS_PRESENT 0xb101 + #define PCIBIOS_FIND_PCI_DEVICE 0xb102 + #define PCIBIOS_FIND_PCI_CLASS_CODE 0xb103 + #define PCIBIOS_GENERATE_SPECIAL_CYCLE 0xb106 + #define PCIBIOS_READ_CONFIG_BYTE 0xb108 + #define PCIBIOS_READ_CONFIG_WORD 0xb109 + #define PCIBIOS_READ_CONFIG_DWORD 0xb10a + #define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b + #define PCIBIOS_WRITE_CONFIG_WORD 0xb10c + #define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d + + /* BIOS32 signature: "_32_" */ + #define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24)) + + /* PCI signature: "PCI " */ + #define PCI_SIGNATURE (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24)) + + /* PCI service signature: "$PCI" */ + #define PCI_SERVICE (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24)) + + /* + * This is the standard structure used to identify the entry point + * to the BIOS32 Service Directory, as documented in + * Standard BIOS 32-bit Service Directory Proposal + * Revision 0.4 May 24, 1993 + * Phoenix Technologies Ltd. + * Norwood, MA + * and the PCI BIOS specification. + */ + + union bios32 { + struct { + unsigned long signature; /* _32_ */ + unsigned long entry; /* 32 bit physical address */ + unsigned char revision; /* Revision level, 0 */ + unsigned char length; /* Length in paragraphs should be 01 */ + unsigned char checksum; /* All bytes must add up to zero */ + unsigned char reserved[5]; /* Must be zero */ + } fields; + char chars[16]; + }; + + /* + * Physical address of the service directory. I don't know if we're + * allowed to have more than one of these or not, so just in case + * we'll make bios32_init() take a memory start parameter and store + * the array there. + */ + + static unsigned long bios32_entry = 0; + static struct { + unsigned long address; + unsigned short segment; + } bios32_indirect = { 0, KERNEL_CS }; + + #ifdef CONFIG_PCI + /* + * Returns the entry point for the given service, NULL on error + */ + + static unsigned long bios32_service(unsigned long service) + { + unsigned char return_code; /* %al */ + unsigned long address; /* %ebx */ + unsigned long length; /* %ecx */ + unsigned long entry; /* %edx */ + + __asm__("lcall (%%edi)" + : "=a" (return_code), + "=b" (address), + "=c" (length), + "=d" (entry) + : "0" (service), + "1" (0), + "D" (&bios32_indirect)); + + switch (return_code) { + case 0: + return address + entry; + case 0x80: /* Not present */ + printk("bios32_service(%ld) : not present\n", service); + return 0; + default: /* Shouldn't happen */ + printk("bios32_service(%ld) : returned 0x%x, mail drew@colorado.edu\n", + service, return_code); + return 0; + } + } + + static long pcibios_entry = 0; + static struct { + unsigned long address; + unsigned short segment; + } pci_indirect = { 0, KERNEL_CS }; + + void NCR53c810_test(void); + + static unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end) + { + unsigned long signature; + unsigned char present_status; + unsigned char major_revision; + unsigned char minor_revision; + int pack; + + if ((pcibios_entry = bios32_service(PCI_SERVICE))) { + pci_indirect.address = pcibios_entry; + + __asm__("lcall (%%edi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:\tshl $8, %%eax\n\t" + "movw %%bx, %%ax" + : "=d" (signature), + "=a" (pack) + : "1" (PCIBIOS_PCI_BIOS_PRESENT), + "D" (&pci_indirect) + : "bx", "cx"); + + present_status = (pack >> 16) & 0xff; + major_revision = (pack >> 8) & 0xff; + minor_revision = pack & 0xff; + if (present_status || (signature != PCI_SIGNATURE)) { + printk ("pcibios_init : %s : BIOS32 Service Directory says PCI BIOS is present,\n" + " but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n" + " and signature of 0x%08lx (%c%c%c%c). mail drew@Colorado.EDU\n", + (signature == PCI_SIGNATURE) ? "WARNING" : "ERROR", + present_status, signature, + (char) (signature >> 0), (char) (signature >> 8), + (char) (signature >> 16), (char) (signature >> 24)); + + if (signature != PCI_SIGNATURE) + pcibios_entry = 0; + } + if (pcibios_entry) { + printk ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%lx\n", + major_revision, minor_revision, pcibios_entry); + } + } + + #if 0 + NCR53c810_test(); + #endif + return memory_start; + } + + int pcibios_present(void) + { + return pcibios_entry ? 1 : 0; + } + + int pcibios_find_class (unsigned long class_code, unsigned short index, + unsigned char *bus, unsigned char *device_fn) + { + unsigned long bx; + unsigned long ret; + + __asm__ ("lcall (%%edi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=b" (bx), + "=a" (ret) + : "1" (PCIBIOS_FIND_PCI_CLASS_CODE), + "c" (class_code), + "S" ((int) index), + "D" (&pci_indirect)); + *bus = (bx >> 8) & 0xff; + *device_fn = bx & 0xff; + return (int) (ret & 0xff00) >> 8; + } + + + int pcibios_find_device (unsigned short vendor, unsigned short device_id, + unsigned short index, unsigned char *bus, unsigned char *device_fn) + { + unsigned short bx; + unsigned short ret; + + __asm__("lcall (%%edi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=b" (bx), + "=a" (ret) + : "1" (PCIBIOS_FIND_PCI_DEVICE), + "c" (device_id), + "d" (vendor), + "S" ((int) index), + "D" (&pci_indirect)); + *bus = (bx >> 8) & 0xff; + *device_fn = bx & 0xff; + return (int) (ret & 0xff00) >> 8; + } + + int pcibios_read_config_byte(unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned char *value) + { + unsigned long ret; + unsigned long bx = (bus << 8) | device_fn; + + __asm__("lcall (%%esi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=c" (*value), + "=a" (ret) + : "1" (PCIBIOS_READ_CONFIG_BYTE), + "b" (bx), + "D" ((long) where), + "S" (&pci_indirect)); + return (int) (ret & 0xff00) >> 8; + } + + int pcibios_read_config_word (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned short *value) + { + unsigned long ret; + unsigned long bx = (bus << 8) | device_fn; + + __asm__("lcall (%%esi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=c" (*value), + "=a" (ret) + : "1" (PCIBIOS_READ_CONFIG_WORD), + "b" (bx), + "D" ((long) where), + "S" (&pci_indirect)); + return (int) (ret & 0xff00) >> 8; + } + + int pcibios_read_config_dword (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned long *value) + { + unsigned long ret; + unsigned long bx = (bus << 8) | device_fn; + + __asm__("lcall (%%esi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=c" (*value), + "=a" (ret) + : "1" (PCIBIOS_READ_CONFIG_DWORD), + "b" (bx), + "D" ((long) where), + "S" (&pci_indirect)); + return (int) (ret & 0xff00) >> 8; + } + + int pcibios_write_config_byte (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned char value) + { + unsigned long ret; + unsigned long bx = (bus << 8) | device_fn; + + __asm__("lcall (%%esi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=a" (ret) + : "0" (PCIBIOS_WRITE_CONFIG_BYTE), + "c" (value), + "b" (bx), + "D" ((long) where), + "S" (&pci_indirect)); + return (int) (ret & 0xff00) >> 8; + } + + int pcibios_write_config_word (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned short value) + { + unsigned long ret; + unsigned long bx = (bus << 8) | device_fn; + + __asm__("lcall (%%esi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=a" (ret) + : "0" (PCIBIOS_WRITE_CONFIG_WORD), + "c" (value), + "b" (bx), + "D" ((long) where), + "S" (&pci_indirect)); + return (int) (ret & 0xff00) >> 8; + } + + int pcibios_write_config_dword (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned long value) + { + unsigned long ret; + unsigned long bx = (bus << 8) | device_fn; + + __asm__("lcall (%%esi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=a" (ret) + : "0" (PCIBIOS_WRITE_CONFIG_DWORD), + "c" (value), + "b" (bx), + "D" ((long) where), + "S" (&pci_indirect)); + return (int) (ret & 0xff00) >> 8; + } + + void NCR53c810_test(void) + { + unsigned char bus, device_fn; + unsigned short index; + int ret; + unsigned char row, col; + unsigned long val; + + for (index = 0; index < 4; ++index) { + ret = pcibios_find_device ( + (unsigned short) PCI_VENDOR_ID_NCR, + (unsigned short) PCI_DEVICE_ID_NCR_53C810, + index, &bus, &device_fn); + if (ret) + break; + printk ("ncr53c810 : at PCI bus %d, device %d, function %d.", + bus, ((device_fn & 0xf8) >> 3), (device_fn & 7)); + for (row = 0; row < 0x3c; row += 0x10) { + printk ("\n reg 0x%02x ", row); + for (col = 0; col < 0x10; col += 4) { + if (!(ret = pcibios_read_config_dword (bus, device_fn, row+col, &val))) + printk ("0x%08lx ", val); + else + printk ("error 0x%02x ", ret); + } + } + printk ("\n"); + } + } + + char *pcibios_strerror (int error) + { + static char buf[80]; + + switch (error) { + case PCIBIOS_SUCCESSFUL: + return "SUCCESSFUL"; + + case PCIBIOS_FUNC_NOT_SUPPORTED: + return "FUNC_NOT_SUPPORTED"; + + case PCIBIOS_BAD_VENDOR_ID: + return "SUCCESSFUL"; + + case PCIBIOS_DEVICE_NOT_FOUND: + return "DEVICE_NOT_FOUND"; + + case PCIBIOS_BAD_REGISTER_NUMBER: + return "BAD_REGISTER_NUMBER"; + + default: + sprintf (buf, "UNKNOWN RETURN 0x%x", error); + return buf; + } + } + + #endif + + unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end) + { + union bios32 *check; + unsigned char sum; + int i, length; + + /* + * Follow the standard procedure for locating the BIOS32 Service + * directory by scanning the permissible address range from + * 0xe0000 through 0xfffff for a valid BIOS32 structure. + * + * The PCI BIOS doesn't seem to work too well on many machines, + * so we disable this unless it's really needed (NCR SCSI driver) + */ + + for (check = (union bios32 *) 0xe0000; check <= (union bios32 *) 0xffff0; ++check) { + if (check->fields.signature != BIOS32_SIGNATURE) + continue; + length = check->fields.length * 16; + if (!length) + continue; + sum = 0; + for (i = 0; i < length ; ++i) + sum += check->chars[i]; + if (sum != 0) + continue; + if (check->fields.revision != 0) { + printk("bios32_init : unsupported revision %d at 0x%p, mail drew@colorado.edu\n", + check->fields.revision, check); + continue; + } + printk ("bios32_init : BIOS32 Service Directory structure at 0x%p\n", check); + if (!bios32_entry) { + bios32_indirect.address = bios32_entry = check->fields.entry; + printk ("bios32_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry); + } else { + printk ("bios32_init : multiple entries, mail drew@colorado.edu\n"); + /* + * Jeremy Fitzhardinge reports at least one PCI BIOS + * with two different service directories, and as both + * worked for him, we'll just mention the fact, and + * not actually disallow it.. + */ + #if 0 + return memory_start; + #endif + } + } + #ifdef CONFIG_PCI + if (bios32_entry) { + memory_start = pcibios_init (memory_start, memory_end); + } + #endif + return memory_start; + } diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/bios_alpha.c LINUX_ALPHA_SDK/sources/linux/kernel/bios_alpha.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/bios_alpha.c Thu Feb 9 19:57:35 1995 --- LINUX_ALPHA_SDK/sources/linux/kernel/bios_alpha.c Tue Jan 24 05:01:43 1995 *************** *** 0 **** --- 1,1229 ---- + /* + * bios_alpha.c - PCI BIOS functions for Alpha systems not using + * BIOS emulation code. + * + * Written by Dave Rusling (david.rusling@reo.mts.dec.com) + * + * For more information, please consult + * + * PCI BIOS Specification Revision + * PCI Local Bus Specification + * PCI System Design Guide + * + * PCI Special Interest Group + * M/S HF3-15A + * 5200 N.E. Elam Young Parkway + * Hillsboro, Oregon 97124-6497 + * +1 (503) 696-2000 + * +1 (800) 433-5177 + * + * Manuals are $25 each or $50 for all three, plus $7 shipping + * within the United States, $35 abroad. + * + * + * CHANGELOG : + */ + + #include + #include + #include + #include + #include + #include + + /* + * This module is only needed if we have configured PCI into the system. + */ + #ifdef CONFIG_PCI + + unsigned int free_memory; + + /* + * WARNING: this does not belong here and it is eb66/noname specific code. + * It will not work on the EB64+ systems. + */ + #define IOC_REG_STATUS_0 0x40 + #define IOC_STATUS_0_M_ERR 0x00000010 + /* 4 = error */ + #define IOC_STATUS_0_M_CODE 0x00000700 + /* 10:8 = error code */ + + #define ST_DEC_EB64P 20 /* EB64+ systype */ + + /* + * EB64+ type systems (21064 + APECS). + */ + #define EPIC_CSR_M_NDEV 0x800 + + /*********************************************************************************** + * Local Macros * + ***********************************************************************************/ + /* + * On Alpha based PCI systems, there are two ways of getting at PCI configuration + * space. For 21066 based systems, the access is direct and each bit in 31:11 selects + * one and only one device. For systems using the APECS PCI/Memory support chipset + * (21064, 21164 based systems), 31:11 contains the device number required. This + * allows more than 20 PCI devices to be supported. + */ + #define _APECS_PCI (system_type == ST_DEC_EB64P) + /* + * The standard PCI BIOS entry points pass and return device_fn which is an 8 bit + * quantity containing the slot and function required. + * + * 7:4 = slot + * 3:0 = function + * + */ + #define _DEVICE_FN(slot,function) (((slot << 3) & 0xf8) | (function & 0x07)) + + /* + * The following macros define Type 0 and Type 1 configuration commands (addresses + * punted out onto the PCI bus). + * + * Type 0: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:11 Device select bit. + * 10:8 Function number + * 7:2 Register number + * + * Type 1: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:24 reserved + * 23:16 bus number (8 bits = 128 possible buses) + * 15:11 Device number (5 bits) + * 10:8 function number + * 7:2 register number + * + * Notes: + * The function number selects which function of a multi-function device + * (eg scsi and ethernet. + * + * On the EB66 and EB64+, you select the device by picking a bit between 11 and 31 + * (by left shifting). This PCI code assumes that the low order device number is + * 11, hence the lack of a shift by 11 bits. Also note that bits 1:0 are + * specified via a register. + * + * The register selects a DWORD (32 bit) register offset. Hence it doesn't + * get shifted by 2 bits as we want to "drop" the bottom two bits. + * + */ + #define PCI_CONFIG_TYPE_0(device,function,register) \ + ( (unsigned long)( (register & 0x3f) | ((function & 0x7) << 8) | (1 << (device + 11)) ) ) + + #define PCI_CONFIG_TYPE_0_APECS(device,function,register) \ + ( (unsigned long)( (register & 0x3f) | ((function & 0x7) << 8) | (device << 11) ) ) + + #define PCI_CONFIG_TYPE_1(bus,device,function,register) \ + ( (unsigned long)( (register & 0x3f) | ((function & 0x7) << 8) | ((device & 0x1f) << 11) | \ + ((bus & 0xff) << 16) ) ) + + /* + * Given the bus, device, function and register build either a Type 0 or Type 1 + * configuration command for the appropriate PCI subsystem (21066) or support + * chipset (APECS). + */ + #define _CREATE_CONFIGURATION_COMMAND(command,bus,device,function,register) \ + { \ + if (bus == 0) { \ + if _APECS_PCI \ + command = PCI_CONFIG_TYPE_0_APECS(device,function,register); \ + else \ + command = PCI_CONFIG_TYPE_0(device,function,register); \ + } else \ + command = PCI_CONFIG_TYPE_1(bus,device,function,register); \ + } + /* + * Select the type of configuration cycle that is going to be issued. This depends + * on whether or not it is for bus 0. + */ + #define _SELECT_CONFIG_CYCLE(bus) \ + { \ + if _APECS_PCI \ + write_cpureg_quad((U64)(bus != 0), 0xfffffc01a0000000ULL | 0x1c0); /* HAX Reg 2 */ \ + else \ + write_cpureg_quad((U64)(bus != 0), 0xfffffc0180000000ULL | 0x20); /* IOC CCT */ \ + } + + /* + * Align things. + */ + #define align(value,alignment) \ + ( (value & (alignment - 1)) == 0 ? value : value + (alignment - (value & (alignment - 1))) ) + + + /* + * Just in case these are not defined. + */ + #ifndef NULL + #define NULL 0 + #endif + + #ifndef TRUE + #define TRUE 1 + #endif + #ifndef FALSE + #define FALSE 0 + #endif + + /* + * Temporary internal macro. If this is defined, then do not write to any of the + * PCI registers, merely read them. This is needed when we are using RPB callbacks + * in device drivers. I this code changes the PCI set up then the system will + * crash in the RPB callbacks. + */ + #define PCI_DONOT_MODIFY 1 + /* + * The root of pci devices found. + */ + static PCIBus_t *root = NULL; /* tree of devices and buses */ + static PCIDevice_t *devices = NULL; /* linked list of all devices */ + static PCIIOBase = PCI_IO_BASE; + static PCIMemBase = 0x200000; + static PCIIRQ = 1; + /* + * Any routines local to this module. + */ + static PCIDevice_t *pcibios_allocate_device(); + static unsigned int pcibios_slot_filled(int bus, int slot); + static void pcibios_set_device_config(PCIDevice_t *device); + static void pcibios_query_device(PCIDevice_t *device); + static PCIBus_t *pcibios_allocate_bus(); + static void pcibios_insert_device(PCIBus_t *bus, PCIDevice_t *device); + static void pcibios_allocate_space(PCIBus_t *bus); + static unsigned int pcibios_scan_bus(PCIBus_t *bus, unsigned int min_dev, unsigned int max_dev); + static void pcibios_show_device(PCIDevice_t *device); + static void pcibios_show_bus(PCIBus_t *bus); + + /* + * External things. + */ + extern int (*alpha_inb)(int port,U64 base); + extern int (*alpha_inw)(int port,U64 base); + extern int (*alpha_inl)(int port,U64 base); + extern void (*alpha_outb)(int v,int port,U64 base); + extern void (*alpha_outw)(int v,int port,U64 base); + extern void (*alpha_outl)(int v,int port,U64 base); + + extern U64 alpha_io_base; + extern U64 alpha_mem_base; + extern U64 alpha_cfg_base; + + extern U64 system_type; + + extern void write_cpureg_quad(U64 v,U64 addr); + extern int read_cpureg_quad(U64 addr); + + /*+-------------------------------------------------------------------------------------+ + | | + | The following routines are local to this module and cannot be called from outside | + | of it. | + | | + /*+-------------------------------------------------------------------------------------+*/ + /* + * Clear the NODEV status and + * return the current value (TRUE/FALSE). + */ + static unsigned int IOPCIClearNODEV() + { + + unsigned int status; + U64 old; + + if _APECS_PCI { + /* + * Get the current NODEV status. + */ + old = read_cpureg_quad(0xfffffc01a0000000ULL); + status = ((old & EPIC_CSR_M_NDEV) != 0); + /* + * Clear it. + */ + write_cpureg_quad(EPIC_CSR_M_NDEV, 0xfffffc01a0000000ULL); + } else { + /* + * Get the current NODEV status. + */ + old = read_cpureg_quad(0xfffffc0180000000ULL | IOC_REG_STATUS_0); + status = ((old & IOC_STATUS_0_M_ERR) != 0); + /* + * Clear it. + */ + write_cpureg_quad(old, 0xfffffc0180000000ULL | IOC_REG_STATUS_0); + } + return status; + } + + /************************************************************************** + * pcibios_slot_filled() * + **************************************************************************/ + /* + * Check to see if a PCI slot has a device, how we do this depends on the + * evaluation board. + */ + extern unsigned int ignore_INT_MCHK; + static unsigned int pcibios_slot_filled(int bus, int slot) + { + unsigned long l; + /* + * First, clear any possible previous NODEV errors. + */ + #ifdef DEBUG + printk("...pcibios_slot_filled() called for bus = %d, slot = %d\n", bus, slot); + #endif + IOPCIClearNODEV(); + + if _APECS_PCI ignore_INT_MCHK = 1; + /* + * Read the vendor and device ids (first longword). + */ + pcibios_read_config_dword(bus, _DEVICE_FN(slot, 0), + PCI_CFG_REG_VENDOR_DEVICE, &l); + /* + * Now do system specific checks for trying to read a non-existant + * slot. + */ + if _APECS_PCI { + if (ignore_INT_MCHK == 0) l = 0; + IOPCIClearNODEV(); + } else { + /* + * Check to see if we caused a PCI NODEV error. + */ + if (!IOPCIClearNODEV()) { + /* + * Check for all 1s as the vendor id (this also means + * that the slot doesn't contain a device). + */ + if ((l & 0xffff) == 0xffff) l = 0; + } else + l = 0; + } + /* + * Return the results + */ + #ifdef DEBUG + printk("...slot filled returning %d\n", l); + #endif + return l; + } + + /************************************************************************** + * pcibios_set_device_config() * + **************************************************************************/ + static void pcibios_set_device_config(PCIDevice_t *device) + { + unsigned long l; + unsigned int busno = (unsigned int)device->parent->number; + + #ifndef PCI_DONOT_MODIFY + /* + * Tell the device where the bases are (and enable use of them). + */ + pcibios_read_config_dword(busno, _DEVICE_FN(device->slot, 0), + PCI_CFG_REG_STATUS_COMMAND, &l); + if (device->PCI_IO_Size != 0) { + pcibios_write_config_dword(busno, _DEVICE_FN(device->slot, 0), + device->PCI_IO_Reg, device->PCI_IO_Base | 0x1); + l |= 0x1; + } + if (device->PCI_Mem_Size != 0) { + pcibios_write_config_dword(busno, _DEVICE_FN(device->slot, 0), + device->PCI_Mem_Reg, device->PCI_Mem_Base); + l |= 0x2; + } + pcibios_write_config_dword(busno, _DEVICE_FN(device->slot, 0), + PCI_CFG_REG_STATUS_COMMAND, l | 0x4); + /* + * Now set up its IRQ. + */ + pcibios_read_config_dword(busno, _DEVICE_FN(device->slot, 0), + PCI_CFG_REG_IRQ, &l); + l = l & 0xFFFFFF00; + l = l | (device->irq & 0xFF); + pcibios_write_config_dword(busno, _DEVICE_FN(device->slot, 0), PCI_CFG_REG_IRQ, l); + #endif + + } + + /************************************************************************** + * pcibios_allocate_device() * + **************************************************************************/ + PCIDevice_t *pcibios_allocate_device() + { + PCIDevice_t *device; + + #ifdef DEBUG + printk("...pcibios_allocate_device() called\n"); + #endif + /* + * Allocate one. + */ + device = (PCIDevice_t *)KSEG_ADDRESS(free_memory); + free_memory += sizeof(PCIDevice_t) + 8; + free_memory += 8 - (free_memory & 0x7); /* align to an 8 byte boundary */ + memset((char *)device, 0, sizeof(PCIDevice_t)); + return device; + } + + /************************************************************************** + * pcibios_query_device() * + **************************************************************************/ + static void pcibios_query_device(PCIDevice_t *device) + { + unsigned long bar, irq; + unsigned int addr, finished; + PCIBus_t *bus; + /* + * Figure out how much memory (and what sort) the given device needs. + */ + #ifdef DEBUG + printk("...pcibios_query_device() called\n"); + #endif + + bus = device->parent; + addr = 0x10; + finished = FALSE; + while (!finished) { + + /* + * Optionally, find out which IRQ this device has been assigned, + * (by the SRM console). + */ + #ifdef PCI_DONOT_MODIFY + pcibios_read_config_dword(bus->number, _DEVICE_FN(device->slot, 0), + PCI_CFG_REG_IRQ, &irq); + irq = irq & 0xFF; + device->irq = irq; + #endif + /* + * Figure out how much space and of what type this device wants. + */ + #ifndef PCI_DONOT_MODIFY + pcibios_write_config_dword(bus->number, _DEVICE_FN(device->slot, 0), + addr, 0xffffffff); + #endif + pcibios_read_config_dword(bus->number, _DEVICE_FN(device->slot, 0), + addr, &bar); + if (bar == 0) + finished = TRUE; + else { + /* + * We've read the base address register back after writing all ones + * and so now we must decode it. + */ + if (bar & 0x1) { + unsigned int i; + /* + * I/O space address register. + */ + device->flags.IO = TRUE; + bar = bar & 0xFFFFFFFE; + #ifdef PCI_DONOT_MODIFY + device->PCI_IO_Base = bar; + #else + i = ((~bar) << 1) | 0x1; + device->PCI_IO_Size = (bar & i) & 0xFFFFFFFF; + #endif + device->PCI_IO_Reg = addr; + addr += 4; + } else { + unsigned int i; + /* + * Memory space address register. + */ + device->flags.MEM = TRUE; + i = (bar > 1) & 0x3; + if ((i == 00) | (i == 1)) { + /* + * 32 bit wide memory address. + */ + bar = bar & 0xfffffff0; + #ifdef PCI_DONOT_MODIFY + device->PCI_Mem_Base = bar; + #else + i = ((~bar) << 1) | 0x1; + device->PCI_Mem_Size = (bar & i) & 0xFFFFFFFF; + #endif + device->PCI_Mem_Reg = addr; + addr += 4; + } else { + /* + * 64 bit wide memory address, ignore for now. + */ + addr = addr + 8; + } + } + if (addr > 0x24) finished = TRUE; + } + } + } + + /************************************************************************** + * pcibios_allocate_bus() * + **************************************************************************/ + static PCIBus_t *pcibios_allocate_bus() + { + PCIBus_t *bus; + + #ifdef DEBUG + printk("...pcibios_allocate_bus() called\n"); + #endif + /* + * Allocate one. + */ + bus = (PCIBus_t *)KSEG_ADDRESS(free_memory); + free_memory += sizeof(PCIDevice_t); + free_memory += 8 - (free_memory & 0x7); /* align to an 8 byte boundary */ + memset((char *)bus, 0, sizeof(PCIBus_t)); + return bus; + } + + /************************************************************************** + * pcibios_insert_device() * + **************************************************************************/ + /* + * Insert the PCI device into the queue of devices in ascending memory + * needs order. + */ + static void pcibios_insert_device(PCIBus_t *bus, PCIDevice_t *device) + { + #ifdef DEBUG + printk("...pcibios_insert_device() called\n"); + #endif + + if (bus->devices != NULL) { + /* + * There are some members of the list. Search through it looking + * for the right place to put this device. + */ + if (bus->devices->next == NULL) { + if (bus->devices->PCI_IO_Size > device->PCI_IO_Size) { + device->next = bus->devices; + bus->devices = device; + } else { + bus->devices->next = device; + device->next = NULL; + } + } else { + PCIDevice_t *last, *next; + + last = bus->devices; + next = last->next; + while (next != NULL) { + if ((last->PCI_IO_Size <= device->PCI_IO_Size) && + (next->PCI_IO_Size >= device->PCI_IO_Size)) { + last->next = device; + device->next = next; + return; + } + last = next; + next = last-> next; + } + /* + * It goes at the end of the list. + */ + last->next = device; + device->next = NULL; + } + } else { + /* + * The list is empty, so make this the first entry. + */ + bus->devices = device; + device->next = NULL; + } + } + + /************************************************************************** + * pcibios_allocate_space() * + **************************************************************************/ + static void pcibios_allocate_space(PCIBus_t *bus) + { + unsigned long l; + unsigned int tio, bio, tmem, bmem; + PCIBus_t *child; + PCIDevice_t *device; + + #ifdef DEBUG + printk("...pcibios_allocate_space() called\n"); + #endif + + /* + * Don't do anything unless this bus has any devices/bridges. + */ + if ((bus->devices != NULL) || (bus->children != NULL)) { + + #ifndef PCI_DONOT_MODIFY + /* + * Align the current bases on appropriate boundaries (4K for IO and + * 1Mb for memory). + */ + bio = PCIIOBase = align(PCIIOBase,0x1000); + bmem = PCIMemBase = align(PCIMemBase, 0x100000); + /* + * Allocate space to each device. + */ + device = bus->devices; + while (device != NULL) { + if ( (!device->flags.bridge) && + ((device->PCI_IO_Size != 0) || (device->PCI_Mem_Size != 0)) ) { + unsigned int busno = (unsigned int)device->parent->number; + /* + * This is a normal device, allocate it some space. + */ + if (device->PCI_IO_Size != 0) { + PCIIOBase = device->PCI_IO_Base = + align(PCIIOBase,device->PCI_IO_Size); + PCIIOBase += device->PCI_IO_Size; + } + if (device->PCI_Mem_Size != 0) { + PCIMemBase = device->PCI_Mem_Base = + align(PCIMemBase,device->PCI_Mem_Size); + PCIMemBase += device->PCI_Mem_Size; + } + /* + * Now allocate it an IRQ. + */ + device->irq = PCIIRQ++; + /* + * Tell the device where the bases are. + */ + pcibios_set_device_config(device); + } + device = device -> next; + } + #endif + /* + * Allocate space for all of the sub-buses. + */ + child = bus->children; + while (child != NULL) { + pcibios_allocate_space(child); + child = child->next; + } + /* + * Align the current bases on 4K and 1MByte boundaries. + */ + #ifndef PCI_DONOT_MODIFY + tio = PCIIOBase = align(PCIIOBase,0x1000); + tmem = PCIMemBase = align(PCIMemBase, 0x100000); + /* + * set up this bus's windows. + */ + bus->PCI_IO_Base = bio; + bus->PCI_IO_Size = tio - bio; + bus->PCI_Mem_Base = bmem; + bus->PCI_Mem_Size = tmem - bmem; + + if (bus->bridge != NULL) { + PCIDevice_t *bridge = bus->bridge; + /* + * Set up the top and bottom of the I/O memory range for this bus. + */ + pcibios_read_config_dword(bridge->parent->number, _DEVICE_FN(bridge->slot, 0), + 0x1c, &l); + l = l | (bio >> 8) | ((tio - 1) & 0xf000); + pcibios_write_config_dword(bridge->parent->number, _DEVICE_FN(bridge->slot, 0), + 0x1c, l); + + l = ((bmem & 0xfff00000) >> 16) | ((tmem - 1) & 0xfff00000) ; + pcibios_write_config_dword(bridge->parent->number, _DEVICE_FN(bridge->slot, 0), + 0x20, l); + /* + * Turn off downstream PF memory address range. + */ + pcibios_write_config_dword(bridge->parent->number, _DEVICE_FN(bridge->slot, 0), + 0x24, 0x0000ffff); + /* + * There is an ISA bus in the system. + */ + pcibios_write_config_dword(bridge->parent->number, _DEVICE_FN(bridge->slot, 0), + 0x3c, 0x00040000); + /* + * clear status bits, enable I/O (for downstream I/O), turn on master + * enable (for upstream I/O), turn on memory enable (for downstream + * memory), turn on master enable (for upstream memory and I/O). + */ + pcibios_write_config_dword(bridge->parent->number, _DEVICE_FN(bridge->slot, 0), + 0x4, 0xffff0007); + } + #endif + } + } + /************************************************************************** + * pcibios_scan_bus() * + **************************************************************************/ + static unsigned int pcibios_scan_bus(PCIBus_t *bus, unsigned int min_dev, + unsigned int max_dev) + { + unsigned int i; + unsigned long l; + unsigned int max; + PCIDevice_t *device; + PCIBus_t *child; + + #ifdef DEBUG + printk("...pcibios_scan_bus() called with bus = %d\n", bus->number); + #endif + + max = bus->secondary; + for (i = min_dev; i <= max_dev; i++) { + l = pcibios_slot_filled(bus->number, i); + if (l != 0) { + /* + * This slot (i) is filled. + */ + device = pcibios_allocate_device(); + device->parent = bus; + /* + * Put it into the simple chain of devices that is used to find + * devices once everything is set up. + */ + device->sibling = devices; + devices = device; + + device->slot = i; + device->vendor = (unsigned short)(l & 0xFFFF); + device->device = (unsigned short)(l >> 16); + device->flags.bridge = FALSE; + /* + * Check to see if this device is a PCI-PCI bridge. + */ + pcibios_read_config_dword(bus->number, _DEVICE_FN(i, 0), + PCI_CFG_REG_REVISION_ID, &l); + l = l >> 8; /* upper 3 bytes */ + device->class = l; + device->flags.bridge = (l == PCI_BRIDGE_CLASS); + /* + * Figure out just how much I/O and memory space this device needs. + * Note that we must have set its parent up by this time. We don't + * do this for bridges. + */ + if (!device->flags.bridge) + pcibios_query_device(device); + /* + * Now insert it into the list of devices held by the parent bus. + * Note that we can only do this when we know how much memory and + * I/O it requires as the device list is in ascending memory order. + */ + pcibios_insert_device(bus, device); + /* + * Check to see if this device is a PCI-PCI bridge. + */ + if (device->flags.bridge) { + unsigned long buses; + /* + * Insert it into the tree of buses. + */ + child = pcibios_allocate_bus(); + child->next = bus->children; + bus->children = child; + child->bridge = device; + child->parent = bus; + + #ifndef PCI_DONOT_MODIFY + /* + * Set up the primary, secondary and subordinate bus numbers. + */ + max = max + 1; + child->number = (unsigned char)max; + child->primary = bus->secondary; + child->secondary = (unsigned char)max; + child->subordinate = 0xFF; + /* + * clear all status bits and turn off memory, I/O and master enables. + */ + pcibios_write_config_dword(bus->number, _DEVICE_FN(i, 0), 0x04, 0xffff0000); + /* + * configure the bus numbers for this bridge. + */ + pcibios_read_config_dword(bus->number, _DEVICE_FN(i, 0), 0x18, &buses); + buses = buses & 0xff000000; + buses = buses | (unsigned int)(child->primary) | + ((unsigned int)(child->secondary) << 8) | + ((unsigned int)(child->subordinate) << 16); + pcibios_write_config_dword(bus->number, _DEVICE_FN(i, 0), 0x18, buses); + /* + * scan all subordinate buses. + */ + max = pcibios_scan_bus(child, 0, PCI_21050_MAX_DEVICES); + /* + * Set the subordinate bus number to it's real value. + */ + child->subordinate = (unsigned char)max; + buses = (buses & 0xff00ffff) | ((unsigned int)(child->subordinate) << 16); + pcibios_write_config_dword(bus->number, _DEVICE_FN(i, 0), 0x18, buses); + #endif + } + } + } + /* + * We've scanned the bus and so we know all about what's on the other + * side of any bridges that may be on this bus plus any devices. + * + * Return how far we've got finding sub-buses. + */ + return max; + } + + /************************************************************************** + * pcibios_show_device() * + **************************************************************************/ + static void pcibios_show_device(PCIDevice_t *device) + { + printk("PCI slot %d, vendor = 0x%X, device = 0x%X, IRQ = %d\n", device->slot, + device->vendor, device->device, device->irq); + #ifdef PCIDEBUG + printk("\tat address %X\n", device); + printk("\tparent = %X, sibling = %X, next = %X\n", device->parent, + device->sibling, device->next); + #endif + printk("\tPCI IO Base = 0x%X, PCI Memory Base = 0x%X\n", + device->PCI_IO_Base, device->PCI_Mem_Base); + switch (device->class) { + case 0x000000: + printk("\tNon-VGA compatible device\n"); + break; + case 0x000100: + printk("\tVGA compatible device\n"); + break; + case 0x010000: + printk("\tSCSI bus controller\n"); + break; + case 0x010100: + printk("\tIDE controller\n"); + break; + case 0x010200: + printk("\tFloppy disk controller\n"); + break; + case 0x020000: + printk("\tEthernet controller\n"); + break; + case 0x030000: + printk("\tVGA compatible controller\n"); + break; + case 0x038000: + printk("\tDisplay controller\n"); + break; + case 0x060100: + printk("\tISA bridge\n"); + break; + case 0x060400: + printk("\tPCI-PCI bridge\n"); + break; + } + if (device->print != NULL) + (device->print)(device); + } + + /************************************************************************** + * pcibios_show_bus() * + **************************************************************************/ + static void pcibios_show_bus(PCIBus_t *bus) + { + PCIDevice_t *device; + PCIBus_t *child; + + printk("\n"); + #ifdef PCIDEBUG + printk("Bus = %d (address = %X)\n", bus->number, bus); + printk("\tprimary = %d, secondary = %d, subordinate = %d\n", + bus->primary, bus->secondary, bus->subordinate); + printk("\tbridge = %X\n", bus->bridge); + printk("\tchildren = %X, next = %X\n", bus->children, bus->next); + printk("\tPCI I/O space = %X, PCI Mem space = %X\n", + bus->PCI_IO_Size, bus->PCI_Mem_Size); + printk("\tPCI I/O base = %X, PCI Mem base = %X\n", + bus->PCI_IO_Base, bus->PCI_Mem_Base); + #else + printk("Bus = %d\n", bus->number); + printk("\tprimary = %d, secondary = %d, subordinate = %d\n", + bus->primary, bus->secondary, bus->subordinate); + printk("\tPCI I/O space = %X, PCI Mem space = %X\n", + bus->PCI_IO_Size, bus->PCI_Mem_Size); + printk("\tPCI I/O base = %X, PCI Mem base = %X\n", + bus->PCI_IO_Base, bus->PCI_Mem_Base); + #endif + /* + * Show all the devices on this bus. + */ + device = bus->devices; + while (device != NULL) { + pcibios_show_device(device); + device = device->next; + } + /* + * Show all of the sub-buses. + */ + child = bus->children; + while (child != NULL) { + pcibios_show_bus(child); + child = child->next; + } + printk("\n"); + } + + /*+-------------------------------------------------------------------------------------+ + | | + | The following routines can be called by external modules. Their interface and | + | functionality exactly matches that of the Intel equivalent BIOS code and callbacks. | + | | + /*+-------------------------------------------------------------------------------------+*/ + /************************************************************************** + * bios32_init() * + **************************************************************************/ + unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end) + { + unsigned int max_device; + + #ifdef PCI_DONOT_MODIFY + printk("...NOT modifying existing (SRM) PCI configuration\n"); + #endif + /* + * Init the device allocation pointers + * incase the monitor is restarted. + */ + free_memory = memory_start; + if ((free_memory & 0x7) != 0) + free_memory += 8 - (free_memory & 0x7); /* align to an 8 byte boundary */ + devices = NULL; + + /* + * Allocate the first bus (there's at least one!) + */ + root = pcibios_allocate_bus(); + root->number = root->primary = root->secondary = 0; + /* + * And then scan it and all it's sub-buses. + */ + if _APECS_PCI + max_device = 21; + else + max_device = 10; + root->subordinate = (unsigned char)pcibios_scan_bus(root, 0, max_device); + /* + * Now scan the tree allocating PCI memory and I/O space. + */ + pcibios_allocate_space(root); + /* + * For debug purposes, print out what we found. + */ + pcibios_show_bus(root); + /* + * Return a pointer to above the last memory that we used. + */ + if ((free_memory & 0x7) != 0) + free_memory += 8 - (free_memory & 0x7); /* align to an 8 byte boundary */ + + return free_memory; + } + + /************************************************************************** + * pcibios_present() * + **************************************************************************/ + /* + * Note: this routine appears twice, and returns a different value depending + * on whether PCI was configured into the system or not. + */ + int pcibios_present(void) + { + return 1; + } + + /************************************************************************** + * pcibios_find_device() * + **************************************************************************/ + /* + * Given the vendor and device ids, find the n'th instance of that device + * in the system. + * + */ + int pcibios_find_device (unsigned short vendor, unsigned short device_id, + unsigned short index, unsigned char *bus, unsigned char *device_fn) + { + unsigned short current; + + PCIDevice_t *PCIDevice = devices; + current = 0; + + while (PCIDevice != NULL) { + if ((PCIDevice->vendor == vendor) && (PCIDevice->device == device_id)) { + if (current == index) { + /* + * We have found it. + */ + *device_fn = 0x00; + *device_fn |= (_PCI_Slot(PCIDevice) << 3) & 0xf8; + *bus = _PCI_Bus(PCIDevice); + return PCIBIOS_SUCCESSFUL; + } + current++; + } + PCIDevice = PCIDevice->sibling; + } + /* + * Failed, return an error. + */ + return PCIBIOS_DEVICE_NOT_FOUND; + } + + /************************************************************************** + * pcibios_find_class() * + **************************************************************************/ + /* + * Given the class, find the n'th instance of that device + * in the system. + * + */ + int pcibios_find_class (unsigned long class_code, unsigned short index, + unsigned char *bus, unsigned char *device_fn) + { + unsigned short current; + + PCIDevice_t *PCIDevice = devices; + current = 0; + + while (PCIDevice != NULL) { + if (PCIDevice->class == class_code) { + if (current == index) { + /* + * We have found it. + */ + *device_fn = 0x00; + *device_fn |= (_PCI_Slot(PCIDevice) << 3) & 0xf8; + *bus = _PCI_Bus(PCIDevice); + return PCIBIOS_SUCCESSFUL; + } + current++; + } + PCIDevice = PCIDevice->sibling; + } + /* + * Failed, return an error. + */ + return PCIBIOS_DEVICE_NOT_FOUND; + } + + /************************************************************************** + * pcibios_strerror() * + **************************************************************************/ + char *pcibios_strerror (int error) + { + static char buf[80]; + + switch (error) { + case PCIBIOS_SUCCESSFUL: + return "SUCCESSFUL"; + + case PCIBIOS_FUNC_NOT_SUPPORTED: + return "FUNC_NOT_SUPPORTED"; + + case PCIBIOS_BAD_VENDOR_ID: + return "SUCCESSFUL"; + + case PCIBIOS_DEVICE_NOT_FOUND: + return "DEVICE_NOT_FOUND"; + + case PCIBIOS_BAD_REGISTER_NUMBER: + return "BAD_REGISTER_NUMBER"; + + default: + sprintf (buf, "UNKNOWN RETURN 0x%x", error); + return buf; + } + } + + /************************************************************************** + * pcibios_read_config_byte() * + **************************************************************************/ + int pcibios_read_config_byte(unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned char *value) + { + unsigned int slot, function; + unsigned int command; + + slot = (device_fn & 0xf8) >> 3; + function = (device_fn & 0x07); + + /* + * Build the appropriate configuration command. + */ + _CREATE_CONFIGURATION_COMMAND(command, bus, slot, function, where); + /* + * Now issue it. + */ + _SELECT_CONFIG_CYCLE(bus); /* type 0 or type 1? */ + *value = (*alpha_inb)(command, alpha_cfg_base); + + return PCIBIOS_SUCCESSFUL; + } + /************************************************************************** + * pcibios_read_config_word() * + **************************************************************************/ + int pcibios_read_config_word (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned short *value) + { + unsigned int slot, function; + unsigned int command; + + slot = (device_fn & 0xf8) >> 3; + function = (device_fn & 0x07); + + /* + * Build the appropriate configuration command. + */ + _CREATE_CONFIGURATION_COMMAND(command, bus, slot, function, where); + /* + * Now issue it. + */ + _SELECT_CONFIG_CYCLE(bus); /* type 0 or type 1? */ + *value = (*alpha_inw)(command, alpha_cfg_base); + + return PCIBIOS_SUCCESSFUL; + } + /************************************************************************** + * pcibios_read_config_dword() * + **************************************************************************/ + int pcibios_read_config_dword (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned long *value) + { + unsigned int slot, function; + unsigned int command; + + slot = (device_fn & 0xf8) >> 3; + function = (device_fn & 0x07); + + #ifdef DEBUG + printk("...read_config_dword: bus = %d, function = %d, slot = %d, where = 0x%X\n", + bus, function, slot, where); + #endif + + /* + * Build the appropriate configuration command. + */ + _CREATE_CONFIGURATION_COMMAND(command, bus, slot, function, where); + #ifdef DEBUG + printk("...command = 0x%X\n", command); + #endif + /* + * Now issue it. + */ + #ifdef DEBUG + printk("...selecting config cycle\n"); + #endif + _SELECT_CONFIG_CYCLE(bus); /* type 0 or type 1? */ + #ifdef DEBUG + printk("...issuing configuration cycle\n"); + printk("...alpha_cfg_base = %X %X\n", alpha_cfg_base >> 32, alpha_cfg_base); + #endif + *value = (*alpha_inl)(command, alpha_cfg_base); + + return PCIBIOS_SUCCESSFUL; + } + + /************************************************************************** + * pcibios_write_config_byte() * + **************************************************************************/ + int pcibios_write_config_byte (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned char value) + { + unsigned int slot, function; + unsigned int command; + + slot = (device_fn & 0xf8) >> 3; + function = (device_fn & 0x07); + + /* + * Build the appropriate configuration command. + */ + _CREATE_CONFIGURATION_COMMAND(command, bus, slot, function, where); + /* + * Now issue it. + */ + _SELECT_CONFIG_CYCLE(bus); /* type 0 or type 1? */ + (*alpha_outb)(value, command, alpha_cfg_base); + + return PCIBIOS_SUCCESSFUL; + } + /************************************************************************** + * pcibios_write_config_word() * + **************************************************************************/ + int pcibios_write_config_word (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned short value) + { + unsigned int slot, function; + unsigned int command; + + slot = (device_fn & 0xf8) >> 3; + function = (device_fn & 0x07); + + /* + * Build the appropriate configuration command. + */ + _CREATE_CONFIGURATION_COMMAND(command, bus, slot, function, where); + /* + * Now issue it. + */ + _SELECT_CONFIG_CYCLE(bus); /* type 0 or type 1? */ + (*alpha_outw)(value, command, alpha_cfg_base); + + return PCIBIOS_SUCCESSFUL; + } + /************************************************************************** + * pcibios_write_config_dword() * + **************************************************************************/ + int pcibios_write_config_dword (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned long value) + { + unsigned int slot, function; + unsigned int command; + + slot = (device_fn & 0xf8) >> 3; + function = (device_fn & 0x07); + + #ifdef DEBUG + printk("...write_config_dword: bus = %d, function = %d, slot = %d\n", + bus, function, slot); + #endif + + /* + * Build the appropriate configuration command. + */ + _CREATE_CONFIGURATION_COMMAND(command, bus, slot, function, where); + /* + * Now issue it. + */ + _SELECT_CONFIG_CYCLE(bus); /* type 0 or type 1? */ + (*alpha_outl)(value, command, alpha_cfg_base); + + return PCIBIOS_SUCCESSFUL; + } + + #else + /************************************************************************** + * pcibios_present() * + **************************************************************************/ + /* + * Note: this routine appears twice, and returns a different value depending + * on whether PCI was configured into the system or not. + */ + int pcibios_present(void) + { + return 0; + } + #endif + + + diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/gdb.c LINUX_ALPHA_SDK/sources/linux/kernel/gdb.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/gdb.c Wed Jan 11 16:15:07 1995 --- LINUX_ALPHA_SDK/sources/linux/kernel/gdb.c Wed Feb 8 14:54:35 1995 *************** *** 1088,1094 **** if(rpb->rpb_systype == 6) { int comstat, hi, lo; ! cons_puts(0, "This is a Jensen; I'll use real serial drivers!\n"); is_jensen = 1; comstat = JINB(0x2fb); --- 1088,1094 ---- if(rpb->rpb_systype == 6) { int comstat, hi, lo; ! printk("This is a Jensen; I'll use real serial drivers!\n"); is_jensen = 1; comstat = JINB(0x2fb); diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/irq.c LINUX_ALPHA_SDK/sources/linux/kernel/irq.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/irq.c Fri Dec 30 17:09:58 1994 --- LINUX_ALPHA_SDK/sources/linux/kernel/irq.c Wed Feb 8 14:58:50 1995 *************** *** 28,33 **** --- 28,34 ---- #include #include #include + #include #include #include *************** *** 267,272 **** --- 268,290 ---- outb(0x60 | ((irq>7)?2:irq), 0x20); } + static int save_kb_mode; + save_irqs() + { + #ifndef CALLBACK_KEYBOARD + save_kb_mode = read_kb_mode(); + #endif /* ! CALLBACK_KEYBOARD */ + } + + restore_irqs() + { + outb(cache_21, 0x21); + outb(cache_A1, 0xa1); + #ifndef CALLBACK_KEYBOARD + write_kb_mode(save_kb_mode); + #endif /* ! CALLBACK_KEYBOARD */ + } + #endif /* i386 || __alpha */ int irqaction(unsigned int irq, struct sigaction * new_sa) *************** *** 309,314 **** --- 327,340 ---- int request_irq(unsigned int irq, void (*handler)(int)) { struct sigaction sa; + + #ifdef __alpha + /* JAE: for Alpha, IRQ may indicate SCB vector... */ + if (irq > 15) { + intrsetvec(irq, handler, 0); + return 0; + } + #endif /* __alpha */ sa.sa_handler = handler; sa.sa_flags = 0; diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/printk.c LINUX_ALPHA_SDK/sources/linux/kernel/printk.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/printk.c Tue Dec 13 21:10:49 1994 --- LINUX_ALPHA_SDK/sources/linux/kernel/printk.c Wed Feb 8 14:53:06 1995 *************** *** 228,235 **** else { char tmp = p[1]; p[1] = '\0'; ! cons_puts(0, msg); p[1] = tmp; } #endif /* __alpha */ --- 228,237 ---- else { char tmp = p[1]; p[1] = '\0'; ! cons_puts(0,msg); p[1] = tmp; + if (p[0] == '\n') + cons_puts_n(0,"\r",1); } #endif /* __alpha */ diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/syscall_alpha.S LINUX_ALPHA_SDK/sources/linux/kernel/syscall_alpha.S *** LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/syscall_alpha.S Wed Jan 11 16:15:09 1995 --- LINUX_ALPHA_SDK/sources/linux/kernel/syscall_alpha.S Thu Feb 9 15:32:28 1995 *************** *** 146,151 **** --- 146,153 ---- jsr ra,trace_syscall_result #endif + sll v0,32,v0 # Sign-extend v0 + sra v0,32,v0 blt v0,$99 # v0 < 0 => error stq v0,V0_OFF(sp) # No error: save the return value in v0 diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/traps_alpha.c LINUX_ALPHA_SDK/sources/linux/kernel/traps_alpha.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/kernel/traps_alpha.c Fri Dec 30 17:26:23 1994 --- LINUX_ALPHA_SDK/sources/linux/kernel/traps_alpha.c Thu Feb 9 15:32:29 1995 *************** *** 1,4 **** --- 1,8 ---- /* + #define DEBUG_IO_INTERRUPT + */ + + /* * linux/kernel/traps.c * * Copyright (C) 1991, 1992 Linus Torvalds *************** *** 134,139 **** --- 138,146 ---- } } + #ifdef CONFIG_PCI + unsigned int ignore_INT_MCHK = 0; + #endif void do_interrupt(struct pt_regs *regs) { register int itype = regs->iregs[A0]; *************** *** 155,166 **** --- 162,202 ---- break; case INT_MCHK: + #ifdef CONFIG_PCI + /* + * When we configure PCI we generate accesses to non-existent PCI slots + * (or rather empty PCI slots). As APECS (eg EB64+) generates a hard + * error when this happens, then we have to ignore it. I have not made + * a system specific check here (I'd rather avoid it). However, ignore_INT_MCHK + * is set FALSE for all 21066 based systems in bios_alpha.c. + */ + if (ignore_INT_MCHK) { + U64 mces; + /* + * As well as simply ignoring this machine check, we must clear the Machine + * Check in Progress flag in the MCES register so that the next error does + * not crash the system. + */ + ignore_INT_MCHK--; + mces = rdmces(); + mces |= 0x1; + wrmces(mces); + } else { + die_if_kernel("Machine check (PCI error?)", regs); + panic("Machine check!"); + } + #else die_if_kernel("Machine check", regs); panic("Machine check!"); + #endif break; case INT_IO: + #ifdef DEBUG_IO_INTERRUPT + printk("IO_INTERRUPT: vector 0x%x\n", ivec); + #endif /* DEBUG_IO_INTERRUPT */ + /* first, check for an IRQ */ #define LOW_IRQ_VEC 0x800 *************** *** 231,242 **** --- 267,280 ---- int regnum; U64 *regaddr; + #if 0 /* Kernel is NOT supposed to have unaligned accesses... treat * this as fatal, and fix the bug! */ if((regs->ps & PS_MODE) == PS_MODE_KERNEL) { die_if_kernel("Unaligned access", regs); } + #endif /* 0 */ /* User had an unaligned access. Fix it up silently. Later on * we may wish to add user-warning messages... *************** *** 246,254 **** opcode = regs->iregs[A1]; regnum = regs->iregs[A2]; #ifdef UNA_VERBOSE ! printk("\nUnaligned access in user mode: VA=0x%x, reg=%d, opcode=", ! vaddr, regnum); switch(opcode) { case OPC_LDL: printk("ldl\n"); break; case OPC_LDQ: printk("ldq\n"); break; --- 284,294 ---- opcode = regs->iregs[A1]; regnum = regs->iregs[A2]; + /* #define UNA_VERBOSE */ #ifdef UNA_VERBOSE ! printk("\n%s unaligned access: PC=0x%x, VA=0x%x, reg=%d, opcode=", ! ((regs->ps & PS_MODE) == PS_MODE_KERNEL)?"KERNEL":"USER", ! regs->pc, vaddr, regnum); switch(opcode) { case OPC_LDL: printk("ldl\n"); break; case OPC_LDQ: printk("ldq\n"); break; diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/Makefile LINUX_ALPHA_SDK/sources/linux/miniloader/Makefile *** LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/Makefile Thu Feb 9 19:57:35 1995 --- LINUX_ALPHA_SDK/sources/linux/miniloader/Makefile Wed Feb 8 09:32:42 1995 *************** *** 0 **** --- 1,103 ---- + # + # The following definitions are critical. The mini-loader itself consists of two + # parts, the loader itself and the dispatch code. The dispatch code contains the Alpha + # SRM (System Reference Manual) console callbacks for terminial I/O and is linked + # to the Linux KSEG address of 0x70220000 (see dispatch.ld). The miniloader is + # linked to address 0x200000 because the current version is loaded via the Debug Monitor + # of an Alpha Evaluation Board (see miniboot.ld). + # + # Part of the miniloader's job is to set up the references to the dispatcher. Once Linux + # is loaded, it calls the callbacks through the HWRPB data structure (which is why the + # dispatcher is linked into Linux KSEG space). + # + # As the miniloader does not have a SCSI device (yet), the Linux kernel itself and a + # RAMdisk are linked into the image. A tool called SYSGEN sews together the various + # bits of the image - it relies on the addresses below being correct. + # + # Dave Rusling + # + LOADER_AT = 200000 + LOADER_SIZE = 20000 + DISPATCH_AT = 220000 + DISPATCH_SIZE = 20000 + LINUX_AT = 240000 + LINUX_SIZE = 300000 + RAMDISK_AT = 540000 + RAMDISK_SIZE = 1400000 + + WHERE = -DLOADER_AT=0x$(LOADER_AT) -DDISPATCH_AT=0x$(DISPATCH_AT) -DLINUX_AT=0x$(LINUX_AT) -DRAMDISK_AT=0x$(RAMDISK_AT) + SIZES = -DLOADER_SIZE=0x$(LOADER_SIZE) -DDISPATCH_SIZE=0x$(DISPATCH_SIZE) -DLINUX_SIZE=0x$(LINUX_SIZE) \ + -DRAMDISK_SIZE=0x$(RAMDISK_SIZE) + INCLUDES = -nostdinc -I. -I$(SRCBASE)/include/linux $(INCFLAGS) + DEFINES = -DCALL_PAL_BROKEN -D__GNU__ -DSYSTEM_TYPE=19 -DBOOT_VERBOSE $(WHERE) $(SIZES) + CCFLAGS = $(CFLAGS) $(INCLUDES) $(DEFINES) + CC = alpha-dec-linux-gcc + AS = alpha-dec-linux-gcc + ASFLAGS = $(DEFINES) $(INCLUDES) + S = S + LD = alpha-dec-linux-ld + LDFLAGS_M = -N -T miniboot.ld + LDFLAGS_D = -N -T dispatch.ld + + OBJS_M = miniboot.o boot_main.o printf.o uart.o cpu.o bios_alpha.o + OBJS_D = dispatch_asm.o dispatch.o + + LIBS = ../lib/lib.a + + miniboot: miniboot.nh dispatch.nh ../linux ramdisk + sysgen -s -e$(LOADER_AT) miniboot.nh -s -e$(DISPATCH_AT) dispatch.nh \ + -s -e$(LINUX_AT) ../linux -s -e$(RAMDISK_AT) ramdisk -o miniboot + cp miniboot $(SRCBASE)/miniboot + + dispatch.nh: dispatch + cstrip -va dispatch dispatch.nh + + dispatch: $(OBJS_D) + $(LD) $(LDFLAGS_D) $(OBJS_D) $(LIBS) -o dispatch + + miniboot.nh: miniboot.exe + cstrip -va miniboot.exe miniboot.nh + + miniboot.exe: $(OBJS_M) + $(LD) $(LDFLAGS_M) $(OBJS_M) $(LIBS) -o miniboot.exe + + miniboot.o: miniboot.$(S) + $(AS) -c $(ASFLAGS) miniboot.$(S) + + dispatch_asm.o: dispatch_asm.$(S) + $(AS) -c $(ASFLAGS) dispatch_asm.$(S) + + printf.o: printf.c + $(CC) -c $(CCFLAGS) printf.c + + bios_alpha.o: bios_alpha.c + $(CC) -c $(CCFLAGS) bios_alpha.c + + dispatch.o: dispatch.c + $(CC) -c $(CCFLAGS) dispatch.c + + uart.o: uart.c + $(CC) -c $(CCFLAGS) uart.c + + boot_main.o: boot_main.c + $(CC) -c $(CCFLAGS) boot_main.c + + cpu.o: cpu.c + $(CC) -c $(CCFLAGS) cpu.c + + clean: + rm -f $(OBJS_M) $(OBJS_D) dispatch dispatch.nh miniboot.nh miniboot.exe miniboot + + dep: + rm -f .depend + for f in *.c;do $(CPP) -M $$f >> .depend;done + + dummy: + + # + # include a dependency file if one exists + # + ifeq (.depend,$(wildcard .depend)) + include .depend + endif + diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/bios_alpha.c LINUX_ALPHA_SDK/sources/linux/miniloader/bios_alpha.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/bios_alpha.c Thu Feb 9 19:57:35 1995 --- LINUX_ALPHA_SDK/sources/linux/miniloader/bios_alpha.c Wed Feb 8 09:33:44 1995 *************** *** 0 **** --- 1,1222 ---- + /* + * bios_alpha.c - PCI BIOS functions for Alpha systems not using + * BIOS emulation code. + * + * Written by Dave Rusling (david.rusling@reo.mts.dec.com) + * + * For more information, please consult + * + * PCI BIOS Specification Revision + * PCI Local Bus Specification + * PCI System Design Guide + * + * PCI Special Interest Group + * M/S HF3-15A + * 5200 N.E. Elam Young Parkway + * Hillsboro, Oregon 97124-6497 + * +1 (503) 696-2000 + * +1 (800) 433-5177 + * + * Manuals are $25 each or $50 for all three, plus $7 shipping + * within the United States, $35 abroad. + * + * + * CHANGELOG : + */ + + #include + #include + #include + #include + #include + #include + + /* + * This module is only needed if we have configured PCI into the system. + */ + #ifdef CONFIG_PCI + + unsigned int free_memory; + + /* + * WARNING: this does not belong here and it is eb66/noname specific code. + * It will not work on the EB64+ systems. + */ + #define IOC_REG_STATUS_0 0x40 + #define IOC_STATUS_0_M_ERR 0x00000010 + /* 4 = error */ + #define IOC_STATUS_0_M_CODE 0x00000700 + /* 10:8 = error code */ + + #define ST_DEC_EB64P 20 /* EB64+ systype */ + + /* + * EB64+ type systems (21064 + APECS). + */ + #define EPIC_CSR_M_NDEV 0x800 + + /*********************************************************************************** + * Local Macros * + ***********************************************************************************/ + /* + * On Alpha based PCI systems, there are two ways of getting at PCI configuration + * space. For 21066 based systems, the access is direct and each bit in 31:11 selects + * one and only one device. For systems using the APECS PCI/Memory support chipset + * (21064, 21164 based systems), 31:11 contains the device number required. This + * allows more than 20 PCI devices to be supported. + */ + #define _APECS_PCI (system_type == ST_DEC_EB64P) + /* + * The standard PCI BIOS entry points pass and return device_fn which is an 8 bit + * quantity containing the slot and function required. + * + * 7:4 = slot + * 3:0 = function + * + */ + #define _DEVICE_FN(slot,function) (((slot << 3) & 0xf8) | (function & 0x07)) + + /* + * The following macros define Type 0 and Type 1 configuration commands (addresses + * punted out onto the PCI bus). + * + * Type 0: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:11 Device select bit. + * 10:8 Function number + * 7:2 Register number + * + * Type 1: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:24 reserved + * 23:16 bus number (8 bits = 128 possible buses) + * 15:11 Device number (5 bits) + * 10:8 function number + * 7:2 register number + * + * Notes: + * The function number selects which function of a multi-function device + * (eg scsi and ethernet. + * + * On the EB66 and EB64+, you select the device by picking a bit between 11 and 31 + * (by left shifting). This PCI code assumes that the low order device number is + * 11, hence the lack of a shift by 11 bits. Also note that bits 1:0 are + * specified via a register. + * + * The register selects a DWORD (32 bit) register offset. Hence it doesn't + * get shifted by 2 bits as we want to "drop" the bottom two bits. + * + */ + #define PCI_CONFIG_TYPE_0(device,function,register) \ + ( (unsigned long)( (register & 0x3f) | ((function & 0x7) << 8) | (1 << (device + 11)) ) ) + + #define PCI_CONFIG_TYPE_0_APECS(device,function,register) \ + ( (unsigned long)( (register & 0x3f) | ((function & 0x7) << 8) | (device << 11) ) ) + + #define PCI_CONFIG_TYPE_1(bus,device,function,register) \ + ( (unsigned long)( (register & 0x3f) | ((function & 0x7) << 8) | ((device & 0x1f) << 11) | \ + ((bus & 0xff) << 16) ) ) + + /* + * Given the bus, device, function and register build either a Type 0 or Type 1 + * configuration command for the appropriate PCI subsystem (21066) or support + * chipset (APECS). + */ + #define _CREATE_CONFIGURATION_COMMAND(command,bus,device,function,register) \ + { \ + if (bus == 0) { \ + if _APECS_PCI \ + command = PCI_CONFIG_TYPE_0_APECS(device,function,register); \ + else \ + command = PCI_CONFIG_TYPE_0(device,function,register); \ + } else \ + command = PCI_CONFIG_TYPE_1(bus,device,function,register); \ + } + /* + * Select the type of configuration cycle that is going to be issued. This depends + * on whether or not it is for bus 0. + */ + #define _SELECT_CONFIG_CYCLE(bus) \ + { \ + if _APECS_PCI \ + write_cpureg_quad((U64)(bus != 0), 0xfffffc01a0000000ULL | 0x1c0); /* HAX Reg 2 */ \ + else \ + write_cpureg_quad((U64)(bus != 0), 0xfffffc0180000000ULL | 0x20); /* IOC CCT */ \ + } + + /* + * Align things. + */ + #define align(value,alignment) \ + ( (value & (alignment - 1)) == 0 ? value : value + (alignment - (value & (alignment - 1))) ) + + + /* + * Just in case these are not defined. + */ + #ifndef NULL + #define NULL 0 + #endif + + #ifndef TRUE + #define TRUE 1 + #endif + #ifndef FALSE + #define FALSE 0 + #endif + + /* + * The root of pci devices found. + */ + static PCIBus_t *root = NULL; /* tree of devices and buses */ + static PCIDevice_t *devices = NULL; /* linked list of all devices */ + static PCIIOBase = PCI_IO_BASE; + static PCIMemBase = 0x200000; + static PCIIRQ = 1; + /* + * Any routines local to this module. + */ + static PCIDevice_t *pcibios_allocate_device(); + static unsigned int pcibios_slot_filled(int bus, int slot); + static void pcibios_set_device_config(PCIDevice_t *device); + static void pcibios_query_device(PCIDevice_t *device); + static PCIBus_t *pcibios_allocate_bus(); + static void pcibios_insert_device(PCIBus_t *bus, PCIDevice_t *device); + static void pcibios_allocate_space(PCIBus_t *bus); + static unsigned int pcibios_scan_bus(PCIBus_t *bus, unsigned int min_dev, unsigned int max_dev); + static void pcibios_show_device(PCIDevice_t *device); + static void pcibios_show_bus(PCIBus_t *bus); + + /* + * External things. + */ + extern int (*alpha_inb)(int port,U64 base); + extern int (*alpha_inw)(int port,U64 base); + extern int (*alpha_inl)(int port,U64 base); + extern void (*alpha_outb)(int v,int port,U64 base); + extern void (*alpha_outw)(int v,int port,U64 base); + extern void (*alpha_outl)(int v,int port,U64 base); + + extern U64 alpha_io_base; + extern U64 alpha_mem_base; + extern U64 alpha_cfg_base; + + extern U64 system_type; + + extern void write_cpureg_quad(U64 v,U64 addr); + extern int read_cpureg_quad(U64 addr); + + /*+-------------------------------------------------------------------------------------+ + | | + | The following routines are local to this module and cannot be called from outside | + | of it. | + | | + /*+-------------------------------------------------------------------------------------+*/ + /* + * Clear the NODEV status and + * return the current value (TRUE/FALSE). + */ + static unsigned int IOPCIClearNODEV() + { + + unsigned int status; + U64 old; + + if _APECS_PCI { + /* + * Get the current NODEV status. + */ + old = read_cpureg_quad(0xfffffc01a0000000ULL); + status = ((old & EPIC_CSR_M_NDEV) != 0); + /* + * Clear it. + */ + write_cpureg_quad(EPIC_CSR_M_NDEV, 0xfffffc01a0000000ULL); + } else { + /* + * Get the current NODEV status. + */ + old = read_cpureg_quad(0xfffffc0180000000ULL | IOC_REG_STATUS_0); + status = ((old & IOC_STATUS_0_M_ERR) != 0); + /* + * Clear it. + */ + write_cpureg_quad(old, 0xfffffc0180000000ULL | IOC_REG_STATUS_0); + } + return status; + } + + /************************************************************************** + * pcibios_slot_filled() * + **************************************************************************/ + /* + * Check to see if a PCI slot has a device, how we do this depends on the + * evaluation board. + */ + unsigned int ignore_INT_MCHK; + static unsigned int pcibios_slot_filled(int bus, int slot) + { + unsigned long l; + /* + * First, clear any possible previous NODEV errors. + */ + #ifdef DEBUG + printf("...pcibios_slot_filled() called for bus = %d, slot = %d\n", bus, slot); + #endif + IOPCIClearNODEV(); + + if _APECS_PCI ignore_INT_MCHK = 1; + /* + * Read the vendor and device ids (first longword). + */ + pcibios_read_config_dword(bus, _DEVICE_FN(slot, 0), + PCI_CFG_REG_VENDOR_DEVICE, &l); + /* + * Now do system specific checks for trying to read a non-existant + * slot. + */ + if _APECS_PCI { + if (ignore_INT_MCHK == 0) l = 0; + IOPCIClearNODEV(); + } else { + /* + * Check to see if we caused a PCI NODEV error. + */ + if (!IOPCIClearNODEV()) { + /* + * Check for all 1s as the vendor id (this also means + * that the slot doesn't contain a device). + */ + if ((l & 0xffff) == 0xffff) l = 0; + } else + l = 0; + } + /* + * Return the results + */ + #ifdef DEBUG + printf("...slot filled returning %d\n", l); + #endif + return l; + } + + /************************************************************************** + * pcibios_set_device_config() * + **************************************************************************/ + static void pcibios_set_device_config(PCIDevice_t *device) + { + unsigned long l; + unsigned int busno = (unsigned int)device->parent->number; + + #ifndef PCI_DONOT_MODIFY + /* + * Tell the device where the bases are (and enable use of them). + */ + pcibios_read_config_dword(busno, _DEVICE_FN(device->slot, 0), + PCI_CFG_REG_STATUS_COMMAND, &l); + if (device->PCI_IO_Size != 0) { + pcibios_write_config_dword(busno, _DEVICE_FN(device->slot, 0), + device->PCI_IO_Reg, device->PCI_IO_Base | 0x1); + l |= 0x1; + } + if (device->PCI_Mem_Size != 0) { + pcibios_write_config_dword(busno, _DEVICE_FN(device->slot, 0), + device->PCI_Mem_Reg, device->PCI_Mem_Base); + l |= 0x2; + } + pcibios_write_config_dword(busno, _DEVICE_FN(device->slot, 0), + PCI_CFG_REG_STATUS_COMMAND, l | 0x4); + /* + * Now set up its IRQ. + */ + pcibios_read_config_dword(busno, _DEVICE_FN(device->slot, 0), + PCI_CFG_REG_IRQ, &l); + l = l & 0xFFFFFF00; + l = l | (device->irq & 0xFF); + pcibios_write_config_dword(busno, _DEVICE_FN(device->slot, 0), PCI_CFG_REG_IRQ, l); + #endif + + } + + /************************************************************************** + * pcibios_allocate_device() * + **************************************************************************/ + PCIDevice_t *pcibios_allocate_device() + { + PCIDevice_t *device; + + #ifdef DEBUG + printf("...pcibios_allocate_device() called\n"); + #endif + /* + * Allocate one. + */ + device = (PCIDevice_t *)free_memory; + free_memory += sizeof(PCIDevice_t) + 8; + free_memory += 8 - (free_memory & 0x7); /* align to an 8 byte boundary */ + memset((char *)device, 0, sizeof(PCIDevice_t)); + return device; + } + + /************************************************************************** + * pcibios_query_device() * + **************************************************************************/ + static void pcibios_query_device(PCIDevice_t *device) + { + unsigned long bar, irq; + unsigned int addr, finished; + PCIBus_t *bus; + /* + * Figure out how much memory (and what sort) the given device needs. + */ + #ifdef DEBUG + printf("...pcibios_query_device() called\n"); + #endif + + bus = device->parent; + addr = 0x10; + finished = FALSE; + while (!finished) { + + /* + * Optionally, find out which IRQ this device has been assigned, + * (by the SRM console). + */ + #ifdef PCI_DONOT_MODIFY + pcibios_read_config_dword(bus->number, _DEVICE_FN(device->slot, 0), + PCI_CFG_REG_IRQ, &irq); + irq = irq & 0xFF; + device->irq = irq; + #endif + /* + * Figure out how much space and of what type this device wants. + */ + #ifndef PCI_DONOT_MODIFY + pcibios_write_config_dword(bus->number, _DEVICE_FN(device->slot, 0), + addr, 0xffffffff); + #endif + pcibios_read_config_dword(bus->number, _DEVICE_FN(device->slot, 0), + addr, &bar); + if (bar == 0) + finished = TRUE; + else { + /* + * We've read the base address register back after writing all ones + * and so now we must decode it. + */ + if (bar & 0x1) { + unsigned int i; + /* + * I/O space address register. + */ + device->flags.IO = TRUE; + bar = bar & 0xFFFFFFFE; + #ifdef PCI_DONOT_MODIFY + device->PCI_IO_Base = bar; + #else + i = ((~bar) << 1) | 0x1; + device->PCI_IO_Size = (bar & i) & 0xFFFFFFFF; + #endif + device->PCI_IO_Reg = addr; + addr += 4; + } else { + unsigned int i; + /* + * Memory space address register. + */ + device->flags.MEM = TRUE; + i = (bar > 1) & 0x3; + if ((i == 00) | (i == 1)) { + /* + * 32 bit wide memory address. + */ + bar = bar & 0xfffffff0; + #ifdef PCI_DONOT_MODIFY + device->PCI_Mem_Base = bar; + #else + i = ((~bar) << 1) | 0x1; + device->PCI_Mem_Size = (bar & i) & 0xFFFFFFFF; + #endif + device->PCI_Mem_Reg = addr; + addr += 4; + } else { + /* + * 64 bit wide memory address, ignore for now. + */ + addr = addr + 8; + } + } + if (addr > 0x24) finished = TRUE; + } + } + } + + /************************************************************************** + * pcibios_allocate_bus() * + **************************************************************************/ + static PCIBus_t *pcibios_allocate_bus() + { + PCIBus_t *bus; + + #ifdef DEBUG + printf("...pcibios_allocate_bus() called\n"); + #endif + /* + * Allocate one. + */ + bus = (PCIBus_t *)free_memory; + free_memory += sizeof(PCIDevice_t); + free_memory += 8 - (free_memory & 0x7); /* align to an 8 byte boundary */ + memset((char *)bus, 0, sizeof(PCIBus_t)); + return bus; + } + + /************************************************************************** + * pcibios_insert_device() * + **************************************************************************/ + /* + * Insert the PCI device into the queue of devices in ascending memory + * needs order. + */ + static void pcibios_insert_device(PCIBus_t *bus, PCIDevice_t *device) + { + #ifdef DEBUG + printf("...pcibios_insert_device() called\n"); + #endif + + if (bus->devices != NULL) { + /* + * There are some members of the list. Search through it looking + * for the right place to put this device. + */ + if (bus->devices->next == NULL) { + if (bus->devices->PCI_IO_Size > device->PCI_IO_Size) { + device->next = bus->devices; + bus->devices = device; + } else { + bus->devices->next = device; + device->next = NULL; + } + } else { + PCIDevice_t *last, *next; + + last = bus->devices; + next = last->next; + while (next != NULL) { + if ((last->PCI_IO_Size <= device->PCI_IO_Size) && + (next->PCI_IO_Size >= device->PCI_IO_Size)) { + last->next = device; + device->next = next; + return; + } + last = next; + next = last-> next; + } + /* + * It goes at the end of the list. + */ + last->next = device; + device->next = NULL; + } + } else { + /* + * The list is empty, so make this the first entry. + */ + bus->devices = device; + device->next = NULL; + } + } + + /************************************************************************** + * pcibios_allocate_space() * + **************************************************************************/ + static void pcibios_allocate_space(PCIBus_t *bus) + { + unsigned long l; + unsigned int tio, bio, tmem, bmem; + PCIBus_t *child; + PCIDevice_t *device; + + #ifdef DEBUG + printf("...pcibios_allocate_space() called\n"); + #endif + + /* + * Don't do anything unless this bus has any devices/bridges. + */ + if ((bus->devices != NULL) || (bus->children != NULL)) { + + #ifndef PCI_DONOT_MODIFY + /* + * Align the current bases on appropriate boundaries (4K for IO and + * 1Mb for memory). + */ + bio = PCIIOBase = align(PCIIOBase,0x1000); + bmem = PCIMemBase = align(PCIMemBase, 0x100000); + /* + * Allocate space to each device. + */ + device = bus->devices; + while (device != NULL) { + if ( (!device->flags.bridge) && + ((device->PCI_IO_Size != 0) || (device->PCI_Mem_Size != 0)) ) { + unsigned int busno = (unsigned int)device->parent->number; + /* + * This is a normal device, allocate it some space. + */ + if (device->PCI_IO_Size != 0) { + PCIIOBase = device->PCI_IO_Base = + align(PCIIOBase,device->PCI_IO_Size); + PCIIOBase += device->PCI_IO_Size; + } + if (device->PCI_Mem_Size != 0) { + PCIMemBase = device->PCI_Mem_Base = + align(PCIMemBase,device->PCI_Mem_Size); + PCIMemBase += device->PCI_Mem_Size; + } + /* + * Now allocate it an IRQ. + */ + device->irq = PCIIRQ++; + /* + * Tell the device where the bases are. + */ + pcibios_set_device_config(device); + } + device = device -> next; + } + #endif + /* + * Allocate space for all of the sub-buses. + */ + child = bus->children; + while (child != NULL) { + pcibios_allocate_space(child); + child = child->next; + } + /* + * Align the current bases on 4K and 1MByte boundaries. + */ + #ifndef PCI_DONOT_MODIFY + tio = PCIIOBase = align(PCIIOBase,0x1000); + tmem = PCIMemBase = align(PCIMemBase, 0x100000); + /* + * set up this bus's windows. + */ + bus->PCI_IO_Base = bio; + bus->PCI_IO_Size = tio - bio; + bus->PCI_Mem_Base = bmem; + bus->PCI_Mem_Size = tmem - bmem; + + if (bus->bridge != NULL) { + PCIDevice_t *bridge = bus->bridge; + /* + * Set up the top and bottom of the I/O memory range for this bus. + */ + pcibios_read_config_dword(bridge->parent->number, _DEVICE_FN(bridge->slot, 0), + 0x1c, &l); + l = l | (bio >> 8) | ((tio - 1) & 0xf000); + pcibios_write_config_dword(bridge->parent->number, _DEVICE_FN(bridge->slot, 0), + 0x1c, l); + + l = ((bmem & 0xfff00000) >> 16) | ((tmem - 1) & 0xfff00000) ; + pcibios_write_config_dword(bridge->parent->number, _DEVICE_FN(bridge->slot, 0), + 0x20, l); + /* + * Turn off downstream PF memory address range. + */ + pcibios_write_config_dword(bridge->parent->number, _DEVICE_FN(bridge->slot, 0), + 0x24, 0x0000ffff); + /* + * There is an ISA bus in the system. + */ + pcibios_write_config_dword(bridge->parent->number, _DEVICE_FN(bridge->slot, 0), + 0x3c, 0x00040000); + /* + * clear status bits, enable I/O (for downstream I/O), turn on master + * enable (for upstream I/O), turn on memory enable (for downstream + * memory), turn on master enable (for upstream memory and I/O). + */ + pcibios_write_config_dword(bridge->parent->number, _DEVICE_FN(bridge->slot, 0), + 0x4, 0xffff0007); + } + #endif + } + } + /************************************************************************** + * pcibios_scan_bus() * + **************************************************************************/ + static unsigned int pcibios_scan_bus(PCIBus_t *bus, unsigned int min_dev, + unsigned int max_dev) + { + unsigned int i; + unsigned long l; + unsigned int max; + PCIDevice_t *device; + PCIBus_t *child; + + #ifdef DEBUG + printf("...pcibios_scan_bus() called with bus = %d\n", bus->number); + #endif + + max = bus->secondary; + for (i = min_dev; i <= max_dev; i++) { + l = pcibios_slot_filled(bus->number, i); + if (l != 0) { + /* + * This slot (i) is filled. + */ + device = pcibios_allocate_device(); + device->parent = bus; + /* + * Put it into the simple chain of devices that is used to find + * devices once everything is set up. + */ + device->sibling = devices; + devices = device; + + device->slot = i; + device->vendor = (unsigned short)(l & 0xFFFF); + device->device = (unsigned short)(l >> 16); + device->flags.bridge = FALSE; + /* + * Check to see if this device is a PCI-PCI bridge. + */ + pcibios_read_config_dword(bus->number, _DEVICE_FN(i, 0), + PCI_CFG_REG_REVISION_ID, &l); + l = l >> 8; /* upper 3 bytes */ + device->class = l; + device->flags.bridge = (l == PCI_BRIDGE_CLASS); + /* + * Figure out just how much I/O and memory space this device needs. + * Note that we must have set its parent up by this time. We don't + * do this for bridges. + */ + if (!device->flags.bridge) + pcibios_query_device(device); + /* + * Now insert it into the list of devices held by the parent bus. + * Note that we can only do this when we know how much memory and + * I/O it requires as the device list is in ascending memory order. + */ + pcibios_insert_device(bus, device); + /* + * Check to see if this device is a PCI-PCI bridge. + */ + if (device->flags.bridge) { + unsigned long buses; + /* + * Insert it into the tree of buses. + */ + child = pcibios_allocate_bus(); + child->next = bus->children; + bus->children = child; + child->bridge = device; + child->parent = bus; + + #ifndef PCI_DONOT_MODIFY + /* + * Set up the primary, secondary and subordinate bus numbers. + */ + max = max + 1; + child->number = (unsigned char)max; + child->primary = bus->secondary; + child->secondary = (unsigned char)max; + child->subordinate = 0xFF; + /* + * clear all status bits and turn off memory, I/O and master enables. + */ + pcibios_write_config_dword(bus->number, _DEVICE_FN(i, 0), 0x04, 0xffff0000); + /* + * configure the bus numbers for this bridge. + */ + pcibios_read_config_dword(bus->number, _DEVICE_FN(i, 0), 0x18, &buses); + buses = buses & 0xff000000; + buses = buses | (unsigned int)(child->primary) | + ((unsigned int)(child->secondary) << 8) | + ((unsigned int)(child->subordinate) << 16); + pcibios_write_config_dword(bus->number, _DEVICE_FN(i, 0), 0x18, buses); + /* + * scan all subordinate buses. + */ + max = pcibios_scan_bus(child, 0, PCI_21050_MAX_DEVICES); + /* + * Set the subordinate bus number to it's real value. + */ + child->subordinate = (unsigned char)max; + buses = (buses & 0xff00ffff) | ((unsigned int)(child->subordinate) << 16); + pcibios_write_config_dword(bus->number, _DEVICE_FN(i, 0), 0x18, buses); + #endif + } + } + } + /* + * We've scanned the bus and so we know all about what's on the other + * side of any bridges that may be on this bus plus any devices. + * + * Return how far we've got finding sub-buses. + */ + return max; + } + + /************************************************************************** + * pcibios_show_device() * + **************************************************************************/ + static void pcibios_show_device(PCIDevice_t *device) + { + printf("PCI slot %d, vendor = 0x%X, device = 0x%X, IRQ = %d\n", device->slot, + device->vendor, device->device, device->irq); + #ifdef PCIDEBUG + printf("\tat address %X\n", device); + printf("\tparent = %X, sibling = %X, next = %X\n", device->parent, + device->sibling, device->next); + #endif + printf("\tPCI IO Base = 0x%X, PCI Memory Base = 0x%X\n", + device->PCI_IO_Base, device->PCI_Mem_Base); + switch (device->class) { + case 0x000000: + printf("\tNon-VGA compatible device\n"); + break; + case 0x000100: + printf("\tVGA compatible device\n"); + break; + case 0x010000: + printf("\tSCSI bus controller\n"); + break; + case 0x010100: + printf("\tIDE controller\n"); + break; + case 0x010200: + printf("\tFloppy disk controller\n"); + break; + case 0x020000: + printf("\tEthernet controller\n"); + break; + case 0x030000: + printf("\tVGA compatible controller\n"); + break; + case 0x038000: + printf("\tDisplay controller\n"); + break; + case 0x060100: + printf("\tISA bridge\n"); + break; + case 0x060400: + printf("\tPCI-PCI bridge\n"); + break; + } + if (device->print != NULL) + (device->print)(device); + } + + /************************************************************************** + * pcibios_show_bus() * + **************************************************************************/ + static void pcibios_show_bus(PCIBus_t *bus) + { + PCIDevice_t *device; + PCIBus_t *child; + + printf("\n"); + #ifdef PCIDEBUG + printf("Bus = %d (address = %X)\n", bus->number, bus); + printf("\tprimary = %d, secondary = %d, subordinate = %d\n", + bus->primary, bus->secondary, bus->subordinate); + printf("\tbridge = %X\n", bus->bridge); + printf("\tchildren = %X, next = %X\n", bus->children, bus->next); + printf("\tPCI I/O space = %X, PCI Mem space = %X\n", + bus->PCI_IO_Size, bus->PCI_Mem_Size); + printf("\tPCI I/O base = %X, PCI Mem base = %X\n", + bus->PCI_IO_Base, bus->PCI_Mem_Base); + #else + printf("Bus = %d\n", bus->number); + printf("\tprimary = %d, secondary = %d, subordinate = %d\n", + bus->primary, bus->secondary, bus->subordinate); + printf("\tPCI I/O space = %X, PCI Mem space = %X\n", + bus->PCI_IO_Size, bus->PCI_Mem_Size); + printf("\tPCI I/O base = %X, PCI Mem base = %X\n", + bus->PCI_IO_Base, bus->PCI_Mem_Base); + #endif + /* + * Show all the devices on this bus. + */ + device = bus->devices; + while (device != NULL) { + pcibios_show_device(device); + device = device->next; + } + /* + * Show all of the sub-buses. + */ + child = bus->children; + while (child != NULL) { + pcibios_show_bus(child); + child = child->next; + } + printf("\n"); + } + + /*+-------------------------------------------------------------------------------------+ + | | + | The following routines can be called by external modules. Their interface and | + | functionality exactly matches that of the Intel equivalent BIOS code and callbacks. | + | | + /*+-------------------------------------------------------------------------------------+*/ + /************************************************************************** + * bios32_init() * + **************************************************************************/ + unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end) + { + unsigned int max_device; + + #ifdef PCI_DONOT_MODIFY + printf("...NOT modifying existing (SRM) PCI configuration\n"); + #endif + /* + * Init the device allocation pointers + * incase the monitor is restarted. + */ + free_memory = memory_start; + if ((free_memory & 0x7) != 0) + free_memory += 8 - (free_memory & 0x7); /* align to an 8 byte boundary */ + devices = NULL; + + /* + * Allocate the first bus (there's at least one!) + */ + root = pcibios_allocate_bus(); + root->number = root->primary = root->secondary = 0; + /* + * And then scan it and all it's sub-buses. + */ + if _APECS_PCI + max_device = 21; + else + max_device = 10; + root->subordinate = (unsigned char)pcibios_scan_bus(root, 0, max_device); + /* + * Now scan the tree allocating PCI memory and I/O space. + */ + pcibios_allocate_space(root); + /* + * For debug purposes, print out what we found. + */ + pcibios_show_bus(root); + /* + * Return a pointer to above the last memory that we used. + */ + if ((free_memory & 0x7) != 0) + free_memory += 8 - (free_memory & 0x7); /* align to an 8 byte boundary */ + + return free_memory; + } + + /************************************************************************** + * pcibios_present() * + **************************************************************************/ + /* + * Note: this routine appears twice, and returns a different value depending + * on whether PCI was configured into the system or not. + */ + int pcibios_present(void) + { + return 1; + } + + /************************************************************************** + * pcibios_find_device() * + **************************************************************************/ + /* + * Given the vendor and device ids, find the n'th instance of that device + * in the system. + * + */ + int pcibios_find_device (unsigned short vendor, unsigned short device_id, + unsigned short index, unsigned char *bus, unsigned char *device_fn) + { + unsigned short current; + + PCIDevice_t *PCIDevice = devices; + current = 0; + + while (PCIDevice != NULL) { + if ((PCIDevice->vendor == vendor) && (PCIDevice->device == device_id)) { + if (current == index) { + /* + * We have found it. + */ + *device_fn = 0x00; + *device_fn |= (_PCI_Slot(PCIDevice) << 3) & 0xf8; + *bus = _PCI_Bus(PCIDevice); + return PCIBIOS_SUCCESSFUL; + } + current++; + } + PCIDevice = PCIDevice->sibling; + } + /* + * Failed, return an error. + */ + return PCIBIOS_DEVICE_NOT_FOUND; + } + + /************************************************************************** + * pcibios_find_class() * + **************************************************************************/ + /* + * Given the class, find the n'th instance of that device + * in the system. + * + */ + int pcibios_find_class (unsigned long class_code, unsigned short index, + unsigned char *bus, unsigned char *device_fn) + { + unsigned short current; + + PCIDevice_t *PCIDevice = devices; + current = 0; + + while (PCIDevice != NULL) { + if (PCIDevice->class == class_code) { + if (current == index) { + /* + * We have found it. + */ + *device_fn = 0x00; + *device_fn |= (_PCI_Slot(PCIDevice) << 3) & 0xf8; + *bus = _PCI_Bus(PCIDevice); + return PCIBIOS_SUCCESSFUL; + } + current++; + } + PCIDevice = PCIDevice->sibling; + } + /* + * Failed, return an error. + */ + return PCIBIOS_DEVICE_NOT_FOUND; + } + + /************************************************************************** + * pcibios_strerror() * + **************************************************************************/ + char *pcibios_strerror (int error) + { + static char buf[80]; + + switch (error) { + case PCIBIOS_SUCCESSFUL: + return "SUCCESSFUL"; + + case PCIBIOS_FUNC_NOT_SUPPORTED: + return "FUNC_NOT_SUPPORTED"; + + case PCIBIOS_BAD_VENDOR_ID: + return "SUCCESSFUL"; + + case PCIBIOS_DEVICE_NOT_FOUND: + return "DEVICE_NOT_FOUND"; + + case PCIBIOS_BAD_REGISTER_NUMBER: + return "BAD_REGISTER_NUMBER"; + + default: + sprintf (buf, "UNKNOWN RETURN 0x%x", error); + return buf; + } + } + + /************************************************************************** + * pcibios_read_config_byte() * + **************************************************************************/ + int pcibios_read_config_byte(unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned char *value) + { + unsigned int slot, function; + unsigned int command; + + slot = (device_fn & 0xf8) >> 3; + function = (device_fn & 0x07); + + /* + * Build the appropriate configuration command. + */ + _CREATE_CONFIGURATION_COMMAND(command, bus, slot, function, where); + /* + * Now issue it. + */ + _SELECT_CONFIG_CYCLE(bus); /* type 0 or type 1? */ + *value = (*alpha_inb)(command, alpha_cfg_base); + + return PCIBIOS_SUCCESSFUL; + } + /************************************************************************** + * pcibios_read_config_word() * + **************************************************************************/ + int pcibios_read_config_word (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned short *value) + { + unsigned int slot, function; + unsigned int command; + + slot = (device_fn & 0xf8) >> 3; + function = (device_fn & 0x07); + + /* + * Build the appropriate configuration command. + */ + _CREATE_CONFIGURATION_COMMAND(command, bus, slot, function, where); + /* + * Now issue it. + */ + _SELECT_CONFIG_CYCLE(bus); /* type 0 or type 1? */ + *value = (*alpha_inw)(command, alpha_cfg_base); + + return PCIBIOS_SUCCESSFUL; + } + /************************************************************************** + * pcibios_read_config_dword() * + **************************************************************************/ + int pcibios_read_config_dword (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned long *value) + { + unsigned int slot, function; + unsigned int command; + + slot = (device_fn & 0xf8) >> 3; + function = (device_fn & 0x07); + + #ifdef DEBUG + printf("...read_config_dword: bus = %d, function = %d, slot = %d, where = 0x%X\n", + bus, function, slot, where); + #endif + + /* + * Build the appropriate configuration command. + */ + _CREATE_CONFIGURATION_COMMAND(command, bus, slot, function, where); + #ifdef DEBUG + printf("...command = 0x%X\n", command); + #endif + /* + * Now issue it. + */ + #ifdef DEBUG + printf("...selecting config cycle\n"); + #endif + _SELECT_CONFIG_CYCLE(bus); /* type 0 or type 1? */ + #ifdef DEBUG + printf("...issuing configuration cycle\n"); + printf("...alpha_cfg_base = %X %X\n", alpha_cfg_base >> 32, alpha_cfg_base); + #endif + *value = (*alpha_inl)(command, alpha_cfg_base); + + return PCIBIOS_SUCCESSFUL; + } + + /************************************************************************** + * pcibios_write_config_byte() * + **************************************************************************/ + int pcibios_write_config_byte (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned char value) + { + unsigned int slot, function; + unsigned int command; + + slot = (device_fn & 0xf8) >> 3; + function = (device_fn & 0x07); + + /* + * Build the appropriate configuration command. + */ + _CREATE_CONFIGURATION_COMMAND(command, bus, slot, function, where); + /* + * Now issue it. + */ + _SELECT_CONFIG_CYCLE(bus); /* type 0 or type 1? */ + (*alpha_outb)(value, command, alpha_cfg_base); + + return PCIBIOS_SUCCESSFUL; + } + /************************************************************************** + * pcibios_write_config_word() * + **************************************************************************/ + int pcibios_write_config_word (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned short value) + { + unsigned int slot, function; + unsigned int command; + + slot = (device_fn & 0xf8) >> 3; + function = (device_fn & 0x07); + + /* + * Build the appropriate configuration command. + */ + _CREATE_CONFIGURATION_COMMAND(command, bus, slot, function, where); + /* + * Now issue it. + */ + _SELECT_CONFIG_CYCLE(bus); /* type 0 or type 1? */ + (*alpha_outw)(value, command, alpha_cfg_base); + + return PCIBIOS_SUCCESSFUL; + } + /************************************************************************** + * pcibios_write_config_dword() * + **************************************************************************/ + int pcibios_write_config_dword (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned long value) + { + unsigned int slot, function; + unsigned int command; + + slot = (device_fn & 0xf8) >> 3; + function = (device_fn & 0x07); + + #ifdef DEBUG + printf("...write_config_dword: bus = %d, function = %d, slot = %d\n", + bus, function, slot); + #endif + + /* + * Build the appropriate configuration command. + */ + _CREATE_CONFIGURATION_COMMAND(command, bus, slot, function, where); + /* + * Now issue it. + */ + _SELECT_CONFIG_CYCLE(bus); /* type 0 or type 1? */ + (*alpha_outl)(value, command, alpha_cfg_base); + + return PCIBIOS_SUCCESSFUL; + } + + #else + /************************************************************************** + * pcibios_present() * + **************************************************************************/ + /* + * Note: this routine appears twice, and returns a different value depending + * on whether PCI was configured into the system or not. + */ + int pcibios_present(void) + { + return 0; + } + #endif + + + diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/boot_main.c LINUX_ALPHA_SDK/sources/linux/miniloader/boot_main.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/boot_main.c Thu Feb 9 19:57:36 1995 --- LINUX_ALPHA_SDK/sources/linux/miniloader/boot_main.c Wed Feb 8 09:34:13 1995 *************** *** 0 **** --- 1,789 ---- + #include + #include + #include "miniboot.h" + #include + #include "uart.h" + #include "impure.h" + + #ifndef NULL + #define NULL ((void *)0) + #endif + + + /***************************************************************************** + * Global variables. * + *****************************************************************************/ + /* + * memory allocation + */ + volatile unsigned int firstpfn = 0; + volatile unsigned int lastpfn = 0; + volatile unsigned int lastfree = 0; + volatile unsigned int firstfree = 0; + unsigned int npages = 0; + + /* + * memory mapping + */ + unsigned int ptbr = 0; + unsigned long long vptbr = 0; + PCB boot_pcb; + PCB * pboot_pcb; + + /* + * Counting stuff. + */ + unsigned int num_l2_pages = 0; + unsigned int num_l3_pages = 0; + + /***************************************************************************** + * Macros. * + *****************************************************************************/ + #ifndef TRUE + #define TRUE 1 + #endif + #ifndef FALSE + #define FALSE 0 + #endif + + #define _ALLOCATE_PFN() allocate_pfn() + + #define _PFN_TO_PHYSICAL(pfn) ((unsigned long long)((pfn) << ALPHA_PG_SHIFT)) + #define _PHYSICAL_TO_PFN(physical) ((physical) >> ALPHA_PG_SHIFT) + + #define PASS1_LCA_TYPE 0x100000004ULL /* Pass 1 LCA chip detect */ + + U64 dispatch_block[4]; + + extern U64 system_type; + extern U64 alpha_io_base; + extern U64 alpha_mem_base; + #ifdef CONFIG_PCI + extern U64 alpha_cfg_base; + #endif + + /***************************************************************************** + * Utility routines * + *****************************************************************************/ + /* + * Allocate many free pages in contiguous ascending physical memory. + */ + unsigned int allocate_many_pfn(unsigned int count) + { + unsigned int pfn = 0; + + if (npages < count) { + printf("...Fatal error: not enough memory\n"); + halt(); + } else { + /* + * Take it from the bottom. + */ + pfn = firstfree; + firstfree += count; + npages -= count; + } + return pfn; + } + /* + * Allocate a free page. + */ + unsigned int allocate_pfn() + { + unsigned int pfn = 0; + + if (npages == 0) { + printf("...Fatal error: not enough memory\n"); + halt(); + } else { + /* + * Take it from the bottom. + */ + if (npages > 0) { + pfn = firstfree++; + npages--; + } + } + return pfn; + } + /* + * Given all of the information, build a valid PTE. + */ + unsigned long long build_pte(unsigned int pfn, unsigned int protection) + { + PTE pte; + + pte.pg_quadword = (U64)0; /* Start with a clean PTE */ + pte.pg_v = 1; /* Page is valid */ + pte.pg_prot = protection; + pte.pg_pfnum = pfn; + + return (unsigned long long) pte.pg_quadword; + } + + /* + * Given a VA, make a set of page table entries for it (if they + * don't already exist). + * + * Args: + * + * va virtual address to add page table entries for. + * vpfn the PFN that the virtual address is to be mapped to. + * protection the protection to set the L3 page table entry to (all L1 and + * L2 pages are marked as Kernel read/write). + */ + void add(unsigned long long va, unsigned int vpfn, unsigned int protection) + { + unsigned long long l1, l2, l3; + unsigned int pfn, newpfn; + unsigned long long pa; + PTE pte; + + /* + * Dismantle the VA. + */ + l1 = 0; + l2 = L2PT_OFFSET(va); + l3 = L3PT_OFFSET(va); + + #ifdef NEVER + printf("...Adding PTEs for virtual address 0x%X, pfn = %X\n", va, vpfn); + #endif + /* + * Now build a set of entries for it (if they do not already + * exist). In the next blocks of code, pfn is always the pfn of + * the current entry and newpfn is the pfn that is referenced from + * it. + */ + /* + * L1. The L1 PT PFN is held in the global integer ptbr. + */ + pa = _PFN_TO_PHYSICAL(ptbr) + l1; + if (ReadQ(pa) == 0) { + newpfn = _ALLOCATE_PFN(); /* for L2 */ + num_l2_pages++; + #ifdef NEVER + printf("\tAllocated L2 page table at PFN 0x%X (physical = 0x%X)\n", + newpfn, _PFN_TO_PHYSICAL(newpfn)); + #endif + zeropage_phys(newpfn); + pte.pg_quadword = build_pte(newpfn, PG_KERNEL_RW); + WriteQ(pa,pte.pg_quadword); + } else + pte.pg_quadword = ReadQ(pa); + #ifdef NEVER + printf("L1 PTE at PFN(%d) + 0x%04X = 0x%X\n", + ptbr, l1, ReadQ(pa)); + #endif + pfn = pte.pg_pfnum; + + /* + * L2, pfn inherited from L1 entry (which may have been allocated + * above). + */ + pa = _PFN_TO_PHYSICAL(pfn) + l2; + if (ReadQ(pa) == 0) { + num_l3_pages++; + newpfn = _ALLOCATE_PFN(); + #ifdef NEVER + printf("\tAllocated L3 page table at PFN 0x%X (physical = 0x%X)\n", + newpfn, _PFN_TO_PHYSICAL(newpfn)); + #endif + zeropage_phys(newpfn); + pte.pg_quadword = build_pte(newpfn, PG_KERNEL_RW); + WriteQ(pa, pte.pg_quadword); + } else + pte.pg_quadword = ReadQ(pa); + #ifdef NEVER + printf("L2 PTE at PFN(%d) + 0x%04X = 0x%X\n", + pfn, l2, ReadQ(pa)); + #endif + pfn = pte.pg_pfnum; + + /* + * L3, pfn inherited from L2 entry above. vpfn contains the page frame + * number of the real thing whose PTEs we have just invented above. + */ + pa = _PFN_TO_PHYSICAL(pfn) + l3; + if (ReadQ(pa) == 0) { + pte.pg_quadword = build_pte(vpfn, protection); + WriteQ(pa, pte.pg_quadword); + } else + pte.pg_quadword = ReadQ(pa); + #ifdef NEVER + printf("L3 PTE at PFN(%d) + 0x%04X = 0x%X\n", + pfn, l3, ReadQ(pa)); + #endif + } + + /* + * System specific routine that returns the top of memory (ie the + * amount of physical memory in the system). + */ + #define CSERVE_K_RD_IMPURE 0x0B + + unsigned int memory_size(void) + { + unsigned long long PalImpureBase; + + /* + * HACK ALERT! EB66 mem size is at 368 and the EB64+ is at 350 + */ + PalImpureBase = (unsigned long long) (CNS_Q_BASE + cServe(0, 0, CSERVE_K_RD_IMPURE)); + return (unsigned int)ReadQ(PalImpureBase + (unsigned long long) 0x368) ; + } + + /***************************************************************************** + * Main entry point for system primary bootstrap code * + *****************************************************************************/ + /* + * + * At this point we have been loaded into memory at LOADER_AT and we are running in Kernel + * mode. The Kernal stack base is at the top of memory (wherever that is). Assume that it + * takes up two 8K pages. We are running 1-to-1 memory mapping (ie physical). + */ + boot_main() + { + unsigned int MemoryTop; + unsigned int MemoryBottom; + unsigned int va, pa; + unsigned int pfn; + + int i; + + PTE pte; + + unsigned int n_kseg_pages; + unsigned int ptes_per_page = (ALPHA_PAGE_SIZE/sizeof(PTE)); + + unsigned int kernel_pages; + unsigned int text_pages; + unsigned int total_pages; + FILEHDR *fh; + AOUTHDR *ah; + SCNHDR *sh; + unsigned int nbytes; + unsigned long long offset; + + CRB *crb; + HWRPB *hwrpb; + RPB_PERCPU *percpu; + + char os_name[64]; + + unsigned int linux_pa; + + unsigned char *entry; + int ramdisk_pages; + char *ramdisk_addr; + + char *linux_addr; + + char boot_flags[32]; + + U64 *kernel_args; + + U64 *dispatcher_args; + + /***************************************************************************** + * Initialize. * + *****************************************************************************/ + /* + * First initialize the Evaulation Board environment. + */ + num_l2_pages = num_l3_pages = 0; + + wrfen(); + cpu_init(); + pboot_pcb = &boot_pcb; + + strcpy(boot_flags, "A"); + /* + * Now, announce ourselves. + */ + printf("\nLinux/Alpha Evaluation Board bootstrap\n\n"); + + /* + * Raise the IPL so that no interrupts can occur + */ + printf("...raising ipl from %d to 7\n",ipl(7)); + + /***************************************************************************** + * Work out how much memory there is. * + *****************************************************************************/ + /* + * Note that none of the addresses passed in are OSF or LINUX KSEG addresses. + */ + printf("Moving parts of the image to more convenient locations\n"); + MemoryBottom = DISPATCH_AT + DISPATCH_SIZE; + MemoryTop = memory_size(); + firstpfn = 0; + lastpfn = _PHYSICAL_TO_PFN(MemoryTop - ALPHA_PAGE_SIZE); + + /* + * Work out where the start and end of free memory is. This depends on + * what the miniloader image has got in it... + */ + #ifdef RAMDISK_AT + /* + * We put the RAMdisk into the very top of memory. + */ + #ifdef BOOT_VERBOSE + printf("...copying the RAMdisk to the top of memory (0x%X)\n", + MemoryTop - RAMDISK_SIZE ); + #endif + memcpy(MemoryTop - RAMDISK_SIZE, RAMDISK_AT, RAMDISK_SIZE); + MemoryTop = MemoryTop - RAMDISK_SIZE; + ramdisk_addr = MemoryTop; + #endif + + #ifdef LINUX_AT + /* + * The kernel is in memory at LINUX_AT. Copy it to the top of + * free memory. As we allocate pages from the bottom of memory upwards + * then this will not be overwritten until the Linux Kernel gets its hands + * it. I hope. + */ + linux_addr = MemoryTop - LINUX_SIZE; + #ifdef BOOT_VERBOSE + printf("...moving the in memory Linux Kernel out of the way "); + printf("(0x%X bytes from 0x%X to 0x%X)\n", + LINUX_SIZE, LINUX_AT, linux_addr); + #endif + memcpy(linux_addr, LINUX_AT, LINUX_SIZE); + #endif + + /* + * At this point we know where the top and bottom of memory are and what + * of that we can allocate for our own use and make available to Linux. + */ + + printf("Working out how much free memory there is\n"); + #ifdef BOOT_VERBOSE + printf("...Free memory between 0x%X and 0x%X\n", MemoryBottom, MemoryTop); + printf("...Loader in memory @ 0x%X\n", LOADER_AT); + printf("...Dispatcher in memory @ 0x%X\n", DISPATCH_AT); + #ifdef LINUX_AT + printf("...Linux kernel in memory @ 0x%X\n", linux_addr); + #endif + #ifdef RAMDISK_AT + printf("...Ramdisk in memory @ 0x%X\n", ramdisk_addr); + #endif + #endif + + lastfree = _PHYSICAL_TO_PFN(MemoryTop - ALPHA_PAGE_SIZE); + firstfree = _PHYSICAL_TO_PFN(MemoryBottom); + npages = lastpfn - firstpfn + 1; + #ifdef BOOT_VERBOSE + printf("...%d free pages, first = 0x%X, last = 0x%X\n", npages, firstfree, lastpfn); + #endif + + /* + * RAMDISK. + * We have to pass a Linux KSEG address (70000000+) to the kernel, so convert + * ramdisk_addr into one. + */ + #ifdef RAMDISK_AT + ramdisk_addr = KSEG_ADDRESS(ramdisk_addr); + ramdisk_pages = _PHYSICAL_TO_PFN(RAMDISK_SIZE); + printf("...RAMdisk is @ LINUX KSEG 0x%X\n", ramdisk_addr); + #endif + + /***************************************************************************** + * Startup any device drivers required * + *****************************************************************************/ + + #ifdef CONFIG_PCI + printf("Configuring PCI\n"); + pfn = _ALLOCATE_PFN(); + zeropage_phys(pfn); + bios32_init(_PFN_TO_PHYSICAL(pfn), _PFN_TO_PHYSICAL(pfn) + ALPHA_PAGE_SIZE); + #endif + + /***************************************************************************** + * Build the Page Tables (Part 1) * + *****************************************************************************/ + /* + * We are running with mapping 1-to-1 physical. Before we can turn on memory + * mapping we must set up the PTEs that we need. + */ + printf("Building the Page Tables\n"); + ptbr = _ALLOCATE_PFN(); + zeropage_phys(ptbr); + printf("...L1 PT (ptbr) at PFN 0x%X, physical address 0x%X\n", + ptbr, _PFN_TO_PHYSICAL(ptbr)); + + /* + * Linux Kernel stack. This is laid out (ascending) as a guard page + * followed by n pages of stack. We initialize it in ascending va order. + */ + printf("...building kernel stack pages\n"); + + /* guard page */ + va = KERNEL_INITIAL_SP-KERNEL_INITIAL_STACKSIZE-ALPHA_PAGE_SIZE; + pfn = _ALLOCATE_PFN(); + zeropage_phys(pfn); + add(va, pfn, PG_NOACCESS); + + /* stack pages */ + va += ALPHA_PAGE_SIZE; + for(i = 0; i < _PHYSICAL_TO_PFN(KERNEL_INITIAL_STACKSIZE); i++) { + pfn = _ALLOCATE_PFN(); + zeropage_phys(pfn); + add(va, pfn, PG_KERNEL_RW); + va += ALPHA_PAGE_SIZE; + } + + /* + * Set up our mini KSEG. Map all of the pages in the system to address + * LINUX_KSEG_VADDR upwards. + */ + n_kseg_pages = (lastpfn+ptes_per_page-1)/ptes_per_page; + printf("...Setting up mini-KSEG map... %d pages req'd\n", n_kseg_pages); + va = LINUX_KSEG_VADDR; + for (pfn = 0; pfn < lastpfn; pfn++) { + add(va, pfn, PG_KERNEL_RW); + va += ALPHA_PAGE_SIZE; + } + + /***************************************************************************** + * Set up a dummy HWRPB at the appropriate VA * + *****************************************************************************/ + + printf("Building a HWRPB and setting up the dispatcher\n"); + + /* allocate it */ + pfn = _ALLOCATE_PFN(); + zeropage_phys(pfn); + add(HWRPB_SYSTEM_VADDR, pfn, PG_KERNEL_RW); + + /* fill it out */ + hwrpb = (HWRPB *)_PFN_TO_PHYSICAL(pfn); + hwrpb->rpb_size = sizeof(HWRPB); + hwrpb->rpb_systype = system_type; + hwrpb->rpb_clkint_freq = 977 * 4096; + + percpu = (RPB_PERCPU *) ((long)hwrpb + hwrpb->rpb_percpu_slot_offset); + percpu->rpb_proctype = ~PASS1_LCA_TYPE; + + /* put the CRB a distance up the page */ + crb = (CRB *)((char *)hwrpb + (ALPHA_PAGE_SIZE / 2)); + + dispatch_block[0] = 0; + dispatch_block[1] = KSEG_ADDRESS(DISPATCH_AT); + dispatch_block[2] = 0; + dispatch_block[3] = KSEG_ADDRESS(DISPATCH_AT); + + crb->crb_dispatch_va = KSEG_ADDRESS((unsigned long long)&dispatch_block); + crb->crb_dispatch_pa = KSEG_ADDRESS((unsigned long long)&dispatch_block); + crb->crb_fixup_va = (unsigned long long)0; + crb->crb_fixup_pa = (unsigned long long)0; + + hwrpb->rpb_crb_offset = (char *)crb - (char *)hwrpb; + + printf("...dispatch block is @0x%X, dispatch routine @0x%X\n", + crb->crb_dispatch_va, dispatch_block[1]); + + dispatcher_args = DISPATCH_AT - (4 * sizeof(U64)); + dispatcher_args[0] = system_type; + dispatcher_args[1] = alpha_io_base; + dispatcher_args[2] = alpha_mem_base; + dispatcher_args[3] = alpha_cfg_base; + + /***************************************************************************** + * Load Linux off of the disk * + *****************************************************************************/ + /* + * As a hack (Hack alert!) assume that the linux image has been loaded into + * memory (real memory at linux_addr). + */ + printf("\nAttempting to load Linux\n\n"); + fh = (FILEHDR *)linux_addr; + ah = (AOUTHDR *)(linux_addr + sizeof(FILEHDR)); + + #ifdef BOOT_VERBOSE + printf("...filehdr @0x%x, fh->f_opthdr = 0x%x, aouthdr @0x%x\n", + fh, fh->f_opthdr, ah); + printf(" f_magic: 0x%x, f_nscns: 0x%x, f_timdat: 0x%x\n", + fh->f_magic, fh->f_nscns, fh->f_timdat); + printf(" f_symptr: 0x%x%08x, f_nsyms: 0x%x\n", + (fh->f_symptr>>32)&0xffffffff, fh->f_symptr&0xffffffff, + fh->f_nsyms); + printf(" f_opthdr: 0x%x, f_flags: 0x%x\n", + fh->f_opthdr, fh->f_flags); + + printf("...aouthdr fields:\n"); + printf(" magic: 0%o, vstamp: 0x%x, bldrev: 0x%x, padcell: 0x%x\n", + ah->magic, ah->vstamp, ah->bldrev, ah->padcell); + printf(" text_start: %x%08x, ", (ah->text_start>>32) & 0xffffffff, ah->text_start&0xffffffff); + printf(" tsize: %x%08x\n", (ah->tsize>>32) & 0xffffffff, ah->tsize&0xffffffff); + printf(" data_start: %x%08x, ", (ah->data_start>>32) & 0xffffffff, ah->data_start&0xffffffff); + printf(" dsize: %x%08x\n", (ah->dsize>>32) & 0xffffffff, ah->dsize&0xffffffff); + printf(" bss_start: %x%08x, ", (ah->bss_start>>32) & 0xffffffff, ah->bss_start&0xffffffff); + printf(" bsize: %x%08x\n", (ah->bsize>>32) & 0xffffffff, ah->bsize&0xffffffff); + printf(" entry: %x%08x\n", (ah->entry>>32) & 0xffffffff, ah->entry&0xffffffff); + printf(" gprmask: 0x%x, fprmask: 0x%x, gp_value: 0x%x%08x\n", + ah->gprmask, ah->fprmask, + (ah->gp_value>>32)&0xffffffff, ah->gp_value&0xffffffff); + #endif + /* Do some sanity checks... */ + if(fh->f_magic != ALPHAMAGIC) { + printf("Bad filehdr magic number 0x%x should be 0x%x\n", + fh->f_magic, ALPHAMAGIC); + halt(); + } + if((ah->magic != OMAGIC) && (ah->magic != ZMAGIC)) { + printf("Bad aouthdr magic number 0x%x should be 0x%x\n", + ah->magic, OMAGIC); + halt(); + } + if(ah->text_start != KERNEL_START_VADDR) { + printf("Kernel must start at virtual address 0x%x, not 0x%x\n", + KERNEL_START_VADDR, ah->text_start); + halt(); + } + + /* Generate page tables for the kernel. */ + kernel_pages = (ah->tsize + ah->dsize + ah->bsize + ALPHA_PAGE_SIZE - 1) >> ALPHA_PG_SHIFT; + + if(kernel_pages > npages) { + printf("Not enough physical memory for kernel; need %d pages, have %d\n", kernel_pages, npages); + halt(); + } + text_pages = (ah->tsize + ALPHA_PAGE_SIZE - 1) >> ALPHA_PG_SHIFT; + + /* save the entry point */ + entry = ah->entry; + + #ifdef BOOT_VERBOSE + printf("First block loaded; kernel uses %d page(s)\n", kernel_pages); + printf(" Text: 0x%x - 0x%x\n", ah->text_start, ah->text_start + ah->tsize - 1); + printf(" Data: 0x%x - 0x%x\n", ah->data_start, ah->data_start + ah->dsize - 1); + printf(" BSS: 0x%x - 0x%x\n", ah->bss_start, ah->bss_start + ah->bsize - 1); + #endif + + /* + * Allocate and zero pages for the kernel. + */ + printf("...Allocating and zeroing %d pages for the Linux Kernel\n", + kernel_pages); + va = KERNEL_START_VADDR; + total_pages = kernel_pages; + /* allocate lots of PFNs, the number returned is the lowest one */ + pfn = allocate_many_pfn(kernel_pages); + linux_pa = _PFN_TO_PHYSICAL(pfn); + while (kernel_pages--) { + unsigned int protection; + + if (text_pages != 0) { + text_pages--; + protection = PG_KERNEL_RW; /* HACK ALERT, should be READ only */ + } else + protection = PG_KERNEL_RW; + + zeropage_phys(pfn); + add(va, pfn, protection); + + pfn++; + va += ALPHA_PAGE_SIZE; + } + /* + * Hack alert! Set up at page table entries for one kernel code page + * and for one kernel utility page so that the following code can work. + */ + printf("...allocating a page at VA = 0x%X\n", KUTIL_START_VADDR); + pfn = _ALLOCATE_PFN(); + zeropage_phys(pfn); + add(KUTIL_START_VADDR, pfn, PG_KERNEL_RW); + + /* Now copy Linux into the pages allocated and readied. */ + sh = (SCNHDR *)(linux_addr + sizeof(FILEHDR) + sizeof(AOUTHDR)); + offset = sh->s_scnptr; + #ifdef BOOT_VERBOSE + printf("Text segment offset @0x%x (%d)\n", offset, offset); + #endif + + printf("...copying the Kernel into virtual memory\n"); + #ifdef BOOT_VERBOSE + printf("...copying %d bytes from 0x%X to 0x%X\n", ah->tsize + ah->dsize, + linux_addr + offset, linux_pa); + #endif + memcpy(linux_pa, (char *)linux_addr + offset, ah->tsize + ah->dsize); + + /***************************************************************************** + * Build the Page Tables (Part 2) * + *****************************************************************************/ + /* + * Map the page tables themselves into virtual memory. This must happen *after* + * we've set up the kernel code and kernel utility address spaces as otherwise the + * page tables will not exist. + * + * Note that the virtual addresses for particular page tables are constrained + * to be: + * + * Page Table Virtual Address + * + * L1 SYSTEM_L1PT_VADDR 0x7ff78000 + * L2 SYSTEM_L2PT_VADDR 0x7ff7a000 + * L3 Kernel code KCODE_L3PT_VADDR 0x7ff7c000 + * L3 Kernel util KUTIL_L3PT_VADDR 0x7ff7e000 + * + * As my page table building code allocates page tables as and when they are + * needed, they are not neccessarily in the above order and so they must be + * located using sleight of hand. + */ + printf("Mapping page tables into virtual address space\n"); + + /* L1 is easy */ + add(SYSTEM_L1PT_VADDR, ptbr, PG_KERNEL_RW); + #ifdef BOOT_VERBOSE + printf("...Kernel page tables: L1 @0x%X, ", _PFN_TO_PHYSICAL(ptbr)); + #endif + + /* L2 is relatively easy */ + pte.pg_quadword = ReadQ(_PFN_TO_PHYSICAL(ptbr)); + pfn = pte.pg_pfnum; + add(SYSTEM_L2PT_VADDR, pfn, PG_KERNEL_RW); + #ifdef BOOT_VERBOSE + printf("L2@0x%X, ", _PFN_TO_PHYSICAL(pfn)); + #endif + + /* L3 kernel code - now it gets tricky */ + pte.pg_quadword = ReadQ(_PFN_TO_PHYSICAL(ptbr)); + pfn = pte.pg_pfnum; /* L2 pfn */ + pte.pg_quadword = ReadQ(_PFN_TO_PHYSICAL(pfn) + L2PT_OFFSET(KERNEL_START_VADDR)); + pfn = pte.pg_pfnum; /* L3 pfn */ + add(KCODE_L3PT_VADDR, pfn, PG_KERNEL_RW); + #ifdef BOOT_VERBOSE + printf("L3C@0x%X, ", _PFN_TO_PHYSICAL(pfn)); + #endif + + /* L3 kernel util - now it gets tricky */ + pte.pg_quadword = ReadQ(_PFN_TO_PHYSICAL(ptbr)); + pfn = pte.pg_pfnum; /* L2 pfn */ + pte.pg_quadword = ReadQ(_PFN_TO_PHYSICAL(pfn) + L2PT_OFFSET(KUTIL_START_VADDR)); + pfn = pte.pg_pfnum; /* L3 pfn */ + add(KUTIL_L3PT_VADDR, pfn, PG_KERNEL_RW); + #ifdef BOOT_VERBOSE + printf("L3U@0x%X\n", _PFN_TO_PHYSICAL(pfn)); + #endif + + /* + * The virtual page table base pointer is used as a shortcut to get to the + * L3 entry for any given faulting address. It is a special entry in the L1 + * page table. As Linux only takes up the first entry then we can use the second + * entry which gives us a va of 0x200000000 for the vptbr. + */ + printf("...setting up the virtual page table base register\n"); + vptbr = (unsigned long long) 0x2 << 32; + pte.pg_quadword = build_pte(ptbr, PG_KERNEL_RW); + WriteQ(_PFN_TO_PHYSICAL(ptbr) + sizeof(pte), pte.pg_quadword); + + + #ifdef BOOT_VERBOSE + printf("...%d L2 Page Tables used, %d L3 Page Tables used\n", + num_l2_pages, num_l3_pages); + #endif + /***************************************************************************** + * Set up the Kernel calling information block * + *****************************************************************************/ + /* + * This is located below this image in memory. It is 7*8 bytes long and + * contains the following: + * + * Offset Contents + * 0*8 Linux kernel entry point + * 1*8 First free pfn + * 2*8 Last free pfn + * 3*8 last pfn + * 4*8 ramdisk address + * 5*8 ramdisk pages (each 1024 bytes long) + * 6*8 boot_flags + */ + kernel_args = (U64)LOADER_AT - (7*sizeof(U64)); + kernel_args[0] = entry; + kernel_args[1] = firstfree; + kernel_args[2] = lastfree; + kernel_args[3] = lastpfn; + kernel_args[4] = ramdisk_addr; + kernel_args[5] = (ramdisk_pages * ALPHA_PAGE_SIZE)/1024; + kernel_args[6] = KSEG_ADDRESS((U64)boot_flags); + + printf("Bootstrap complete, kernel @0x%x\n", entry); + printf(" firstpfn = 0x%X, firstfree = 0x%X, lastfree = 0x%X, lastpfn = 0x%X\n", + firstpfn, firstfree, lastfree, lastpfn); + printf(" ramdisk_addr = 0x%X, ramdisk_pages = %d\n", ramdisk_addr, + (ramdisk_pages * ALPHA_PAGE_SIZE)/1024 ); + + /***************************************************************************** + * Swap to the new page tables and jump to the Linux Kernel * + *****************************************************************************/ + + /* change context */ + printf("...turning on virtual addressing and jumping to the Linux Kernel\n"); + /* build the pcb */ + boot_pcb.pcb_ksp = KERNEL_INITIAL_SP; + boot_pcb.pcb_usp = 0; + boot_pcb.pcb_ptbr = ptbr; + boot_pcb.pcb_cc = 0; + boot_pcb.pcb_asn = 0; + boot_pcb.pcb_proc_uniq = 0; + boot_pcb.pcb_fen = 1; + /* now switch to the new scheme of things. */ + + printf("\n------------------------------------------------------------\n\n"); + switch_to_new_map_and_jump(ptbr, vptbr); + + /* + * If we ever get to this point, something has gone seriously wrong!!! + */ + printf("If you can read this, something went VERY wrong!\n"); + #ifdef NEVER + halt(); + #endif + + } + + + cons_puts(int unit, char *buf) + { + int i; + + i = 0; + while (buf[i] != '\0') uart_putchar(COM1, buf[i++]); + return i; + } + + + cons_gets(char * buf) + { + int i; + int retval; + + for(i = 0; ; i++) { + retval = uart_getchar(COM1); + retval &= 0xff; + switch(retval) { + case '\r': + case '\n': + buf[i] = '\0'; + retval = '\r'; + uart_putchar(COM1, '\n'); + return; + + case 0x08: /* BS */ + case 0x7f: /* Delete */ + if(i > 0) { + cons_puts(0, "\b \b"); + i--; + } + break; + + default: + uart_putchar(COM1, retval); + buf[i] = retval; + break; + } + } + } + diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/cpu.c LINUX_ALPHA_SDK/sources/linux/miniloader/cpu.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/cpu.c Thu Feb 9 19:57:36 1995 --- LINUX_ALPHA_SDK/sources/linux/miniloader/cpu.c Wed Feb 8 09:34:56 1995 *************** *** 0 **** --- 1,175 ---- + /* + * CPU initialization code and global data for ALPHA platforms + */ + #include + #include + #include + #include + #include + #include + + #include /* for cli()/sti() */ + #include + /* + * these globals hold pointers to the appropriate low-level routines for + * accessing bus I/O and MEMORY spaces on the current platform. they are + * used in macros defined in . + * + * the values are assigned in cpu_init(), after interrogating the HWRPB + * for the identity of the platform we arer running on. + */ + int (*alpha_inb)(int port,U64 base); + int (*alpha_inw)(int port,U64 base); + int (*alpha_inl)(int port,U64 base); + void (*alpha_outb)(int v,int port,U64 base); + void (*alpha_outw)(int v,int port,U64 base); + void (*alpha_outl)(int v,int port,U64 base); + int (*alpha_jinb)(int port,U64 base); + void (*alpha_joutb)(int v,int port,U64 base); + + /* + * these globals hold the KSEG addresses for the start of the addresse + * spaces, for the platform on which the kernel is executing. they are + * passed as values to low-level assembler routines in io.S, via macros + * defined in . + * + * the values are assigned in cpu_init(), after interrogating the HWRPB + * for the identity of the platform we arer running on. + */ + U64 alpha_io_base; + U64 alpha_mem_base; + #ifdef CONFIG_PCI + U64 alpha_cfg_base; + #endif + U64 system_type; + + /* "standard" platforms' entry points */ + extern int inb_std (int port,U64 base); + extern int inw_std (int port,U64 base); + extern int inl_std (int port,U64 base); + extern void outb_std (int v,int port,U64 base); + extern void outw_std (int v,int port,U64 base); + extern void outl_std (int v,int port,U64 base); + + extern void write_cpureg_long(int v,U64 addr); + extern int read_cpureg_long(U64 addr); + + /* + * DEC processor types for Alpha systems. Found in HWRPB. + * These values are architected. + */ + + #define EV3_CPU 1 /* EV3 */ + #define EV4_CPU 2 /* EV4 (21064) */ + #define LCA4_CPU 4 /* LCA4 (21066/21068) */ + #define EV5_CPU 5 /* EV5 (21164) */ + #define EV45_CPU 6 /* EV4.5 (21064/xxx) */ + + /* + * DEC system types for Alpha systems. Found in HWRPB. + * These values are architected. + */ + + #define ST_ADU 1 /* Alpha ADU systype */ + #define ST_DEC_4000 2 /* Cobra systype */ + #define ST_DEC_7000 3 /* Ruby systype */ + #define ST_DEC_3000_500 4 /* Flamingo systype */ + #define ST_DEC_2000_300 6 /* Jensen systype */ + #define ST_DEC_3000_300 7 /* Pelican systype */ + #define ST_DEC_2100_A500 9 /* Sable systype */ + #define ST_DEC_AXPVME_64 10 /* AXPvme system type */ + #define ST_DEC_AXPPCI_33 11 /* NoName system type */ + #define ST_DEC_TLASER 12 /* Turbolaser systype */ + #define ST_DEC_2100_A50 13 /* Avanti systype */ + #define ST_DEC_MUSTANG 14 /* Mustang systype */ + #define ST_DEC_ALCOR 15 /* Alcor systype */ + #define ST_DEC_1000 17 /* Mikasa systype */ + #define ST_DEC_EB64 18 /* EB64 */ + #define ST_DEC_EB66 19 /* EB66 */ + #define ST_DEC_EB64P 20 /* EB64+ systype */ + + cpu_init() + { + int i; + + /* + * First, save the system type. + */ + system_type = SYSTEM_TYPE; /* defined in the Makefile */ + /* + * Now do the system specific setup. + */ + switch (system_type) { + + case ST_DEC_MUSTANG: /* LCA MUSTANG */ + case ST_DEC_AXPPCI_33: /* LCA NONAME */ + case ST_DEC_2100_A50: /* APECS AVANTI/MUSTANG */ + case ST_DEC_1000: /* APECS MIKASA */ + case ST_DEC_EB66: /* EB66 */ + + /* + * init the base address global variables + */ + alpha_mem_base = 0xfffffc0200000000ULL; + + alpha_io_base = 0xfffffc01c0000000ULL; + #ifdef CONFIG_PCI + alpha_cfg_base = 0xfffffc01e0000000ULL; + #endif + + /* + * assign the transfer vectors for access routines + * to the set of "standard" entries + */ + alpha_inb = inb_std; + alpha_inw = inw_std; + alpha_inl = inl_std; + alpha_outb = outb_std; + alpha_outw = outw_std; + alpha_outl = outl_std; + + /* + * perform system specific initialization. + */ + uart_init(); + + break; + + case ST_DEC_EB64P: + + /* + * init the base address global variables + */ + alpha_mem_base = 0xfffffc0200000000ULL; + alpha_io_base = 0xfffffc01c0000000ULL; + #ifdef CONFIG_PCI + alpha_cfg_base = 0xfffffc01e0000000ULL; + #endif + + /* + * assign the transfer vectors for access routines + * to the set of "standard" entries + */ + alpha_inb = inb_std; + alpha_inw = inw_std; + alpha_inl = inl_std; + alpha_outb = outb_std; + alpha_outw = outw_std; + alpha_outl = outl_std; + + /* + * perform system specific initialization. + */ + uart_init(); + + if (system_type == ST_DEC_EB66) { + outb(0x0A, 0x70); + outb(0x26, 0x71); + outb(0x0B, 0x70); + outb(0x47, 0x71); + } + break; + default: + } + } + diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/dispatch.c LINUX_ALPHA_SDK/sources/linux/miniloader/dispatch.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/dispatch.c Thu Feb 9 19:57:36 1995 --- LINUX_ALPHA_SDK/sources/linux/miniloader/dispatch.c Wed Feb 8 09:35:30 1995 *************** *** 0 **** --- 1,123 ---- + #include + #include + #include "miniboot.h" + #include "uart.h" + + /* "standard" platforms' entry points */ + int (*alpha_inb)(int port,U64 base); + void (*alpha_outb)(int v,int port,U64 base); + + U64 alpha_io_base; + + extern int inb_std (int port,U64 base); + extern void outb_std (int v,int port,U64 base); + + void write_cpureg_long(int v,U64 addr); + int read_cpureg_long(U64 addr); + + /***************************************************************************** + * Console fixup routine * + *****************************************************************************/ + void crb_fixup() + { + #ifdef NEVER + printf("...crb fixup routine called\n"); + #endif + } + + /***************************************************************************** + * Console dispatch routine * + *****************************************************************************/ + /* + * a0 is the function code selected: + * + * 01 GETC + * 02 PUTS + * 03 RESET_TERM + * 04 SET_TERM_INT + * 05 SET_TERM_CTL + * 06 PROCESS_KEYCODE + * 07-0F Reserved + * + * 10 OPEN + * 11 CLOSE + * 12 IOCTL + * 13 READ + * 14 WRITE + * 15-1F Reserved + * + * : + * + */ + U64 crb_dispatch(U64 a0, U64 a1, U64 a2, U64 a3, U64 a4) + { + U64 result, i; + char *cptr; + U64 *dispatcher_args; + + /* + * First grab the arguments from before the start of this image. + */ + dispatcher_args = (U64 *)(KSEG_ADDRESS(DISPATCH_AT) - (4*sizeof(U64))); + alpha_io_base = dispatcher_args[1]; + + #ifdef NEVER + printf("...crb dispatch routine called, a0 = %X, a1 = %X, a2 = %X\n", + a0, a1, a2); + #endif + alpha_inb = inb_std; + alpha_outb = outb_std; + #ifdef NEVER + alpha_io_base = 0xfffffc01c0000000ULL; + #endif + + switch (a0) { + case 0x01: /* GETC */ + if ( (INB(com1Lsr) & 0x1) != 0 ) { + /* 63:61 = 000 = Success, no more to be read */ + result = 0; + result = (char)INB(com1Rbr) & 0177; + if ( (INB(com1Lsr) & 0x1) != 0 ) + /* 63:61 = 001 = success, more to be read */ + result |= 0x2000000000000000ULL; + } else { + /* 63:61 = 100 = failure, no character */ + result = 0x8000000000000000ULL; + } + + break; + case 0x02: /* PUTS */ + /* + * a1 = Unit + * a2 = VA of string + * a3 = Length of string (in bytes). + */ + result = a3; /* 31:0 = count of bytes written */ + cptr = (char *)a2; + while (a3--) { + char c; + + while ((INB(com1Lsr) & 0x20) == 0) ; + c = *cptr++; + OUTB(c, com1Thr); + if (c == '\n') { + while ((INB(com1Lsr) & 0x20) == 0) ; + OUTB('\r', com1Thr); + } + } + break; + case 0x03: + case 0x04: + case 0x05: + case 0x06: + ; + #ifdef NEVER + printf("...crb dispatch routine called, a0 = %X, a1 = %X, a2 = %X\n", + a0, a1, a2); + #endif + } + + return result; + } + + diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/dispatch.ld LINUX_ALPHA_SDK/sources/linux/miniloader/dispatch.ld *** LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/dispatch.ld Thu Feb 9 19:57:36 1995 --- LINUX_ALPHA_SDK/sources/linux/miniloader/dispatch.ld Wed Feb 8 09:36:10 1995 *************** *** 0 **** --- 1,49 ---- + OUTPUT_FORMAT("ecoff-littlealpha") + ENTRY(__dispatch) + SECTIONS + { + .text 0x70220000 : { + _FTEXT = . ; + __istart = . ; + *(.init) + eprol = .; + *(.text) + __fstart = . ; + *(.fini) + _ETEXT = .; + } + .rdata . : { + *(.rdata) + } + .pdata . : { + _fpdata = .; + *(.pdata) + } + .data . : { + _FDATA = .; + *(.data) + CONSTRUCTORS + } + .xdata . : { + *(.xdata) + } + _gp = ALIGN (8) + 0x8000; + .lit8 . : { + *(.lit8) + } + .lita . : { + *(.lita) + } + _EDATA = .; + _FBSS = .; + .sbss . : { + *(.sbss) + *(.scommon) + } + .bss . : { + *(.bss) + *(COMMON) + } + _END = .; + _end = .; + } diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/dispatch_asm.S LINUX_ALPHA_SDK/sources/linux/miniloader/dispatch_asm.S *** LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/dispatch_asm.S Thu Feb 9 19:57:36 1995 --- LINUX_ALPHA_SDK/sources/linux/miniloader/dispatch_asm.S Wed Feb 8 09:36:57 1995 *************** *** 0 **** --- 1,355 ---- + #include + #include + + #ifdef CALL_PAL_BROKEN + #define call_pal .long + #endif + + /* Here are some VMS PALcode functions that we need in order to + * switch to OSF PALcode... + */ + #define PAL_mtpr_vptb 0x2d + + #define PAL_mfpr_pcbb 0x12 + #define PAL_mfpr_vptb 0x29 + #define PAL_ldqp 0x03 + #define PAL_stqp 0x04 + #define PAL_halt_entry 0x00 + #define PAL_cserve_entry 0x09 + #define SWPPAL 10 + + .set noreorder + + /**************************************************************************** + * Console dispatch jacket routine. * + ****************************************************************************/ + /* + * Once Linux has been loaded, this miniloader acts in the same way as + * the SRM console and provides functions via a callback mechanism and the + * HWRPB. This code sets all of that up and calls into the C module dispatch.c + * + */ + .globl __dispatch + .ent __dispatch + __dispatch: + /* + * Save the world. + */ + lda sp, -64*8(sp) + + /* Now save the registers */ + stq t0,1*8(sp) /* $1 */ + stq t1,2*8(sp) /* $2 */ + stq t2,3*8(sp) /* $3 */ + stq t3,4*8(sp) /* $4 */ + stq t4,5*8(sp) /* $5 */ + stq t5,6*8(sp) /* $6 */ + stq t6,7*8(sp) /* $7 */ + stq t7,8*8(sp) /* $8 */ + stq a3,19*8(sp) /* $19 */ + stq a4,20*8(sp) /* $20 */ + stq a5,21*8(sp) /* $21 */ + stq t8,22*8(sp) /* $22 */ + stq t9,23*8(sp) /* $23 */ + stq t10,24*8(sp) /* $24 */ + stq t11,25*8(sp) /* $25 */ + stq ra,26*8(sp) /* $26 */ + stq t12,27*8(sp) /* $27 */ + stq AT,28*8(sp) /* $28 */ + stq gp,29*8(sp) /* $29 */ + + br t0, 1f # get the current PC + 1: ldgp gp, 0(t0) # init gp + jsr ra, crb_dispatch # go do it. + + ldq t0,1*8(sp) + ldq t1,2*8(sp) + ldq t2,3*8(sp) + ldq t3,4*8(sp) + ldq t4,5*8(sp) + ldq t5,6*8(sp) + ldq t6,7*8(sp) + ldq t7,8*8(sp) + ldq a3,19*8(sp) + ldq a4,20*8(sp) + ldq a5,21*8(sp) + ldq t8,22*8(sp) + ldq t9,23*8(sp) + ldq t10,24*8(sp) + ldq t11,25*8(sp) + ldq t12,27*8(sp) + ldq ra,26*8(sp) + ldq AT,28*8(sp) + ldq gp,29*8(sp) + + lda sp, 64*8(sp) + ret zero,(ra) # return. + + .end __dispatch + + /* + * Convert to running in OSF KSEG (directly mapped address space). + */ + .globl __turn_on_kseg + .ent __turn_on_kseg + __turn_on_kseg: + /* + * First, the return address (which wasn't KSEG). + */ + lda t1, -32768(zero) + sll t1, 27, t1 + bis ra, t1, ra + /* + * Now the stack pointer. + */ + bis sp, t1, sp + + ret zero,(ra) + .end __turn_on_kseg + + /* Most PC-class Alpha platforms access ISA I/O space in the same + * manner: by performing a longword read or write to a physical + * address constructed as follows: + * + * base-address | (portnum << swizzle) | length-code + * + * base_address, swizzle, and length-code are all platform specific. + * + * base-address is the physical address at which a particular type of bus + * space starts; ie on JENSEN, EISA I/O space starts at 0x300000000. + * + * swizzle is the amount by which the port (offset) into that space must + * be shifted. On JENSEN, this is (normally) 7. + * + * The length codes specify the operand length, ie byte, word, or long. + * There's also a "tribyte" access code for three-byte accesses, but + * it's not needed, not used, harder to use, and probably not tested 8-) + * + * Example for JENSEN: + * + * We convert this physical address to a 64-bit KSEG address so we can + * use it. Since kseg starts at 0xfffffc0000000000, the base address + * of the I/O area is 0xfffffc0300000000. Here's a trick we use to + * generate this address in only two instructions: + * + * In hex, -1024 = 0xfffffffffffffc00. Add 3, and we get + * -1021 = 0xfffffffffffffc03. Shift left 32, and we get + * 0xfffffc0300000000. + * + * To do this in two instructions: + * lda t0,-1021(zero) + * sll t0,32,t0 + */ + + /****************************************************************************/ + + /* The following routines are the generic ones, for the platforms that + * conform to the "standard", in terms of swizzle and length-code. These + * *are* parameterized, however, as the different platforms can have + * different base-address values for the bus address spaces. + * + * Note also that the "junk" I/O routines needed by the JENSEN platform are + * *not* needed for the "standard" ones; "junk" I/O space is the same as the + * normal bus I/O space. + */ + + /* inb_std - Input a byte from an I/O or MEMORY port. + * + * Calling sequence: + * + * val = inb_std(port, base) + * + */ + .globl inb_std + .ent inb_std + inb_std: + sll a0,5,t1 # Shift portnum left by 5 + # (no len code needed - 00) + addq a1,t1,t1 # Add base to portaddr + ldl v0,0(t1) # Read the port. + and a0,3,t1 # Shift data to position 0 + sll t1,3,t1 + srl v0,t1,v0 + zap v0,0xfe,v0 # Zap unused bytes + ret zero,(ra) + .end inb_std + + /* inw_std - Input a word from an I/O or MEMORY port. + * + * Calling sequence: + * + * val = inw_std(port, base) + * + */ + .globl inw_std + .ent inw_std + inw_std: + sll a0,5,t1 # Shift portnum left by 5 + addq t1,0x08,t1 # add word len code (0x08) + addq a1,t1,t1 # Add base to portaddr + ldl v0,0(t1) # Read the port. + and a0,3,t1 # Shift data to position 0 + sll t1,3,t1 + srl v0,t1,v0 + zap v0,0xfc,v0 # Zap unused bytes + ret zero,(ra) + .end inw_std + + /* inl_std - Input a longword from an I/O or MEMORY port. + * + * Calling sequence: + * + * val = inl(port, base) + * + */ + .globl inl_std + .ent inl_std + inl_std: + sll a0,5,t1 # Shift portnum left by 5 + addq t1,0x18,t1 # add longword len code (0x18) + addq a1,t1,t1 # Add base to portaddr + ldl v0,0(t1) # Read the port. + and a0,3,t1 # Shift data to position 0 + sll t1,3,t1 + srl v0,t1,v0 + zap v0,0xf0,v0 # Zap unused bytes + ret zero,(ra) + .end inl_std + + /* outb_std - Output a byte to an I/O or MEMORY port. + * + * Calling sequence: + * + * void outb_std(val, port, base) + * + */ + .globl outb_std + .ent outb_std + outb_std: + sll a1,5,t1 # Shift portnum left by 5 + # (no len code needed - 00) + addq a2,t1,t1 # Add base to portaddr + and a1,3,t2 # Shift data into position + sll t2,3,t2 + sll a0,t2,t3 + stl t3,0(t1) # Write the port. + mb # Memory Barrier; force it out + ret zero,(ra) + .end outb_std + + /* outw_std - Output a word to an I/O or MEMORY port. + * + * Calling sequence: + * + * void outw_std(val, port, base) + * + */ + .globl outw_std + .ent outw_std + outw_std: + sll a1,5,t1 # Shift portnum left by 5 + addq t1,0x08,t1 # add word len code (0x08) + addq a2,t1,t1 # Add base to portaddr + and a1,3,t2 # Shift data into position + sll t2,3,t2 + sll a0,t2,t3 + stl t3,0(t1) # Write the port. + mb # Memory Barrier; force it out + ret zero,(ra) + .end outw_std + + /* outl_std - Output a longword to an I/O or MEMORY port. + * + * Calling sequence: + * + * void outl(val, port, base) + * + * outl_p is a "slower" form of the same operation used on the x86. + * Since we execute a couple of instructions after the port access + * ourselves, a special form which adds a couple of instructions after + * the access should not be needed... + */ + .globl outl_std + .ent outl_std + outl_std: + sll a1,5,t1 # Shift portnum left by 5 + addq t1,0x18,t1 # add longword len code (0x18) + addq a2,t1,t1 # Add base to portaddr + and a1,3,t2 # Shift data into position + sll t2,3,t2 + sll a0,t2,t3 + stl t3,0(t1) # Write the port. + mb # Memory Barrier; force it out + ret zero,(ra) + .end outl_std + + /* + * read_cpureg - Read a CPU register + */ + + .globl read_cpureg_long + .ent read_cpureg_long + read_cpureg_long: + ldl v0,0(a0) + ret zero,(ra) + .end read_cpureg_long + + /* + * write_cpureg_long - Write a CPU register + */ + .globl write_cpureg_long + .ent write_cpureg_long + write_cpureg_long: + stl a0,0(a1) + mb + ret zero,(ra) + .end write_cpureg_long + + /* + * read_cpureg_long - Read a CPU register + */ + + .globl read_cpureg_quad + .ent read_cpureg_quad + read_cpureg_quad: + ldq v0,0(a0) + ret zero,(ra) + .end read_cpureg_quad + + /* + * write_cpureg_quad - Write a CPU register + */ + .globl write_cpureg_quad + .ent write_cpureg_quad + write_cpureg_quad: + stq a0,0(a1) + mb + ret zero,(ra) + .end write_cpureg_quad + + /* Set the current interrupt priority level, returning the previous IPL + * + * Calling sequence: + * + * old_ipl = ipl(new_ipl) + * + * The SWPIPL pal function does this all for us 8-) + */ + + .globl ipl + .ent ipl + ipl: + call_pal PAL_swpipl + ret zero,(ra) + .end ipl + + + .global wrfen + .ent wrfen + wrfen: + lda a0, 1(zero) + call_pal PAL_wrfen + ret zero, (ra) + .end wrfen + + diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/impure.h LINUX_ALPHA_SDK/sources/linux/miniloader/impure.h *** LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/impure.h Thu Feb 9 19:57:36 1995 --- LINUX_ALPHA_SDK/sources/linux/miniloader/impure.h Wed Feb 8 09:37:32 1995 *************** *** 0 **** --- 1,537 ---- + #ifndef __IMPURE_LOADED + #define __IMPURE_LOADED 1 + /* + ***************************************************************************** + ** * + ** Copyright © 1994 * + ** by Digital Equipment Corporation, Maynard, Massachusetts. * + ** * + ** All Rights Reserved * + ** * + ** Permission is hereby granted to use, copy, modify and distribute * + ** this software and its documentation, in both source code and * + ** object code form, and without fee, for the purpose of distribution * + ** of this software or modifications of this software within products * + ** incorporating an integrated circuit implementing Digital's AXP * + ** architecture, regardless of the source of such integrated circuit, * + ** provided that the above copyright notice and this permission notice * + ** appear in all copies, and that the name of Digital Equipment * + ** Corporation not be used in advertising or publicity pertaining to * + ** distribution of the document or software without specific, written * + ** prior permission. * + ** * + ** Digital Equipment Corporation disclaims all warranties and/or * + ** guarantees with regard to this software, including all implied * + ** warranties of fitness for a particular purpose and merchantability, * + ** and makes no representations regarding the use of, or the results * + ** of the use of, the software and documentation in terms of correctness, * + ** accuracy, reliability, currentness or otherwise; and you rely on * + ** the software, documentation and results solely at your own risk. * + ** * + ** AXP is a trademark of Digital Equipment Corporation. * + ** * + ***************************************************************************** + ** + ** FACILITY: + ** + ** DECchip 21064/21066 OSF/1 PALcode + ** + ** MODULE: + ** + ** impure.h + ** + ** MODULE DESCRIPTION: + ** + ** PAL impure scratch and logout area data structure + ** definitions + ** + ** AUTHOR: ER + ** + ** CREATION DATE: 23-Feb-1994 + ** + ** $Id: impure.h,v 1.1 1995/02/08 14:37:32 rusling Exp $ + ** + ** MODIFICATION HISTORY: + ** + ** $Log: impure.h,v $ + * Revision 1.1 1995/02/08 14:37:32 rusling + * Alpha Miniloader PAL impure area definitions. + * + ** Revision 2.3 1994/06/30 15:14:10 samberg + ** Added srom revision and processor id parameters + ** + ** Revision 2.2 1994/06/16 14:47:56 samberg + ** For ANSI, changed $ to _, except for pvc and reg def + ** + ** Revision 2.1 1994/04/01 21:55:51 ericr + ** 1-APR-1994 V2 OSF/1 PALcode + ** + ** Revision 1.6 1994/03/28 17:52:28 ericr + ** Changed SAVE_FPRS macro to clear all DTB entries + ** + ** Revision 1.5 1994/03/23 19:55:01 ericr + ** Moved SAVE_FPR macro call to the end of SAVE_STATE + ** + ** Revision 1.4 1994/03/14 20:47:50 ericr + ** Added common area offset definitions. + ** Changed base of saved state area from 0x40 to 0x100 + ** Created SAVE_GPRS, SAVE_FPRS, and SAVE_PAL macros + ** Changed SAVE_STATE to be a composite of SAVE macros + ** + ** Revision 1.3 1994/03/08 20:28:49 ericr + ** Fixed bug in RESTORE_GPRS + ** + ** Revision 1.2 1994/03/08 00:12:27 ericr + ** Moved SAVE_STATE macro to here from macros.h + ** Added RESTORE_GPRS macro + ** + ** Revision 1.1 1994/02/28 18:23:46 ericr + ** Initial revision + ** + */ + + /* + ** NOTE: + ** Offset definitions must be 12-bits or less, as the HW_LD + ** and HW_ST instructions only support a 12-bit signed displacement. + */ + + /* + ** Common Area Offset Definitions: + */ + + #define CNS_Q_RCS_ID 0 + #define CNS_Q_SCRATCH 0xA0 + #define CNS_Q_BASE 0x100 /* Base of saved state area */ + + /* + ** Processor Saved State Area Offset Definitions: + ** + ** These offsets are relative to the CNS_Q_BASE offset + ** defined in the common area. + */ + + #define CNS_Q_GPR 0x0 + #define CNS_Q_FPR 0x100 + #define CNS_Q_PT 0x200 + #define CNS_Q_EXC_ADDR 0x300 + #define CNS_Q_PS 0x308 + #define CNS_Q_PAL_BASE 0x310 + #define CNS_Q_HIER 0x318 + #define CNS_Q_SIRR 0x320 + #define CNS_Q_ICCSR 0x328 + #define CNS_Q_ABOX_CTL 0x330 + + #ifdef DC21064 + #define CNS_Q_BIU_CTL 0x338 + + #define CNS_Q_SROM_REV 0x340 + #define CNS_Q_PROC_ID 0x348 + #define CNS_Q_MEM_SIZE 0x350 + #define CNS_Q_CYCLE_CNT 0x358 + #define CNS_Q_SIGNATURE 0x360 + #define CNS_Q_PROC_MASK 0x368 + #define CNS_Q_SYSCTX 0x370 + + #define CNS_K_SIZE 0x378 + + #endif /* DC21064 */ + + #ifdef DC21066 + #define CNS_L_BCR0 0x338 + #define CNS_L_BCR1 0x33C + #define CNS_L_BCR2 0x340 + #define CNS_L_BCR3 0x344 + #define CNS_L_BMR0 0x348 + #define CNS_L_BMR1 0x34C + #define CNS_L_BMR2 0x350 + #define CNS_L_BMR3 0x354 + + #define CNS_Q_SROM_REV 0x358 + #define CNS_Q_PROC_ID 0x360 + #define CNS_Q_MEM_SIZE 0x368 + #define CNS_Q_CYCLE_CNT 0x370 + #define CNS_Q_SIGNATURE 0x378 + #define CNS_Q_PROC_MASK 0x380 + #define CNS_Q_SYSCTX 0x388 + + #define CNS_K_SIZE 0x390 + + #endif /* DC21066 */ + + /* + ** Short Corrected Error Logout Frame Offset Definitions: + */ + + #define LAS_Q_BASE (CNS_Q_BASE+CNS_K_SIZE) + + #define LAS_L_FRAME 0x0000 + #define LAS_L_FLAG 0x0004 + #define LAS_L_CPU 0x0008 + #define LAS_L_SYS 0x000C + #define LAS_Q_MCHK_CODE 0x0010 + + #ifdef DC21064 + + #define LAS_Q_BIU_STAT 0x0018 + #define LAS_Q_BIU_ADDR 0x0020 + #define LAS_Q_DC_STAT 0x0028 + #define LAS_Q_FILL_SYNDROME 0x0030 + #define LAS_Q_FILL_ADDR 0x0038 + #define LAS_Q_BC_TAG 0x0040 + + #define LAS_K_SIZE 0x0048 /* Frame size */ + + #endif /* DC21064 */ + + #ifdef DC21066 + + #define LAS_Q_ESR 0x0018 + #define LAS_Q_EAR 0x0020 + #define LAS_Q_DC_STAT 0x0028 + #define LAS_Q_IOC_STAT0 0x0030 + #define LAS_Q_IOC_STAT1 0x0038 + + #define LAS_K_SIZE 0x0040 /* Frame size */ + + #endif /* DC21066 */ + + /* + ** Long Machine Check Error Logout Frame Offset Definitions: + */ + + #define LAF_Q_BASE (LAS_Q_BASE+LAS_K_SIZE) + + #define LAF_L_FRAME 0x0000 + #define LAF_L_FLAG 0x0004 + #define LAF_L_CPU 0x0008 + #define LAF_L_SYS 0x000C + + #define LAF_Q_PT0 0x0010 + #define LAF_Q_PT1 0x0018 + #define LAF_Q_PT2 0x0020 + #define LAF_Q_PT3 0x0028 + #define LAF_Q_PT4 0x0030 + #define LAF_Q_PT5 0x0038 + #define LAF_Q_PT6 0x0040 + #define LAF_Q_PT7 0x0048 + #define LAF_Q_PT8 0x0050 + #define LAF_Q_PT9 0x0058 + #define LAF_Q_PT10 0x0060 + #define LAF_Q_PT11 0x0068 + #define LAF_Q_PT12 0x0070 + #define LAF_Q_PT13 0x0078 + #define LAF_Q_PT14 0x0080 + #define LAF_Q_PT15 0x0088 + #define LAF_Q_PT16 0x0090 + #define LAF_Q_PT17 0x0098 + #define LAF_Q_PT18 0x00A0 + #define LAF_Q_PT19 0x00A8 + #define LAF_Q_PT20 0x00B0 + #define LAF_Q_PT21 0x00B8 + #define LAF_Q_PT22 0x00C0 + #define LAF_Q_PT23 0x00C8 + #define LAF_Q_PT24 0x00D0 + #define LAF_Q_PT25 0x00D8 + #define LAF_Q_PT26 0x00E0 + #define LAF_Q_PT27 0x00E8 + #define LAF_Q_PT28 0x00F0 + #define LAF_Q_PT29 0x00F8 + #define LAF_Q_PT30 0x0100 + #define LAF_Q_PT31 0x0108 + + #define LAF_Q_EXC_ADDR 0x0110 + #define LAF_Q_PAL_BASE 0x0130 + #define LAF_Q_HIER 0x0138 + #define LAF_Q_HIRR 0x0140 + #define LAF_Q_MM_CSR 0x0148 + #define LAF_Q_DC_STAT 0x0150 + #define LAF_Q_DC_ADDR 0x0158 + #define LAF_Q_ABOX_CTL 0x0160 + + #ifdef DC21064 + + #define LAF_Q_BIU_STAT 0x0168 + #define LAF_Q_BIU_ADDR 0x0170 + #define LAF_Q_BIU_CTL 0x0178 + #define LAF_Q_FILL_SYNDROME 0x0180 + #define LAF_Q_FILL_ADDR 0x0188 + #define LAF_Q_VA 0x0190 + #define LAF_Q_BC_TAG 0x0198 + + #define LAF_K_SIZE 0x01A0 /* Frame size */ + + #endif /* DC21064 */ + + #ifdef DC21066 + + #define LAF_Q_ESR 0x0168 + #define LAF_Q_EAR 0x0170 + #define LAF_Q_CAR 0x0178 + #define LAF_Q_IOC_STAT0 0x0180 + #define LAF_Q_IOC_STAT1 0x0188 + #define LAF_Q_VA 0x0190 + + #define LAF_K_SIZE 0x0198 /* Frame size */ + + #endif /* DC21066 */ + + #define LAF_Q_SYS_BASE LAF_K_SIZE + + + /* + ** Macro to save the internal state of the general purpose + ** register file. + ** + ** Register Usage Conventions: + ** + ** t0 (r1) - Saved in pt0. + ** t1 (r2) - Base address of the save state area. + */ + #define SAVE_GPRS \ + stq_p r0, (CNS_Q_GPR + 0x00)(t1); \ + mfpr r0, pt0; \ + stq_p r0, (CNS_Q_GPR + 0x08)(t1); \ + mfpr r0, pt1; \ + stq_p r0, (CNS_Q_GPR + 0x10)(t1); \ + stq_p r3, (CNS_Q_GPR + 0x18)(t1); \ + stq_p r4, (CNS_Q_GPR + 0x20)(t1); \ + stq_p r5, (CNS_Q_GPR + 0x28)(t1); \ + stq_p r6, (CNS_Q_GPR + 0x30)(t1); \ + stq_p r7, (CNS_Q_GPR + 0x38)(t1); \ + stq_p r8, (CNS_Q_GPR + 0x40)(t1); \ + stq_p r9, (CNS_Q_GPR + 0x48)(t1); \ + stq_p r10, (CNS_Q_GPR + 0x50)(t1); \ + stq_p r11, (CNS_Q_GPR + 0x58)(t1); \ + stq_p r12, (CNS_Q_GPR + 0x60)(t1); \ + stq_p r13, (CNS_Q_GPR + 0x68)(t1); \ + stq_p r14, (CNS_Q_GPR + 0x70)(t1); \ + stq_p r15, (CNS_Q_GPR + 0x78)(t1); \ + stq_p r16, (CNS_Q_GPR + 0x80)(t1); \ + stq_p r17, (CNS_Q_GPR + 0x88)(t1); \ + stq_p r18, (CNS_Q_GPR + 0x90)(t1); \ + stq_p r19, (CNS_Q_GPR + 0x98)(t1); \ + stq_p r20, (CNS_Q_GPR + 0xA0)(t1); \ + stq_p r21, (CNS_Q_GPR + 0xA8)(t1); \ + stq_p r22, (CNS_Q_GPR + 0xB0)(t1); \ + stq_p r23, (CNS_Q_GPR + 0xB8)(t1); \ + stq_p r24, (CNS_Q_GPR + 0xC0)(t1); \ + stq_p r25, (CNS_Q_GPR + 0xC8)(t1); \ + stq_p r26, (CNS_Q_GPR + 0xD0)(t1); \ + stq_p r27, (CNS_Q_GPR + 0xD8)(t1); \ + stq_p r28, (CNS_Q_GPR + 0xE0)(t1); \ + stq_p r29, (CNS_Q_GPR + 0xE8)(t1); \ + stq_p r30, (CNS_Q_GPR + 0xF0)(t1); \ + stq_p r31, (CNS_Q_GPR + 0xF8)(t1) + + /* + ** Macro to save the internal state of the floating point + ** register file. + ** + ** Register Usage Conventions: + ** + ** t0 (r1) - Scratch + ** t1 (r2) - Base address of console save state area. + ** t2 (r3) - Scratch + ** t3 (r4) - Scratch + */ + #define SAVE_FPRS \ + mtpr zero, dtbZap; \ + mfpr t0, pt2; \ + bis zero, 1, t3; \ + sll t3, ICCSR_V_FPE, t3; \ + bis t0, t3, t3; \ + mtpr t3, pt2_iccsr; \ + mfpr t2, ptPtbr; \ + bis t2, 1, t3; \ + mtpr t3, ptPtbr; \ + stt f0, (CNS_Q_FPR + 0x00)(t1); \ + stt f1, (CNS_Q_FPR + 0x08)(t1); \ + stt f2, (CNS_Q_FPR + 0x10)(t1); \ + stt f3, (CNS_Q_FPR + 0x18)(t1); \ + stt f4, (CNS_Q_FPR + 0x20)(t1); \ + stt f5, (CNS_Q_FPR + 0x28)(t1); \ + stt f6, (CNS_Q_FPR + 0x30)(t1); \ + stt f7, (CNS_Q_FPR + 0x38)(t1); \ + stt f8, (CNS_Q_FPR + 0x40)(t1); \ + stt f9, (CNS_Q_FPR + 0x48)(t1); \ + stt f10, (CNS_Q_FPR + 0x50)(t1); \ + stt f11, (CNS_Q_FPR + 0x58)(t1); \ + stt f12, (CNS_Q_FPR + 0x60)(t1); \ + stt f13, (CNS_Q_FPR + 0x68)(t1); \ + stt f14, (CNS_Q_FPR + 0x70)(t1); \ + stt f15, (CNS_Q_FPR + 0x78)(t1); \ + stt f16, (CNS_Q_FPR + 0x80)(t1); \ + stt f17, (CNS_Q_FPR + 0x88)(t1); \ + stt f18, (CNS_Q_FPR + 0x90)(t1); \ + stt f19, (CNS_Q_FPR + 0x98)(t1); \ + stt f20, (CNS_Q_FPR + 0xA0)(t1); \ + stt f21, (CNS_Q_FPR + 0xA8)(t1); \ + stt f22, (CNS_Q_FPR + 0xB0)(t1); \ + stt f23, (CNS_Q_FPR + 0xB8)(t1); \ + stt f24, (CNS_Q_FPR + 0xC0)(t1); \ + stt f25, (CNS_Q_FPR + 0xC8)(t1); \ + stt f26, (CNS_Q_FPR + 0xD0)(t1); \ + stt f27, (CNS_Q_FPR + 0xD8)(t1); \ + stt f28, (CNS_Q_FPR + 0xE0)(t1); \ + stt f29, (CNS_Q_FPR + 0xE8)(t1); \ + stt f30, (CNS_Q_FPR + 0xF0)(t1); \ + stt f31, (CNS_Q_FPR + 0xF8)(t1); \ + mtpr zero, dtbZap; \ + mtpr t2, ptPtbr; \ + mtpr t0, pt2_iccsr + + /* + ** Macro to save the internal state of the PAL temporary + ** registers. + ** + ** Register Usage Conventions: + ** + ** t1 (r2) - Base address of the save state area. + */ + #define SAVE_PALS \ + mfpr r0, pt0; \ + stq_p r0, (CNS_Q_PT + 0x00)(t1); \ + mfpr r0, pt1; \ + stq_p r0, (CNS_Q_PT + 0x08)(t1); \ + mfpr r0, pt2; \ + stq_p r0, (CNS_Q_PT + 0x10)(t1); \ + mfpr r0, pt3; \ + stq_p r0, (CNS_Q_PT + 0x18)(t1); \ + mfpr r0, pt4; \ + stq_p r0, (CNS_Q_PT + 0x20)(t1); \ + mfpr r0, pt5; \ + stq_p r0, (CNS_Q_PT + 0x28)(t1); \ + mfpr r0, pt6; \ + stq_p r0, (CNS_Q_PT + 0x30)(t1); \ + mfpr r0, pt7; \ + stq_p r0, (CNS_Q_PT + 0x38)(t1); \ + mfpr r0, pt8; \ + stq_p r0, (CNS_Q_PT + 0x40)(t1); \ + mfpr r0, pt9; \ + stq_p r0, (CNS_Q_PT + 0x48)(t1); \ + mfpr r0, pt10; \ + stq_p r0, (CNS_Q_PT + 0x50)(t1); \ + mfpr r0, pt11; \ + stq_p r0, (CNS_Q_PT + 0x58)(t1); \ + mfpr r0, pt12; \ + stq_p r0, (CNS_Q_PT + 0x60)(t1); \ + mfpr r0, pt13; \ + stq_p r0, (CNS_Q_PT + 0x68)(t1); \ + mfpr r0, pt14; \ + stq_p r0, (CNS_Q_PT + 0x70)(t1); \ + mfpr r0, pt15; \ + stq_p r0, (CNS_Q_PT + 0x78)(t1); \ + mfpr r0, pt16; \ + stq_p r0, (CNS_Q_PT + 0x80)(t1); \ + mfpr r0, pt17; \ + stq_p r0, (CNS_Q_PT + 0x88)(t1); \ + mfpr r0, pt18; \ + stq_p r0, (CNS_Q_PT + 0x90)(t1); \ + mfpr r0, pt19; \ + stq_p r0, (CNS_Q_PT + 0x98)(t1); \ + mfpr r0, pt20; \ + stq_p r0, (CNS_Q_PT + 0xA0)(t1); \ + mfpr r0, pt21; \ + stq_p r0, (CNS_Q_PT + 0xA8)(t1); \ + mfpr r0, pt22; \ + stq_p r0, (CNS_Q_PT + 0xB0)(t1); \ + mfpr r0, pt23; \ + stq_p r0, (CNS_Q_PT + 0xB8)(t1); \ + mfpr r0, pt24; \ + stq_p r0, (CNS_Q_PT + 0xC0)(t1); \ + mfpr r0, pt25; \ + stq_p r0, (CNS_Q_PT + 0xC8)(t1); \ + mfpr r0, pt26; \ + stq_p r0, (CNS_Q_PT + 0xD0)(t1); \ + mfpr r0, pt27; \ + stq_p r0, (CNS_Q_PT + 0xD8)(t1); \ + mfpr r0, pt28; \ + stq_p r0, (CNS_Q_PT + 0xE0)(t1); \ + mfpr r0, pt29; \ + stq_p r0, (CNS_Q_PT + 0xE8)(t1); \ + mfpr r0, pt30; \ + stq_p r0, (CNS_Q_PT + 0xF0)(t1); \ + mfpr r0, pt31; \ + stq_p r0, (CNS_Q_PT + 0xF8)(t1) + + /* + ** Macro to save the internal state of the machine to the + ** impure scratch area. + ** + ** Register Usage Conventions: + ** + ** t0 (r1) - Saved in pt0. + ** t1 (r2) - Base address of impure scratch area. + */ + #define SAVE_STATE \ + lda t1, CNS_Q_BASE(t1); \ + SAVE_GPRS; \ + SAVE_PALS; \ + mfpr r0, excAddr; \ + stq_p r0, CNS_Q_EXC_ADDR(t1); \ + mfpr r0, ps; \ + stq_p r0, CNS_Q_PS(t1); \ + mfpr r0, palBase; \ + stq_p r0, CNS_Q_PAL_BASE(t1); \ + mfpr r0, hier; \ + stq_p r0, CNS_Q_HIER(t1); \ + mfpr r0, sirr; \ + stq_p r0, CNS_Q_SIRR(t1); \ + mfpr r0, iccsr; \ + stq_p r0, CNS_Q_ICCSR(t1); \ + SAVE_FPRS; \ + STALL; \ + STALL + + /* + ** Macro to restore the internal state of the general purpose + ** register file from the impure scratch area. + ** + ** Register Usage Conventions: + ** + ** t1 (r2) - Base address of the save state area. + */ + #define RESTORE_GPRS \ + ldq_p r0, (CNS_Q_GPR + 0x00)(t1); \ + ldq_p r1, (CNS_Q_GPR + 0x08)(t1); \ + ldq_p r3, (CNS_Q_GPR + 0x18)(t1); \ + ldq_p r4, (CNS_Q_GPR + 0x20)(t1); \ + ldq_p r5, (CNS_Q_GPR + 0x28)(t1); \ + ldq_p r6, (CNS_Q_GPR + 0x30)(t1); \ + ldq_p r7, (CNS_Q_GPR + 0x38)(t1); \ + ldq_p r8, (CNS_Q_GPR + 0x40)(t1); \ + ldq_p r9, (CNS_Q_GPR + 0x48)(t1); \ + ldq_p r10, (CNS_Q_GPR + 0x50)(t1); \ + ldq_p r11, (CNS_Q_GPR + 0x58)(t1); \ + ldq_p r12, (CNS_Q_GPR + 0x60)(t1); \ + ldq_p r13, (CNS_Q_GPR + 0x68)(t1); \ + ldq_p r14, (CNS_Q_GPR + 0x70)(t1); \ + ldq_p r15, (CNS_Q_GPR + 0x78)(t1); \ + ldq_p r16, (CNS_Q_GPR + 0x80)(t1); \ + ldq_p r17, (CNS_Q_GPR + 0x88)(t1); \ + ldq_p r18, (CNS_Q_GPR + 0x90)(t1); \ + ldq_p r19, (CNS_Q_GPR + 0x98)(t1); \ + ldq_p r20, (CNS_Q_GPR + 0xA0)(t1); \ + ldq_p r21, (CNS_Q_GPR + 0xA8)(t1); \ + ldq_p r22, (CNS_Q_GPR + 0xB0)(t1); \ + ldq_p r23, (CNS_Q_GPR + 0xB8)(t1); \ + ldq_p r24, (CNS_Q_GPR + 0xC0)(t1); \ + ldq_p r25, (CNS_Q_GPR + 0xC8)(t1); \ + ldq_p r26, (CNS_Q_GPR + 0xD0)(t1); \ + ldq_p r27, (CNS_Q_GPR + 0xD8)(t1); \ + ldq_p r28, (CNS_Q_GPR + 0xE0)(t1); \ + ldq_p r29, (CNS_Q_GPR + 0xE8)(t1); \ + ldq_p r30, (CNS_Q_GPR + 0xF0)(t1); \ + ldq_p r31, (CNS_Q_GPR + 0xF8)(t1); \ + ldq_p r2, (CNS_Q_GPR + 0x10)(t1) + + #endif /* __IMPURE_LOADED */ + + + + + + + + diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/miniboot.S LINUX_ALPHA_SDK/sources/linux/miniloader/miniboot.S *** LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/miniboot.S Thu Feb 9 19:57:36 1995 --- LINUX_ALPHA_SDK/sources/linux/miniloader/miniboot.S Wed Feb 8 09:38:15 1995 *************** *** 0 **** --- 1,527 ---- + #include + #include + + #ifdef CALL_PAL_BROKEN + #define call_pal .long + #endif + + /* Here are some VMS PALcode functions that we need in order to + * switch to OSF PALcode... + */ + #define PAL_mtpr_vptb 0x2d + + #define PAL_mfpr_pcbb 0x12 + #define PAL_mfpr_vptb 0x29 + #define PAL_ldqp 0x03 + #define PAL_stqp 0x04 + #define PAL_halt_entry 0x00 + #define PAL_cserve_entry 0x09 + #define SWPPAL 10 + + .set noreorder + + .globl __start + .ent __start + __start: + + #ifdef HALT_ON_STARTUP + call_pal PAL_halt # offset 0 + #else + bis zero,zero,zero # offset 0 + #endif + /* + * Get the gp register set up correctly. + */ + br t0,1f # offset 4 + .quad _gp # offset 8 + 1: ldq gp,0(t0) # offset 16 + /* + * Change the sp to below this image (0x200000) + */ + ldah sp, 32(zero) + /* + * Allow enough space for the parameters that we will need to pass to + * the Linux Kernel. + */ + subq sp,7*8,sp + stq zero, 0*8(sp) + stq zero, 1*8(sp) + stq zero, 2*8(sp) + stq zero, 3*8(sp) + stq zero, 4*8(sp) + stq zero, 5*8(sp) + stq zero, 6*8(sp) + /* + * Get us into kseg. + */ + jsr ra, __turn_on_kseg + /* + * Zero a few arguments and jump into boot_main. + */ + bis zero,zero,a0 + bis zero,zero,a1 + bis zero,zero,a2 + + jsr ra,boot_main + + call_pal PAL_halt + .end __start + + + /* + * Convert to running in OSF KSEG (directly mapped address space). + */ + .globl __turn_on_kseg + .ent __turn_on_kseg + __turn_on_kseg: + /* + * First, the return address (which wasn't KSEG). + */ + lda t1, -32768(zero) + sll t1, 27, t1 + bis ra, t1, ra + /* + * Now the stack pointer. + */ + bis sp, t1, sp + + ret zero,(ra) + .end __turn_on_kseg + + /* Zeros out one page of physical memory. A0 = pfn of physical page + * to zero out. Uses physical mapping. + */ + .globl zeropage_phys + .ent zeropage_phys + zeropage_phys: + sll a0,13,a0 # Convert r16 from pfn to physaddr + lda t0,1024(zero) # Number of quads in a page + $301: stq zero,0(a0) # stuff a quadword + lda a0,8(a0) # Increment pointer + subq t0,1,t0 # Decrement count + bne t0,$301 # Loop if not zero + ret zero,(ra) # done! + .end zeropage_phys + + + /* Switch to new virtual-memory mapping. + * + * Usage: + * a0 = ptbr page table base register + * a1 = vptbr virtual page table base register + */ + + .extern vptbr + + .globl switch_to_new_map_and_jump + .ent switch_to_new_map_and_jump + switch_to_new_map_and_jump: + /* + * Make sure that we're in OSF KSEG address land + */ + jsr ra, __turn_on_kseg + /* + * Write the new virtual page table base register. Registers t0, + * t8-t11 and a0 are unpredicable after this call. + */ + lda sp, -8(sp) + stq a0, 0(sp) + + /* Write the new vptptr... */ + bis a1, zero, a0 + call_pal PAL_wrvptptr + + ldq a0, 0(sp) + lda sp, 8(sp) + + /* + * Build a Process Context Block (PCB). + */ + ldl a1, pboot_pcb # a1 = addr of pcb + #ifdef NEVER + stq sp,0(a1) # ksp = sp + stq zero,8(a1) # usp = 0 for now + + stq a0,16(a1) # store ptbr into pcb + stq zero,24(a1) # cc and asn + stq zero,32(a1) # proc_uniq + lda a0, 1(zero) + stq a0,40(a1) # fen on + #else + stq sp,0(a1) # ksp = sp + #endif + + /* + * Now jump over into the new memory space. The way + * to do this is to load up the pcb and switch process + * context. Again, Registers t0, + * t8-t11 and a0 are unpredicable after this call. + */ + bis a1, zero, a0 # get the pcb back into a0 + call_pal PAL_swpctx # Go to new proc ctx + + lda a0,-2(zero) # Flush ALL TBs + call_pal PAL_tbi + /* + * Using OSF KSEG addressing, load the Linux Kernel parameters + * from the block below this image in memory. + */ + ldah sp, 32(zero) + lda t2, -32768(zero) + sll t2, 27, t2 + bis sp, t2, sp + /* + * Now the stack pointer is pointing at 0xfffffc0000200000. Now + * wind it back and pull out the arguments. + */ + subq sp,7*8,sp + ldq t0,0*8(sp) + ldq a0,1*8(sp) + ldq a1,2*8(sp) + ldq a2,3*8(sp) + ldq a3,4*8(sp) + ldq a4,5*8(sp) + ldq a5,6*8(sp) + addq sp,7*8,sp + + jmp zero,(t0) # Away we go! + + .end switch_to_new_map_and_jump + + + .globl imb + .ent imb + imb: + call_pal PAL_imb + ret zero,(ra) + .end imb + + + + .globl entMM + .ent entMM + entMM: call_pal PAL_halt + .end entMM + + .globl entIF + .ent entIF + entIF: subq a0,3,a0 # If a0 == 3, this is an FEN fault. + beq a0,1f # Try setting FEN to 1 and trying again... + call_pal PAL_halt + 1: lda sp,-48(sp) + stq a0,0(sp) + stq t0,8(sp) + stq t8,16(sp) + stq t9,24(sp) + stq t10,32(sp) + stq t11,40(sp) + lda a0,1(zero) + call_pal PAL_wrfen + ldq a0,0(sp) + ldq t0,8(sp) + ldq t8,16(sp) + ldq t9,24(sp) + ldq t10,32(sp) + ldq t11,40(sp) + lda sp,48(sp) + call_pal PAL_rti + + .end entIF + + /* + * Where compilers cannot dereference quadword addresses + * (ie NT), then we must have a assembler routines for this. + */ + .globl ReadQ + .ent ReadQ 2 + ReadQ: + .option O1 + .frame sp, 0, ra + + ldq v0, 0(a0) + ret zero, (ra) + .end ReadQ + + .globl WriteQ + .ent WriteQ 2 + WriteQ: + .option O1 + .frame sp, 0, ra + + stq a1, 0(a0) + ret zero, (ra) + .end WriteQ + + .globl halt + .ent halt 2 + halt: + .option O1 + .frame sp, 0, ra + call_pal PAL_halt_entry + ret zero, (ra) + .end halt + + + .globl rdsp + .ent rdsp + rdsp: + .option 01 + .frame sp, 0, ra + bis sp, zero, v0 + ret zero, (ra) + .end rdsp + + .globl cServe + .ent cServe 2 + cServe: + .option O1 + .frame sp, 0, ra + call_pal PAL_cserve_entry + ret zero, (ra) + .end cServe + + /* Most PC-class Alpha platforms access ISA I/O space in the same + * manner: by performing a longword read or write to a physical + * address constructed as follows: + * + * base-address | (portnum << swizzle) | length-code + * + * base_address, swizzle, and length-code are all platform specific. + * + * base-address is the physical address at which a particular type of bus + * space starts; ie on JENSEN, EISA I/O space starts at 0x300000000. + * + * swizzle is the amount by which the port (offset) into that space must + * be shifted. On JENSEN, this is (normally) 7. + * + * The length codes specify the operand length, ie byte, word, or long. + * There's also a "tribyte" access code for three-byte accesses, but + * it's not needed, not used, harder to use, and probably not tested 8-) + * + * Example for JENSEN: + * + * We convert this physical address to a 64-bit KSEG address so we can + * use it. Since kseg starts at 0xfffffc0000000000, the base address + * of the I/O area is 0xfffffc0300000000. Here's a trick we use to + * generate this address in only two instructions: + * + * In hex, -1024 = 0xfffffffffffffc00. Add 3, and we get + * -1021 = 0xfffffffffffffc03. Shift left 32, and we get + * 0xfffffc0300000000. + * + * To do this in two instructions: + * lda t0,-1021(zero) + * sll t0,32,t0 + */ + + /****************************************************************************/ + + /* The following routines are the generic ones, for the platforms that + * conform to the "standard", in terms of swizzle and length-code. These + * *are* parameterized, however, as the different platforms can have + * different base-address values for the bus address spaces. + * + * Note also that the "junk" I/O routines needed by the JENSEN platform are + * *not* needed for the "standard" ones; "junk" I/O space is the same as the + * normal bus I/O space. + */ + + /* inb_std - Input a byte from an I/O or MEMORY port. + * + * Calling sequence: + * + * val = inb_std(port, base) + * + */ + .globl inb_std + .ent inb_std + inb_std: + sll a0,5,t1 # Shift portnum left by 5 + # (no len code needed - 00) + addq a1,t1,t1 # Add base to portaddr + ldl v0,0(t1) # Read the port. + and a0,3,t1 # Shift data to position 0 + sll t1,3,t1 + srl v0,t1,v0 + zap v0,0xfe,v0 # Zap unused bytes + ret zero,(ra) + .end inb_std + + /* inw_std - Input a word from an I/O or MEMORY port. + * + * Calling sequence: + * + * val = inw_std(port, base) + * + */ + .globl inw_std + .ent inw_std + inw_std: + sll a0,5,t1 # Shift portnum left by 5 + addq t1,0x08,t1 # add word len code (0x08) + addq a1,t1,t1 # Add base to portaddr + ldl v0,0(t1) # Read the port. + and a0,3,t1 # Shift data to position 0 + sll t1,3,t1 + srl v0,t1,v0 + zap v0,0xfc,v0 # Zap unused bytes + ret zero,(ra) + .end inw_std + + /* inl_std - Input a longword from an I/O or MEMORY port. + * + * Calling sequence: + * + * val = inl(port, base) + * + */ + .globl inl_std + .ent inl_std + inl_std: + sll a0,5,t1 # Shift portnum left by 5 + addq t1,0x18,t1 # add longword len code (0x18) + addq a1,t1,t1 # Add base to portaddr + ldl v0,0(t1) # Read the port. + and a0,3,t1 # Shift data to position 0 + sll t1,3,t1 + srl v0,t1,v0 + zap v0,0xf0,v0 # Zap unused bytes + ret zero,(ra) + .end inl_std + + /* outb_std - Output a byte to an I/O or MEMORY port. + * + * Calling sequence: + * + * void outb_std(val, port, base) + * + */ + .globl outb_std + .ent outb_std + outb_std: + sll a1,5,t1 # Shift portnum left by 5 + # (no len code needed - 00) + addq a2,t1,t1 # Add base to portaddr + and a1,3,t2 # Shift data into position + sll t2,3,t2 + sll a0,t2,t3 + stl t3,0(t1) # Write the port. + mb # Memory Barrier; force it out + ret zero,(ra) + .end outb_std + + /* outw_std - Output a word to an I/O or MEMORY port. + * + * Calling sequence: + * + * void outw_std(val, port, base) + * + */ + .globl outw_std + .ent outw_std + outw_std: + sll a1,5,t1 # Shift portnum left by 5 + addq t1,0x08,t1 # add word len code (0x08) + addq a2,t1,t1 # Add base to portaddr + and a1,3,t2 # Shift data into position + sll t2,3,t2 + sll a0,t2,t3 + stl t3,0(t1) # Write the port. + mb # Memory Barrier; force it out + ret zero,(ra) + .end outw_std + + /* outl_std - Output a longword to an I/O or MEMORY port. + * + * Calling sequence: + * + * void outl(val, port, base) + * + * outl_p is a "slower" form of the same operation used on the x86. + * Since we execute a couple of instructions after the port access + * ourselves, a special form which adds a couple of instructions after + * the access should not be needed... + */ + .globl outl_std + .ent outl_std + outl_std: + sll a1,5,t1 # Shift portnum left by 5 + addq t1,0x18,t1 # add longword len code (0x18) + addq a2,t1,t1 # Add base to portaddr + and a1,3,t2 # Shift data into position + sll t2,3,t2 + sll a0,t2,t3 + stl t3,0(t1) # Write the port. + mb # Memory Barrier; force it out + ret zero,(ra) + .end outl_std + + /* + * read_cpureg - Read a CPU register + */ + + .globl read_cpureg_long + .ent read_cpureg_long + read_cpureg_long: + ldl v0,0(a0) + ret zero,(ra) + .end read_cpureg_long + + /* + * write_cpureg_long - Write a CPU register + */ + .globl write_cpureg_long + .ent write_cpureg_long + write_cpureg_long: + stl a0,0(a1) + mb + ret zero,(ra) + .end write_cpureg_long + + /* + * read_cpureg_long - Read a CPU register + */ + + .globl read_cpureg_quad + .ent read_cpureg_quad + read_cpureg_quad: + ldq v0,0(a0) + ret zero,(ra) + .end read_cpureg_quad + + /* + * write_cpureg_quad - Write a CPU register + */ + .globl write_cpureg_quad + .ent write_cpureg_quad + write_cpureg_quad: + stq a0,0(a1) + mb + ret zero,(ra) + .end write_cpureg_quad + + /* Set the current interrupt priority level, returning the previous IPL + * + * Calling sequence: + * + * old_ipl = ipl(new_ipl) + * + * The SWPIPL pal function does this all for us 8-) + */ + + .globl ipl + .ent ipl + ipl: + call_pal PAL_swpipl + ret zero,(ra) + .end ipl + + + .global wrfen + .ent wrfen + wrfen: + lda a0, 1(zero) + call_pal PAL_wrfen + ret zero, (ra) + .end wrfen + diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/miniboot.h LINUX_ALPHA_SDK/sources/linux/miniloader/miniboot.h *** LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/miniboot.h Thu Feb 9 19:57:36 1995 --- LINUX_ALPHA_SDK/sources/linux/miniloader/miniboot.h Wed Feb 8 09:38:39 1995 *************** *** 0 **** --- 1,84 ---- + /* + * This module contains miniboot specific definitions and macros. + */ + + #ifndef MINIBOOT_H + #define MINIBOOT_H 1 + + #ifndef U64 + #define U64 unsigned long long + #endif + + #ifndef TRUE + #define TRUE 1 + #endif + #ifndef FALSE + #define FALSE 0 + #endif + /* + * IO Base Addresses. These are different for different I/O chips. + */ + /******************************************************************************** + * 21066 embedded PCI/Memory I/O controller being used * + ********************************************************************************/ + #ifdef _ALPHA_21066_IO + + #define PCI_IO_BASE 0xfffffc01c0000000ULL + #define PCI_MEM_BASE 0xfffffc0200000000ULL + #ifdef CONFIG_PCI + #define PCI_CFG_BASE 0xfffffc01e0000000ULL + #endif + + #endif + + /******************************************************************************** + * APECS PCI/Memory I/O chipset being used * + ********************************************************************************/ + #ifdef _ALPHA_APECS_IO + + #define PCI_IO_BASE 0xfffffc01c0000000ULL + #define PCI_MEM_BASE 0xfffffc0200000000ULL + #ifdef CONFIG_PCI + #define PCI_CFG_BASE 0xfffffc01e0000000ULL + #endif + + #endif + + /******************************************************************************** + * EB64 Home brewed I/O chipset being used * + ********************************************************************************/ + + #ifdef _ALPHA_EB64_IO + #endif + /******************************************************************************** + * MACROS for using the inb and outb routines * + ********************************************************************************/ + extern U64 alpha_io_base; + extern U64 alpha_mem_base; + #ifdef CONFIG_PCI + extern U64 alpha_cfg_base; + #endif + extern U64 system_type; + + extern int (*alpha_inb)(int port,U64 base); + extern int (*alpha_inw)(int port,U64 base); + extern int (*alpha_inl)(int port,U64 base); + extern void (*alpha_outb)(int v,int port,U64 base); + extern void (*alpha_outw)(int v,int port,U64 base); + extern void (*alpha_outl)(int v,int port,U64 base); + + #define INB(port) (*alpha_inb)((port), alpha_io_base) + #define OUTB(value, port) (*alpha_outb)((value), (port), alpha_io_base) + #define INW(port) (*alpha_inw)((port), alpha_io_base) + #define OUTW(value, port) (*alpha_outw)((value), (port), alpha_io_base) + #define INL(port) (*alpha_inl)((port), alpha_io_base) + #define OUTL(value, port) (*alpha_outl)((value), (port), alpha_io_base) + + /******************************************************************************** + * General macros * + ********************************************************************************/ + extern U64 system_type; + #define _SYSTEM_TYPE system_type; + + #endif + diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/miniboot.ld LINUX_ALPHA_SDK/sources/linux/miniloader/miniboot.ld *** LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/miniboot.ld Thu Feb 9 19:57:36 1995 --- LINUX_ALPHA_SDK/sources/linux/miniloader/miniboot.ld Wed Feb 8 09:39:06 1995 *************** *** 0 **** --- 1,49 ---- + OUTPUT_FORMAT("ecoff-littlealpha") + ENTRY(__start) + SECTIONS + { + .text 0x200000 : { + _FTEXT = . ; + __istart = . ; + *(.init) + eprol = .; + *(.text) + __fstart = . ; + *(.fini) + _ETEXT = .; + } + .rdata . : { + *(.rdata) + } + .pdata . : { + _fpdata = .; + *(.pdata) + } + .data . : { + _FDATA = .; + *(.data) + CONSTRUCTORS + } + .xdata . : { + *(.xdata) + } + _gp = ALIGN (8) + 0x8000; + .lit8 . : { + *(.lit8) + } + .lita . : { + *(.lita) + } + _EDATA = .; + _FBSS = .; + .sbss . : { + *(.sbss) + *(.scommon) + } + .bss . : { + *(.bss) + *(COMMON) + } + _END = .; + _end = .; + } diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/osfboot.h LINUX_ALPHA_SDK/sources/linux/miniloader/osfboot.h *** LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/osfboot.h Thu Feb 9 19:57:36 1995 --- LINUX_ALPHA_SDK/sources/linux/miniloader/osfboot.h Wed Feb 8 09:41:17 1995 *************** *** 0 **** --- 1,51 ---- + /* Definitions of executable file formats for Linux/Alpha, + * Modified for a 32-bit compiler environment from the original DEC OSF/1 + * definitions. This will change or go away as we go to a self-hosted + * environment. + */ + + typedef struct _filehdr { + unsigned short f_magic; /* Magic number (must be ALPHAMAGIC) */ + unsigned short f_nscns; /* Number of sections */ + int f_timdat; /* Time/date of creation */ + U64 f_symptr; /* Pointer to symbolic header */ + int f_nsyms; + unsigned short f_opthdr; /* sozeof optional header */ + unsigned short f_flags; /* flags */ + } FILEHDR ; + + #define ALPHAMAGIC 0603 + + typedef struct _aouthdr { + short magic; /* Magic number (must be OMAGIC) */ + short vstamp; /* Version stamp */ + short bldrev; /* Build revision */ + short padcell; /* Pad to 64 bits */ + U64 tsize; /* Size of text segment */ + U64 dsize; /* Size of data segment */ + U64 bsize; /* Size of bss segment */ + U64 entry; /* Virtual address of entry point */ + U64 text_start; /* VA of start of text segment */ + U64 data_start; /* VA of start of data segment */ + U64 bss_start; /* VA of start of bss segment */ + int gprmask; /* general purpose register mask */ + int fprmask; /* floating point register mask */ + U64 gp_value; /* gp value for this exe */ + } AOUTHDR; + + #define OMAGIC 0407 + #define ZMAGIC 0413 + + typedef struct _scnhdr { + char s_name[8]; /* Section name */ + U64 s_paddr; /* Section physical address */ + U64 s_vaddr; /* Virtual address */ + U64 s_size; /* Size in bytes */ + U64 s_scnptr; /* file ptr to raw data in section */ + U64 s_relptr; /* file ptr to relocation */ + U64 s_lnnoptr; /* file ptr to gp histogram */ + unsigned short s_nreloc; /* number of relocation entries */ + unsigned short s_nlnno; /* number of gp histogram entries */ + int s_flags; /* flags */ + } SCNHDR; + diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/printf.c LINUX_ALPHA_SDK/sources/linux/miniloader/printf.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/printf.c Thu Feb 9 19:57:36 1995 --- LINUX_ALPHA_SDK/sources/linux/miniloader/printf.c Wed Feb 8 09:41:43 1995 *************** *** 0 **** --- 1,263 ---- + /* + * linux/kernel/vsprintf.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file README.legal in the main directory of this archive + * for more details. + */ + + /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ + /* + * Wirzenius wrote this portably, Torvalds fucked it up :-) + */ + + /* + * 680x0 support by Hamish Macdonald + */ + + + /* we use this so that we can do without the ctype library */ + #define is_digit(c) ((c) >= '0' && (c) <= '9') + + static int skip_atoi(const char **s) + { + int i=0; + + while (is_digit(**s)) + i = i*10 + *((*s)++) - '0'; + return i; + } + + #define ZEROPAD 1 /* pad with zero */ + #define SIGN 2 /* unsigned/signed long */ + #define PLUS 4 /* show plus */ + #define SPACE 8 /* space if plus */ + #define LEFT 16 /* left justified */ + #define SPECIAL 32 /* 0x */ + #define SMALL 64 /* use 'abcdef' instead of 'ABCDEF' */ + + + + static char * number(char * str, int num, int base, int size, int precision + ,int type) + { + char c,sign,tmp[36]; + const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int i; + + if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz"; + if (type&LEFT) type &= ~ZEROPAD; + if (base<2 || base>36) + return 0; + c = (type & ZEROPAD) ? '0' : ' ' ; + if (type&SIGN && num<0) { + sign='-'; + num = -num; + } else + sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0); + if (sign) size--; + if (type&SPECIAL) + if (base==16) size -= 2; + else if (base==8) size--; + i=0; + if (num==0) + tmp[i++]='0'; + else while (num!=0) { + tmp[i++]=digits[num%base]; + num = num/base; + } + if (i>precision) precision=i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + *str++ = ' '; + if (sign) + *str++ = sign; + if (type&SPECIAL) + if (base==8) + *str++ = '0'; + else if (base==16) { + *str++ = '0'; + *str++ = digits[33]; + } + if (!(type&LEFT)) + while(size-->0) + *str++ = c; + while(i0) + *str++ = tmp[i]; + while(size-->0) + *str++ = ' '; + return str; + } + + int sprintf(char *buf, const char *fmt, unsigned int a1, + unsigned int a2, + unsigned int a3, + unsigned int a4) + { + int len; + int i; + char * str; + char *s; + int *ip; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', or 'L' for integer fields */ + unsigned int args[4]; + int curarg=0; + + args[0] = a1; + args[1] = a2; + args[2] = a3; + args[3] = a4; + + for (str=buf ; *fmt ; ++fmt) { + if (*fmt != '%') { + if(*fmt == '\n') { + /* Precede CR with LF */ + *str++ = '\r'; + } + *str++ = *fmt; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (is_digit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + /* it's the next argument */ + field_width = (int)(args[curarg++]); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (is_digit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + /* it's the next argument */ + precision = (int)(args[curarg++]); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { + qualifier = *fmt; + ++fmt; + } + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + *str++ = ' '; + *str++ = (unsigned char)(args[curarg++]); + while (--field_width > 0) + *str++ = ' '; + break; + + case 's': + s = (char *)(args[curarg++]); + if (!s) + s = ""; + len = strlen(s); + if (precision < 0) + precision = len; + else if (len > precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + *str++ = ' '; + for (i = 0; i < len; ++i) + *str++ = *s++; + while (len < field_width--) + *str++ = ' '; + break; + + case 'o': + str = number(str, (unsigned long)(args[curarg++]), 8, + field_width, precision, flags); + break; + + case 'p': + if (field_width == -1) { + field_width = 8; + flags |= ZEROPAD; + } + str = number(str, + (unsigned long)(args[curarg++]), 16, + field_width, precision, flags); + break; + + case 'x': + flags |= SMALL; + case 'X': + str = number(str, (unsigned long)(args[curarg++]), 16, + field_width, precision, flags); + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + str = number(str, (unsigned long)(args[curarg++]), 10, + field_width, precision, flags); + break; + + case 'n': + ip = (int *)(args[curarg++]); + *ip = (str - buf); + break; + + default: + if (*fmt != '%') + *str++ = '%'; + if (*fmt) + *str++ = *fmt; + else + --fmt; + break; + } + } + *str = '\0'; + return str-buf; + } + + printf(const char * fmt, unsigned int a1, unsigned int a2, + unsigned int a3, unsigned int a4) + { + char buf[132]; + + sprintf(buf, fmt, a1, a2, a3, a4); + cons_puts(0, buf); + } diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/uart.c LINUX_ALPHA_SDK/sources/linux/miniloader/uart.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/uart.c Thu Feb 9 19:57:36 1995 --- LINUX_ALPHA_SDK/sources/linux/miniloader/uart.c Wed Feb 8 09:42:17 1995 *************** *** 0 **** --- 1,178 ---- + + /***************************************************************************** + + Copyright © 1993, 1994 Digital Equipment Corporation, + Maynard, Massachusetts. + + All Rights Reserved + + Permission to use, copy, modify, and distribute this software and its + documentation for any purpose and without fee is hereby granted, provided + that the copyright notice and this permission notice appear in all copies + of software and supporting documentation, and that the name of Digital not + be used in advertising or publicity pertaining to distribution of the software + without specific, written prior permission. Digital grants this permission + provided that you prominently mark, as not part of the original, any + modifications made to this software or documentation. + + Digital Equipment Corporation disclaims all warranties and/or guarantees + with regard to this software, including all implied warranties of fitness for + a particular purpose and merchantability, and makes no representations + regarding the use of, or the results of the use of, the software and + documentation in terms of correctness, accuracy, reliability, currentness or + otherwise; and you rely on the software, documentation and results solely at + your own risk. + + ******************************************************************************/ + + #ifndef LINT + static char *rcsid = "$Id: uart.c,v 1.1 1995/02/08 14:42:17 rusling Exp $"; + #endif + + /* + * $Log: uart.c,v $ + * Revision 1.1 1995/02/08 14:42:17 rusling + * Alpha miniloader UART support code. + * + * Revision 1.9 1994/08/07 06:44:52 fdh + * Flush the receive buffers when initing the com ports. + * + * Revision 1.8 1994/08/05 20:16:23 fdh + * Updated Copyright header and RCS $Id: identifier. + * + * Revision 1.7 1994/07/28 17:14:53 fdh + * Removed unused definitions. + * + * Revision 1.6 1994/06/21 14:29:39 rusling + * fixed up WNT compile warnings. + * + * Revision 1.5 1994/06/17 19:35:37 fdh + * Clean-up... + * + * Revision 1.4 1994/01/19 10:40:08 rusling + * Ported to Alpha Windows NT. + * + * Revision 1.3 1993/11/22 16:02:20 rusling + * Moved the IO Bus init call out of uart_init() and + * explicitly into main() (in /rom/cmd.c). + * + * Revision 1.2 1993/11/19 17:03:16 fdh + * Fixup include declarations. + * + * Revision 1.1 1993/06/08 19:56:26 fdh + * Initial revision + * + */ + + + + /* + * Last modified by FDH May 03 + */ + + #include "miniboot.h" + #include "uart.h" + + + int outputport; + int inputport; + + int uart_charav(int port) + { + if (port == COM1) return((INB(com1Lsr) & 1) != 0); + if (port == COM2) return((INB(com2Lsr) & 1) != 0); + return (TRUE); + } + + char uart_getchar(int port) + { + while (!uart_charav(port)); + if(port == COM1) return((char)INB(com1Rbr) & 0177); + else if (port == COM2) return((char)INB(com2Rbr) & 0177); + else return(-1); + } + + void uart_putchar(int port, char c) + { + int lsr, thr; + switch(port) + { + case COM1: + lsr = com1Lsr; + thr = com1Thr; + break; + case COM2: + lsr = com2Lsr; + thr = com2Thr; + break; + default: + return; + } + + while ((INB(lsr) & 0x20) == 0); + OUTB(c,thr); + if (c == '\n') uart_putchar(port, '\r'); + } + + + void uart_init_line(int line, int baud) + { + int i; + int baudconst; + switch (baud) + { + case 56000: baudconst = 2; break; + case 38400: baudconst = 3; break; + case 19200: baudconst = 6; break; + case 9600: baudconst = 12; break; + case 4800: baudconst = 24; break; + case 2400: baudconst = 48; break; + case 1200: baudconst = 96; break; + case 300: baudconst = 384; break; + case 150: baudconst = 768; break; + default: baudconst = 12; break; + } + if (line == 1) + { + OUTB(0x87, com1Lcr); + OUTB(0, com1Dlm); + OUTB(baudconst, com1Dll); + OUTB(0x07, com1Lcr); + OUTB(0x0F, com1Mcr); + + for(i=10;i>0;i--) { + if (INB(com1Lsr) == (unsigned int)0) break; + INB(com1Rbr); + } + } + if (line == 2) + { + OUTB(0x87, com2Lcr); + OUTB(0, com2Dlm); + OUTB(baudconst, com2Dll); + OUTB(0x07, com2Lcr); + OUTB(0x0F, com2Mcr); + + for(i=10;i>0;i--) { + if (INB(com2Lsr) == (unsigned int)0) break; + INB(com2Rbr); + } + } + } + + int uart_init() + { + int code; + + code = 1; + + inputport = COM1; + outputport = COM1; + + uart_init_line(1, 9600); + uart_init_line(2, 9600); + + return (code); + } + + diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/uart.h LINUX_ALPHA_SDK/sources/linux/miniloader/uart.h *** LINUX_ALPHA_SDK/sources/linux.0.1.0/miniloader/uart.h Thu Feb 9 19:57:36 1995 --- LINUX_ALPHA_SDK/sources/linux/miniloader/uart.h Wed Feb 8 09:42:37 1995 *************** *** 0 **** --- 1,78 ---- + #ifndef __UART_H_LOADED + #define __UART_H_LOADED + /***************************************************************************** + + Copyright © 1993, 1994 Digital Equipment Corporation, + Maynard, Massachusetts. + + All Rights Reserved + + Permission to use, copy, modify, and distribute this software and its + documentation for any purpose and without fee is hereby granted, provided + that the copyright notice and this permission notice appear in all copies + of software and supporting documentation, and that the name of Digital not + be used in advertising or publicity pertaining to distribution of the software + without specific, written prior permission. Digital grants this permission + provided that you prominently mark, as not part of the original, any + modifications made to this software or documentation. + + Digital Equipment Corporation disclaims all warranties and/or guarantees + with regard to this software, including all implied warranties of fitness for + a particular purpose and merchantability, and makes no representations + regarding the use of, or the results of the use of, the software and + documentation in terms of correctness, accuracy, reliability, currentness or + otherwise; and you rely on the software, documentation and results solely at + your own risk. + + ******************************************************************************/ + + /* + * $Id: uart.h,v 1.1 1995/02/08 14:42:37 rusling Exp $; + */ + + /* + * $Log: uart.h,v $ + * Revision 1.1 1995/02/08 14:42:37 rusling + * Alpha miniloader UART definitions. + * + * Revision 1.3 1994/08/05 20:13:47 fdh + * Updated Copyright header and RCS $Id: identifier. + * + * Revision 1.2 1994/06/20 14:18:59 fdh + * Fixup header file preprocessor #include conditionals. + * + * Revision 1.1 1993/06/08 19:56:16 fdh + * Initial revision + * + */ + + + + #define COM1 1 + #define COM2 2 + + #define com1Rbr 0x3f8 + #define com1Thr 0x3f8 + #define com1Ier 0x3f9 + #define com1Iir 0x3fa + #define com1Lcr 0x3fb + #define com1Mcr 0x3fc + #define com1Lsr 0x3fd + #define com1Msr 0x3fe + #define com1Scr 0x3ff + #define com1Dll 0x3f8 + #define com1Dlm 0x3f9 + + #define com2Rbr 0x2f8 + #define com2Thr 0x2f8 + #define com2Ier 0x2f9 + #define com2Iir 0x2fa + #define com2Lcr 0x2fb + #define com2Mcr 0x2fc + #define com2Lsr 0x2fd + #define com2Msr 0x2fe + #define com2Scr 0x2ff + #define com2Dll 0x2f8 + #define com2Dlm 0x2f9 + + #endif /* __UART_H_LOADED */ diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/net/inet/ip.c LINUX_ALPHA_SDK/sources/linux/net/inet/ip.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/net/inet/ip.c Tue Dec 13 14:43:54 1994 --- LINUX_ALPHA_SDK/sources/linux/net/inet/ip.c Wed Feb 8 14:48:38 1995 *************** *** 441,446 **** --- 441,447 ---- if (wlen) { unsigned long bogus; + #ifdef i386 __asm__("clc\n" "1:\t" "lodsl\n\t" *************** *** 454,459 **** --- 455,462 ---- "adcw $0, %w0" : "=r" (sum), "=S" (buff), "=r" (wlen), "=a" (bogus) : "0" (sum), "1" (buff), "2" (wlen)); + #elif defined(__alpha) + #endif /* i386 | __alpha */ } return (~sum) & 0xffff; } *************** *** 469,474 **** --- 472,478 ---- /* Do the first multiple of 4 bytes and convert to 16 bits. */ if (len > 3) { + #ifdef i386 __asm__("clc\n" "1:\t" "lodsl\n\t" *************** *** 482,497 **** --- 486,507 ---- : "=b" (sum) , "=S" (buff) : "0" (sum), "c" (len >> 2) ,"1" (buff) : "ax", "cx", "si", "bx" ); + #elif defined(__alpha) + #endif /* i386 | __alpha */ } if (len & 2) { + #ifdef i386 __asm__("lodsw\n\t" "addw %%ax, %%bx\n\t" "adcw $0, %%bx" : "=b" (sum), "=S" (buff) : "0" (sum), "1" (buff) : "bx", "ax", "si"); + #elif defined(__alpha) + #endif /* i386 | __alpha */ } if (len & 1) { + #ifdef i386 __asm__("lodsb\n\t" "movb $0, %%ah\n\t" "addw %%ax, %%bx\n\t" *************** *** 499,504 **** --- 509,516 ---- : "=b" (sum), "=S" (buff) : "0" (sum), "1" (buff) : "bx", "ax", "si"); + #elif defined(__alpha) + #endif /* i386 | __alpha */ } sum =~sum; return(sum & 0xffff); diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/net/inet/tcp.c LINUX_ALPHA_SDK/sources/linux/net/inet/tcp.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/net/inet/tcp.c Tue Dec 13 14:43:55 1994 --- LINUX_ALPHA_SDK/sources/linux/net/inet/tcp.c Wed Feb 8 14:48:40 1995 *************** *** 527,540 **** --- 527,544 ---- if (saddr == 0) saddr = my_addr(); print_th(th); + #ifdef i386 __asm__("\t addl %%ecx,%%ebx\n" "\t adcl %%edx,%%ebx\n" "\t adcl $0, %%ebx\n" : "=b"(sum) : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_TCP*256) : "cx","bx","dx" ); + #elif defined(__alpha) + #endif /* i386 | __alpha */ if (len > 3) { + #ifdef i386 __asm__("\tclc\n" "1:\n" "\t lodsl\n" *************** *** 544,552 **** --- 548,559 ---- : "=b"(sum) , "=S"(th) : "0"(sum), "c"(len/4) ,"1"(th) : "ax", "cx", "bx", "si" ); + #elif defined(__alpha) + #endif /* i386 | __alpha */ } /* Convert from 32 bits to 16 bits. */ + #ifdef i386 __asm__("\t movl %%ebx, %%ecx\n" "\t shrl $16,%%ecx\n" "\t addw %%cx, %%bx\n" *************** *** 554,572 **** --- 561,585 ---- : "=b"(sum) : "0"(sum) : "bx", "cx"); + #elif defined(__alpha) + #endif /* i386 | __alpha */ /* Check for an extra word. */ if ((len & 2) != 0) { + #ifdef i386 __asm__("\t lodsw\n" "\t addw %%ax,%%bx\n" "\t adcw $0, %%bx\n" : "=b"(sum), "=S"(th) : "0"(sum) ,"1"(th) : "si", "ax", "bx"); + #elif defined(__alpha) + #endif /* i386 | __alpha */ } /* Now check for the extra byte. */ if ((len & 1) != 0) { + #ifdef i386 __asm__("\t lodsb\n" "\t movb $0,%%ah\n" "\t addw %%ax,%%bx\n" *************** *** 574,579 **** --- 587,594 ---- : "=b"(sum) : "0"(sum) ,"S"(th) : "si", "ax", "bx"); + #elif defined(__alpha) + #endif /* i386 | __alpha */ } /* We only want the bottom 16 bits, but we never cleared the top 16. */ diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/net/inet/udp.c LINUX_ALPHA_SDK/sources/linux/net/inet/udp.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/net/inet/udp.c Tue Dec 13 14:43:55 1994 --- LINUX_ALPHA_SDK/sources/linux/net/inet/udp.c Wed Feb 8 14:48:42 1995 *************** *** 146,159 **** --- 146,163 ---- print_udp(uh); + #ifdef i386 __asm__("\t addl %%ecx,%%ebx\n" "\t adcl %%edx,%%ebx\n" "\t adcl $0, %%ebx\n" : "=b"(sum) : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_UDP*256) : "cx","bx","dx" ); + #elif defined(__alpha) + #endif /* i386 | __alpha */ if (len > 3) { + #ifdef i386 __asm__("\tclc\n" "1:\n" "\t lodsl\n" *************** *** 163,171 **** --- 167,178 ---- : "=b"(sum) , "=S"(uh) : "0"(sum), "c"(len/4) ,"1"(uh) : "ax", "cx", "bx", "si" ); + #elif defined(__alpha) + #endif /* i386 | __alpha */ } /* Convert from 32 bits to 16 bits. */ + #ifdef i386 __asm__("\t movl %%ebx, %%ecx\n" "\t shrl $16,%%ecx\n" "\t addw %%cx, %%bx\n" *************** *** 173,191 **** --- 180,204 ---- : "=b"(sum) : "0"(sum) : "bx", "cx"); + #elif defined(__alpha) + #endif /* i386 | __alpha */ /* Check for an extra word. */ if ((len & 2) != 0) { + #ifdef i386 __asm__("\t lodsw\n" "\t addw %%ax,%%bx\n" "\t adcw $0, %%bx\n" : "=b"(sum), "=S"(uh) : "0"(sum) ,"1"(uh) : "si", "ax", "bx"); + #elif defined(__alpha) + #endif /* i386 | __alpha */ } /* Now check for the extra byte. */ if ((len & 1) != 0) { + #ifdef i386 __asm__("\t lodsb\n" "\t movb $0,%%ah\n" "\t addw %%ax,%%bx\n" *************** *** 193,198 **** --- 206,213 ---- : "=b"(sum) : "0"(sum) ,"S"(uh) : "si", "ax", "bx"); + #elif defined(__alpha) + #endif /* i386 | __alpha */ } /* We only want the bottom 16 bits, but we never cleared the top 16. */ diff -c -r LINUX_ALPHA_SDK/sources/linux.0.1.0/tools/version.c LINUX_ALPHA_SDK/sources/linux/tools/version.c *** LINUX_ALPHA_SDK/sources/linux.0.1.0/tools/version.c Tue Dec 13 14:43:20 1994 --- LINUX_ALPHA_SDK/sources/linux/tools/version.c Thu Feb 9 19:46:20 1995 *************** *** 16,21 **** --- 16,27 ---- UTS_MACHINE, UTS_DOMAINNAME }; + #ifdef __alpha + char *linux_banner = + "Linux/Alpha version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" + LINUX_COMPILE_HOST ") " UTS_VERSION "\n"; + #else char *linux_banner = "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") " UTS_VERSION "\n"; + #endif